On Thu, Jun 25, 2020 at 5:24 AM Saravana Kannan <sarava...@google.com> wrote: > > 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. */
Yes, this needs to go away if you make the other change. > > 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); But it would be good to somehow limit this to the devices affected by deferred probing or we'll end up reordering dpm_list unnecessarily for many times in the actual majority of cases. > + > pinctrl_init_done(dev); > > if (dev->pm_domain && dev->pm_domain->sync) > -- > 2.27.0.111.gc72c7da667-goog >