diff options
author | Simon Glass <sjg@chromium.org> | 2015-04-19 07:20:58 -0600 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2015-04-22 11:13:17 -0600 |
commit | 07d260e047680971d926bc9a573f9291f39fc988 (patch) | |
tree | 250495e7f5848a94c9fc65ca2012681bbe19add7 | |
parent | a7b8250210cd1b449a06f7d20769944ebeca1a41 (diff) | |
download | u-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.c | 12 |
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; |