[PATCH 1/2] dm: core: Add logging on unbind failure

This failure path is tricky to debug since it continues after failure and there are a lot of error paths. Add logging to help.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/core/device-remove.c | 20 ++++++++++++-------- drivers/core/uclass.c | 4 ++-- 2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c index ff5b28cb6a7..8736fd9821e 100644 --- a/drivers/core/device-remove.c +++ b/drivers/core/device-remove.c @@ -10,6 +10,7 @@
#include <common.h> #include <errno.h> +#include <log.h> #include <malloc.h> #include <dm/device.h> #include <dm/device-internal.h> @@ -30,11 +31,14 @@ int device_chld_unbind(struct udevice *dev, struct driver *drv) continue;
ret = device_unbind(pos); - if (ret && !saved_ret) + if (ret && !saved_ret) { + log_warning("device '%s' failed to unbind\n", + pos->name); saved_ret = ret; + } }
- return saved_ret; + return log_ret(saved_ret); }
int device_chld_remove(struct udevice *dev, struct driver *drv, @@ -63,13 +67,13 @@ int device_unbind(struct udevice *dev) int ret;
if (!dev) - return -EINVAL; + return log_msg_ret("dev", -EINVAL);
if (dev->flags & DM_FLAG_ACTIVATED) - return -EINVAL; + return log_msg_ret("active", -EINVAL);
if (!(dev->flags & DM_FLAG_BOUND)) - return -EINVAL; + return log_msg_ret("not-bound", -EINVAL);
drv = dev->driver; assert(drv); @@ -77,12 +81,12 @@ int device_unbind(struct udevice *dev) if (drv->unbind) { ret = drv->unbind(dev); if (ret) - return ret; + return log_msg_ret("unbind", ret); }
ret = device_chld_unbind(dev, NULL); if (ret) - return ret; + return log_msg_ret("child unbind", ret);
if (dev->flags & DM_FLAG_ALLOC_PDATA) { free(dev->platdata); @@ -98,7 +102,7 @@ int device_unbind(struct udevice *dev) } ret = uclass_unbind_device(dev); if (ret) - return ret; + return log_msg_ret("uc", ret);
if (dev->parent) list_del(&dev->sibling_node); diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 58b19a42109..b24b677c55d 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -120,10 +120,10 @@ int uclass_destroy(struct uclass *uc) uclass_node); ret = device_remove(dev, DM_REMOVE_NORMAL); if (ret) - return ret; + return log_msg_ret("remove", ret); ret = device_unbind(dev); if (ret) - return ret; + return log_msg_ret("unbind", ret); }
uc_drv = uc->uc_drv;

When removing a device the power domains it uses are generally powered off. But when we are trying to unbind all devices (e.g. for running tests) we don't want to probe a device in the 'remove' path.
Add a new flag to skip this power-down step.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/core/device-remove.c | 3 ++- drivers/core/uclass.c | 2 +- include/dm/device.h | 11 +++++++---- 3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c index 8736fd9821e..efdb0f29058 100644 --- a/drivers/core/device-remove.c +++ b/drivers/core/device-remove.c @@ -198,7 +198,8 @@ int device_remove(struct udevice *dev, uint flags) } }
- if (!(drv->flags & + if (!(flags & DM_REMOVE_NO_PD) && + !(drv->flags & (DM_FLAG_DEFAULT_PD_CTRL_OFF | DM_FLAG_REMOVE_WITH_PD_ON)) && dev != gd->cur_serial_dev) dev_power_domain_off(dev); diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index b24b677c55d..68493029364 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -118,7 +118,7 @@ int uclass_destroy(struct uclass *uc) while (!list_empty(&uc->dev_head)) { dev = list_first_entry(&uc->dev_head, struct udevice, uclass_node); - ret = device_remove(dev, DM_REMOVE_NORMAL); + ret = device_remove(dev, DM_REMOVE_NORMAL | DM_REMOVE_NO_PD); if (ret) return log_msg_ret("remove", ret); ret = device_unbind(dev); diff --git a/include/dm/device.h b/include/dm/device.h index a56164b19bb..17e57bf829c 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -80,18 +80,21 @@ struct driver_info; */ enum { /* Normal remove, remove all devices */ - DM_REMOVE_NORMAL = 1 << 0, + DM_REMOVE_NORMAL = 1 << 0,
/* Remove devices with active DMA */ - DM_REMOVE_ACTIVE_DMA = DM_FLAG_ACTIVE_DMA, + DM_REMOVE_ACTIVE_DMA = DM_FLAG_ACTIVE_DMA,
/* Remove devices which need some final OS preparation steps */ - DM_REMOVE_OS_PREPARE = DM_FLAG_OS_PREPARE, + DM_REMOVE_OS_PREPARE = DM_FLAG_OS_PREPARE,
/* Add more use cases here */
/* Remove devices with any active flag */ - DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_OS_PREPARE, + DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_OS_PREPARE, + + /* Don't power down any attached power domains */ + DM_REMOVE_NO_PD = 1 << 1, };
/**

When removing a device the power domains it uses are generally powered off. But when we are trying to unbind all devices (e.g. for running tests) we don't want to probe a device in the 'remove' path.
Add a new flag to skip this power-down step.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/core/device-remove.c | 3 ++- drivers/core/uclass.c | 2 +- include/dm/device.h | 11 +++++++---- 3 files changed, 10 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next, thanks!

This failure path is tricky to debug since it continues after failure and there are a lot of error paths. Add logging to help.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/core/device-remove.c | 20 ++++++++++++-------- drivers/core/uclass.c | 4 ++-- 2 files changed, 14 insertions(+), 10 deletions(-)
Applied to u-boot-dm/next, thanks!
participants (2)
-
Simon Glass
-
sjg@google.com