dm: core: Handle recursive unbinding of uclass devices
authorSimon Glass <sjg@chromium.org>
Sun, 19 Apr 2015 13:20:58 +0000 (07:20 -0600)
committerSimon Glass <sjg@chromium.org>
Wed, 22 Apr 2015 17:13:17 +0000 (11:13 -0600)
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>
drivers/core/uclass.c

index 7627ad141b5ef68abbd2fdf4212d9a97b09565a5..9fec8c9c7ad1d0da945e09e1d2660cd43520fcc8 100644 (file)
@@ -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;