[PATCH 15/20] cpuidle/powernv: Add support for POWER ISA v3 idle states
Ram Pai
linuxram at us.ibm.com
Tue Nov 29 18:35:23 AEDT 2016
Sorry. please ignore this email.
RP
On Mon, Nov 28, 2016 at 11:08:59PM -0800, linuxram at us.ibm.com wrote:
> From: Shreyas B. Prabhu <shreyas at linux.vnet.ibm.com>
>
> POWER ISA v3 defines a new idle processor core mechanism. In summary,
> a) new instruction named stop is added.
> b) new per thread SPR named PSSCR is added which controls the behavior
> of stop instruction.
>
> Supported idle states and value to be written to PSSCR register to enter
> any idle state is exposed via ibm,cpu-idle-state-names and
> ibm,cpu-idle-state-psscr respectively. To enter an idle state,
> platform provided power_stop() needs to be invoked with the appropriate
> PSSCR value.
>
> This patch adds support for this new mechanism in cpuidle powernv driver.
>
> Cc: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Lorenzo Pieralisi <Lorenzo.Pieralisi at arm.com>
> Cc: linux-pm at vger.kernel.org
> Cc: Michael Ellerman <mpe at ellerman.id.au>
> Cc: Paul Mackerras <paulus at ozlabs.org>
> Cc: linuxppc-dev at lists.ozlabs.org
> Reviewed-by: Gautham R. Shenoy <ego at linux.vnet.ibm.com>
> Signed-off-by: Shreyas B. Prabhu <shreyas at linux.vnet.ibm.com>
> Signed-off-by: Michael Ellerman <mpe at ellerman.id.au>
> Signed-off-by: Ram Pai <linuxram at us.ibm.com>
> (cherry-picked from 3005c597ba46480b42e1fea3512c408f1830b816)
> ---
> drivers/cpuidle/cpuidle-powernv.c | 61 +++++++++++++++++++++++++++++++++++++
> 1 files changed, 61 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
> index bdf8dae..cab1b4b 100644
> --- a/drivers/cpuidle/cpuidle-powernv.c
> +++ b/drivers/cpuidle/cpuidle-powernv.c
> @@ -20,6 +20,8 @@
> #include <asm/opal.h>
> #include <asm/runlatch.h>
>
> +#define POWERNV_THRESHOLD_LATENCY_NS 200000
> +
> struct cpuidle_driver powernv_idle_driver = {
> .name = "powernv_idle",
> .owner = THIS_MODULE,
> @@ -27,6 +29,9 @@ struct cpuidle_driver powernv_idle_driver = {
>
> static int max_idle_state;
> static struct cpuidle_state *cpuidle_state_table;
> +
> +static u64 stop_psscr_table[CPUIDLE_STATE_MAX];
> +
> static u64 snooze_timeout;
> static bool snooze_timeout_en;
>
> @@ -91,6 +96,17 @@ static int fastsleep_loop(struct cpuidle_device *dev,
> return index;
> }
> #endif
> +
> +static int stop_loop(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv,
> + int index)
> +{
> + ppc64_runlatch_off();
> + power9_idle_stop(stop_psscr_table[index]);
> + ppc64_runlatch_on();
> + return index;
> +}
> +
> /*
> * States for dedicated partition case.
> */
> @@ -170,6 +186,8 @@ static int powernv_add_idle_states(void)
> u32 latency_ns[CPUIDLE_STATE_MAX];
> u32 residency_ns[CPUIDLE_STATE_MAX];
> u32 flags[CPUIDLE_STATE_MAX];
> + u64 psscr_val[CPUIDLE_STATE_MAX];
> + const char *names[CPUIDLE_STATE_MAX];
> int i, rc;
>
> /* Currently we have snooze statically defined */
> @@ -208,12 +226,35 @@ static int powernv_add_idle_states(void)
> pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n");
> goto out;
> }
> + if (of_property_read_string_array(power_mgt,
> + "ibm,cpu-idle-state-names", names, dt_idle_states) < 0) {
> + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n");
> + goto out;
> + }
> +
> + /*
> + * If the idle states use stop instruction, probe for psscr values
> + * which are necessary to specify required stop level.
> + */
> + if (flags[0] & (OPAL_PM_STOP_INST_FAST | OPAL_PM_STOP_INST_DEEP))
> + if (of_property_read_u64_array(power_mgt,
> + "ibm,cpu-idle-state-psscr", psscr_val, dt_idle_states)) {
> + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-states-psscr in DT\n");
> + goto out;
> + }
>
> rc = of_property_read_u32_array(power_mgt,
> "ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states);
>
>
> for (i = 0; i < dt_idle_states; i++) {
> + /*
> + * If an idle state has exit latency beyond
> + * POWERNV_THRESHOLD_LATENCY_NS then don't use it
> + * in cpu-idle.
> + */
> + if (latency_ns[i] > POWERNV_THRESHOLD_LATENCY_NS)
> + continue;
>
> /*
> * Cpuidle accepts exit_latency and target_residency in us.
> @@ -226,6 +267,16 @@ static int powernv_add_idle_states(void)
> powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIME_VALID;
> powernv_states[nr_idle_states].target_residency = 100;
> powernv_states[nr_idle_states].enter = nap_loop;
> + } else if ((flags[i] & OPAL_PM_STOP_INST_FAST) &&
> + !(flags[i] & OPAL_PM_TIMEBASE_STOP)) {
> + strncpy(powernv_states[nr_idle_states].name,
> + names[i], CPUIDLE_NAME_LEN);
> + strncpy(powernv_states[nr_idle_states].desc,
> + names[i], CPUIDLE_NAME_LEN);
> + powernv_states[nr_idle_states].flags = 0;
> +
> + powernv_states[nr_idle_states].enter = stop_loop;
> + stop_psscr_table[nr_idle_states] = psscr_val[i];
> }
>
> /*
> @@ -242,6 +293,16 @@ static int powernv_add_idle_states(void)
> CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TIMER_STOP;
> powernv_states[nr_idle_states].target_residency = 300000;
> powernv_states[nr_idle_states].enter = fastsleep_loop;
> + } else if ((flags[i] & OPAL_PM_STOP_INST_DEEP) &&
> + (flags[i] & OPAL_PM_TIMEBASE_STOP)) {
> + strncpy(powernv_states[nr_idle_states].name,
> + names[i], CPUIDLE_NAME_LEN);
> + strncpy(powernv_states[nr_idle_states].desc,
> + names[i], CPUIDLE_NAME_LEN);
> +
> + powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
> + powernv_states[nr_idle_states].enter = stop_loop;
> + stop_psscr_table[nr_idle_states] = psscr_val[i];
> }
> #endif
> powernv_states[nr_idle_states].exit_latency =
> --
> 1.7.1
--
Ram Pai
More information about the Linuxppc-dev
mailing list