@@ -711,6 +711,7 @@ static void dpm_noirq_resume_devices(pm_message_t state)
711711 dev = to_device (dpm_noirq_list .next );
712712 get_device (dev );
713713 list_move_tail (& dev -> power .entry , & dpm_late_early_list );
714+
714715 mutex_unlock (& dpm_list_mtx );
715716
716717 if (!is_async (dev )) {
@@ -725,8 +726,9 @@ static void dpm_noirq_resume_devices(pm_message_t state)
725726 }
726727 }
727728
728- mutex_lock (& dpm_list_mtx );
729729 put_device (dev );
730+
731+ mutex_lock (& dpm_list_mtx );
730732 }
731733 mutex_unlock (& dpm_list_mtx );
732734 async_synchronize_full ();
@@ -852,6 +854,7 @@ void dpm_resume_early(pm_message_t state)
852854 dev = to_device (dpm_late_early_list .next );
853855 get_device (dev );
854856 list_move_tail (& dev -> power .entry , & dpm_suspended_list );
857+
855858 mutex_unlock (& dpm_list_mtx );
856859
857860 if (!is_async (dev )) {
@@ -865,8 +868,10 @@ void dpm_resume_early(pm_message_t state)
865868 pm_dev_err (dev , state , " early" , error );
866869 }
867870 }
868- mutex_lock ( & dpm_list_mtx );
871+
869872 put_device (dev );
873+
874+ mutex_lock (& dpm_list_mtx );
870875 }
871876 mutex_unlock (& dpm_list_mtx );
872877 async_synchronize_full ();
@@ -1029,7 +1034,12 @@ void dpm_resume(pm_message_t state)
10291034 }
10301035 if (!list_empty (& dev -> power .entry ))
10311036 list_move_tail (& dev -> power .entry , & dpm_prepared_list );
1037+
1038+ mutex_unlock (& dpm_list_mtx );
1039+
10321040 put_device (dev );
1041+
1042+ mutex_lock (& dpm_list_mtx );
10331043 }
10341044 mutex_unlock (& dpm_list_mtx );
10351045 async_synchronize_full ();
@@ -1107,14 +1117,16 @@ void dpm_complete(pm_message_t state)
11071117 get_device (dev );
11081118 dev -> power .is_prepared = false;
11091119 list_move (& dev -> power .entry , & list );
1120+
11101121 mutex_unlock (& dpm_list_mtx );
11111122
11121123 trace_device_pm_callback_start (dev , "" , state .event );
11131124 device_complete (dev , state );
11141125 trace_device_pm_callback_end (dev , 0 );
11151126
1116- mutex_lock (& dpm_list_mtx );
11171127 put_device (dev );
1128+
1129+ mutex_lock (& dpm_list_mtx );
11181130 }
11191131 list_splice (& list , & dpm_list );
11201132 mutex_unlock (& dpm_list_mtx );
@@ -1299,17 +1311,21 @@ static int dpm_noirq_suspend_devices(pm_message_t state)
12991311 error = device_suspend_noirq (dev );
13001312
13011313 mutex_lock (& dpm_list_mtx );
1314+
13021315 if (error ) {
13031316 pm_dev_err (dev , state , " noirq" , error );
13041317 dpm_save_failed_dev (dev_name (dev ));
1305- put_device (dev );
1306- break ;
1307- }
1308- if (!list_empty (& dev -> power .entry ))
1318+ } else if (!list_empty (& dev -> power .entry )) {
13091319 list_move (& dev -> power .entry , & dpm_noirq_list );
1320+ }
1321+
1322+ mutex_unlock (& dpm_list_mtx );
1323+
13101324 put_device (dev );
13111325
1312- if (async_error )
1326+ mutex_lock (& dpm_list_mtx );
1327+
1328+ if (error || async_error )
13131329 break ;
13141330 }
13151331 mutex_unlock (& dpm_list_mtx );
@@ -1476,23 +1492,28 @@ int dpm_suspend_late(pm_message_t state)
14761492 struct device * dev = to_device (dpm_suspended_list .prev );
14771493
14781494 get_device (dev );
1495+
14791496 mutex_unlock (& dpm_list_mtx );
14801497
14811498 error = device_suspend_late (dev );
14821499
14831500 mutex_lock (& dpm_list_mtx );
1501+
14841502 if (!list_empty (& dev -> power .entry ))
14851503 list_move (& dev -> power .entry , & dpm_late_early_list );
14861504
14871505 if (error ) {
14881506 pm_dev_err (dev , state , " late" , error );
14891507 dpm_save_failed_dev (dev_name (dev ));
1490- put_device (dev );
1491- break ;
14921508 }
1509+
1510+ mutex_unlock (& dpm_list_mtx );
1511+
14931512 put_device (dev );
14941513
1495- if (async_error )
1514+ mutex_lock (& dpm_list_mtx );
1515+
1516+ if (error || async_error )
14961517 break ;
14971518 }
14981519 mutex_unlock (& dpm_list_mtx );
@@ -1752,21 +1773,27 @@ int dpm_suspend(pm_message_t state)
17521773 struct device * dev = to_device (dpm_prepared_list .prev );
17531774
17541775 get_device (dev );
1776+
17551777 mutex_unlock (& dpm_list_mtx );
17561778
17571779 error = device_suspend (dev );
17581780
17591781 mutex_lock (& dpm_list_mtx );
1782+
17601783 if (error ) {
17611784 pm_dev_err (dev , state , "" , error );
17621785 dpm_save_failed_dev (dev_name (dev ));
1763- put_device (dev );
1764- break ;
1765- }
1766- if (!list_empty (& dev -> power .entry ))
1786+ } else if (!list_empty (& dev -> power .entry )) {
17671787 list_move (& dev -> power .entry , & dpm_suspended_list );
1788+ }
1789+
1790+ mutex_unlock (& dpm_list_mtx );
1791+
17681792 put_device (dev );
1769- if (async_error )
1793+
1794+ mutex_lock (& dpm_list_mtx );
1795+
1796+ if (error || async_error )
17701797 break ;
17711798 }
17721799 mutex_unlock (& dpm_list_mtx );
@@ -1883,28 +1910,31 @@ int dpm_prepare(pm_message_t state)
18831910 struct device * dev = to_device (dpm_list .next );
18841911
18851912 get_device (dev );
1913+
18861914 mutex_unlock (& dpm_list_mtx );
18871915
18881916 trace_device_pm_callback_start (dev , "" , state .event );
18891917 error = device_prepare (dev , state );
18901918 trace_device_pm_callback_end (dev , error );
18911919
18921920 mutex_lock (& dpm_list_mtx );
1893- if (error ) {
1894- if (error == - EAGAIN ) {
1895- put_device (dev );
1896- error = 0 ;
1897- continue ;
1898- }
1921+
1922+ if (!error ) {
1923+ dev -> power .is_prepared = true;
1924+ if (!list_empty (& dev -> power .entry ))
1925+ list_move_tail (& dev -> power .entry , & dpm_prepared_list );
1926+ } else if (error == - EAGAIN ) {
1927+ error = 0 ;
1928+ } else {
18991929 dev_info (dev , "not prepared for power transition: code %d\n" ,
19001930 error );
1901- put_device (dev );
1902- break ;
19031931 }
1904- dev -> power . is_prepared = true;
1905- if (! list_empty ( & dev -> power . entry ))
1906- list_move_tail ( & dev -> power . entry , & dpm_prepared_list );
1932+
1933+ mutex_unlock ( & dpm_list_mtx );
1934+
19071935 put_device (dev );
1936+
1937+ mutex_lock (& dpm_list_mtx );
19081938 }
19091939 mutex_unlock (& dpm_list_mtx );
19101940 trace_suspend_resume (TPS ("dpm_prepare" ), state .event , false);
0 commit comments