]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
dm: core: Fix handling of uclass pre_unbind method
authorSimon Glass <sjg@chromium.org>
Sat, 23 Oct 2021 23:26:05 +0000 (17:26 -0600)
committerSimon Glass <sjg@chromium.org>
Sun, 28 Nov 2021 23:51:51 +0000 (16:51 -0700)
This method is currently called after the platform data has been freed.
But the pre_unbind() method may wish to access this, e.g. to free some
data structures stored there.

Split the unbinding of devices into two pieces, as is done with removal.
This corrects the problem.

Also tidy a code-style issue in device_remove() while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/core/device-remove.c
drivers/core/uclass.c
include/dm/uclass-internal.h

index 11d3959d20f4b23eb23fd9d720c821b9c24e4b48..69c50da44a9966405c3fd0cbb3c58bdc84cbd0c2 100644 (file)
@@ -95,6 +95,9 @@ int device_unbind(struct udevice *dev)
        if (ret)
                return log_msg_ret("child unbind", ret);
 
+       ret = uclass_pre_unbind_device(dev);
+       if (ret)
+               return log_msg_ret("uc", ret);
        if (dev_get_flags(dev) & DM_FLAG_ALLOC_PDATA) {
                free(dev_get_plat(dev));
                dev_set_plat(dev, NULL);
@@ -142,10 +145,8 @@ void device_free(struct udevice *dev)
        }
        if (dev->parent) {
                size = dev->parent->driver->per_child_auto;
-               if (!size) {
-                       size = dev->parent->uclass->uc_drv->
-                                       per_child_auto;
-               }
+               if (!size)
+                       size = dev->parent->uclass->uc_drv->per_child_auto;
                if (size) {
                        free(dev_get_parent_priv(dev));
                        dev_set_parent_priv(dev, NULL);
index c5a50952fd0d29729aafe7355cd5b2bd1e115e6f..2fede896bfb5f19b16772d4602b6e20601301ac4 100644 (file)
@@ -682,7 +682,7 @@ err:
 }
 
 #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
-int uclass_unbind_device(struct udevice *dev)
+int uclass_pre_unbind_device(struct udevice *dev)
 {
        struct uclass *uc;
        int ret;
@@ -694,7 +694,13 @@ int uclass_unbind_device(struct udevice *dev)
                        return ret;
        }
 
+       return 0;
+}
+
+int uclass_unbind_device(struct udevice *dev)
+{
        list_del(&dev->uclass_node);
+
        return 0;
 }
 #endif
index 57c664c6daac88a94f0c26db444abecae7417212..49808c5c856a743615da154ac06c8aa191c86a70 100644 (file)
@@ -243,6 +243,17 @@ int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
  */
 int uclass_bind_device(struct udevice *dev);
 
+#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
+/**
+ * uclass_pre_unbind_device() - Prepare to deassociate device with a uclass
+ *
+ * Call any handled needed before uclass_unbind_device() is called
+ *
+ * @dev:       Pointer to the device
+ * #return 0 on success, -ve on error
+ */
+int uclass_pre_unbind_device(struct udevice *dev);
+
 /**
  * uclass_unbind_device() - Deassociate device with a uclass
  *
@@ -251,9 +262,10 @@ int uclass_bind_device(struct udevice *dev);
  * @dev:       Pointer to the device
  * #return 0 on success, -ve on error
  */
-#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
 int uclass_unbind_device(struct udevice *dev);
+
 #else
+static inline int uclass_pre_unbind_device(struct udevice *dev) { return 0; }
 static inline int uclass_unbind_device(struct udevice *dev) { return 0; }
 #endif