summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2024-01-29 19:28:37 +0300
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2024-02-05 16:28:54 +0300
commit96db0f947a14df754586ac38bc0d50ab8dae013c (patch)
treecb2a7705667879869bc3309c6334869c9df34350
parenta4b64b893428734fc872a162ca7d92aa1ca1c429 (diff)
downloadlinux-96db0f947a14df754586ac38bc0d50ab8dae013c.tar.xz
PM: sleep: Move devices to new lists earlier in each suspend phase
During a system-wide suspend of devices, dpm_noirq_suspend_devices(), dpm_suspend_late() and dpm_suspend() move devices from one list to another. They do it with each device after its PM callback in the given suspend phase has run or has been scheduled for asynchronous execution, in case it is deleted from the current list in the meantime. However, devices can be moved to a new list before invoking their PM callbacks (which usually is the case for the devices whose callbacks are executed asynchronously anyway), because doing so does not affect the ordering of that list. In either case, each device is moved to the new list after the previous device has been moved to it or gone away, and if a device is removed, it does not matter which list it is in at that point, because deleting an entry from a list does not change the ordering of the other entries in it. Accordingly, modify the functions mentioned above to move devices to new lists without waiting for their PM callbacks to run regardless of whether or not they run asynchronously. No intentional functional impact. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/base/power/main.c24
1 files changed, 3 insertions, 21 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 89a3ddd642c9..bcd043c1d385 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1304,18 +1304,12 @@ static int dpm_noirq_suspend_devices(pm_message_t state)
while (!list_empty(&dpm_late_early_list)) {
struct device *dev = to_device(dpm_late_early_list.prev);
+ list_move(&dev->power.entry, &dpm_noirq_list);
get_device(dev);
mutex_unlock(&dpm_list_mtx);
error = device_suspend_noirq(dev);
- mutex_lock(&dpm_list_mtx);
-
- if (!error && !list_empty(&dev->power.entry))
- list_move(&dev->power.entry, &dpm_noirq_list);
-
- mutex_unlock(&dpm_list_mtx);
-
put_device(dev);
mutex_lock(&dpm_list_mtx);
@@ -1486,19 +1480,13 @@ int dpm_suspend_late(pm_message_t state)
while (!list_empty(&dpm_suspended_list)) {
struct device *dev = to_device(dpm_suspended_list.prev);
+ list_move(&dev->power.entry, &dpm_late_early_list);
get_device(dev);
mutex_unlock(&dpm_list_mtx);
error = device_suspend_late(dev);
- mutex_lock(&dpm_list_mtx);
-
- if (!list_empty(&dev->power.entry))
- list_move(&dev->power.entry, &dpm_late_early_list);
-
- mutex_unlock(&dpm_list_mtx);
-
put_device(dev);
mutex_lock(&dpm_list_mtx);
@@ -1763,19 +1751,13 @@ int dpm_suspend(pm_message_t state)
while (!list_empty(&dpm_prepared_list)) {
struct device *dev = to_device(dpm_prepared_list.prev);
+ list_move(&dev->power.entry, &dpm_suspended_list);
get_device(dev);
mutex_unlock(&dpm_list_mtx);
error = device_suspend(dev);
- mutex_lock(&dpm_list_mtx);
-
- if (!error && !list_empty(&dev->power.entry))
- list_move(&dev->power.entry, &dpm_suspended_list);
-
- mutex_unlock(&dpm_list_mtx);
-
put_device(dev);
mutex_lock(&dpm_list_mtx);