diff options
author | Marco Felsch <m.felsch@pengutronix.de> | 2021-06-25 09:25:30 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2021-06-25 10:01:00 +0200 |
commit | cd23b6facf33cc9bdaa90ea8c0479ef6959f2860 (patch) | |
tree | ac21e99434cc129425e36ca034abc30731436f7e /include | |
parent | b052703f0d141a1caf7dfaca16f905308e03487f (diff) | |
download | barebox-cd23b6facf33cc9bdaa90ea8c0479ef6959f2860.tar.gz barebox-cd23b6facf33cc9bdaa90ea8c0479ef6959f2860.tar.xz |
common: add initial barebox deep-probe support
The barebox 'deep probe' or 'probe on demand' mechanism is the answer of
unwanted -EPROBE_DEFER failures. The EPROBE_DEFER error code was
introduced by commit ab3da15bc14c ("base: Introduce deferred probing")
and since then it causes a few problems.
The error is returned if either the device is not yet present or the
driver is not yet registered. This makes sense on linux systems where
modules and hot-plug devices are used very often but not for barebox.
The module support is rarely used and devices aren't hot pluggable.
The current barebox behaviour populates all devices before the drivers
are registered so all devices are present during the driver
registration. So the driver probe() function gets called immediately
after the driver registration and causes the -EPROBE_DEFER error if this
driver depends on an other not yet registered driver.
To get rid of the EPROBE_DEFER error code we need to reorder the device
population and the driver registration. All drivers must be registered
first. In an ideal world all driver can be registered by the same
initcall level. Then devices are getting populated which causes calling
the driver probe() function but this time resources/devices are created
on demand if not yet available.
Dependencies between devices are normally expressed as references to
other device nodes. With deep probe barebox provides helper functions
which take a device node and probe the device behind that node if
necessary. This means instead of returning -EPROBE_DEFER, we can now
make the desired resources available once we need them.
If the resource can't be created we are returning -ENODEV since we are
not supporting hot-plugging. Dropping EPROBE_DEFER is the long-term
goal, avoid initcall shifting is the short-term goal.
Call it deep-probe since the on-demand device creation can create very
deep stacks. This commit adds the initial support for: spi, i2c, reset,
regulator, gpio and clk resource on-demand creation. The deep-probe
mechanism must be enabled for each board to avoid breaking changes using
deep_probe_enable(). This can be changed later after all boards are
converted to the new mechanism.
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
Link: https://lore.pengutronix.de/20201021115813.31645-8-m.felsch@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Link: https://lore.barebox.org/20210625072540.32717-10-s.hauer@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-generic/barebox.lds.h | 10 | ||||
-rw-r--r-- | include/deep-probe.h | 26 | ||||
-rw-r--r-- | include/of.h | 26 |
3 files changed, 61 insertions, 1 deletions
diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h index a7d32160d1..c5f9d97547 100644 --- a/include/asm-generic/barebox.lds.h +++ b/include/asm-generic/barebox.lds.h @@ -114,6 +114,13 @@ KEEP(*(.rsa_keys.rodata.*)); \ __rsa_keys_end = .; \ +#define BAREBOX_DEEP_PROBE \ + STRUCT_ALIGN(); \ + __barebox_deep_probe_start = .; \ + KEEP(*(SORT_BY_NAME(.barebox_deep_probe*))) \ + __barebox_deep_probe_end = .; + + #ifdef CONFIG_CONSTRUCTORS #define KERNEL_CTORS() . = ALIGN(8); \ __ctors_start = .; \ @@ -136,7 +143,8 @@ BAREBOX_CLK_TABLE \ BAREBOX_DTB \ BAREBOX_RSA_KEYS \ - BAREBOX_PCI_FIXUP + BAREBOX_PCI_FIXUP \ + BAREBOX_DEEP_PROBE #if defined(CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE) && \ CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE < CONFIG_BAREBOX_MAX_BARE_INIT_SIZE diff --git a/include/deep-probe.h b/include/deep-probe.h new file mode 100644 index 0000000000..f75ad1065c --- /dev/null +++ b/include/deep-probe.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __DEEP_PROBE_H +#define __DEEP_PROBE_H + +#include <linux/stringify.h> +#include <linux/types.h> + +struct deep_probe_entry { + const struct of_device_id *device_id; +}; + +bool deep_probe_is_supported(void); + +extern struct deep_probe_entry __barebox_deep_probe_start; +extern struct deep_probe_entry __barebox_deep_probe_end; + +#define __BAREBOX_DEEP_PROBE_ENABLE(_entry,_device_id) \ + static const struct deep_probe_entry _entry \ + __attribute__ ((used,section (".barebox_deep_probe_" __stringify(_entry)))) = { \ + .device_id = _device_id, \ + } + +#define BAREBOX_DEEP_PROBE_ENABLE(_device_id) \ + __BAREBOX_DEEP_PROBE_ENABLE(__UNIQUE_ID(deepprobe),_device_id) + +#endif /* __DEEP_PROBE_H */ diff --git a/include/of.h b/include/of.h index 3bce92e848..98de9d8480 100644 --- a/include/of.h +++ b/include/of.h @@ -277,6 +277,11 @@ extern struct device_d *of_device_enable_and_register_by_name(const char *name); extern struct device_d *of_device_enable_and_register_by_alias( const char *alias); +extern int of_device_ensure_probed(struct device_node *np); +extern int of_device_ensure_probed_by_alias(const char *alias); +extern int of_devices_ensure_probed_by_property(const char *property_name); +extern int of_devices_ensure_probed_by_dev_id(const struct of_device_id *ids); + struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node); int of_parse_partitions(struct cdev *cdev, struct device_node *node); int of_fixup_partitions(struct device_node *np, struct cdev *cdev); @@ -360,6 +365,27 @@ static inline struct device_d *of_platform_device_create(struct device_node *np, return NULL; } +static inline int of_device_ensure_probed(struct device_node *np) +{ + return 0; +} + +static inline int of_device_ensure_probed_by_alias(const char *alias) +{ + return 0; +} + +static inline int of_devices_ensure_probed_by_property(const char *property_name) +{ + return 0; +} + +static inline int +of_devices_ensure_probed_by_dev_id(const struct of_device_id *ids) +{ + return 0; +} + static inline int of_bus_n_addr_cells(struct device_node *np) { return 0; |