* [PATCH v3 01/14] Introduce slices
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 02/14] Introduce idle slice Daniel Glöckner
` (12 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
slices, the barebox idea of locking
barebox has pollers which execute code in the background whenever one of the
delay functions (udelay, mdelay, ...) or is_timeout() are called. This
introduces resource problems when some device triggers a poller by calling
a delay function and then the poller code calls into the same device again.
As an example consider a I2C GPIO expander which drives a LED which shall
be used as a heartbeat LED:
poller -> LED on/off -> GPIO high/low -> I2C transfer
The I2C controller has a timeout loop using is_timeout() and thus can trigger
a poller run. With this the following can happen during an unrelated I2C
transfer:
I2C transfer -> is_timeout() -> poller -> LED on/off -> GPIO high/low -> I2C transfer
We end up with issuing an I2C transfer during another I2C transfer and
things go downhill.
Due to the lack of interrupts we can't do real locking in barebox. We use
a mechanism called slices instead. A slice describes a resource to which
other slices can be attached. Whenever a slice is needed it must be acquired.
Acquiring a slice never fails, it just increases the acquired counter of
the slice and its dependent slices. when a slice shall be used inside a
poller it must first be tested if the slice is already in use. If it is,
we can't do the operation on the slice now and must return and hope that
we have more luck in the next poller call.
slices can be attached other slices as dependencies. In the example above
LED driver would add a dependency to the GPIO controller and the GPIO driver
would add a dependency to the I2C bus:
GPIO driver probe:
slice_add(&gpio->slice, i2c_device_slice(i2cdev));
LED driver probe:
slice_add(&led->slice, gpio_slice(gpio));
The GPIO code would call slice_acquire(&gpio->slice) before doing any
operation on the GPIO chip providing this GPIO, likewise the I2C core
would call slice_acquire(&i2cbus->slice) before doing an operation on
this I2C bus.
The heartbeat poller code would call slice_acquired(led_slice(led)) and
only continue when the slice is not acquired.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/Kconfig | 8 ++
common/Makefile | 1 +
common/slice.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++
include/slice.h | 31 +++++
4 files changed, 343 insertions(+)
create mode 100644 common/slice.c
create mode 100644 include/slice.h
diff --git a/commands/Kconfig b/commands/Kconfig
index 3789f33c3..608643fce 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -253,6 +253,14 @@ config CMD_POLLER
is_timeout() or one of the various delay functions. The poller command prints
informations about registered pollers.
+config CMD_SLICE
+ tristate
+ prompt "slice"
+ help
+ slices are a way to protect resources from being accessed by pollers. The slice
+ command can be used to print informations about slices and also to manipulate
+ them on the command line for debugging purposes.
+
# end Information commands
endmenu
diff --git a/common/Makefile b/common/Makefile
index 53859d8d1..141109b23 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -11,6 +11,7 @@ obj-y += bootsource.o
obj-$(CONFIG_ELF) += elf.o
obj-y += restart.o
obj-y += poweroff.o
+obj-y += slice.o
obj-$(CONFIG_MACHINE_ID) += machine_id.o
obj-$(CONFIG_AUTO_COMPLETE) += complete.o
obj-y += version.o
diff --git a/common/slice.c b/common/slice.c
new file mode 100644
index 000000000..085d67604
--- /dev/null
+++ b/common/slice.c
@@ -0,0 +1,303 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) "slice: " fmt
+
+#include <common.h>
+#include <slice.h>
+
+/*
+ * slices, the barebox idea of locking
+ *
+ * barebox has pollers which execute code in the background whenever one of the
+ * delay functions (udelay, mdelay, ...) or is_timeout() are called. This
+ * introduces resource problems when some device triggers a poller by calling
+ * a delay function and then the poller code calls into the same device again.
+ *
+ * As an example consider a I2C GPIO expander which drives a LED which shall
+ * be used as a heartbeat LED:
+ *
+ * poller -> LED on/off -> GPIO high/low -> I2C transfer
+ *
+ * The I2C controller has a timeout loop using is_timeout() and thus can trigger
+ * a poller run. With this the following can happen during an unrelated I2C
+ * transfer:
+ *
+ * I2C transfer -> is_timeout() -> poller -> LED on/off -> GPIO high/low -> I2C transfer
+ *
+ * We end up with issuing an I2C transfer during another I2C transfer and
+ * things go downhill.
+ *
+ * Due to the lack of interrupts we can't do real locking in barebox. We use
+ * a mechanism called slices instead. A slice describes a resource to which
+ * other slices can be attached. Whenever a slice is needed it must be acquired.
+ * Acquiring a slice never fails, it just increases the acquired counter of
+ * the slice and its dependent slices. when a slice shall be used inside a
+ * poller it must first be tested if the slice is already in use. If it is,
+ * we can't do the operation on the slice now and must return and hope that
+ * we have more luck in the next poller call.
+ *
+ * slices can be attached other slices as dependencies. In the example above
+ * LED driver would add a dependency to the GPIO controller and the GPIO driver
+ * would add a dependency to the I2C bus:
+ *
+ * GPIO driver probe:
+ *
+ * slice_depends_on(&gpio->slice, i2c_device_slice(i2cdev));
+ *
+ * LED driver probe:
+ *
+ * slice_depends_on(&led->slice, gpio_slice(gpio));
+ *
+ * The GPIO code would call slice_acquire(&gpio->slice) before doing any
+ * operation on the GPIO chip providing this GPIO, likewise the I2C core
+ * would call slice_acquire(&i2cbus->slice) before doing an operation on
+ * this I2C bus.
+ *
+ * The heartbeat poller code would call slice_acquired(led_slice(led)) and
+ * only continue when the slice is not acquired.
+ */
+
+/*
+ * slices are not required to have a device and thus a name, but it really
+ * helps debugging when it has one.
+ */
+static const char *slice_name(struct slice *slice)
+{
+ return slice->name;
+}
+
+static void __slice_acquire(struct slice *slice, int add)
+{
+ slice->acquired += add;
+
+ if (slice->acquired < 0) {
+ pr_err("Slice %s acquired count drops below zero\n",
+ slice_name(slice));
+ dump_stack();
+ slice->acquired = 0;
+ return;
+ }
+}
+
+/**
+ * slice_acquire: acquire a slice
+ * @slice: The slice to acquire
+ *
+ * This acquires a slice and its dependencies
+ */
+void slice_acquire(struct slice *slice)
+{
+ __slice_acquire(slice, 1);
+}
+
+/**
+ * slice_release: release a slice
+ * @slice: The slice to release
+ *
+ * This releases a slice and its dependencies
+ */
+void slice_release(struct slice *slice)
+{
+ __slice_acquire(slice, -1);
+}
+
+/**
+ * slice_acquired: test if a slice is acquired
+ * @slice: The slice to test
+ *
+ * This tests if a slice is acquired. Returns true if it is, false otherwise
+ */
+bool slice_acquired(struct slice *slice)
+{
+ struct slice_entry *se;
+ bool ret = false;
+
+ if (slice->acquired > 0)
+ return true;
+
+ if (slice->acquired < 0) {
+ pr_err("Recursive dependency detected in slice %s\n",
+ slice_name(slice));
+ panic("Cannot continue");
+ }
+
+ slice->acquired = -1;
+
+ list_for_each_entry(se, &slice->deps, list)
+ if (slice_acquired(se->slice)) {
+ ret = true;
+ break;
+ }
+
+ slice->acquired = 0;
+
+ return ret;
+}
+
+static void __slice_debug_acquired(struct slice *slice, int level)
+{
+ struct slice_entry *se;
+
+ pr_debug("%*s%s: %d\n", level * 4, "",
+ slice_name(slice),
+ slice->acquired);
+
+ list_for_each_entry(se, &slice->deps, list)
+ __slice_debug_acquired(se->slice, level + 1);
+}
+
+/**
+ * slice_debug_acquired: print the acquired state of a slice
+ *
+ * @slice: The slice to print
+ *
+ * This prints the acquired state of a slice and its dependencies.
+ */
+void slice_debug_acquired(struct slice *slice)
+{
+ if (!slice_acquired(slice))
+ return;
+
+ __slice_debug_acquired(slice, 0);
+}
+
+/**
+ * slice_depends_on: Add a dependency to a slice
+ *
+ * @slice: The slice to add the dependency to
+ * @dep: The slice @slice depends on
+ *
+ * This makes @slice dependent on @dep. In other words, acquiring @slice
+ * will lead to also acquiring @dep.
+ */
+void slice_depends_on(struct slice *slice, struct slice *dep)
+{
+ struct slice_entry *se = xzalloc(sizeof(*se));
+
+ pr_debug("Adding dependency %s (%d) to slice %s (%d)\n",
+ slice_name(dep), dep->acquired,
+ slice_name(slice), slice->acquired);
+
+ se->slice = dep;
+
+ list_add_tail(&se->list, &slice->deps);
+}
+
+static LIST_HEAD(slices);
+
+/**
+ * slice_init - initialize a slice before usage
+ * @slice: The slice to initialize
+ * @name: The name of the slice
+ *
+ * This initializes a slice before usage. @name should be a meaningful name, when
+ * a device context is available to the caller it is recommended to pass its
+ * dev_name() as name argument.
+ */
+void slice_init(struct slice *slice, const char *name)
+{
+ INIT_LIST_HEAD(&slice->deps);
+ slice->name = xstrdup(name);
+ list_add_tail(&slice->list, &slices);
+}
+
+/**
+ * slice_exit: Remove a slice
+ * @slice: The slice to remove the dependency from
+ */
+void slice_exit(struct slice *slice)
+{
+ struct slice *s;
+ struct slice_entry *se, *tmp;
+
+ list_del(&slice->list);
+
+ /* remove our dependencies */
+ list_for_each_entry_safe(se, tmp, &slice->deps, list) {
+ list_del(&se->list);
+ free(se);
+ }
+
+ /* remove this slice from other slices dependencies */
+ list_for_each_entry(s, &slices, list) {
+ list_for_each_entry_safe(se, tmp, &s->deps, list) {
+ if (se->slice == slice) {
+ list_del(&se->list);
+ free(se);
+ }
+ }
+ }
+
+ free(slice->name);
+}
+
+#if defined CONFIG_CMD_SLICE
+
+#include <command.h>
+#include <getopt.h>
+
+static void slice_info(void)
+{
+ struct slice *slice;
+ struct slice_entry *se;
+
+ list_for_each_entry(slice, &slices, list) {
+ printf("slice %s: acquired=%d\n",
+ slice_name(slice), slice->acquired);
+ list_for_each_entry(se, &slice->deps, list)
+ printf(" dep: %s\n", slice_name(se->slice));
+ }
+}
+
+static int __slice_acquire_name(const char *name, int add)
+{
+ struct slice *slice;
+
+ list_for_each_entry(slice, &slices, list) {
+ if (!strcmp(slice->name, name)) {
+ __slice_acquire(slice, add);
+ return 0;
+ }
+ }
+
+ printf("No such slice: %s\n", name);
+
+ return 1;
+}
+
+BAREBOX_CMD_HELP_START(slice)
+BAREBOX_CMD_HELP_TEXT("slice debugging command")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-i", "Print information about slices")
+BAREBOX_CMD_HELP_OPT ("-a <devname>", "acquire a slice")
+BAREBOX_CMD_HELP_OPT ("-r <devname>", "release a slice")
+BAREBOX_CMD_HELP_END
+
+static int do_slice(int argc, char *argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "a:r:i")) > 0) {
+ switch (opt) {
+ case 'a':
+ return __slice_acquire_name(optarg, 1);
+ case 'r':
+ return __slice_acquire_name(optarg, -1);
+ case 'i':
+ slice_info();
+ return 0;
+ }
+ }
+
+ return COMMAND_ERROR_USAGE;
+}
+
+BAREBOX_CMD_START(slice)
+ .cmd = do_slice,
+ BAREBOX_CMD_DESC("debug slices")
+ BAREBOX_CMD_OPTS("[-ari]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_HELP(cmd_slice_help)
+BAREBOX_CMD_END
+#endif
diff --git a/include/slice.h b/include/slice.h
new file mode 100644
index 000000000..5538fc434
--- /dev/null
+++ b/include/slice.h
@@ -0,0 +1,31 @@
+#ifndef __SLICE_H
+#define __SLICE_H
+
+enum slice_action {
+ SLICE_ACQUIRE = 1,
+ SLICE_RELEASE = -1,
+ SLICE_TEST = 0,
+};
+
+struct slice {
+ int acquired;
+ struct list_head deps;
+ char *name;
+ struct list_head list;
+};
+
+struct slice_entry {
+ struct slice *slice;
+ struct list_head list;
+};
+
+void slice_acquire(struct slice *slice);
+void slice_release(struct slice *slice);
+bool slice_acquired(struct slice *slice);
+void slice_depends_on(struct slice *slice, struct slice *dep);
+void slice_init(struct slice *slice, const char *name);
+void slice_exit(struct slice *slice);
+
+void slice_debug_acquired(struct slice *slice);
+
+#endif /* __SLICE_H */
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 02/14] Introduce idle slice
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 01/14] Introduce slices Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 03/14] net: Add a slice to struct eth_device Daniel Glöckner
` (11 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List; +Cc: Daniel Glöckner
Some code can't foresee which resources will be used by its poller. This
is the case especially in pollers that will execute arbitrary commands
input by the user. With this commit a special slice is introduced that is
released only when Barebox is waiting for console input and only when it
is doing that outside of any command. Code that wants to depend on the
idle slice must select CONFIG_IDLE_SLICE to make it available.
Signed-off-by: Daniel Glöckner <dg@emlix.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/hush.c | 5 +++++
common/ratp/ratp.c | 7 ++++++-
common/slice.c | 22 ++++++++++++++++++++++
common/startup.c | 2 ++
include/ratp_bb.h | 1 -
include/slice.h | 5 +++++
lib/readline.c | 6 +-----
7 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/common/hush.c b/common/hush.c
index c24b2c7cd..61424d98e 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -460,7 +460,12 @@ static void get_user_input(struct in_str *i)
else
prompt = CONFIG_PROMPT_HUSH_PS2;
+ idle_slice_release();
+
n = readline(prompt, console_buffer, CONFIG_CBSIZE);
+
+ idle_slice_acquire();
+
if (n == -1 ) {
i->interrupt = 1;
n = 0;
diff --git a/common/ratp/ratp.c b/common/ratp/ratp.c
index d2fdb631b..a57e69350 100644
--- a/common/ratp/ratp.c
+++ b/common/ratp/ratp.c
@@ -315,10 +315,13 @@ static int ratp_console_register(struct ratp_ctx *ctx)
return 0;
}
-void barebox_ratp_command_run(void)
+static void barebox_ratp_command_run(void)
{
int ret;
+ if (slice_acquired(&idle_slice))
+ return;
+
if (!ratp_command)
return;
@@ -385,6 +388,8 @@ static void ratp_poller(struct poller_struct *poller)
free(buf);
+ barebox_ratp_command_run();
+
return;
out:
diff --git a/common/slice.c b/common/slice.c
index 085d67604..b64b822ec 100644
--- a/common/slice.c
+++ b/common/slice.c
@@ -3,6 +3,7 @@
#define pr_fmt(fmt) "slice: " fmt
#include <common.h>
+#include <init.h>
#include <slice.h>
/*
@@ -231,6 +232,27 @@ void slice_exit(struct slice *slice)
free(slice->name);
}
+struct slice idle_slice;
+
+void idle_slice_acquire(void)
+{
+ slice_acquire(&idle_slice);
+}
+
+void idle_slice_release(void)
+{
+ slice_release(&idle_slice);
+}
+
+static int idle_slice_init(void)
+{
+ slice_init(&idle_slice, "idle");
+ slice_acquire(&idle_slice);
+ return 0;
+}
+
+pure_initcall(idle_slice_init);
+
#if defined CONFIG_CMD_SLICE
#include <command.h>
diff --git a/common/startup.c b/common/startup.c
index 511675ed5..aecb045f4 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -268,8 +268,10 @@ enum autoboot_state do_autoboot_countdown(void)
break;
}
+ idle_slice_release();
ret = console_countdown(global_autoboot_timeout, flags, abortkeys,
&outkey);
+ idle_slice_acquire();
if (ret == 0)
autoboot_state = AUTOBOOT_BOOT;
diff --git a/include/ratp_bb.h b/include/ratp_bb.h
index a4f28c642..b710f99bf 100644
--- a/include/ratp_bb.h
+++ b/include/ratp_bb.h
@@ -41,7 +41,6 @@ struct ratp_bb_pkt {
};
int barebox_ratp(struct console_device *cdev);
-void barebox_ratp_command_run(void);
int barebox_ratp_fs_call(struct ratp_bb_pkt *tx, struct ratp_bb_pkt **rx);
int barebox_ratp_fs_mount(const char *path);
diff --git a/include/slice.h b/include/slice.h
index 5538fc434..37d5350eb 100644
--- a/include/slice.h
+++ b/include/slice.h
@@ -28,4 +28,9 @@ void slice_exit(struct slice *slice);
void slice_debug_acquired(struct slice *slice);
+extern struct slice idle_slice;
+
+void idle_slice_acquire(void);
+void idle_slice_release(void);
+
#endif /* __SLICE_H */
diff --git a/lib/readline.c b/lib/readline.c
index 3d16c1838..e5370f9c7 100644
--- a/lib/readline.c
+++ b/lib/readline.c
@@ -3,7 +3,6 @@
#include <init.h>
#include <libbb.h>
#include <poller.h>
-#include <ratp_bb.h>
#include <xfuncs.h>
#include <complete.h>
#include <linux/ctype.h>
@@ -200,11 +199,8 @@ int readline(const char *prompt, char *buf, int len)
puts (prompt);
while (1) {
- while (!tstc()) {
+ while (!tstc())
poller_call();
- if (IS_ENABLED(CONFIG_CONSOLE_RATP))
- barebox_ratp_command_run();
- }
ichar = read_key();
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 03/14] net: Add a slice to struct eth_device
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 01/14] Introduce slices Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 02/14] Introduce idle slice Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 04/14] net: mdiobus: Add slice Daniel Glöckner
` (10 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
Add ethernet code safe for being called from a poller.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
include/net.h | 8 ++++++++
net/eth.c | 21 ++++++++++++++++++---
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/include/net.h b/include/net.h
index 54db8a179..8d2b4923d 100644
--- a/include/net.h
+++ b/include/net.h
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <clock.h>
#include <led.h>
+#include <slice.h>
#include <xfuncs.h>
#include <linux/phy.h>
#include <linux/string.h> /* memcpy */
@@ -63,6 +64,8 @@ struct eth_device {
char *bootarg;
char *linuxdevname;
+ struct slice slice;
+
bool ifup;
#define ETH_MODE_DHCP 0
#define ETH_MODE_STATIC 1
@@ -72,6 +75,11 @@ struct eth_device {
#define dev_to_edev(d) container_of(d, struct eth_device, dev)
+static inline struct slice *eth_device_slice(struct eth_device *edev)
+{
+ return &edev->slice;
+}
+
static inline const char *eth_name(struct eth_device *edev)
{
return edev->devname;
diff --git a/net/eth.c b/net/eth.c
index e3d0d06ef..2df0a74a5 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -219,20 +219,32 @@ int eth_send(struct eth_device *edev, void *packet, int length)
if (ret)
return ret;
+ slice_acquire(eth_device_slice(edev));
+
led_trigger_network(LED_TRIGGER_NET_TX);
- return edev->send(edev, packet, length);
+ ret = edev->send(edev, packet, length);
+
+ slice_release(eth_device_slice(edev));
+
+ return ret;
}
static int __eth_rx(struct eth_device *edev)
{
int ret;
+ slice_acquire(eth_device_slice(edev));
+
ret = eth_carrier_check(edev, 0);
if (ret)
- return ret;
+ goto out;
+
+ ret = edev->recv(edev);
+out:
+ slice_release(eth_device_slice(edev));
- return edev->recv(edev);
+ return ret;
}
int eth_rx(void)
@@ -353,6 +365,8 @@ int eth_register(struct eth_device *edev)
if (ret)
return ret;
+ slice_init(&edev->slice, dev_name(dev));
+
edev->devname = xstrdup(dev_name(&edev->dev));
dev_add_param_ip(dev, "ipaddr", NULL, NULL, &edev->ipaddr, edev);
@@ -431,6 +445,7 @@ void eth_unregister(struct eth_device *edev)
free(edev->devname);
unregister_device(&edev->dev);
+ slice_exit(&edev->slice);
list_del(&edev->list);
}
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 04/14] net: mdiobus: Add slice
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (2 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 03/14] net: Add a slice to struct eth_device Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 05/14] usb: Add a slice to usb host controllers Daniel Glöckner
` (9 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
By adding a slice to the mdio bus we make the mdio code safe for being
called in a poller.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/net/phy/mdio_bus.c | 43 ++++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 38 +++++++++++++--------------------
2 files changed, 58 insertions(+), 23 deletions(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 3480e2ffb..99d23ffed 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -239,6 +239,8 @@ int mdiobus_register(struct mii_bus *bus)
return -EINVAL;
}
+ slice_init(&bus->slice, dev_name(&bus->dev));
+
if (bus->reset)
bus->reset(bus);
@@ -272,6 +274,8 @@ void mdiobus_unregister(struct mii_bus *bus)
bus->phy_map[i] = NULL;
}
+ slice_exit(&bus->slice);
+
list_del(&bus->list);
}
EXPORT_SYMBOL(mdiobus_unregister);
@@ -357,6 +361,45 @@ static int mdio_bus_match(struct device_d *dev, struct driver_d *drv)
return 1;
}
+/**
+ * mdiobus_read - Convenience function for reading a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @regnum: register number to read
+ */
+int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
+{
+ int ret;
+
+ slice_acquire(&bus->slice);
+
+ ret = bus->read(bus, addr, regnum);
+
+ slice_release(&bus->slice);
+
+ return ret;
+}
+
+/**
+ * mdiobus_write - Convenience function for writing a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ */
+int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
+{
+ int ret;
+
+ slice_acquire(&bus->slice);
+
+ ret = bus->write(bus, addr, regnum, val);
+
+ slice_release(&bus->slice);
+
+ return ret;
+}
+
static ssize_t phydev_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags)
{
int i = count;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index a9fdf44f1..3f0f31b35 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -16,6 +16,7 @@
#define __PHY_H
#include <driver.h>
+#include <slice.h>
#include <linux/list.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
@@ -116,9 +117,16 @@ struct mii_bus {
struct list_head list;
bool is_multiplexed;
+
+ struct slice slice;
};
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)
+static inline struct slice *mdiobus_slice(struct mii_bus *bus)
+{
+ return &bus->slice;
+}
+
int mdiobus_register(struct mii_bus *bus);
void mdiobus_unregister(struct mii_bus *bus);
struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr);
@@ -134,28 +142,8 @@ struct mii_bus *mdiobus_get_bus(int busnum);
struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np);
-/**
- * mdiobus_read - Convenience function for reading a given MII mgmt register
- * @bus: the mii_bus struct
- * @addr: the phy address
- * @regnum: register number to read
- */
-static inline int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
-{
- return bus->read(bus, addr, regnum);
-}
-
-/**
- * mdiobus_write - Convenience function for writing a given MII mgmt register
- * @bus: the mii_bus struct
- * @addr: the phy address
- * @regnum: register number to write
- * @val: value to write to @regnum
- */
-static inline int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
-{
- return bus->write(bus, addr, regnum, val);
-}
+int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
+int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
/* phy_device: An instance of a PHY
*
@@ -376,11 +364,15 @@ int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
int phy_register_fixup_for_id(const char *bus_id,
int (*run)(struct phy_device *));
int phy_scan_fixups(struct phy_device *phydev);
-
int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad);
void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, int devad,
u16 data);
+static inline bool phy_acquired(struct phy_device *phydev)
+{
+ return phydev && phydev->bus && slice_acquired(&phydev->bus->slice);
+}
+
#ifdef CONFIG_PHYLIB
int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *));
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 05/14] usb: Add a slice to usb host controllers
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (3 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 04/14] net: mdiobus: Add slice Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 06/14] usbnet: Add slice Daniel Glöckner
` (8 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/usb/core/usb.c | 7 +++++++
include/usb/usb.h | 7 +++++++
2 files changed, 14 insertions(+)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 30c251f40..847529526 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -78,11 +78,16 @@ static inline int usb_host_acquire(struct usb_host *host)
if (host->sem)
return -EAGAIN;
host->sem++;
+
+ slice_acquire(&host->slice);
+
return 0;
}
static inline void usb_host_release(struct usb_host *host)
{
+ slice_release(&host->slice);
+
if (host->sem > 0)
host->sem--;
}
@@ -92,11 +97,13 @@ int usb_register_host(struct usb_host *host)
list_add_tail(&host->list, &host_list);
host->busnum = host_busnum++;
host->sem = 0;
+ slice_init(&host->slice, dev_name(host->hw_dev));
return 0;
}
void usb_unregister_host(struct usb_host *host)
{
+ slice_exit(&host->slice);
list_del(&host->list);
}
diff --git a/include/usb/usb.h b/include/usb/usb.h
index c2085eae8..1b51a00dd 100644
--- a/include/usb/usb.h
+++ b/include/usb/usb.h
@@ -20,6 +20,7 @@
#define _USB_H_
#include <driver.h>
+#include <slice.h>
#include <usb/ch9.h>
#include <usb/ch11.h>
#include <usb/usb_defs.h>
@@ -165,11 +166,17 @@ struct usb_host {
struct usb_device *root_dev;
int sem;
struct usb_phy *usbphy;
+ struct slice slice;
};
int usb_register_host(struct usb_host *);
void usb_unregister_host(struct usb_host *host);
+static inline struct slice *usb_device_slice(struct usb_device *udev)
+{
+ return &udev->host->slice;
+}
+
int usb_host_detect(struct usb_host *host);
int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 06/14] usbnet: Add slice
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (4 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 05/14] usb: Add a slice to usb host controllers Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 07/14] net: Call net_poll() in a poller Daniel Glöckner
` (7 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
Both the ethernet device and the mdio bus of a USB network controller
need the USB bus. Add dependencies to it.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/net/usb/usbnet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 739703458..46ea73247 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -233,6 +233,9 @@ int usbnet_probe(struct usb_device *usbdev, const struct usb_device_id *prod)
eth_register(edev);
+ slice_depends_on(eth_device_slice(edev), usb_device_slice(usbdev));
+ slice_depends_on(mdiobus_slice(&undev->miibus), usb_device_slice(usbdev));
+
return 0;
out1:
dev_dbg(&edev->dev, "err: %d\n", status);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 07/14] net: Call net_poll() in a poller
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (5 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 06/14] usbnet: Add slice Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 08/14] net: reply to ping requests Daniel Glöckner
` (6 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
This patch moves the ethernet receive loop into a poller. With this
network protocols no longer have to call net_loop() explicitly but
can do it implicitly by calling is_timeout() when waiting for packets.
Having the network receive loop running in a poller has the advantage
that we have it running continuously and not only when we explicitly
expect packets to come in. With this we can reasonably well answer to
ping requests which is implemented in the next patch. This also helps
protocols that run in the background like fastboot over UDP.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
fs/nfs.c | 2 --
fs/tftp.c | 2 --
include/net.h | 3 ---
net/dhcp.c | 1 -
net/dns.c | 1 -
net/eth.c | 15 ++++++++++-----
net/net.c | 14 +++++++++++---
net/netconsole.c | 4 +---
net/nfs.c | 1 -
net/ping.c | 2 --
net/sntp.c | 2 --
11 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/fs/nfs.c b/fs/nfs.c
index 15ddab791..ebf851f65 100644
--- a/fs/nfs.c
+++ b/fs/nfs.c
@@ -447,8 +447,6 @@ again:
nfs_timer_start = get_time_ns();
while (1) {
- net_poll();
-
if (is_timeout(nfs_timer_start, NFS_TIMEOUT)) {
tries++;
if (tries == NFS_MAX_RESEND)
diff --git a/fs/tftp.c b/fs/tftp.c
index d186e7983..e5a58a4da 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -207,8 +207,6 @@ static int tftp_poll(struct file_priv *priv)
return -ETIMEDOUT;
}
- net_poll();
-
return 0;
}
diff --git a/include/net.h b/include/net.h
index 8d2b4923d..583dc14ed 100644
--- a/include/net.h
+++ b/include/net.h
@@ -244,9 +244,6 @@ IPaddr_t net_get_nameserver(void);
const char *net_get_domainname(void);
struct eth_device *net_route(IPaddr_t ip);
-/* Do the work */
-void net_poll(void);
-
static inline struct iphdr *net_eth_to_iphdr(char *pkt)
{
return (struct iphdr *)(pkt + ETHER_HDR_SIZE);
diff --git a/net/dhcp.c b/net/dhcp.c
index a27fa8999..ef22d2cef 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -513,7 +513,6 @@ int dhcp_request(struct eth_device *edev, const struct dhcp_req_param *param,
ret = -ETIMEDOUT;
goto out1;
}
- net_poll();
if (is_timeout(dhcp_start, 3 * SECOND)) {
dhcp_start = get_time_ns();
printf("T ");
diff --git a/net/dns.c b/net/dns.c
index ffe98ef9e..851bf3722 100644
--- a/net/dns.c
+++ b/net/dns.c
@@ -231,7 +231,6 @@ int resolv(const char *host, IPaddr_t *ip)
if (ctrlc()) {
break;
}
- net_poll();
if (is_timeout(dns_timer_start, SECOND)) {
dns_timer_start = get_time_ns();
printf("T ");
diff --git a/net/eth.c b/net/eth.c
index 2df0a74a5..6c8f31f6b 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -234,14 +234,19 @@ static int __eth_rx(struct eth_device *edev)
{
int ret;
- slice_acquire(eth_device_slice(edev));
+ if (!phy_acquired(edev->phydev)) {
+ ret = eth_carrier_check(edev, 0);
+ if (ret)
+ return ret;
+ }
- ret = eth_carrier_check(edev, 0);
- if (ret)
- goto out;
+ if (slice_acquired(eth_device_slice(edev)))
+ return 0;
+
+ slice_acquire(eth_device_slice(edev));
ret = edev->recv(edev);
-out:
+
slice_release(eth_device_slice(edev));
return ret;
diff --git a/net/net.c b/net/net.c
index 5fd6246ab..197b551e7 100644
--- a/net/net.c
+++ b/net/net.c
@@ -239,8 +239,6 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et
if (retries > PKT_NUM_RETRIES)
return -ETIMEDOUT;
-
- net_poll();
}
pr_debug("Got ARP REPLY for %pI4: %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -249,11 +247,21 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et
return 0;
}
-void net_poll(void)
+static void net_poll(struct poller_struct *poller)
{
eth_rx();
}
+static struct poller_struct net_poller = {
+ .func = net_poll,
+};
+
+static int init_net_poll(void)
+{
+ return poller_register(&net_poller, "net");
+}
+device_initcall(init_net_poll);
+
static uint16_t net_udp_new_localport(void)
{
static uint16_t localport;
diff --git a/net/netconsole.c b/net/netconsole.c
index 0fece65a2..c692db942 100644
--- a/net/netconsole.c
+++ b/net/netconsole.c
@@ -59,7 +59,7 @@ static int nc_getc(struct console_device *cdev)
return 0;
while (!kfifo_len(priv->fifo))
- net_poll();
+ udelay(1);
kfifo_getc(priv->fifo, &c);
@@ -77,8 +77,6 @@ static int nc_tstc(struct console_device *cdev)
if (priv->busy)
return kfifo_len(priv->fifo) ? 1 : 0;
- net_poll();
-
return kfifo_len(priv->fifo) ? 1 : 0;
}
diff --git a/net/nfs.c b/net/nfs.c
index 591417e0d..266351da0 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -710,7 +710,6 @@ static int do_nfs(int argc, char *argv[])
nfs_err = -EINTR;
break;
}
- net_poll();
if (is_timeout(nfs_timer_start, NFS_TIMEOUT * SECOND)) {
show_progress(-1);
nfs_send();
diff --git a/net/ping.c b/net/ping.c
index a71f59a80..f3de0c27a 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -89,8 +89,6 @@ static int do_ping(int argc, char *argv[])
break;
}
- net_poll();
-
if (is_timeout(ping_start, SECOND)) {
/* No answer, send another packet */
ping_start = get_time_ns();
diff --git a/net/sntp.c b/net/sntp.c
index b4e6d6439..f693a2e8a 100644
--- a/net/sntp.c
+++ b/net/sntp.c
@@ -145,8 +145,6 @@ s64 sntp(const char *server)
break;
}
- net_poll();
-
if (is_timeout(sntp_start, 1 * SECOND)) {
sntp_start = get_time_ns();
ret = sntp_send();
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 08/14] net: reply to ping requests
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (6 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 07/14] net: Call net_poll() in a poller Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 09/14] usbnet: Be more friendly in the receive path Daniel Glöckner
` (5 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
Now that we have the network receive function running in a poller we
can reasonably well answer to ping requests. Implement this feature.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
net/net.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/net/net.c b/net/net.c
index 197b551e7..cb0013519 100644
--- a/net/net.c
+++ b/net/net.c
@@ -570,12 +570,54 @@ static int net_handle_udp(unsigned char *pkt, int len)
return -EINVAL;
}
-static int net_handle_icmp(unsigned char *pkt, int len)
+static int ping_reply(struct eth_device *edev, unsigned char *pkt, int len)
+{
+ struct ethernet *et = (struct ethernet *)pkt;
+ struct icmphdr *icmp;
+ struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+ unsigned char *packet;
+ int ret;
+
+ memcpy(et->et_dest, et->et_src, 6);
+ memcpy(et->et_src, edev->ethaddr, 6);
+ et->et_protlen = htons(PROT_IP);
+
+ icmp = net_eth_to_icmphdr(pkt);
+
+ icmp->type = ICMP_ECHO_REPLY;
+ icmp->checksum = 0;
+ icmp->checksum = ~net_checksum((unsigned char *)icmp,
+ len - sizeof(struct iphdr) - ETHER_HDR_SIZE);
+ ip->check = 0;
+ ip->frag_off = 0;
+ net_copy_ip((void *)&ip->daddr, &ip->saddr);
+ net_copy_ip((void *)&ip->saddr, &edev->ipaddr);
+ ip->check = ~net_checksum((unsigned char *)ip, sizeof(struct iphdr));
+
+ packet = net_alloc_packet();
+ if (!packet)
+ return 0;
+
+ memcpy(packet, pkt, ETHER_HDR_SIZE + len);
+
+ ret = eth_send(edev, packet, ETHER_HDR_SIZE + len);
+
+ free(packet);
+
+ return 0;
+}
+
+static int net_handle_icmp(struct eth_device *edev, unsigned char *pkt, int len)
{
struct net_connection *con;
+ struct icmphdr *icmp;
pr_debug("%s\n", __func__);
+ icmp = net_eth_to_icmphdr(pkt);
+ if (icmp->type == ICMP_ECHO_REQUEST)
+ ping_reply(edev, pkt, len);
+
list_for_each_entry(con, &connection_list, list) {
if (con->proto == IPPROTO_ICMP) {
con->handler(con->priv, pkt, len);
@@ -612,7 +654,7 @@ static int net_handle_ip(struct eth_device *edev, unsigned char *pkt, int len)
switch (ip->protocol) {
case IPPROTO_ICMP:
- return net_handle_icmp(pkt, len);
+ return net_handle_icmp(edev, pkt, len);
case IPPROTO_UDP:
return net_handle_udp(pkt, len);
}
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 09/14] usbnet: Be more friendly in the receive path
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (7 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 08/14] net: reply to ping requests Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 10/14] poller: Allow to run pollers inside of pollers Daniel Glöckner
` (4 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
To recognize if we have a receive packet pending we must set up a USB
bulk transfer. When there's no incoming packet we must wait until the
transfer times out. We do this with every poller call which can
considerably slow down the system. With this patch we do two things
against this:
- lower the timeout for the bulk transfer
- When we haven't received a packet for longer then lower the frequency
of calling into the USB stack to once every 100ms
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/net/usb/usbnet.c | 19 ++++++++++++++++++-
include/usb/usbnet.h | 3 +++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 46ea73247..aa48678f8 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -122,12 +122,29 @@ static int usbnet_recv(struct eth_device *edev)
dev_dbg(&edev->dev, "%s\n",__func__);
+ /*
+ * we must let the usb_bulk_msg below timeout before we realize
+ * that we have no packet received. Since this function runs
+ * inside a poller we considerably slow down barebox when we
+ * wait for the timeout too often. To improve this we only poll
+ * with full speed when we actually have received a packet in the
+ * last 100ms.
+ */
+ if (is_timeout(dev->last_pkt_received, 100 * MSECOND) &&
+ !is_timeout(dev->last_recv_call, 100 * MSECOND)) {
+ return 0;
+ }
+
+ dev->last_recv_call = get_time_ns();
+
len = dev->rx_urb_size;
- ret = usb_bulk_msg(dev->udev, dev->in, dev->rx_buf, len, &alen, 100);
+ ret = usb_bulk_msg(dev->udev, dev->in, dev->rx_buf, len, &alen, 2);
if (ret)
return ret;
+ dev->last_pkt_received = get_time_ns();
+
if (alen) {
if (info->rx_fixup)
return info->rx_fixup(dev, dev->rx_buf, alen);
diff --git a/include/usb/usbnet.h b/include/usb/usbnet.h
index 450db47b4..7ff32f280 100644
--- a/include/usb/usbnet.h
+++ b/include/usb/usbnet.h
@@ -54,6 +54,9 @@ struct usbnet {
# define EVENT_RX_MEMORY 2
# define EVENT_STS_SPLIT 3
# define EVENT_LINK_RESET 4
+
+ uint64_t last_pkt_received;
+ uint64_t last_recv_call;
};
#if 0
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 10/14] poller: Allow to run pollers inside of pollers
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (8 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 09/14] usbnet: Be more friendly in the receive path Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-17 7:00 ` Sascha Hauer
2020-06-15 17:20 ` [PATCH v3 11/14] defconfigs: update renamed fastboot options Daniel Glöckner
` (3 subsequent siblings)
13 siblings, 1 reply; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
This adds a slice to each poller which is acquired before the poller is
executed. This allows us to run pollers inside of other pollers.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/poller.c | 19 ++++++++++---------
include/poller.h | 2 ++
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/common/poller.c b/common/poller.c
index 95f828b43..2525034bb 100644
--- a/common/poller.c
+++ b/common/poller.c
@@ -14,7 +14,6 @@
#include <clock.h>
static LIST_HEAD(poller_list);
-static int poller_active;
int poller_register(struct poller_struct *poller, const char *name)
{
@@ -22,6 +21,7 @@ int poller_register(struct poller_struct *poller, const char *name)
return -EBUSY;
poller->name = xstrdup(name);
+ slice_init(&poller->slice, poller->name);
list_add_tail(&poller->list, &poller_list);
poller->registered = 1;
@@ -33,7 +33,7 @@ int poller_unregister(struct poller_struct *poller)
if (!poller->registered)
return -ENODEV;
-
+ slice_exit(&poller->slice);
list_del(&poller->list);
poller->registered = 0;
free(poller->name);
@@ -111,15 +111,16 @@ void poller_call(void)
{
struct poller_struct *poller, *tmp;
- if (poller_active)
- return;
-
- poller_active = 1;
+ list_for_each_entry_safe(poller, tmp, &poller_list, list) {
+ if (slice_acquired(&poller->slice))
+ continue;
- list_for_each_entry_safe(poller, tmp, &poller_list, list)
+ slice_acquire(&poller->slice);
+ idle_slice_acquire();
poller->func(poller);
-
- poller_active = 0;
+ idle_slice_release();
+ slice_release(&poller->slice);
+ }
}
#if defined CONFIG_CMD_POLLER
diff --git a/include/poller.h b/include/poller.h
index 886557252..c8b682968 100644
--- a/include/poller.h
+++ b/include/poller.h
@@ -7,11 +7,13 @@
#define POLLER_H
#include <linux/list.h>
+#include <slice.h>
struct poller_struct {
void (*func)(struct poller_struct *poller);
int registered;
struct list_head list;
+ struct slice slice;
char *name;
};
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 10/14] poller: Allow to run pollers inside of pollers
2020-06-15 17:20 ` [PATCH v3 10/14] poller: Allow to run pollers inside of pollers Daniel Glöckner
@ 2020-06-17 7:00 ` Sascha Hauer
0 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2020-06-17 7:00 UTC (permalink / raw)
To: Daniel Glöckner; +Cc: Barebox List
On Mon, Jun 15, 2020 at 07:20:43PM +0200, Daniel Glöckner wrote:
> From: Sascha Hauer <s.hauer@pengutronix.de>
>
> This adds a slice to each poller which is acquired before the poller is
> executed. This allows us to run pollers inside of other pollers.
Letting pollers run inside of pollers is only necessary when pollers
have dependencies to other pollers. I don't think anymore that we should
allow this. Dependencies between pollers make the whole think more
complicated. Also pollers should be short lived and adding dependencies
between them contradicts this.
Therefore I want to make another suggestion how we can solve this. The
series should be ready later this day.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 11/14] defconfigs: update renamed fastboot options
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (9 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 10/14] poller: Allow to run pollers inside of pollers Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 12/14] globalvar: Add helper for deprecated variable names Daniel Glöckner
` (2 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List; +Cc: Daniel Glöckner
The split of the generic Fastboot code from the Fastboot USB gadget
included renaming the CONFIG_USB_GADGET_FASTBOOT_* options to
CONFIG_FASTBOOT_*. Update all defconfigs to use the new names.
Signed-off-by: Daniel Glöckner <dg@emlix.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/configs/imx23_defconfig | 2 +-
arch/arm/configs/imx28_defconfig | 2 +-
arch/arm/configs/imx_v7_defconfig | 2 +-
arch/arm/configs/imx_v8_defconfig | 2 +-
arch/arm/configs/kindle-mx50_defconfig | 2 +-
arch/arm/configs/omap_defconfig | 2 +-
arch/arm/configs/zii_vf610_dev_defconfig | 2 +-
7 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/configs/imx23_defconfig b/arch/arm/configs/imx23_defconfig
index bff9c08c4..48bf14a39 100644
--- a/arch/arm/configs/imx23_defconfig
+++ b/arch/arm/configs/imx23_defconfig
@@ -22,6 +22,7 @@ CONFIG_BLSPEC=y
CONFIG_CONSOLE_ALLOW_COLOR=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_RESET_SOURCE=y
+CONFIG_FASTBOOT_CMD_OEM=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -90,7 +91,6 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DFU=y
CONFIG_USB_GADGET_SERIAL=y
CONFIG_USB_GADGET_FASTBOOT=y
-CONFIG_USB_GADGET_FASTBOOT_CMD_OEM=y
CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_STM=y
CONFIG_MCI=y
diff --git a/arch/arm/configs/imx28_defconfig b/arch/arm/configs/imx28_defconfig
index 4442c79cc..beb0bc2f7 100644
--- a/arch/arm/configs/imx28_defconfig
+++ b/arch/arm/configs/imx28_defconfig
@@ -25,6 +25,7 @@ CONFIG_CONSOLE_ALLOW_COLOR=y
CONFIG_PBL_CONSOLE=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_RESET_SOURCE=y
+CONFIG_FASTBOOT_CMD_OEM=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -105,7 +106,6 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DFU=y
CONFIG_USB_GADGET_SERIAL=y
CONFIG_USB_GADGET_FASTBOOT=y
-CONFIG_USB_GADGET_FASTBOOT_CMD_OEM=y
CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_STM=y
CONFIG_MCI=y
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 5bf908ee8..fb7872434 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -66,6 +66,7 @@ CONFIG_CONSOLE_ACTIVATE_NONE=y
CONFIG_PARTITION_DISK_EFI=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_RESET_SOURCE=y
+CONFIG_FASTBOOT_CMD_OEM=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -160,7 +161,6 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DFU=y
CONFIG_USB_GADGET_SERIAL=y
CONFIG_USB_GADGET_FASTBOOT=y
-CONFIG_USB_GADGET_FASTBOOT_CMD_OEM=y
CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_IMX_IPUV3=y
CONFIG_DRIVER_VIDEO_IMX_IPUV3_LVDS=y
diff --git a/arch/arm/configs/imx_v8_defconfig b/arch/arm/configs/imx_v8_defconfig
index 06fb40608..b96867ad0 100644
--- a/arch/arm/configs/imx_v8_defconfig
+++ b/arch/arm/configs/imx_v8_defconfig
@@ -25,6 +25,7 @@ CONFIG_CONSOLE_RATP=y
CONFIG_PARTITION_DISK_EFI=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_RESET_SOURCE=y
+CONFIG_FASTBOOT_SPARSE=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -106,7 +107,6 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_SERIAL=y
CONFIG_USB_GADGET_FASTBOOT=y
-CONFIG_USB_GADGET_FASTBOOT_SPARSE=y
CONFIG_MCI=y
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
CONFIG_MCI_IMX_ESDHC=y
diff --git a/arch/arm/configs/kindle-mx50_defconfig b/arch/arm/configs/kindle-mx50_defconfig
index 855daef71..552b2d6d3 100644
--- a/arch/arm/configs/kindle-mx50_defconfig
+++ b/arch/arm/configs/kindle-mx50_defconfig
@@ -20,6 +20,7 @@ CONFIG_BOOTM_OFTREE=y
CONFIG_CONSOLE_ACTIVATE_ALL=y
CONFIG_CONSOLE_ALLOW_COLOR=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_FASTBOOT_CMD_OEM=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_MEMINFO=y
@@ -50,7 +51,6 @@ CONFIG_USB_EHCI=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_SERIAL=y
CONFIG_USB_GADGET_FASTBOOT=y
-CONFIG_USB_GADGET_FASTBOOT_CMD_OEM=y
CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
diff --git a/arch/arm/configs/omap_defconfig b/arch/arm/configs/omap_defconfig
index 9d71d0274..59892cb23 100644
--- a/arch/arm/configs/omap_defconfig
+++ b/arch/arm/configs/omap_defconfig
@@ -34,6 +34,7 @@ CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_STATE=y
CONFIG_BOOTCHOOSER=y
CONFIG_RESET_SOURCE=y
+CONFIG_FASTBOOT_CMD_OEM=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
CONFIG_CMD_MEMINFO=y
@@ -121,7 +122,6 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DFU=y
CONFIG_USB_GADGET_SERIAL=y
CONFIG_USB_GADGET_FASTBOOT=y
-CONFIG_USB_GADGET_FASTBOOT_CMD_OEM=y
CONFIG_USB_MUSB=y
CONFIG_USB_MUSB_AM335X=y
CONFIG_USB_MUSB_HOST=y
diff --git a/arch/arm/configs/zii_vf610_dev_defconfig b/arch/arm/configs/zii_vf610_dev_defconfig
index 7161d740a..45c24d6df 100644
--- a/arch/arm/configs/zii_vf610_dev_defconfig
+++ b/arch/arm/configs/zii_vf610_dev_defconfig
@@ -22,6 +22,7 @@ CONFIG_CONSOLE_RATP=y
CONFIG_PARTITION_DISK_EFI=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_RESET_SOURCE=y
+CONFIG_FASTBOOT_CMD_OEM=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -113,7 +114,6 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DFU=y
CONFIG_USB_GADGET_SERIAL=y
CONFIG_USB_GADGET_FASTBOOT=y
-CONFIG_USB_GADGET_FASTBOOT_CMD_OEM=y
CONFIG_MCI=y
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
CONFIG_MCI_IMX_ESDHC=y
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 12/14] globalvar: Add helper for deprecated variable names
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (10 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 11/14] defconfigs: update renamed fastboot options Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 13/14] fastboot: rename usbgadget.fastboot_* variables to fastboot.* Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 14/14] fastboot net: implement fastboot over UDP Daniel Glöckner
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List
From: Sascha Hauer <s.hauer@pengutronix.de>
When globalvars are renamed across releases it's not nice when variables
in the persistent environment loose their meaning. This adds a helper
function which adds an alias for the old names. When the persistent
variables still use the old names then their values are automatically
written to variables with the new names.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/globalvar.c | 41 +++++++++++++++++++++++++++++++++++++++--
include/globalvar.h | 5 +++++
2 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/common/globalvar.c b/common/globalvar.c
index c87f2c933..5e91cc815 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -293,6 +293,40 @@ int nvvar_remove(const char *name)
return ret;
}
+struct globalvar_deprecated {
+ char *newname;
+ char *oldname;
+ struct list_head list;
+};
+
+static LIST_HEAD(globalvar_deprecated_list);
+
+void globalvar_alias_deprecated(const char *oldname, const char *newname)
+{
+ struct globalvar_deprecated *gd;
+
+ gd = xzalloc(sizeof(*gd));
+ gd->newname = xstrdup(newname);
+ gd->oldname = xstrdup(oldname);
+ list_add_tail(&gd->list, &globalvar_deprecated_list);
+}
+
+static const char *globalvar_new_name(const char *oldname)
+{
+ struct globalvar_deprecated *gd;
+
+ list_for_each_entry(gd, &globalvar_deprecated_list, list) {
+ if (!strcmp(oldname, gd->oldname)) {
+ pr_warn("nv.%s is deprecated, converting to nv.%s\n", oldname,
+ gd->newname);
+ nv_dirty = 1;
+ return gd->newname;
+ }
+ }
+
+ return oldname;
+}
+
int nvvar_load(void)
{
char *val;
@@ -308,6 +342,8 @@ int nvvar_load(void)
return -ENOENT;
while ((d = readdir(dir))) {
+ const char *n;
+
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
@@ -316,10 +352,11 @@ int nvvar_load(void)
pr_debug("%s: Setting \"%s\" to \"%s\"\n",
__func__, d->d_name, val);
- ret = __nvvar_add(d->d_name, val);
+ n = globalvar_new_name(d->d_name);
+ ret = __nvvar_add(n, val);
if (ret)
pr_err("failed to create nv variable %s: %s\n",
- d->d_name, strerror(-ret));
+ n, strerror(-ret));
}
closedir(dir);
diff --git a/include/globalvar.h b/include/globalvar.h
index fc85e93e1..db229e239 100644
--- a/include/globalvar.h
+++ b/include/globalvar.h
@@ -33,6 +33,7 @@ int nvvar_remove(const char *name);
void globalvar_print(void);
void dev_param_init_from_nv(struct device_d *dev, const char *name);
+void globalvar_alias_deprecated(const char *newname, const char *oldname);
#else
static inline int globalvar_add_simple(const char *name, const char *value)
@@ -114,6 +115,10 @@ static inline void dev_param_init_from_nv(struct device_d *dev, const char *name
{
}
+static inline void globalvar_alias_deprecated(const char *newname, const char *oldname)
+{
+}
+
#endif
void nv_var_set_clean(void);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 13/14] fastboot: rename usbgadget.fastboot_* variables to fastboot.*
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (11 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 12/14] globalvar: Add helper for deprecated variable names Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
2020-06-15 17:20 ` [PATCH v3 14/14] fastboot net: implement fastboot over UDP Daniel Glöckner
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List; +Cc: Daniel Glöckner
There is nothing USB-specific in the defined usbgadget.fastboot_*
variables. Rename them to be usable also for the UDP fastboot transport.
The usbgadget.fastboot_function variable is used to define the files and
devices accessible with the erase and flash commands. Since "function" is
a term from the USB specification and the Fastboot specification uses the
term "partition", we rename that variable to "fastboot.partitions".
Signed-off-by: Daniel Glöckner <dg@emlix.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/user/usb.rst | 4 ++--
commands/usbgadget.c | 2 +-
common/fastboot.c | 24 +++++++++++++++++++++---
common/usbgadget.c | 16 ++--------------
include/fastboot.h | 3 +++
5 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
index 4c1b2925f..ca5f8138d 100644
--- a/Documentation/user/usb.rst
+++ b/Documentation/user/usb.rst
@@ -266,7 +266,7 @@ USB Gadget autostart Options
See :ref:`command_usbgadget` -a. (Default 0).
``global.usbgadget.dfu_function``
Function description for DFU. See :ref:`command_usbgadget` -D [desc].
-``global.usbgadget.fastboot_function``
+``global.fastboot.partitions``
Function description for fastboot. See :ref:`command_usbgadget` -A [desc].
-``global.usbgadget.fastboot_bbu``
+``global.fastboot.bbu``
Export barebox update handlers. See :ref:`command_usbgadget` -b. (Default 0).
diff --git a/commands/usbgadget.c b/commands/usbgadget.c
index 193da86de..9133402f5 100644
--- a/commands/usbgadget.c
+++ b/commands/usbgadget.c
@@ -57,7 +57,7 @@ BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-a\t", "Create CDC ACM function")
BAREBOX_CMD_HELP_OPT ("-A <desc>", "Create Android Fastboot function. If 'desc' is not provided, "
- "try to use 'global.usbgadget.fastboot_function' variable.")
+ "try to use 'global.fastboot.partitions' variable.")
BAREBOX_CMD_HELP_OPT ("-b\t", "include registered barebox update handlers (fastboot specific)")
BAREBOX_CMD_HELP_OPT ("-D <desc>", "Create DFU function. If 'desc' is not provided, "
"try to use 'global.usbgadget.dfu_function' variable.")
diff --git a/common/fastboot.c b/common/fastboot.c
index 6f54e939e..2db8165ce 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -46,6 +46,8 @@
#define FASTBOOT_VERSION "0.4"
static unsigned int fastboot_max_download_size = SZ_8M;
+int fastboot_bbu;
+char *fastboot_partitions;
struct fb_variable {
char *name;
@@ -948,14 +950,30 @@ void fastboot_exec_cmd(struct fastboot *fb, const char *cmdbuf)
static int fastboot_globalvars_init(void)
{
if (IS_ENABLED(CONFIG_FASTBOOT_SPARSE))
- globalvar_add_simple_int("usbgadget.fastboot_max_download_size",
+ globalvar_add_simple_int("fastboot.max_download_size",
&fastboot_max_download_size, "%u");
+ globalvar_add_simple_bool("fastboot.bbu", &fastboot_bbu);
+ globalvar_add_simple_string("fastboot.partitions",
+ &fastboot_partitions);
+
+ globalvar_alias_deprecated("usbgadget.fastboot_function",
+ "fastboot.partitions");
+ globalvar_alias_deprecated("usbgadget.fastboot_bbu",
+ "fastboot.bbu");
+ globalvar_alias_deprecated("usbgadget.fastboot_max_download_size",
+ "fastboot.max_download_size");
return 0;
}
device_initcall(fastboot_globalvars_init);
-BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_max_download_size,
- global.usbgadget.fastboot_max_download_size,
+BAREBOX_MAGICVAR_NAMED(global_fastboot_max_download_size,
+ global.fastboot.max_download_size,
"Fastboot maximum download size");
+BAREBOX_MAGICVAR_NAMED(global_fastboot_partitions,
+ global.fastboot.partitions,
+ "Partitions exported for update via fastboot");
+BAREBOX_MAGICVAR_NAMED(global_fastboot_bbu,
+ global.fastboot.bbu,
+ "Export barebox update handlers via fastboot");
diff --git a/common/usbgadget.c b/common/usbgadget.c
index a8f104cf1..25fd99493 100644
--- a/common/usbgadget.c
+++ b/common/usbgadget.c
@@ -30,8 +30,6 @@
static int autostart;
static int acm;
static char *dfu_function;
-static char *fastboot_function;
-static int fastboot_bbu;
static struct file_list *parse(const char *files)
{
@@ -56,8 +54,8 @@ int usbgadget_register(bool dfu, const char *dfu_opts,
dfu_opts = dfu_function;
if (fastboot && !fastboot_opts &&
- fastboot_function && *fastboot_function)
- fastboot_opts = fastboot_function;
+ fastboot_partitions && *fastboot_partitions)
+ fastboot_opts = fastboot_partitions;
if (!dfu_opts && !fastboot_opts && !acm)
return COMMAND_ERROR_USAGE;
@@ -116,12 +114,8 @@ static int usbgadget_globalvars_init(void)
if (IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART)) {
globalvar_add_simple_bool("usbgadget.autostart", &autostart);
globalvar_add_simple_bool("usbgadget.acm", &acm);
- globalvar_add_simple_bool("usbgadget.fastboot_bbu",
- &fastboot_bbu);
}
globalvar_add_simple_string("usbgadget.dfu_function", &dfu_function);
- globalvar_add_simple_string("usbgadget.fastboot_function",
- &fastboot_function);
return 0;
}
@@ -136,9 +130,3 @@ BAREBOX_MAGICVAR_NAMED(global_usbgadget_acm,
BAREBOX_MAGICVAR_NAMED(global_usbgadget_dfu_function,
global.usbgadget.dfu_function,
"usbgadget: Create DFU function");
-BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_function,
- global.usbgadget.fastboot_function,
- "usbgadget: Create Android Fastboot function");
-BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_bbu,
- global.usbgadget.fastboot_bbu,
- "usbgadget: export barebox update handlers via fastboot");
diff --git a/include/fastboot.h b/include/fastboot.h
index b3e7155ef..88ec47849 100644
--- a/include/fastboot.h
+++ b/include/fastboot.h
@@ -54,6 +54,9 @@ enum fastboot_msg_type {
FASTBOOT_MSG_DATA,
};
+extern int fastboot_bbu;
+extern char *fastboot_partitions;
+
int fastboot_generic_init(struct fastboot *fb, bool export_bbu);
void fastboot_generic_close(struct fastboot *fb);
void fastboot_generic_free(struct fastboot *fb);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 14/14] fastboot net: implement fastboot over UDP
2020-06-15 17:20 [PATCH v3 00/14] Slices and fastboot over UDP Daniel Glöckner
` (12 preceding siblings ...)
2020-06-15 17:20 ` [PATCH v3 13/14] fastboot: rename usbgadget.fastboot_* variables to fastboot.* Daniel Glöckner
@ 2020-06-15 17:20 ` Daniel Glöckner
13 siblings, 0 replies; 16+ messages in thread
From: Daniel Glöckner @ 2020-06-15 17:20 UTC (permalink / raw)
To: Barebox List; +Cc: Edmund Henniges, Daniel Glöckner
From: Edmund Henniges <eh@emlix.com>
This implements the UDP variant of the fastboot protocol. The only way to
start the service for now is to compile with CONFIG_FASTBOOT_NET_ON_BOOT.
The service will bind to the network interface that provides the IPv4
gateway.
Sending an OKAY packet before performing a restart is necessary since
contrary to USB the host will not notice when a UDP server disappears.
Signed-off-by: Edmund Henniges <eh@emlix.com>
Signed-off-by: Daniel Glöckner <dg@emlix.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/fastboot.c | 3 +
include/fastboot.h | 1 +
include/fastboot_net.h | 12 +
net/Kconfig | 10 +
net/Makefile | 1 +
net/fastboot.c | 550 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 577 insertions(+)
create mode 100644 include/fastboot_net.h
create mode 100644 net/fastboot.c
diff --git a/common/fastboot.c b/common/fastboot.c
index 2db8165ce..130dc46e1 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -250,6 +250,7 @@ static char *fastboot_msg[] = {
[FASTBOOT_MSG_FAIL] = "FAIL",
[FASTBOOT_MSG_INFO] = "INFO",
[FASTBOOT_MSG_DATA] = "DATA",
+ [FASTBOOT_MSG_NONE] = "",
};
int fastboot_tx_print(struct fastboot *fb, enum fastboot_msg_type type,
@@ -278,6 +279,7 @@ int fastboot_tx_print(struct fastboot *fb, enum fastboot_msg_type type,
case FASTBOOT_MSG_INFO:
pr_info("%pV\n", &vaf);
break;
+ case FASTBOOT_MSG_NONE:
case FASTBOOT_MSG_DATA:
break;
}
@@ -292,6 +294,7 @@ int fastboot_tx_print(struct fastboot *fb, enum fastboot_msg_type type,
static void cb_reboot(struct fastboot *fb, const char *cmd)
{
+ fastboot_tx_print(fb, FASTBOOT_MSG_OKAY, "");
restart_machine();
}
diff --git a/include/fastboot.h b/include/fastboot.h
index 88ec47849..5c3e2894d 100644
--- a/include/fastboot.h
+++ b/include/fastboot.h
@@ -52,6 +52,7 @@ enum fastboot_msg_type {
FASTBOOT_MSG_FAIL,
FASTBOOT_MSG_INFO,
FASTBOOT_MSG_DATA,
+ FASTBOOT_MSG_NONE,
};
extern int fastboot_bbu;
diff --git a/include/fastboot_net.h b/include/fastboot_net.h
new file mode 100644
index 000000000..e4b9d9809
--- /dev/null
+++ b/include/fastboot_net.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef __FASTBOOT_NET__
+#define __FASTBOOT_NET__
+
+#include <fastboot.h>
+
+struct fastboot_net;
+
+struct fastboot_net *fastboot_net_init(struct fastboot_opts *opts);
+void fastboot_net_free(struct fastboot_net *fbn);
+
+#endif
diff --git a/net/Kconfig b/net/Kconfig
index 12b6bdb56..a3c8c10f3 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -31,4 +31,14 @@ config NET_SNTP
bool
prompt "sntp support"
+config NET_FASTBOOT
+ bool
+ select BANNER
+ select FILE_LIST
+ select FASTBOOT_BASE
+ prompt "Android Fastboot support"
+ help
+ This option adds support for the UDP variant of the Fastboot
+ protocol.
+
endif
diff --git a/net/Makefile b/net/Makefile
index eb8d43915..962b2dec5 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_NET_RESOLV)+= dns.o
obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o
obj-$(CONFIG_NET_IFUP) += ifup.o
+obj-$(CONFIG_NET_FASTBOOT) += fastboot.o
diff --git a/net/fastboot.c b/net/fastboot.c
new file mode 100644
index 000000000..27a758b05
--- /dev/null
+++ b/net/fastboot.c
@@ -0,0 +1,550 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Copyright 2020 Edmund Henniges <eh@emlix.com>
+ * Copyright 2020 Daniel Glöckner <dg@emlix.com>
+ * Ported from U-Boot to Barebox
+ */
+
+#define pr_fmt(fmt) "net fastboot: " fmt
+
+#include <common.h>
+#include <net.h>
+#include <fastboot.h>
+#include <fastboot_net.h>
+#include <environment.h>
+#include <progress.h>
+#include <unistd.h>
+#include <init.h>
+#include <globalvar.h>
+#include <magicvar.h>
+
+#define FASTBOOT_PORT 5554
+#define MAX_MTU 1500
+#define PACKET_SIZE (min(PKTSIZE, MAX_MTU + ETHER_HDR_SIZE) \
+ - (net_eth_to_udp_payload(0) - (char *)0))
+
+enum {
+ FASTBOOT_ERROR = 0,
+ FASTBOOT_QUERY = 1,
+ FASTBOOT_INIT = 2,
+ FASTBOOT_FASTBOOT = 3,
+};
+
+enum {
+ MAY_NOT_SEND,
+ MAY_SEND_MESSAGE,
+ MAY_SEND_ACK,
+};
+
+struct __packed fastboot_header {
+ u8 id;
+ u8 flags;
+ u16 seq;
+};
+
+struct fastboot_net {
+ struct fastboot fastboot;
+
+ struct net_connection *net_con;
+ struct fastboot_header response_header;
+ struct poller_struct poller;
+ struct poller_struct keep_alive_poller;
+ u64 host_waits_since;
+ bool sequence_number_seen;
+ bool active_download;
+ bool download_needs_cleanup;
+ bool reinit;
+ u8 may_send;
+ char command[65];
+
+ IPaddr_t host_addr;
+ u16 host_port;
+ u8 host_mac[ETH_ALEN];
+ u16 sequence_number;
+ u16 last_payload_len;
+ uchar last_payload[64 + sizeof(struct fastboot_header)];
+};
+
+static const ushort udp_version = 1;
+
+static bool is_current_connection(struct fastboot_net *fbn)
+{
+ return fbn->host_addr == net_read_ip(&fbn->net_con->ip->daddr) &&
+ fbn->host_port == fbn->net_con->udp->uh_dport;
+}
+
+static void fastboot_abort(struct fastboot_net *fbn)
+{
+ fbn->reinit = true;
+ if (fbn->active_download) {
+ /*
+ * It is safe to call fastboot_download_finished here because
+ * reinit is true.
+ */
+ fastboot_download_finished(&fbn->fastboot);
+ fbn->active_download = false;
+ }
+ fbn->fastboot.active = false;
+ /*
+ * If the host sends a data packet at a time when an empty packet was
+ * expected, fastboot_abort is called and an error message is sent.
+ * We don't want to execute the contents of the bad packet afterwards.
+ * Clearing command also tells our keep-alive poller to stop sending
+ * messages.
+ */
+ fbn->command[0] = 0;
+}
+
+static void fastboot_send(struct fastboot_net *fbn,
+ struct fastboot_header header,
+ const char *error_msg)
+{
+ short tmp;
+ uchar *packet = net_udp_get_payload(fbn->net_con);
+ uchar *packet_base = packet;
+ bool current_session = false;
+
+ if (fbn->sequence_number == ntohs(header.seq) &&
+ is_current_connection(fbn))
+ current_session = true;
+
+ if (error_msg)
+ header.id = FASTBOOT_ERROR;
+
+ /* send header */
+ memcpy(packet, &header, sizeof(header));
+ packet += sizeof(header);
+
+ switch (header.id) {
+ case FASTBOOT_QUERY:
+ /* send sequence number */
+ tmp = htons(fbn->sequence_number);
+ memcpy(packet, &tmp, sizeof(tmp));
+ packet += sizeof(tmp);
+ break;
+ case FASTBOOT_INIT:
+ /* send udp version and packet size */
+ tmp = htons(udp_version);
+ memcpy(packet, &tmp, sizeof(tmp));
+ packet += sizeof(tmp);
+ tmp = htons(PACKET_SIZE);
+ memcpy(packet, &tmp, sizeof(tmp));
+ packet += sizeof(tmp);
+ break;
+ case FASTBOOT_ERROR:
+ pr_err("%s\n", error_msg);
+
+ /* send error message */
+ tmp = strlen(error_msg);
+ memcpy(packet, error_msg, tmp);
+ packet += tmp;
+
+ if (current_session)
+ fastboot_abort(fbn);
+ break;
+ }
+
+ if (current_session && header.id != FASTBOOT_QUERY) {
+ fbn->sequence_number++;
+ fbn->sequence_number_seen = false;
+ fbn->last_payload_len = packet - packet_base;
+ memcpy(fbn->last_payload, packet_base, fbn->last_payload_len);
+ }
+ net_udp_send(fbn->net_con, packet - packet_base);
+}
+
+static int fastboot_write_net(struct fastboot *fb, const char *buf,
+ unsigned int n)
+{
+ struct fastboot_net *fbn = container_of(fb, struct fastboot_net,
+ fastboot);
+ struct fastboot_header response_header;
+ uchar *packet;
+ uchar *packet_base;
+ u64 start;
+ int selapsed;
+
+ if (fbn->reinit)
+ return 0;
+
+ if (fbn->may_send == MAY_NOT_SEND) {
+ start = get_time_ns();
+ selapsed = 5;
+ do {
+ if (is_timeout(start, selapsed * SECOND)) {
+ pr_err("No fastboot packet from host for %d seconds\n",
+ selapsed);
+
+ if (selapsed > 60) {
+ pr_err("Giving up\n");
+ fastboot_abort(fbn);
+ /*
+ * Don't continue this session if the
+ * packet we have given up waiting for
+ * arrives. And don't retransmit an old
+ * packet since that might cause the
+ * host to continue with the next
+ * sequence number.
+ */
+ fbn->sequence_number += 10;
+ fbn->sequence_number_seen = false;
+ } else {
+ selapsed += 5;
+ }
+ }
+ if (fbn->reinit)
+ return 0;
+ } while (fbn->may_send == MAY_NOT_SEND);
+ }
+
+ if (n && fbn->may_send == MAY_SEND_ACK) {
+ fastboot_send(fbn, fbn->response_header,
+ "Have message but only ACK allowed");
+ return -EPROTO;
+ } else if (!n && fbn->may_send == MAY_SEND_MESSAGE) {
+ fastboot_send(fbn, fbn->response_header,
+ "Want to send ACK but message expected");
+ return -EPROTO;
+ }
+
+ response_header = fbn->response_header;
+ response_header.flags = 0;
+ response_header.seq = htons(fbn->sequence_number);
+ ++fbn->sequence_number;
+ fbn->sequence_number_seen = false;
+ fbn->may_send = MAY_NOT_SEND;
+
+ packet = net_udp_get_payload(fbn->net_con);
+ packet_base = packet;
+
+ /* Write headers */
+ memcpy(packet, &response_header, sizeof(response_header));
+ packet += sizeof(response_header);
+ /* Write response */
+ memcpy(packet, buf, n);
+ packet += n;
+
+ /* Save packet for retransmitting */
+ fbn->last_payload_len = packet - packet_base;
+ memcpy(fbn->last_payload, packet_base, fbn->last_payload_len);
+
+ memcpy(fbn->net_con->et->et_dest, fbn->host_mac, ETH_ALEN);
+ net_write_ip(&fbn->net_con->ip->daddr, fbn->host_addr);
+ fbn->net_con->udp->uh_dport = fbn->host_port;
+ net_udp_send(fbn->net_con, fbn->last_payload_len);
+
+ return 0;
+}
+
+static void fastboot_start_download_net(struct fastboot *fb)
+{
+ struct fastboot_net *fbn = container_of(fb, struct fastboot_net,
+ fastboot);
+
+ fastboot_start_download_generic(fb);
+
+ /* we might already have lost the connection */
+ if (fbn->reinit)
+ fastboot_download_finished(fb);
+ else
+ fbn->active_download = true;
+}
+
+/* must send exactly one packet on all code paths */
+static void fastboot_data_download(struct fastboot_net *fbn,
+ const void *fastboot_data,
+ unsigned int fastboot_data_len)
+{
+ int ret;
+
+ if (fastboot_data_len == 0 ||
+ (fbn->fastboot.download_bytes + fastboot_data_len) >
+ fbn->fastboot.download_size) {
+ fastboot_send(fbn, fbn->response_header,
+ "Received invalid data length");
+ return;
+ }
+
+ ret = fastboot_handle_download_data(&fbn->fastboot, fastboot_data,
+ fastboot_data_len);
+ if (ret < 0) {
+ fastboot_send(fbn, fbn->response_header, strerror(-ret));
+ return;
+ }
+
+ fastboot_tx_print(&fbn->fastboot, FASTBOOT_MSG_NONE, "");
+}
+
+static void fastboot_handle_type_fastboot(struct fastboot_net *fbn,
+ struct fastboot_header header,
+ char *fastboot_data,
+ unsigned int fastboot_data_len)
+{
+ fbn->response_header = header;
+ fbn->host_waits_since = get_time_ns();
+ fbn->may_send = fastboot_data_len ? MAY_SEND_ACK : MAY_SEND_MESSAGE;
+ if (fbn->active_download) {
+ if (!fastboot_data_len && fbn->fastboot.download_bytes
+ == fbn->fastboot.download_size) {
+ /*
+ * Can't call fastboot_download_finished here
+ * because it will call fastboot_tx_print
+ * multiple times.
+ */
+ fbn->active_download = false;
+ } else {
+ fastboot_data_download(fbn, fastboot_data,
+ fastboot_data_len);
+ }
+ } else if (!fbn->command[0]) {
+ if (fastboot_data_len >= sizeof(fbn->command)) {
+ fastboot_send(fbn, header, "command too long");
+ } else {
+ memcpy(fbn->command, fastboot_data, fastboot_data_len);
+ fbn->command[fastboot_data_len] = 0;
+ }
+ }
+}
+
+static void fastboot_check_retransmit(struct fastboot_net *fbn,
+ struct fastboot_header header)
+{
+ if (ntohs(header.seq) == fbn->sequence_number - 1 &&
+ is_current_connection(fbn)) {
+ /* Retransmit last sent packet */
+ memcpy(net_udp_get_payload(fbn->net_con),
+ fbn->last_payload, fbn->last_payload_len);
+ net_udp_send(fbn->net_con, fbn->last_payload_len);
+ }
+}
+
+static void fastboot_handler(void *ctx, char *packet, unsigned int raw_len)
+{
+ unsigned int len = net_eth_to_udplen(packet);
+ struct ethernet *eth_header = (struct ethernet *)packet;
+ struct iphdr *ip_header = net_eth_to_iphdr(packet);
+ struct udphdr *udp_header = net_eth_to_udphdr(packet);
+ char *payload = net_eth_to_udp_payload(packet);
+ struct fastboot_net *fbn = ctx;
+ struct fastboot_header header;
+ char *fastboot_data = payload + sizeof(header);
+ u16 tot_len = ntohs(ip_header->tot_len);
+
+ /* catch bogus tot_len values */
+ if ((char *)ip_header - packet + tot_len > raw_len)
+ return;
+
+ /* catch packets split into fragments that are too small to reply */
+ if (fastboot_data - (char *)ip_header > tot_len)
+ return;
+
+ /* catch packets too small to be valid */
+ if (len < sizeof(struct fastboot_header))
+ return;
+
+ memcpy(&header, payload, sizeof(header));
+ header.flags = 0;
+ len -= sizeof(header);
+
+ /* catch remaining fragmented packets */
+ if (fastboot_data - (char *)ip_header + len > tot_len) {
+ fastboot_send(fbn, header,
+ "can't reassemble fragmented frames");
+ return;
+ }
+ /* catch too large packets */
+ if (len > PACKET_SIZE) {
+ fastboot_send(fbn, header, "packet too large");
+ return;
+ }
+
+ memcpy(fbn->net_con->et->et_dest, eth_header->et_src, ETH_ALEN);
+ net_copy_ip(&fbn->net_con->ip->daddr, &ip_header->saddr);
+ fbn->net_con->udp->uh_dport = udp_header->uh_sport;
+
+ switch (header.id) {
+ case FASTBOOT_QUERY:
+ fastboot_send(fbn, header, NULL);
+ break;
+ case FASTBOOT_INIT:
+ if (ntohs(header.seq) != fbn->sequence_number) {
+ fastboot_check_retransmit(fbn, header);
+ break;
+ }
+ fbn->host_addr = net_read_ip(&ip_header->saddr);
+ fbn->host_port = udp_header->uh_sport;
+ memcpy(fbn->host_mac, eth_header->et_src, ETH_ALEN);
+ fastboot_abort(fbn);
+ fastboot_send(fbn, header, NULL);
+ break;
+ case FASTBOOT_FASTBOOT:
+ if (!is_current_connection(fbn))
+ break;
+ memcpy(fbn->host_mac, eth_header->et_src, ETH_ALEN);
+ if (ntohs(header.seq) != fbn->sequence_number) {
+ fastboot_check_retransmit(fbn, header);
+ } else if (!fbn->sequence_number_seen) {
+ fbn->sequence_number_seen = true;
+ fastboot_handle_type_fastboot(fbn, header,
+ fastboot_data, len);
+ }
+ break;
+ default:
+ fastboot_send(fbn, header, "unknown packet type");
+ break;
+ }
+}
+
+static void fastboot_poll(struct poller_struct *poller)
+{
+ struct fastboot_net *fbn = container_of(poller, struct fastboot_net,
+ poller);
+
+ if (fbn->download_needs_cleanup) {
+ if (fbn->active_download)
+ return;
+ /*
+ * fastboot_download_finished has already been called when
+ * reinit was set
+ */
+ if (!fbn->reinit)
+ fastboot_download_finished(&fbn->fastboot);
+ fbn->download_needs_cleanup = 0;
+ }
+
+ if (!fbn->command[0])
+ return;
+
+ fbn->reinit = false;
+ fastboot_tx_print(&fbn->fastboot, FASTBOOT_MSG_NONE, "");
+ fastboot_exec_cmd(&fbn->fastboot, fbn->command);
+ fbn->command[0] = 0;
+ fbn->download_needs_cleanup = fbn->active_download;
+}
+
+static void fastboot_send_keep_alive(struct poller_struct *poller)
+{
+ struct fastboot_net *fbn = container_of(poller, struct fastboot_net,
+ keep_alive_poller);
+
+ if (!fbn->command[0])
+ return;
+
+ /*
+ * Sending the message will reset may_send to MAY_NOT_SEND and the
+ * ACK from the host will reset host_waits_since to the current time.
+ */
+ if (fbn->may_send == MAY_SEND_MESSAGE &&
+ is_timeout_non_interruptible(fbn->host_waits_since,
+ 30ULL * NSEC_PER_SEC))
+ fastboot_tx_print(&fbn->fastboot, FASTBOOT_MSG_INFO,
+ "still busy");
+}
+
+void fastboot_net_free(struct fastboot_net *fbn)
+{
+ fastboot_generic_close(&fbn->fastboot);
+ poller_unregister(&fbn->keep_alive_poller);
+ poller_unregister(&fbn->poller);
+ net_unregister(fbn->net_con);
+ fastboot_generic_free(&fbn->fastboot);
+ free(fbn);
+}
+
+struct fastboot_net *fastboot_net_init(struct fastboot_opts *opts)
+{
+ struct fastboot_net *fbn;
+ int ret;
+
+ fbn = xzalloc(sizeof(*fbn));
+ INIT_LIST_HEAD(&fbn->fastboot.variables);
+ fbn->fastboot.write = fastboot_write_net;
+ fbn->fastboot.start_download = fastboot_start_download_net;
+
+ if (opts) {
+ fbn->fastboot.files = opts->files;
+ fbn->fastboot.cmd_exec = opts->cmd_exec;
+ fbn->fastboot.cmd_flash = opts->cmd_flash;
+ ret = fastboot_generic_init(&fbn->fastboot, opts->export_bbu);
+ } else {
+ fbn->fastboot.files = file_list_parse(fastboot_partitions
+ ? fastboot_partitions
+ : "");
+ ret = fastboot_generic_init(&fbn->fastboot, fastboot_bbu);
+ }
+ if (ret)
+ goto fail_generic_init;
+
+ fbn->net_con = net_udp_new(IP_BROADCAST, FASTBOOT_PORT,
+ fastboot_handler, fbn);
+ if (IS_ERR(fbn->net_con)) {
+ ret = PTR_ERR(fbn->net_con);
+ goto fail_net_con;
+ }
+ net_udp_bind(fbn->net_con, FASTBOOT_PORT);
+
+ eth_open(fbn->net_con->edev);
+ fbn->poller.func = fastboot_poll;
+ ret = poller_register(&fbn->poller, "fastboot-net");
+ if (ret)
+ goto fail_poller;
+
+ fbn->keep_alive_poller.func = fastboot_send_keep_alive;
+ ret = poller_register(&fbn->keep_alive_poller,
+ "fastboot-net-keep-alive");
+ if (ret)
+ goto fail_poller2;
+
+ slice_depends_on(&fbn->poller.slice, &idle_slice);
+ slice_depends_on(&fbn->keep_alive_poller.slice, &fbn->net_con->edev->slice);
+
+ return fbn;
+
+fail_poller2:
+ poller_unregister(&fbn->poller);
+fail_poller:
+ net_unregister(fbn->net_con);
+fail_net_con:
+ fastboot_generic_free(&fbn->fastboot);
+fail_generic_init:
+ free(fbn);
+ return ERR_PTR(ret);
+}
+
+static struct fastboot_net *fastboot_net_obj;
+static int fastboot_net_autostart;
+
+static int fastboot_on_boot(void)
+{
+ struct fastboot_net *fbn;
+
+ globalvar_add_simple_bool("fastboot.net.autostart",
+ &fastboot_net_autostart);
+
+ if (!fastboot_net_autostart)
+ return 0;
+
+ ifup_all(0);
+ fbn = fastboot_net_init(NULL);
+
+ if (IS_ERR(fbn))
+ return PTR_ERR(fbn);
+
+ fastboot_net_obj = fbn;
+ return 0;
+}
+
+static void fastboot_net_exit(void)
+{
+ if (fastboot_net_obj)
+ fastboot_net_free(fastboot_net_obj);
+}
+
+postenvironment_initcall(fastboot_on_boot);
+predevshutdown_exitcall(fastboot_net_exit);
+
+BAREBOX_MAGICVAR_NAMED(global_fastboot_net_autostart,
+ global.fastboot.net.autostart,
+ "If true, automatically start fastboot over UDP during startup");
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread