[RFC v2 07/12] PM / cpu_domains: Add PM Domain governor for CPUs
From: Stephen Boyd <hidden>
Date: 2016-02-26 19:33:38
Also in:
linux-arm-msm, linux-pm
On 02/12, Lina Iyer wrote:
quoted hunk ↗ jump to hunk
@@ -52,6 +55,76 @@ struct cpu_pm_domain *to_cpu_pd(struct generic_pm_domain *d) return res; } +static bool cpu_pd_down_ok(struct dev_pm_domain *pd) +{ + struct generic_pm_domain *genpd = pd_to_genpd(pd); + struct cpu_pm_domain *cpu_pd = to_cpu_pd(genpd); + int qos = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); + u64 sleep_ns; + ktime_t earliest, next_wakeup; + int cpu; + int i; + + /* Reset the last set genpd state, default to index 0 */ + genpd->state_idx = 0; + + /* We dont want to power down, if QoS is 0 */ + if (!qos) + return false; + + /* + * Find the sleep time for the cluster. + * The time between now and the first wake up of any CPU that + * are in this domain hierarchy is the time available for the + * domain to be idle. + */ + earliest = ktime_set(KTIME_SEC_MAX, 0); + for_each_cpu_and(cpu, cpu_pd->cpus, cpu_online_mask) {
We're not worried about hotplug happening in parallel because preemption is disabled here?
+ next_wakeup = tick_nohz_get_next_wakeup(cpu); + if (earliest.tv64 > next_wakeup.tv64)
if (ktime_before(next_wakeup, earliest))
+ earliest = next_wakeup;
+ }
+
+ sleep_ns = ktime_to_ns(ktime_sub(earliest, ktime_get()));
+ if (sleep_ns <= 0)
+ return false;
+
+ /*
+ * Find the deepest sleep state that satisfies the residency
+ * requirement and the QoS constraint
+ */
+ for (i = genpd->state_count - 1; i >= 0; i--) {
+ u64 state_sleep_ns;
+
+ state_sleep_ns = genpd->states[i].power_off_latency_ns +
+ genpd->states[i].power_on_latency_ns +
+ genpd->states[i].residency_ns;
+
+ /*
+ * If we cant sleep to save power in the state, move ons/cant/can't/
+ * to the next lower idle state. + */ + if (state_sleep_ns > sleep_ns) + continue; + + /* + * We also dont want to sleep more than we should to
s/dont/don't/
+ * gaurantee QoS. + */ + if (state_sleep_ns < (qos * NSEC_PER_USEC))
Maybe we should make qos into qos_ns? Presumably the compiler would hoist out the multiplication here, but it doesn't hurt to do it explicitly.
+ break; + } + + if (i >= 0) + genpd->state_idx = i; + + return (i >= 0) ? true : false;
Just return i >= 0? -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project