@@ -1127,16 +1127,26 @@ static int dpm_suspend_noirq(pm_message_t state)
1127
1127
*
1128
1128
* Runtime PM is disabled for @dev while this function is being executed.
1129
1129
*/
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 )
1131
1131
{
1132
1132
pm_callback_t callback = NULL ;
1133
1133
char * info = NULL ;
1134
- int error ;
1134
+ int error = 0 ;
1135
1135
1136
1136
__pm_runtime_disable (dev , false);
1137
1137
1138
+ if (async_error )
1139
+ goto Complete ;
1140
+
1141
+ if (pm_wakeup_pending ()) {
1142
+ async_error = - EBUSY ;
1143
+ goto Complete ;
1144
+ }
1145
+
1138
1146
if (dev -> power .syscore )
1139
- return 0 ;
1147
+ goto Complete ;
1148
+
1149
+ dpm_wait_for_children (dev , async );
1140
1150
1141
1151
if (dev -> pm_domain ) {
1142
1152
info = "late power domain " ;
@@ -1160,10 +1170,40 @@ static int device_suspend_late(struct device *dev, pm_message_t state)
1160
1170
error = dpm_run_callback (callback , dev , state , info );
1161
1171
if (!error )
1162
1172
dev -> power .is_late_suspended = true;
1173
+ else
1174
+ async_error = error ;
1163
1175
1176
+ Complete :
1177
+ complete_all (& dev -> power .completion );
1164
1178
return error ;
1165
1179
}
1166
1180
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
+
1167
1207
/**
1168
1208
* dpm_suspend_late - Execute "late suspend" callbacks for all devices.
1169
1209
* @state: PM transition of the system being carried out.
@@ -1174,19 +1214,20 @@ static int dpm_suspend_late(pm_message_t state)
1174
1214
int error = 0 ;
1175
1215
1176
1216
mutex_lock (& dpm_list_mtx );
1217
+ pm_transition = state ;
1218
+ async_error = 0 ;
1219
+
1177
1220
while (!list_empty (& dpm_suspended_list )) {
1178
1221
struct device * dev = to_device (dpm_suspended_list .prev );
1179
1222
1180
1223
get_device (dev );
1181
1224
mutex_unlock (& dpm_list_mtx );
1182
1225
1183
- error = device_suspend_late (dev , state );
1226
+ error = device_suspend_late (dev );
1184
1227
1185
1228
mutex_lock (& dpm_list_mtx );
1186
1229
if (error ) {
1187
1230
pm_dev_err (dev , state , " late" , error );
1188
- suspend_stats .failed_suspend_late ++ ;
1189
- dpm_save_failed_step (SUSPEND_SUSPEND_LATE );
1190
1231
dpm_save_failed_dev (dev_name (dev ));
1191
1232
put_device (dev );
1192
1233
break ;
@@ -1195,17 +1236,18 @@ static int dpm_suspend_late(pm_message_t state)
1195
1236
list_move (& dev -> power .entry , & dpm_late_early_list );
1196
1237
put_device (dev );
1197
1238
1198
- if (pm_wakeup_pending ()) {
1199
- error = - EBUSY ;
1239
+ if (async_error )
1200
1240
break ;
1201
- }
1202
1241
}
1203
1242
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 );
1205
1247
dpm_resume_early (resume_event (state ));
1206
- else
1248
+ } else {
1207
1249
dpm_show_time (starttime , state , "late" );
1208
-
1250
+ }
1209
1251
return error ;
1210
1252
}
1211
1253
0 commit comments