diff options
| -rw-r--r-- | drivers/cpuidle/lpm-levels-of.c | 42 | ||||
| -rw-r--r-- | drivers/cpuidle/lpm-levels.h | 2 |
2 files changed, 39 insertions, 5 deletions
diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c index 8316d8aa9227..b40231dd8dd1 100644 --- a/drivers/cpuidle/lpm-levels-of.c +++ b/drivers/cpuidle/lpm-levels-of.c @@ -39,6 +39,7 @@ static const struct lpm_type_str lpm_types[] = { }; static DEFINE_PER_CPU(uint32_t *, max_residency); +static DEFINE_PER_CPU(uint32_t *, min_residency); static struct lpm_level_avail *cpu_level_available[NR_CPUS]; static struct platform_device *lpm_pdev; @@ -75,7 +76,8 @@ static void set_optimum_cpu_residency(struct lpm_cpu *cpu, int cpu_id, { int i, j; bool mode_avail; - uint32_t *residency = per_cpu(max_residency, cpu_id); + uint32_t *maximum_residency = per_cpu(max_residency, cpu_id); + uint32_t *minimum_residency = per_cpu(min_residency, cpu_id); for (i = 0; i < cpu->nlevels; i++) { struct power_params *pwr = &cpu->levels[i].pwr; @@ -84,19 +86,28 @@ static void set_optimum_cpu_residency(struct lpm_cpu *cpu, int cpu_id, lpm_cpu_mode_allow(cpu_id, i, true); if (!mode_avail) { - residency[i] = 0; + maximum_residency[i] = 0; + minimum_residency[i] = 0; continue; } - residency[i] = ~0; + maximum_residency[i] = ~0; for (j = i + 1; j < cpu->nlevels; j++) { mode_avail = probe_time || lpm_cpu_mode_allow(cpu_id, j, true); if (mode_avail && - (residency[i] > pwr->residencies[j]) && + (maximum_residency[i] > pwr->residencies[j]) && (pwr->residencies[j] != 0)) - residency[i] = pwr->residencies[j]; + maximum_residency[i] = pwr->residencies[j]; + } + + minimum_residency[i] = pwr->time_overhead_us; + for (j = i-1; j >= 0; j--) { + if (probe_time || lpm_cpu_mode_allow(cpu_id, j, true)) { + minimum_residency[i] = maximum_residency[j] + 1; + break; + } } } } @@ -116,6 +127,7 @@ static void set_optimum_cluster_residency(struct lpm_cluster *cluster, if (!mode_avail) { pwr->max_residency = 0; + pwr->min_residency = 0; continue; } @@ -129,6 +141,16 @@ static void set_optimum_cluster_residency(struct lpm_cluster *cluster, (pwr->residencies[j] != 0)) pwr->max_residency = pwr->residencies[j]; } + + pwr->min_residency = pwr->time_overhead_us; + for (j = i-1; j >= 0; j--) { + if (probe_time || + lpm_cluster_mode_allow(cluster, j, true)) { + pwr->min_residency = + cluster->levels[j].pwr.max_residency + 1; + break; + } + } } } @@ -137,6 +159,10 @@ uint32_t *get_per_cpu_max_residency(int cpu) return per_cpu(max_residency, cpu); } +uint32_t *get_per_cpu_min_residency(int cpu) +{ + return per_cpu(min_residency, cpu); +} ssize_t lpm_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -930,6 +956,12 @@ struct lpm_cluster *parse_cluster(struct device_node *node, GFP_KERNEL); if (!per_cpu(max_residency, i)) return ERR_PTR(-ENOMEM); + per_cpu(min_residency, i) = devm_kzalloc( + &lpm_pdev->dev, + sizeof(uint32_t) * c->cpu->nlevels, + GFP_KERNEL); + if (!per_cpu(min_residency, i)) + return ERR_PTR(-ENOMEM); set_optimum_cpu_residency(c->cpu, i, true); } } diff --git a/drivers/cpuidle/lpm-levels.h b/drivers/cpuidle/lpm-levels.h index f6979c4d4d9f..63fe0a0fbc08 100644 --- a/drivers/cpuidle/lpm-levels.h +++ b/drivers/cpuidle/lpm-levels.h @@ -28,6 +28,7 @@ struct power_params { uint32_t energy_overhead; /* Enter + exit over head */ uint32_t time_overhead_us; /* Enter + exit overhead */ uint32_t residencies[NR_LPM_LEVELS]; + uint32_t min_residency; uint32_t max_residency; }; @@ -125,6 +126,7 @@ bool lpm_cpu_mode_allow(unsigned int cpu, bool lpm_cluster_mode_allow(struct lpm_cluster *cluster, unsigned int mode, bool from_idle); uint32_t *get_per_cpu_max_residency(int cpu); +uint32_t *get_per_cpu_min_residency(int cpu); extern struct lpm_cluster *lpm_root_node; #ifdef CONFIG_SMP |
