aboutsummaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorMark Brown2012-07-05 14:04:44 +0100
committerGreg Kroah-Hartman2012-07-16 18:05:45 -0700
commit8153584e3fdf78753bf653d5f583b6ecb86e5e70 (patch)
tree34c5cc5b62d52ea9957919f938446f23161c2eb4 /drivers/base
parent5a7689fd5b4f2094e7a32beae67f290f8619b042 (diff)
driver core: Move deferred devices to the end of dpm_list before probing
When deferred probe was originally added the idea was that devices which defer their probes would move themselves to the end of dpm_list in order to try to keep the assumptions that we're making about the list being in roughly the order things should be suspended correct. However this hasn't been what's been happening and doing it requires a lot of duplicated code to do the moves. Instead take a simple, brute force solution and have the deferred probe code push devices to the end of dpm_list before it retries the probe. This does mean we lock the dpm_list a bit more often but it's very simple and the code shouldn't be a fast path. We do the move with the deferred mutex dropped since doing things with fewer locks held simultaneously seems like a good idea. This approach was most recently suggested by Grant Likely. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Grant Likely <grant.likely@secretlab.ca>, Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/dd.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6cd2c6ca9b0d..9b0aca479580 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -85,8 +85,20 @@ static void deferred_probe_work_func(struct work_struct *work)
* manipulate the deferred list
*/
mutex_unlock(&deferred_probe_mutex);
+
+ /*
+ * Force the device to the end of the dpm_list since
+ * the PM code assumes that the order we add things to
+ * the list is a good order for suspend but deferred
+ * probe makes that very unsafe.
+ */
+ device_pm_lock();
+ device_pm_move_last(dev);
+ device_pm_unlock();
+
dev_dbg(dev, "Retrying from deferred list\n");
bus_probe_device(dev);
+
mutex_lock(&deferred_probe_mutex);
put_device(dev);