Commit 5ddcc03a authored by Aboorva Devarajan's avatar Aboorva Devarajan Committed by Michael Ellerman

powerpc/cpuidle: Set CPUIDLE_FLAG_POLLING for snooze state

During the comparative study of cpuidle governors, it is noticed that the
menu governor does not select CEDE state in some scenarios even though when
the sleep duration of the CPU exceeds the target residency of the CEDE idle
state this is because the CPU exits the snooze "polling" state when snooze
time limit is reached in the snooze_loop(), which is not a real wake up
and it just means that the polling state selection was not adequate.

cpuidle governors rely on CPUIDLE_FLAG_POLLING flag to be set for the
polling states to handle the condition mentioned above.

Hence, set the CPUIDLE_FLAG_POLLING flag for snooze state (polling state)
in powerpc arch to make the cpuidle governor work as expected.

Reference Commits:

- Timeout enabled for snooze state:
  commit 78eaa10f
  ("cpuidle: powernv/pseries: Auto-promotion of snooze to deeper idle state")

- commit dc2251bf
  ("cpuidle: Eliminate the CPUIDLE_DRIVER_STATE_START symbol")

- Fix wakeup stats in governor for polling states
  commit 5f26bdce
  ("cpuidle: menu: Fix wakeup statistics updates for polling state")
Signed-off-by: default avatarAboorva Devarajan <aboorvad@linux.vnet.ibm.com>
Tested-by: default avatarVishal Chourasia <vishalc@linux.vnet.ibm.com>
Reviewed-by: default avatarVaidyanathan Srinivasan <svaidy@linux.ibm.com>
Reviewed-by: default avatarVishal Chourasia <vishalc@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20221114145611.37669-1-aboorvad@linux.vnet.ibm.com
parent 3ae7c96d
...@@ -76,6 +76,7 @@ static int snooze_loop(struct cpuidle_device *dev, ...@@ -76,6 +76,7 @@ static int snooze_loop(struct cpuidle_device *dev,
local_irq_enable(); local_irq_enable();
snooze_exit_time = get_tb() + get_snooze_timeout(dev, drv, index); snooze_exit_time = get_tb() + get_snooze_timeout(dev, drv, index);
dev->poll_time_limit = false;
ppc64_runlatch_off(); ppc64_runlatch_off();
HMT_very_low(); HMT_very_low();
while (!need_resched()) { while (!need_resched()) {
...@@ -86,6 +87,7 @@ static int snooze_loop(struct cpuidle_device *dev, ...@@ -86,6 +87,7 @@ static int snooze_loop(struct cpuidle_device *dev,
* cleared to order subsequent test of need_resched(). * cleared to order subsequent test of need_resched().
*/ */
clear_thread_flag(TIF_POLLING_NRFLAG); clear_thread_flag(TIF_POLLING_NRFLAG);
dev->poll_time_limit = true;
smp_mb(); smp_mb();
break; break;
} }
...@@ -155,7 +157,8 @@ static struct cpuidle_state powernv_states[CPUIDLE_STATE_MAX] = { ...@@ -155,7 +157,8 @@ static struct cpuidle_state powernv_states[CPUIDLE_STATE_MAX] = {
.desc = "snooze", .desc = "snooze",
.exit_latency = 0, .exit_latency = 0,
.target_residency = 0, .target_residency = 0,
.enter = snooze_loop }, .enter = snooze_loop,
.flags = CPUIDLE_FLAG_POLLING },
}; };
static int powernv_cpuidle_cpu_online(unsigned int cpu) static int powernv_cpuidle_cpu_online(unsigned int cpu)
......
...@@ -44,6 +44,7 @@ static int snooze_loop(struct cpuidle_device *dev, ...@@ -44,6 +44,7 @@ static int snooze_loop(struct cpuidle_device *dev,
pseries_idle_prolog(); pseries_idle_prolog();
local_irq_enable(); local_irq_enable();
snooze_exit_time = get_tb() + snooze_timeout; snooze_exit_time = get_tb() + snooze_timeout;
dev->poll_time_limit = false;
while (!need_resched()) { while (!need_resched()) {
HMT_low(); HMT_low();
...@@ -54,6 +55,7 @@ static int snooze_loop(struct cpuidle_device *dev, ...@@ -54,6 +55,7 @@ static int snooze_loop(struct cpuidle_device *dev,
* loop anyway. Require a barrier after polling is * loop anyway. Require a barrier after polling is
* cleared to order subsequent test of need_resched(). * cleared to order subsequent test of need_resched().
*/ */
dev->poll_time_limit = true;
clear_thread_flag(TIF_POLLING_NRFLAG); clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb(); smp_mb();
break; break;
...@@ -268,7 +270,8 @@ static struct cpuidle_state dedicated_states[NR_DEDICATED_STATES] = { ...@@ -268,7 +270,8 @@ static struct cpuidle_state dedicated_states[NR_DEDICATED_STATES] = {
.desc = "snooze", .desc = "snooze",
.exit_latency = 0, .exit_latency = 0,
.target_residency = 0, .target_residency = 0,
.enter = &snooze_loop }, .enter = &snooze_loop,
.flags = CPUIDLE_FLAG_POLLING },
{ /* CEDE */ { /* CEDE */
.name = "CEDE", .name = "CEDE",
.desc = "CEDE", .desc = "CEDE",
...@@ -286,7 +289,8 @@ static struct cpuidle_state shared_states[] = { ...@@ -286,7 +289,8 @@ static struct cpuidle_state shared_states[] = {
.desc = "snooze", .desc = "snooze",
.exit_latency = 0, .exit_latency = 0,
.target_residency = 0, .target_residency = 0,
.enter = &snooze_loop }, .enter = &snooze_loop,
.flags = CPUIDLE_FLAG_POLLING },
{ /* Shared Cede */ { /* Shared Cede */
.name = "Shared Cede", .name = "Shared Cede",
.desc = "Shared Cede", .desc = "Shared Cede",
......
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