[PATCH v4 20/21] dm: core: Switch uclass_*_device_err to use uclass_*_device_check

Michal Suchanek msuchanek at suse.de
Sun Sep 25 10:28:13 CEST 2022


The _err variant iterators use the simple iterators without suffix as
basis.

However, there is no user that uclass_next_device_err for iteration,
many users of uclass_first_device_err use it to get the first and
(assumed) only device of an uclass, and a couple that use
uclass_next_device_err to get the device following a known device in the
uclass list.

While there are some truly singleton device classes in which more than
one device cannot exist these are quite rare, and most classes can have
multiple devices even if it is not the case on the SoC's EVB.

In a later patch the simple iterators will be updated to not stop on
error and return next device instead. With this in many cases the code
that expects the first device or an error if it fails to probe may get
the next device instead. Use the _check iterators as the basis of _err
iterators to preserve the old behavior.

This is problematic for eth_get_dev: it relies on the broken behavior
that returns an error but not the device on which the error happened
which gives the caller no reasonable way to report or handle the error.
With this change the device is returned but eth_get_dev stores the
returned device pointer directly in a global state without checking the
return value. Unset the pointer again in the error case.

Signed-off-by: Michal Suchanek <msuchanek at suse.de>
---
 drivers/core/uclass.c | 28 ++++++++++++++--------------
 include/dm/uclass.h   | 22 +++++++++++-----------
 net/eth-uclass.c      |  2 ++
 3 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index a591e22403..b7d11bdd23 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -586,19 +586,6 @@ int uclass_first_device(enum uclass_id id, struct udevice **devp)
 	return uclass_get_device_tail(dev, ret, devp);
 }
 
-int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
-{
-	int ret;
-
-	ret = uclass_first_device(id, devp);
-	if (ret)
-		return ret;
-	else if (!*devp)
-		return -ENODEV;
-
-	return 0;
-}
-
 int uclass_next_device(struct udevice **devp)
 {
 	struct udevice *dev = *devp;
@@ -611,11 +598,24 @@ int uclass_next_device(struct udevice **devp)
 	return uclass_get_device_tail(dev, ret, devp);
 }
 
+int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_check(id, devp);
+	if (ret)
+		return ret;
+	else if (!*devp)
+		return -ENODEV;
+
+	return 0;
+}
+
 int uclass_next_device_err(struct udevice **devp)
 {
 	int ret;
 
-	ret = uclass_next_device(devp);
+	ret = uclass_next_device_check(devp);
 	if (ret)
 		return ret;
 	else if (!*devp)
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index f6c0110b06..5e9da2b106 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -332,17 +332,6 @@ int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv,
  */
 int uclass_first_device(enum uclass_id id, struct udevice **devp);
 
-/**
- * uclass_first_device_err() - Get the first device in a uclass
- *
- * The device returned is probed if necessary, and ready for use
- *
- * @id: Uclass ID to look up
- * @devp: Returns pointer to the first device in that uclass, or NULL if none
- * Return: 0 if found, -ENODEV if not found, other -ve on error
- */
-int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
-
 /**
  * uclass_next_device() - Get the next device in a uclass
  *
@@ -358,6 +347,17 @@ int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
  */
 int uclass_next_device(struct udevice **devp);
 
+/**
+ * uclass_first_device_err() - Get the first device in a uclass
+ *
+ * The device returned is probed if necessary, and ready for use
+ *
+ * @id: Uclass ID to look up
+ * @devp: Returns pointer to the first device in that uclass, or NULL if none
+ * Return: 0 if found, -ENODEV if not found, other -ve on error
+ */
+int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
+
 /**
  * uclass_next_device_err() - Get the next device in a uclass
  *
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 8c3f9cc31b..f41da4b37b 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -93,6 +93,8 @@ struct udevice *eth_get_dev(void)
 		if (eth_errno)
 			eth_errno = uclass_first_device_err(UCLASS_ETH,
 							    &uc_priv->current);
+		if (eth_errno)
+			uc_priv->current = NULL;
 	}
 	return uc_priv->current;
 }
-- 
2.37.3



More information about the U-Boot mailing list