Re: [PATCH v6 10/11] cpuidle/powernv: Add support for POWER ISA v3 idle states
From: Benjamin Herrenschmidt <hidden>
Date: 2016-06-13 21:48:56
Also in:
linux-pm, lkml
On Wed, 2016-06-08 at 11:54 -0500, Shreyas B. Prabhu wrote:
quoted hunk ↗ jump to hunk
/* * States for dedicated partition case. */@@ -167,6 +183,8 @@ static int powernv_add_idle_states(void)int nr_idle_states = 1; /* Snooze */ int dt_idle_states; u32 *latency_ns, *residency_ns, *flags; + u64 *psscr_val = NULL; + const char *names[CPUIDLE_STATE_MAX]; int i, rc; /* Currently we have snooze statically defined */@@ -199,12 +217,41 @@ static int powernv_add_idle_states(void)goto out_free_latency; } + rc = of_property_read_string_array(power_mgt, + "ibm,cpu-idle-state-names", names, + dt_idle_states);
Ok so from this I assume that dt_idle_states is the number of entries, which has been checked properly to be < CPUIDLE_STATE_MAX correct ? Beause ...
+ if (rc < 0) {
+ pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n");
+ goto out_free_latency;
+ }
+
+ /*
+ * 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)) {
+ psscr_val = kcalloc(dt_idle_states, sizeof(*psscr_val),
+ GFP_KERNEL);
+ rc = of_property_read_u64_array(power_mgt,
+ "ibm,cpu-idle-state-psscr",
+ psscr_val, dt_idle_states);Here, psscr val is only one u64 ... shouldn't you kmalloc sizeof(..) * dt_idle_states ?
+ if (rc) {
+ pr_warn("cpuidle-powernv: missing ibm,cpu-idle-states-psscr in DT\n");
+ goto out_free_psscr;
+ }
+ }
residency_ns = kzalloc(sizeof(*residency_ns) * dt_idle_states, GFP_KERNEL);Just like we do here
quoted hunk ↗ jump to hunk
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. * Use default target_residency values if f/w does not expose it.@@ -216,6 +263,16 @@ 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_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]; } /*@@ -231,6 +288,16 @@ static int powernv_add_idle_states(void)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; + } 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 =@@ -245,6 +312,8 @@ static int powernv_add_idle_states(void)} kfree(residency_ns); +out_free_psscr: + kfree(psscr_val); out_free_latency: kfree(latency_ns); out_free_flags: