Thread (14 messages) 14 messages, 4 authors, 2018-02-15

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

From: Bo Yan <hidden>
Date: 2018-02-02 21:28:26
Also in: lkml

On 02/02/2018 11:34 AM, Saravana Kannan wrote:
On 02/02/2018 03:54 AM, Rafael J. Wysocki wrote:
quoted
On Wednesday, January 24, 2018 9:53:14 PM CET Bo Yan wrote:
quoted
On 01/23/2018 06:02 PM, Rafael J. Wysocki wrote:
quoted
On Tuesday, January 23, 2018 10:57:55 PM CET Bo Yan wrote:
quoted
   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.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help