Under the following conditions: - driver A is built in and can probe device-A - driver B is a module and can probe device-B - device-A is supplier of device-B
Without this patch: 1. device-A is added. 2. device-B is added. 3. dpm_list is now [device-A, device-B]. 4. driver-A defers probe of device-A. 5. deferred probe of device-A is reattempted 6. device-A is moved to end of dpm_list. 6. dpm_list is now [device-B, device-A]. 7. driver-B is loaded and probes device-B. 8. dpm_list stays as [device-B, device-A]. Suspend (which goes in the reverse order of dpm_list) fails because device-A (supplier) is suspended before device-B (consumer). With this patch: 1. device-A is added. 2. device-B is added. 3. dpm_list is now [device-A, device-B]. 4. driver-A defers probe of device-A. 5. deferred probe of device-A is reattempted later. 6. dpm_list is now [device-B, device-A]. 7. driver-B is loaded and probes device-B. 8. dpm_list is now [device-A, device-B]. Suspend works because device-B (consumer) is suspended before device-A (supplier). Fixes: 494fd7b7ad10 ("PM / core: fix deferred probe breaking suspend resume order") Fixes: 716a7a259690 ("driver core: fw_devlink: Add support for batching fwnode parsing") Cc: Geert Uytterhoeven <ge...@linux-m68k.org> Signed-off-by: Saravana Kannan <sarava...@google.com> --- drivers/base/dd.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 9a1d940342ac..52b2148c7983 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -109,6 +109,8 @@ static void deferred_probe_work_func(struct work_struct *work) * probe makes that very unsafe. */ device_pm_move_to_tail(dev); + /* Greg/Rafael: SHOULD I DELETE THIS? ^^ I think I should, but + * I'm worried if it'll have some unintended consequeneces. */ dev_dbg(dev, "Retrying from deferred list\n"); bus_probe_device(dev); @@ -557,6 +559,20 @@ static int really_probe(struct device *dev, struct device_driver *drv) goto re_probe; } + /* + * The devices are added to the dpm_list (resume/suspend (reverse + * order) list) as they are registered with the driver core. But the + * order the devices are added doesn't necessarily match the real + * dependency order. + * + * The successful probe order is a much better signal. If a device just + * probed successfully, then we know for sure that all the devices that + * probed before it don't depend on the device. So, we can safely move + * the device to the end of the dpm_list. As more devices probe, + * they'll automatically get ordered correctly. + */ + device_pm_move_to_tail(dev); + pinctrl_init_done(dev); if (dev->pm_domain && dev->pm_domain->sync) -- 2.27.0.111.gc72c7da667-goog