@@ -469,7 +469,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
469
469
* The driver of @dev will not receive interrupts while this function is being
470
470
* executed.
471
471
*/
472
- static int device_resume_noirq (struct device * dev , pm_message_t state )
472
+ static int device_resume_noirq (struct device * dev , pm_message_t state , bool async )
473
473
{
474
474
pm_callback_t callback = NULL ;
475
475
char * info = NULL ;
@@ -484,6 +484,8 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
484
484
if (!dev -> power .is_noirq_suspended )
485
485
goto Out ;
486
486
487
+ dpm_wait (dev -> parent , async );
488
+
487
489
if (dev -> pm_domain ) {
488
490
info = "noirq power domain " ;
489
491
callback = pm_noirq_op (& dev -> pm_domain -> ops , state );
@@ -507,10 +509,29 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
507
509
dev -> power .is_noirq_suspended = false;
508
510
509
511
Out :
512
+ complete_all (& dev -> power .completion );
510
513
TRACE_RESUME (error );
511
514
return error ;
512
515
}
513
516
517
+ static bool is_async (struct device * dev )
518
+ {
519
+ return dev -> power .async_suspend && pm_async_enabled
520
+ && !pm_trace_is_enabled ();
521
+ }
522
+
523
+ static void async_resume_noirq (void * data , async_cookie_t cookie )
524
+ {
525
+ struct device * dev = (struct device * )data ;
526
+ int error ;
527
+
528
+ error = device_resume_noirq (dev , pm_transition , true);
529
+ if (error )
530
+ pm_dev_err (dev , pm_transition , " async" , error );
531
+
532
+ put_device (dev );
533
+ }
534
+
514
535
/**
515
536
* dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
516
537
* @state: PM transition of the system being carried out.
@@ -520,29 +541,48 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
520
541
*/
521
542
static void dpm_resume_noirq (pm_message_t state )
522
543
{
544
+ struct device * dev ;
523
545
ktime_t starttime = ktime_get ();
524
546
525
547
mutex_lock (& dpm_list_mtx );
526
- while (!list_empty (& dpm_noirq_list )) {
527
- struct device * dev = to_device (dpm_noirq_list .next );
528
- int error ;
548
+ pm_transition = state ;
549
+
550
+ /*
551
+ * Advanced the async threads upfront,
552
+ * in case the starting of async threads is
553
+ * delayed by non-async resuming devices.
554
+ */
555
+ list_for_each_entry (dev , & dpm_noirq_list , power .entry ) {
556
+ reinit_completion (& dev -> power .completion );
557
+ if (is_async (dev )) {
558
+ get_device (dev );
559
+ async_schedule (async_resume_noirq , dev );
560
+ }
561
+ }
529
562
563
+ while (!list_empty (& dpm_noirq_list )) {
564
+ dev = to_device (dpm_noirq_list .next );
530
565
get_device (dev );
531
566
list_move_tail (& dev -> power .entry , & dpm_late_early_list );
532
567
mutex_unlock (& dpm_list_mtx );
533
568
534
- error = device_resume_noirq (dev , state );
535
- if (error ) {
536
- suspend_stats .failed_resume_noirq ++ ;
537
- dpm_save_failed_step (SUSPEND_RESUME_NOIRQ );
538
- dpm_save_failed_dev (dev_name (dev ));
539
- pm_dev_err (dev , state , " noirq" , error );
569
+ if (!is_async (dev )) {
570
+ int error ;
571
+
572
+ error = device_resume_noirq (dev , state , false);
573
+ if (error ) {
574
+ suspend_stats .failed_resume_noirq ++ ;
575
+ dpm_save_failed_step (SUSPEND_RESUME_NOIRQ );
576
+ dpm_save_failed_dev (dev_name (dev ));
577
+ pm_dev_err (dev , state , " noirq" , error );
578
+ }
540
579
}
541
580
542
581
mutex_lock (& dpm_list_mtx );
543
582
put_device (dev );
544
583
}
545
584
mutex_unlock (& dpm_list_mtx );
585
+ async_synchronize_full ();
546
586
dpm_show_time (starttime , state , "noirq" );
547
587
resume_device_irqs ();
548
588
cpuidle_resume ();
@@ -742,12 +782,6 @@ static void async_resume(void *data, async_cookie_t cookie)
742
782
put_device (dev );
743
783
}
744
784
745
- static bool is_async (struct device * dev )
746
- {
747
- return dev -> power .async_suspend && pm_async_enabled
748
- && !pm_trace_is_enabled ();
749
- }
750
-
751
785
/**
752
786
* dpm_resume - Execute "resume" callbacks for non-sysdev devices.
753
787
* @state: PM transition of the system being carried out.
0 commit comments