Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e9fc6f0 authored by Gautham R. Shenoy's avatar Gautham R. Shenoy Committed by Michael Ellerman
Browse files

cpuidle:powernv: Add helper function to populate powernv idle states.



In the current code for powernv_add_idle_states, there is a lot of code
duplication while initializing an idle state in powernv_states table.

Add an inline helper function to populate the powernv_states[] table
for a given idle state. Invoke this for populating the "Nap",
"Fastsleep" and the stop states in powernv_add_idle_states.

Signed-off-by: default avatarGautham R. Shenoy <ego@linux.vnet.ibm.com>
Acked-by: default avatarBalbir Singh <bsingharora@gmail.com>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent dd34c74c
Loading
Loading
Loading
Loading
+53 −36
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@
#include <asm/opal.h>
#include <asm/runlatch.h>

/*
 * Expose only those Hardware idle states via the cpuidle framework
 * that have latency value below POWERNV_THRESHOLD_LATENCY_NS.
 */
#define POWERNV_THRESHOLD_LATENCY_NS 200000

static struct cpuidle_driver powernv_idle_driver = {
@@ -167,6 +171,24 @@ static int powernv_cpuidle_driver_init(void)
	return 0;
}

static inline void add_powernv_state(int index, const char *name,
				     unsigned int flags,
				     int (*idle_fn)(struct cpuidle_device *,
						    struct cpuidle_driver *,
						    int),
				     unsigned int target_residency,
				     unsigned int exit_latency,
				     u64 psscr_val)
{
	strlcpy(powernv_states[index].name, name, CPUIDLE_NAME_LEN);
	strlcpy(powernv_states[index].desc, name, CPUIDLE_NAME_LEN);
	powernv_states[index].flags = flags;
	powernv_states[index].target_residency = target_residency;
	powernv_states[index].exit_latency = exit_latency;
	powernv_states[index].enter = idle_fn;
	stop_psscr_table[index] = psscr_val;
}

static int powernv_add_idle_states(void)
{
	struct device_node *power_mgt;
@@ -236,6 +258,7 @@ static int powernv_add_idle_states(void)
		"ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states);

	for (i = 0; i < dt_idle_states; i++) {
		unsigned int exit_latency, target_residency;
		/*
		 * If an idle state has exit latency beyond
		 * POWERNV_THRESHOLD_LATENCY_NS then don't use it
@@ -243,28 +266,33 @@ static int powernv_add_idle_states(void)
		 */
		if (latency_ns[i] > POWERNV_THRESHOLD_LATENCY_NS)
			continue;
		/*
		 * Firmware passes residency and latency values in ns.
		 * cpuidle expects it in us.
		 */
		exit_latency = latency_ns[i] / 1000;
		if (!rc)
			target_residency = residency_ns[i] / 1000;
		else
			target_residency = 0;

		/*
		 * Cpuidle accepts exit_latency and target_residency in us.
		 * Use default target_residency values if f/w does not expose it.
		 * For nap and fastsleep, use default target_residency
		 * values if f/w does not expose it.
		 */
		if (flags[i] & OPAL_PM_NAP_ENABLED) {
			if (!rc)
				target_residency = 100;
			/* Add NAP state */
			strcpy(powernv_states[nr_idle_states].name, "Nap");
			strcpy(powernv_states[nr_idle_states].desc, "Nap");
			powernv_states[nr_idle_states].flags = 0;
			powernv_states[nr_idle_states].target_residency = 100;
			powernv_states[nr_idle_states].enter = nap_loop;
			add_powernv_state(nr_idle_states, "Nap",
					  CPUIDLE_FLAG_NONE, nap_loop,
					  target_residency, exit_latency, 0);
		} 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];
			add_powernv_state(nr_idle_states, names[i],
					  CPUIDLE_FLAG_NONE, stop_loop,
					  target_residency, exit_latency,
					  psscr_val[i]);
		}

		/*
@@ -274,32 +302,21 @@ static int powernv_add_idle_states(void)
#ifdef CONFIG_TICK_ONESHOT
		if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
			flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) {
			if (!rc)
				target_residency = 300000;
			/* Add FASTSLEEP state */
			strcpy(powernv_states[nr_idle_states].name, "FastSleep");
			strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
			powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
			powernv_states[nr_idle_states].target_residency = 300000;
			powernv_states[nr_idle_states].enter = fastsleep_loop;
			add_powernv_state(nr_idle_states, "FastSleep",
					  CPUIDLE_FLAG_TIMER_STOP,
					  fastsleep_loop,
					  target_residency, exit_latency, 0);
		} 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];
			add_powernv_state(nr_idle_states, names[i],
					  CPUIDLE_FLAG_TIMER_STOP, stop_loop,
					  target_residency, exit_latency,
					  psscr_val[i]);
		}
#endif
		powernv_states[nr_idle_states].exit_latency =
				((unsigned int)latency_ns[i]) / 1000;

		if (!rc) {
			powernv_states[nr_idle_states].target_residency =
				((unsigned int)residency_ns[i]) / 1000;
		}

		nr_idle_states++;
	}
out:
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct cpuidle_state {
};

/* Idle State Flags */
#define CPUIDLE_FLAG_NONE       (0x00)
#define CPUIDLE_FLAG_COUPLED	(0x02) /* state applies to multiple cpus */
#define CPUIDLE_FLAG_TIMER_STOP (0x04)  /* timer is stopped on this state */