Skip to content

Commit de377b3

Browse files
Chuansheng-Liurafaeljw
authored andcommitted
PM / sleep: Asynchronous threads for suspend_late
In analogy with commits 5af84b8 and 97df8c1, using asynchronous threads can improve the overall suspend_late time significantly. This patch is for suspend_late phase. Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 28b6fd6 commit de377b3

File tree

1 file changed

+54
-12
lines changed

1 file changed

+54
-12
lines changed

drivers/base/power/main.c

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,16 +1127,26 @@ static int dpm_suspend_noirq(pm_message_t state)
11271127
*
11281128
* Runtime PM is disabled for @dev while this function is being executed.
11291129
*/
1130-
static int device_suspend_late(struct device *dev, pm_message_t state)
1130+
static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
11311131
{
11321132
pm_callback_t callback = NULL;
11331133
char *info = NULL;
1134-
int error;
1134+
int error = 0;
11351135

11361136
__pm_runtime_disable(dev, false);
11371137

1138+
if (async_error)
1139+
goto Complete;
1140+
1141+
if (pm_wakeup_pending()) {
1142+
async_error = -EBUSY;
1143+
goto Complete;
1144+
}
1145+
11381146
if (dev->power.syscore)
1139-
return 0;
1147+
goto Complete;
1148+
1149+
dpm_wait_for_children(dev, async);
11401150

11411151
if (dev->pm_domain) {
11421152
info = "late power domain ";
@@ -1160,10 +1170,40 @@ static int device_suspend_late(struct device *dev, pm_message_t state)
11601170
error = dpm_run_callback(callback, dev, state, info);
11611171
if (!error)
11621172
dev->power.is_late_suspended = true;
1173+
else
1174+
async_error = error;
11631175

1176+
Complete:
1177+
complete_all(&dev->power.completion);
11641178
return error;
11651179
}
11661180

1181+
static void async_suspend_late(void *data, async_cookie_t cookie)
1182+
{
1183+
struct device *dev = (struct device *)data;
1184+
int error;
1185+
1186+
error = __device_suspend_late(dev, pm_transition, true);
1187+
if (error) {
1188+
dpm_save_failed_dev(dev_name(dev));
1189+
pm_dev_err(dev, pm_transition, " async", error);
1190+
}
1191+
put_device(dev);
1192+
}
1193+
1194+
static int device_suspend_late(struct device *dev)
1195+
{
1196+
reinit_completion(&dev->power.completion);
1197+
1198+
if (pm_async_enabled && dev->power.async_suspend) {
1199+
get_device(dev);
1200+
async_schedule(async_suspend_late, dev);
1201+
return 0;
1202+
}
1203+
1204+
return __device_suspend_late(dev, pm_transition, false);
1205+
}
1206+
11671207
/**
11681208
* dpm_suspend_late - Execute "late suspend" callbacks for all devices.
11691209
* @state: PM transition of the system being carried out.
@@ -1174,19 +1214,20 @@ static int dpm_suspend_late(pm_message_t state)
11741214
int error = 0;
11751215

11761216
mutex_lock(&dpm_list_mtx);
1217+
pm_transition = state;
1218+
async_error = 0;
1219+
11771220
while (!list_empty(&dpm_suspended_list)) {
11781221
struct device *dev = to_device(dpm_suspended_list.prev);
11791222

11801223
get_device(dev);
11811224
mutex_unlock(&dpm_list_mtx);
11821225

1183-
error = device_suspend_late(dev, state);
1226+
error = device_suspend_late(dev);
11841227

11851228
mutex_lock(&dpm_list_mtx);
11861229
if (error) {
11871230
pm_dev_err(dev, state, " late", error);
1188-
suspend_stats.failed_suspend_late++;
1189-
dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
11901231
dpm_save_failed_dev(dev_name(dev));
11911232
put_device(dev);
11921233
break;
@@ -1195,17 +1236,18 @@ static int dpm_suspend_late(pm_message_t state)
11951236
list_move(&dev->power.entry, &dpm_late_early_list);
11961237
put_device(dev);
11971238

1198-
if (pm_wakeup_pending()) {
1199-
error = -EBUSY;
1239+
if (async_error)
12001240
break;
1201-
}
12021241
}
12031242
mutex_unlock(&dpm_list_mtx);
1204-
if (error)
1243+
async_synchronize_full();
1244+
if (error) {
1245+
suspend_stats.failed_suspend_late++;
1246+
dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
12051247
dpm_resume_early(resume_event(state));
1206-
else
1248+
} else {
12071249
dpm_show_time(starttime, state, "late");
1208-
1250+
}
12091251
return error;
12101252
}
12111253

0 commit comments

Comments
 (0)