[U-Boot] [PATCH 3/3] dm: core: Add uclass_first/next_ok_device()
Simon Glass
sjg at chromium.org
Thu Apr 20 01:29:56 UTC 2017
Sometimes it is useful to iterate through all devices in a uclass and
skip over those which do not work correctly (e.g fail to probe). Add two
new functions to provide this feature.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
drivers/core/uclass.c | 29 +++++++++++++++++++++++++++++
include/dm/uclass.h | 31 +++++++++++++++++++++++++++++++
test/dm/test-fdt.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 105 insertions(+)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 42613031ff..eac30d965d 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -456,6 +456,35 @@ int uclass_next_device(struct udevice **devp)
return uclass_get_device_tail(dev, ret, devp);
}
+struct udevice *uclass_first_ok_device(enum uclass_id id)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_find_first_device(id, &dev);
+ if (!dev)
+ return NULL;
+ ret = device_probe(dev);
+ if (ret)
+ return uclass_next_ok_device(dev);
+
+ return dev;
+}
+
+struct udevice *uclass_next_ok_device(struct udevice *dev)
+{
+ int ret;
+
+ do {
+ ret = uclass_find_next_device(&dev);
+ if (!dev)
+ return NULL;
+ ret = device_probe(dev);
+ } while (ret);
+
+ return dev;
+}
+
int uclass_bind_device(struct udevice *dev)
{
struct uclass *uc;
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 63da868ae5..b53fba5c2c 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -262,6 +262,37 @@ int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
int uclass_next_device(struct udevice **devp);
/**
+ * uclass_first_ok_device() - Get the first functioning device in a uclass
+ *
+ * The device returned is probed if necessary, and ready for use. Any devices
+ * which fail to probe are skipped. It is not possible to discover the error
+ * for any devices which fail to probe. You should use uclass_first_device()
+ * if you care about that.
+ *
+ * @id: Uclass ID to look up
+ * @return: pointer to the first functioning device in that uclass if one
+ * can be found, or NULL if there is no such device (e.g. if the rest of the
+ * devices cannot be probed).
+ */
+struct udevice *uclass_first_ok_device(enum uclass_id id);
+
+/**
+ * uclass_next_ok_device() - Get the next functioning device in a uclass
+ *
+ * The device returned is probed if necessary, and ready for use. Any devices
+ * which fail to probe are skipped. It is not possible to discover the error
+ * for any devices which fail to probe. You should use uclass_next_device()
+ * if you care about that.
+ *
+ * @dev: Pointer to the previous device (e.g. returned from
+ * uclass_first_ok_device() or uclass_next_ok_device()
+ * @return: pointer to the next functioning device in the same uclass if one
+ * can be found, or NULL if there is no such device (e.g. if the rest of the
+ * devices cannot be probed).
+ */
+struct udevice *uclass_next_ok_device(struct udevice *dev);
+
+/**
* uclass_resolve_seq() - Resolve a device's sequence number
*
* On entry dev->seq is -1, and dev->req_seq may be -1 (to allocate a
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 1770b86fed..69c1a89246 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -338,3 +338,48 @@ static int dm_test_first_next_device(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_first_next_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test uclass_first_ok_device() and uclass_next_ok_device() */
+static int dm_test_first_next_ok_device(struct unit_test_state *uts)
+{
+ struct dm_testprobe_pdata *pdata;
+ struct udevice *dev, *parent = NULL, *devlist[4];
+ int count;
+
+ /* There should be 4 devices */
+ for (dev = uclass_first_ok_device(UCLASS_TEST_PROBE), count = 0;
+ dev;
+ dev = uclass_next_ok_device(dev)) {
+ devlist[count++] = dev;
+ parent = dev_get_parent(dev);
+ }
+ ut_asserteq(4, count);
+
+ /* Remove them and try again, with an error on the second one */
+ pdata = dev_get_platdata(devlist[1]);
+ pdata->probe_err = -ENOMEM;
+ device_remove(parent, DM_REMOVE_NORMAL);
+ ut_asserteq_ptr(devlist[0], uclass_first_ok_device(UCLASS_TEST_PROBE));
+ ut_asserteq_ptr(devlist[2], uclass_next_ok_device(devlist[0]));
+ ut_asserteq_ptr(devlist[3], uclass_next_ok_device(devlist[2]));
+ ut_asserteq_ptr(NULL, uclass_next_ok_device(devlist[3]));
+
+ /* Now an error on the first one */
+ pdata = dev_get_platdata(devlist[0]);
+ pdata->probe_err = -ENOENT;
+ device_remove(parent, DM_REMOVE_NORMAL);
+ ut_asserteq_ptr(devlist[2], uclass_first_ok_device(UCLASS_TEST_PROBE));
+ ut_asserteq_ptr(devlist[3], uclass_next_ok_device(devlist[2]));
+ ut_asserteq_ptr(NULL, uclass_next_ok_device(devlist[3]));
+
+ /* Now errors on all */
+ pdata = dev_get_platdata(devlist[2]);
+ pdata->probe_err = -ENOENT;
+ pdata = dev_get_platdata(devlist[3]);
+ pdata->probe_err = -ENOENT;
+ device_remove(parent, DM_REMOVE_NORMAL);
+ ut_asserteq_ptr(NULL, uclass_first_ok_device(UCLASS_TEST_PROBE));
+
+ return 0;
+}
+DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
--
2.12.2.816.g2cccc81164-goog
More information about the U-Boot
mailing list