[U-Boot] [PATCH v2 1/1] core/uclass: iterate over all devices of a uclass

Heinrich Schuchardt
2017-04-19T11:26:24Z

When iterating over the devices of an uclass the iteration stops
at the first device that cannot be probed.
When calling booefi this will result in no block device being
passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including
&sd_emmc_a {
status = "okay";
}
This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device
iterate internally until they find the first device that can be
probed or the end of the device list is reached.

Debug output is provided for the two functions.

Reported-by: Andreas Färber <afaerber@suse.de>
Cc: Simon Glass <sjg@chromium.org>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2:
As suggested by Simon Glass correct uclass_first_device() and
uclass_next_device() instead of uclass_get_device_tail() to
avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html
---
drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 04fb45b..cff3a3f 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -420,16 +420,30 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
}
#endif

+/**
+ * uclass_first_device() - Finds first device of an uclass that can be probed
+ * @id: uclass id
+ * @devp: device found or NULL
+ * @return always 0
+ *
+ * For iterating over all devices of an uclass use
+ * for(uclass_first_device(id, &dev); dev; uclass_next_device(&dev)).
+ */
int uclass_first_device(enum uclass_id id, struct udevice **devp)
{
struct udevice *dev;
- int ret;

*devp = NULL;
- ret = uclass_find_first_device(id, &dev);
- if (!dev)
- return 0;
- return uclass_get_device_tail(dev, ret, devp);
+ for (uclass_find_first_device(id, &dev); dev;
+ uclass_find_next_device(&dev)) {
+
+ uclass_get_device_tail(dev, 0, devp);
+ if (*devp)
+ break;
+ }
+ debug("%s(%d): %s\n", __func__, id, dev ? dev->name : "(EOL)");
+
+ return 0;
}

int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
@@ -445,16 +459,24 @@ int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
return 0;
}

+/**
+ * uclass_next_device() - Find next device of an uclass that can be probed
+ * @devp: device found or NULL
+ * @return always 0
+ */
int uclass_next_device(struct udevice **devp)
{
struct udevice *dev = *devp;
- int ret;

- *devp = NULL;
- ret = uclass_find_next_device(&dev);
- if (!dev)
- return 0;
- return uclass_get_device_tail(dev, ret, devp);
+ for (*devp = NULL; !*devp; ) {
+ uclass_find_next_device(&dev);
+ if (!dev)
+ break;
+ uclass_get_device_tail(dev, 0, devp);
+ }
+ debug("%s: %s\n", __func__, dev ? dev->name : "(EOL)");
+
+ return 0;
}

int uclass_bind_device(struct udevice *dev)
--
2.1.4