Skip to content

Commit 9136246

Browse files
lukaszluba-armrafaeljw
authored andcommitted
PM: EM: Use the new .get_cost() callback while registering EM
The Energy Model (EM) allows to provide the 'cost' values when the device driver provides the .get_cost() optional callback. This removes restriction which is in the EM calculation function of the 'cost' for each performance state. Now, the driver is in charge of providing the right values which are then used by Energy Aware Scheduler. Signed-off-by: Lukasz Luba <lukasz.luba@arm.com> Reviewed-by: Ionela Voinescu <ionela.voinescu@arm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent fc3a9a9 commit 9136246

1 file changed

Lines changed: 28 additions & 11 deletions

File tree

kernel/power/energy_model.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ static void em_debug_remove_pd(struct device *dev) {}
121121
#endif
122122

123123
static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd,
124-
int nr_states, struct em_data_callback *cb)
124+
int nr_states, struct em_data_callback *cb,
125+
unsigned long flags)
125126
{
126127
unsigned long power, freq, prev_freq = 0, prev_cost = ULONG_MAX;
127128
struct em_perf_state *table;
@@ -173,10 +174,22 @@ static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd,
173174
/* Compute the cost of each performance state. */
174175
fmax = (u64) table[nr_states - 1].frequency;
175176
for (i = nr_states - 1; i >= 0; i--) {
176-
unsigned long power_res = em_scale_power(table[i].power);
177+
unsigned long power_res, cost;
178+
179+
if (flags & EM_PERF_DOMAIN_ARTIFICIAL) {
180+
ret = cb->get_cost(dev, table[i].frequency, &cost);
181+
if (ret || !cost || cost > EM_MAX_POWER) {
182+
dev_err(dev, "EM: invalid cost %lu %d\n",
183+
cost, ret);
184+
goto free_ps_table;
185+
}
186+
} else {
187+
power_res = em_scale_power(table[i].power);
188+
cost = div64_u64(fmax * power_res, table[i].frequency);
189+
}
190+
191+
table[i].cost = cost;
177192

178-
table[i].cost = div64_u64(fmax * power_res,
179-
table[i].frequency);
180193
if (table[i].cost >= prev_cost) {
181194
table[i].flags = EM_PERF_STATE_INEFFICIENT;
182195
dev_dbg(dev, "EM: OPP:%lu is inefficient\n",
@@ -197,7 +210,8 @@ static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd,
197210
}
198211

199212
static int em_create_pd(struct device *dev, int nr_states,
200-
struct em_data_callback *cb, cpumask_t *cpus)
213+
struct em_data_callback *cb, cpumask_t *cpus,
214+
unsigned long flags)
201215
{
202216
struct em_perf_domain *pd;
203217
struct device *cpu_dev;
@@ -215,7 +229,7 @@ static int em_create_pd(struct device *dev, int nr_states,
215229
return -ENOMEM;
216230
}
217231

218-
ret = em_create_perf_table(dev, pd, nr_states, cb);
232+
ret = em_create_perf_table(dev, pd, nr_states, cb, flags);
219233
if (ret) {
220234
kfree(pd);
221235
return ret;
@@ -332,6 +346,7 @@ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
332346
bool milliwatts)
333347
{
334348
unsigned long cap, prev_cap = 0;
349+
unsigned long flags = 0;
335350
int cpu, ret;
336351

337352
if (!dev || !nr_states || !cb)
@@ -378,14 +393,16 @@ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
378393
}
379394
}
380395

381-
ret = em_create_pd(dev, nr_states, cb, cpus);
396+
if (milliwatts)
397+
flags |= EM_PERF_DOMAIN_MILLIWATTS;
398+
else if (cb->get_cost)
399+
flags |= EM_PERF_DOMAIN_ARTIFICIAL;
400+
401+
ret = em_create_pd(dev, nr_states, cb, cpus, flags);
382402
if (ret)
383403
goto unlock;
384404

385-
if (milliwatts)
386-
dev->em_pd->flags |= EM_PERF_DOMAIN_MILLIWATTS;
387-
else if (cb->get_cost)
388-
dev->em_pd->flags |= EM_PERF_DOMAIN_ARTIFICIAL;
405+
dev->em_pd->flags |= flags;
389406

390407
em_cpufreq_update_efficiencies(dev);
391408

0 commit comments

Comments
 (0)