Re: [PATCH] cpufreq: skip cpufreq resume if it's not suspended

From: Bo Yan
Date: Fri Feb 02 2018 - 16:28:29 EST


On 02/02/2018 11:34 AM, Saravana Kannan wrote:
On 02/02/2018 03:54 AM, Rafael J. Wysocki wrote:
On Wednesday, January 24, 2018 9:53:14 PM CET Bo Yan wrote:

On 01/23/2018 06:02 PM, Rafael J. Wysocki wrote:
On Tuesday, January 23, 2018 10:57:55 PM CET Bo Yan wrote:
ÂÂ drivers/cpufreq/cpufreq.c | 4 ++++
ÂÂ 1 file changed, 4 insertions(+)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 41d148af7748..95b1c4afe14e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1680,6 +1680,10 @@ void cpufreq_resume(void)
ÂÂÂÂÂÂ if (!cpufreq_driver)
ÂÂÂÂÂÂÂÂÂÂ return;

+ÂÂÂ if (unlikely(!cpufreq_suspended)) {
+ÂÂÂÂÂÂÂ pr_warn("%s: resume after failing suspend\n", __func__);
+ÂÂÂÂÂÂÂ return;
+ÂÂÂ }
ÂÂÂÂÂÂ cpufreq_suspended = false;

ÂÂÂÂÂÂ if (!has_target() && !cpufreq_driver->resume)

Good catch, but rather than doing this it would be better to avoid
calling cpufreq_resume() at all if cpufreq_suspend() has not been called.
Yes, I thought about that, but there is no good way to skip over it
without introducing another flag. cpufreq_resume is called by
dpm_resume, cpufreq_suspend is called by dpm_suspend. In the failure
case, dpm_resume is called, but dpm_suspend is not. So on a higher level
it's already unbalanced.

One possibility is to rely on the pm_transition flag. So something like:


diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index dc259d20c967..8469e6fc2b2c 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -842,6 +842,7 @@ static void async_resume(void *data, async_cookie_t
cookie)
ÂÂ void dpm_resume(pm_message_t state)
ÂÂ {
ÂÂÂÂÂÂÂÂÂ struct device *dev;
+ÂÂÂÂÂÂ bool suspended = (pm_transition.event != PM_EVENT_ON);
ÂÂÂÂÂÂÂÂÂ ktime_t starttime = ktime_get();

ÂÂÂÂÂÂÂÂÂ trace_suspend_resume(TPS("dpm_resume"), state.event, true);
@@ -885,7 +886,8 @@ void dpm_resume(pm_message_t state)
ÂÂÂÂÂÂÂÂÂ async_synchronize_full();
ÂÂÂÂÂÂÂÂÂ dpm_show_time(starttime, state, NULL);

-ÂÂÂÂÂÂ cpufreq_resume();
+ÂÂÂÂÂÂ if (likely(suspended))
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ cpufreq_resume();
ÂÂÂÂÂÂÂÂÂ trace_suspend_resume(TPS("dpm_resume"), state.event, false);
ÂÂ }

I was thinking about something else.

Anyway, I think your original patch is OK too, but without printing the
message. Just combine the cpufreq_suspended check with the cpufreq_driver
one and the unlikely() thing is not necessary.


I rather have this fixed in the dpm_suspend/resume() code. This is just masking the first issue that's being caused by unbalanced error handling. If that means adding flags in dpm_suspend/resume() then that's what we should do right now and clean it up later if it can be improved. Making cpufreq more messy doesn't seem like the right answer.

Thanks,
Saravana


dpm_suspend and dpm_resume by themselves are not balanced in this particular case. As it's currently structured, dpm_resume can't be omitted even if dpm_suspend is skipped due to earlier failure. I think checking cpufreq_suspended flag is a reasonable compromise. If we can find a way to make dpm_suspend/dpm_resume also balanced, that will be best.