cpuidle: Do not return from cpuidle_play_dead() on callback failures
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 15 Nov 2024 20:58:31 +0000 (21:58 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 19 Nov 2024 20:46:51 +0000 (21:46 +0100)
If the :enter_dead() idle state callback fails for a certain state,
there may be still a shallower state for which it will work.

Because the only caller of cpuidle_play_dead(), native_play_dead(),
falls back to hlt_play_dead() if it returns an error, it should
better try all of the idle states for which :enter_dead() is present
before failing, so change it accordingly.

Also notice that the :enter_dead() state callback is not expected
to return on success (the CPU should be "dead" then), so make
cpuidle_play_dead() ignore its return value.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Tested-by: Mario Limonciello <mario.limonciello@amd.com> # 6.12-rc7
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
Link: https://patch.msgid.link/3318440.aeNJFYEL58@rjwysocki.net
drivers/cpuidle/cpuidle.c

index 06ace16..0835da4 100644 (file)
@@ -69,11 +69,15 @@ int cpuidle_play_dead(void)
        if (!drv)
                return -ENODEV;
 
-       /* Find lowest-power state that supports long-term idle */
-       for (i = drv->state_count - 1; i >= 0; i--)
+       for (i = drv->state_count - 1; i >= 0; i--) {
                if (drv->states[i].enter_dead)
-                       return drv->states[i].enter_dead(dev, i);
+                       drv->states[i].enter_dead(dev, i);
+       }
 
+       /*
+        * If :enter_dead() is successful, it will never return, so reaching
+        * here means that all of them failed above or were not present.
+        */
        return -ENODEV;
 }