summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/cpuidle/lpm-levels-of.c42
-rw-r--r--drivers/cpuidle/lpm-levels.h2
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