summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-04-19 07:20:58 -0600
committerSimon Glass <sjg@chromium.org>2015-04-22 11:13:17 -0600
commit07d260e047680971d926bc9a573f9291f39fc988 (patch)
tree250495e7f5848a94c9fc65ca2012681bbe19add7
parenta7b8250210cd1b449a06f7d20769944ebeca1a41 (diff)
downloadu-boot-07d260e047680971d926bc9a573f9291f39fc988.tar.gz
u-boot-07d260e047680971d926bc9a573f9291f39fc988.tar.bz2
u-boot-07d260e047680971d926bc9a573f9291f39fc988.zip
dm: core: Handle recursive unbinding of uclass devices
Since a device can have children in the same uclass as itself, we need to handle unbinding carefully: we must allow that unbinding a device in a uclass may cause another device in the same uclass to be unbound. Adjust the code to cope. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Joe Hershberger <joe.hershberger@ni.com> Tested-by: Joe Hershberger <joe.hershberger@ni.com>
-rw-r--r--drivers/core/uclass.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 7627ad141b..9fec8c9c7a 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -99,10 +99,18 @@ fail_mem:
int uclass_destroy(struct uclass *uc)
{
struct uclass_driver *uc_drv;
- struct udevice *dev, *tmp;
+ struct udevice *dev;
int ret;
- list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node) {
+ /*
+ * We cannot use list_for_each_entry_safe() here. If a device in this
+ * uclass has a child device also in this uclass, it will be also be
+ * unbound (by the recursion in the call to device_unbind() below).
+ * We can loop until the list is empty.
+ */
+ while (!list_empty(&uc->dev_head)) {
+ dev = list_first_entry(&uc->dev_head, struct udevice,
+ uclass_node);
ret = device_remove(dev);
if (ret)
return ret;