Commit 9c4b2867 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

cpuidle: menu: Fix menu_select() for CPUIDLE_DRIVER_STATE_START == 0

Commit a9ceb78b (cpuidle,menu: use interactivity_req to disable
polling) exposed a bug in menu_select() causing it to return -1
on systems with CPUIDLE_DRIVER_STATE_START equal to zero, although
it should have returned 0.  As a result, idle states are not entered
by CPUs on those systems.

Namely, on the systems in question data->last_state_idx is initially
equal to -1 and the above commit modified the condition that would
have caused it to be changed to 0 to be less likely to trigger which
exposed the problem.  However, setting data->last_state_idx initially
to -1 doesn't make sense at all and on the affected systems it should
always be set to CPUIDLE_DRIVER_STATE_START (ie. 0) unconditionally,
so make that happen.

Fixes: a9ceb78b (cpuidle,menu: use interactivity_req to disable polling)
Reported-and-tested-by: default avatarSudeep Holla <sudeep.holla@arm.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 84599238
...@@ -294,8 +294,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) ...@@ -294,8 +294,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
data->needs_update = 0; data->needs_update = 0;
} }
data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1;
/* Special case when user has set very strict latency requirement */ /* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0)) if (unlikely(latency_req == 0))
return 0; return 0;
...@@ -326,6 +324,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) ...@@ -326,6 +324,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
if (latency_req > interactivity_req) if (latency_req > interactivity_req)
latency_req = interactivity_req; latency_req = interactivity_req;
if (CPUIDLE_DRIVER_STATE_START > 0) {
data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1;
/* /*
* We want to default to C1 (hlt), not to busy polling * We want to default to C1 (hlt), not to busy polling
* unless the timer is happening really really soon. * unless the timer is happening really really soon.
...@@ -334,6 +334,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) ...@@ -334,6 +334,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
!drv->states[CPUIDLE_DRIVER_STATE_START].disabled && !drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
data->last_state_idx = CPUIDLE_DRIVER_STATE_START; data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
} else {
data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
}
/* /*
* Find the idle state with the lowest power while satisfying * Find the idle state with the lowest power while satisfying
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment