Skip to content

Commit 4add3e7

Browse files
committed
PM: sleep: stats: Call dpm_save_failed_step() at most once per phase
If the handling of two or more devices fails in one suspend-resume phase, it should be counted once in the statistics which is not guaranteed to happen during system-wide resume of devices due to the possible asynchronous execution of device callbacks. Address this by using the async_error static variable during system-wide device resume to indicate that there has been a device resume error and the given suspend-resume phase should be counted as failing. Signed-off-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Stanislaw Gruszka <[email protected]> Reviewed-by: Ulf Hansson <[email protected]>
1 parent 9ff544f commit 4add3e7

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

drivers/base/power/main.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ static void device_resume_noirq(struct device *dev, pm_message_t state, bool asy
685685
TRACE_RESUME(error);
686686

687687
if (error) {
688-
dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
688+
async_error = error;
689689
dpm_save_failed_dev(dev_name(dev));
690690
pm_dev_err(dev, state, async ? " async noirq" : " noirq", error);
691691
}
@@ -705,6 +705,9 @@ static void dpm_noirq_resume_devices(pm_message_t state)
705705
ktime_t starttime = ktime_get();
706706

707707
trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, true);
708+
709+
async_error = 0;
710+
708711
mutex_lock(&dpm_list_mtx);
709712
pm_transition = state;
710713

@@ -734,6 +737,9 @@ static void dpm_noirq_resume_devices(pm_message_t state)
734737
mutex_unlock(&dpm_list_mtx);
735738
async_synchronize_full();
736739
dpm_show_time(starttime, state, 0, "noirq");
740+
if (async_error)
741+
dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
742+
737743
trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
738744
}
739745

@@ -815,7 +821,7 @@ static void device_resume_early(struct device *dev, pm_message_t state, bool asy
815821
complete_all(&dev->power.completion);
816822

817823
if (error) {
818-
dpm_save_failed_step(SUSPEND_RESUME_EARLY);
824+
async_error = error;
819825
dpm_save_failed_dev(dev_name(dev));
820826
pm_dev_err(dev, state, async ? " async early" : " early", error);
821827
}
@@ -839,6 +845,9 @@ void dpm_resume_early(pm_message_t state)
839845
ktime_t starttime = ktime_get();
840846

841847
trace_suspend_resume(TPS("dpm_resume_early"), state.event, true);
848+
849+
async_error = 0;
850+
842851
mutex_lock(&dpm_list_mtx);
843852
pm_transition = state;
844853

@@ -868,6 +877,9 @@ void dpm_resume_early(pm_message_t state)
868877
mutex_unlock(&dpm_list_mtx);
869878
async_synchronize_full();
870879
dpm_show_time(starttime, state, 0, "early");
880+
if (async_error)
881+
dpm_save_failed_step(SUSPEND_RESUME_EARLY);
882+
871883
trace_suspend_resume(TPS("dpm_resume_early"), state.event, false);
872884
}
873885

@@ -971,7 +983,7 @@ static void device_resume(struct device *dev, pm_message_t state, bool async)
971983
TRACE_RESUME(error);
972984

973985
if (error) {
974-
dpm_save_failed_step(SUSPEND_RESUME);
986+
async_error = error;
975987
dpm_save_failed_dev(dev_name(dev));
976988
pm_dev_err(dev, state, async ? " async" : "", error);
977989
}
@@ -1030,6 +1042,8 @@ void dpm_resume(pm_message_t state)
10301042
mutex_unlock(&dpm_list_mtx);
10311043
async_synchronize_full();
10321044
dpm_show_time(starttime, state, 0, NULL);
1045+
if (async_error)
1046+
dpm_save_failed_step(SUSPEND_RESUME);
10331047

10341048
cpufreq_resume();
10351049
devfreq_resume();

0 commit comments

Comments
 (0)