summaryrefslogtreecommitdiff
path: root/drivers/cpuidle/cpuidle-powernv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle/cpuidle-powernv.c')
-rw-r--r--drivers/cpuidle/cpuidle-powernv.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 59372077ec7c..845bafcfa792 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -29,18 +29,25 @@ struct cpuidle_driver powernv_idle_driver = {
static int max_idle_state;
static struct cpuidle_state *cpuidle_state_table;
+static u64 snooze_timeout;
+static bool snooze_timeout_en;
static int snooze_loop(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
+ u64 snooze_exit_time;
+
local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
+ snooze_exit_time = get_tb() + snooze_timeout;
ppc64_runlatch_off();
while (!need_resched()) {
HMT_low();
HMT_very_low();
+ if (snooze_timeout_en && get_tb() > snooze_exit_time)
+ break;
}
HMT_medium();
@@ -60,6 +67,8 @@ static int nap_loop(struct cpuidle_device *dev,
return index;
}
+/* Register for fastsleep only in oneshot mode of broadcast */
+#ifdef CONFIG_TICK_ONESHOT
static int fastsleep_loop(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
@@ -83,7 +92,7 @@ static int fastsleep_loop(struct cpuidle_device *dev,
return index;
}
-
+#endif
/*
* States for dedicated partition case.
*/
@@ -209,7 +218,14 @@ static int powernv_add_idle_states(void)
powernv_states[nr_idle_states].flags = 0;
powernv_states[nr_idle_states].target_residency = 100;
powernv_states[nr_idle_states].enter = &nap_loop;
- } else if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
+ }
+
+ /*
+ * All cpuidle states with CPUIDLE_FLAG_TIMER_STOP set must come
+ * within this config dependency check.
+ */
+#ifdef CONFIG_TICK_ONESHOT
+ if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) {
/* Add FASTSLEEP state */
strcpy(powernv_states[nr_idle_states].name, "FastSleep");
@@ -218,7 +234,7 @@ static int powernv_add_idle_states(void)
powernv_states[nr_idle_states].target_residency = 300000;
powernv_states[nr_idle_states].enter = &fastsleep_loop;
}
-
+#endif
powernv_states[nr_idle_states].exit_latency =
((unsigned int)latency_ns[i]) / 1000;
@@ -252,6 +268,11 @@ static int powernv_idle_probe(void)
cpuidle_state_table = powernv_states;
/* Device tree can indicate more idle states */
max_idle_state = powernv_add_idle_states();
+ if (max_idle_state > 1) {
+ snooze_timeout_en = true;
+ snooze_timeout = powernv_states[1].target_residency *
+ tb_ticks_per_usec;
+ }
} else
return -ENODEV;