diff options
| author | Tom Rini <[email protected]> | 2026-03-18 18:36:50 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-03-18 18:36:50 -0600 |
| commit | eb00c710508d09b2a3b9aca75dd18280f1304703 (patch) | |
| tree | f91864725bde06d16a7243e0a539b28b03c0f125 /drivers/core | |
| parent | 28608c808774a39ec47d31353b141db547136e58 (diff) | |
| parent | dc88ac7681084b2aff8c3c4e1bb3e861451489a3 (diff) | |
Merge patch series "bootm: Clean up arch-specific, pre-OS clean-up"
Simon Glass <[email protected]> says:
Each arch does something slightly different before booting the OS. Some
archs even do different things depending on the CPU type.
It is quite hard to know what actually happens in the final milliseconds
before the OS boot.
This series attempts to start cleaning up U-Boot in this area.
The basic intent is to create a new bootm_final() function which can be
called by all archs. It provides some flags for a couple of necessary
variations but otherwise it is generic.
All architectures are converted over to use this new function.
board_quiesce_devices() is moved into bootm_final() so that all archs
benefit from it.
This series fixes a bug in device_remove() is fixed where removing a
parent with specialised flags (e.g. DM_REMOVE_ACTIVE_ALL) could leave
children activated, since they do not match the flags. This fixes is
needed to avoid bootm_final() causing test failures on sandbox.
Future work could take this a little further:
- Convert EFI loader to use the same function
- Improve comments for cleanup_before_linux() across architectures
- Support fake-run tracing on all archs
Link: https://lore.kernel.org/r/[email protected]
Diffstat (limited to 'drivers/core')
| -rw-r--r-- | drivers/core/device-remove.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c index 437080ed778..557afb8d817 100644 --- a/drivers/core/device-remove.c +++ b/drivers/core/device-remove.c @@ -198,7 +198,7 @@ static int flags_remove(uint flags, uint drv_flags) int device_remove(struct udevice *dev, uint flags) { const struct driver *drv; - int ret; + int ret, cret; if (!dev) return -EINVAL; @@ -211,24 +211,34 @@ int device_remove(struct udevice *dev, uint flags) return ret; /* + * Remove the device if called with the "normal" remove flag set, + * or if the remove flag matches any of the drivers remove flags + */ + drv = dev->driver; + assert(drv); + cret = flags_remove(flags, drv->flags); + + /* + * Remove all children. If this device is being removed due to + * active-DMA or OS-prepare flags, drop the active-flag requirement + * for children so they are removed even without matching active + * flags, since a deactivated device must not have activated + * children. Preserve other flags (e.g. DM_REMOVE_NON_VITAL) so + * that vital children are still protected. + * * If the child returns EKEYREJECTED, continue. It just means that it * didn't match the flags. */ - ret = device_chld_remove(dev, NULL, flags); + ret = device_chld_remove(dev, NULL, + cret ? flags : + (flags & ~DM_REMOVE_ACTIVE_ALL)); if (ret && ret != -EKEYREJECTED) return ret; - /* - * Remove the device if called with the "normal" remove flag set, - * or if the remove flag matches any of the drivers remove flags - */ - drv = dev->driver; - assert(drv); - ret = flags_remove(flags, drv->flags); - if (ret) { + if (cret) { log_debug("%s: When removing: flags=%x, drv->flags=%x, err=%d\n", - dev->name, flags, drv->flags, ret); - return ret; + dev->name, flags, drv->flags, cret); + return cret; } ret = uclass_pre_remove_device(dev); |
