dm: core: Fix handling of uclass pre_unbind method
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>
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 11d3959..69c50da 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -95,6 +95,9 @@
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 @@
}
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);
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index c5a5095..2fede89 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -682,7 +682,7 @@
}
#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 @@
return ret;
}
+ return 0;
+}
+
+int uclass_unbind_device(struct udevice *dev)
+{
list_del(&dev->uclass_node);
+
return 0;
}
#endif
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index 57c664c..49808c5 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -243,6 +243,17 @@
*/
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 @@
* @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