Skip to content

Commit 8f4cd93

Browse files
committed
Merge branch 'pm-em' into linux-next
* pm-em: PM: EM: Introduce em_adjust_cpu_capacity() PM: EM: Move CPU capacity check to em_adjust_new_capacity() PM: EM: Documentation: Fix typos in example driver code PM: EM: Documentation: fix typo in energy-model.rst PM: EM: Fix potential division-by-zero error in em_compute_costs()
2 parents c27a659 + 4a6b1cf commit 8f4cd93

3 files changed

Lines changed: 51 additions & 31 deletions

File tree

Documentation/power/energy-model.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ Drivers must provide a pointer to the allocated and initialized new EM
230230
and will be visible to other sub-systems in the kernel (thermal, powercap).
231231
The main design goal for this API is to be fast and avoid extra calculations
232232
or memory allocations at runtime. When pre-computed EMs are available in the
233-
device driver, than it should be possible to simply re-use them with low
233+
device driver, then it should be possible to simply reuse them with low
234234
performance overhead.
235235

236236
In order to free the EM, provided earlier by the driver (e.g. when the module
@@ -381,17 +381,17 @@ up periodically to check the temperature and modify the EM data::
381381
26 rcu_read_unlock();
382382
27
383383
28 /* Calculate 'cost' values for EAS */
384-
29 ret = em_dev_compute_costs(dev, table, pd->nr_perf_states);
384+
29 ret = em_dev_compute_costs(dev, new_table, pd->nr_perf_states);
385385
30 if (ret) {
386386
31 dev_warn(dev, "EM: compute costs failed %d\n", ret);
387-
32 em_free_table(em_table);
387+
32 em_table_free(em_table);
388388
33 return;
389389
34 }
390390
35
391391
36 ret = em_dev_update_perf_domain(dev, em_table);
392392
37 if (ret) {
393393
38 dev_warn(dev, "EM: update failed %d\n", ret);
394-
39 em_free_table(em_table);
394+
39 em_table_free(em_table);
395395
40 return;
396396
41 }
397397
42

include/linux/energy_model.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ int em_dev_compute_costs(struct device *dev, struct em_perf_state *table,
179179
int em_dev_update_chip_binning(struct device *dev);
180180
int em_update_performance_limits(struct em_perf_domain *pd,
181181
unsigned long freq_min_khz, unsigned long freq_max_khz);
182+
void em_adjust_cpu_capacity(unsigned int cpu);
182183
void em_rebuild_sched_domains(void);
183184

184185
/**
@@ -403,6 +404,7 @@ int em_update_performance_limits(struct em_perf_domain *pd,
403404
{
404405
return -EINVAL;
405406
}
407+
static inline void em_adjust_cpu_capacity(unsigned int cpu) {}
406408
static inline void em_rebuild_sched_domains(void) {}
407409
#endif
408410

kernel/power/energy_model.c

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
233233
unsigned long prev_cost = ULONG_MAX;
234234
int i, ret;
235235

236+
/* This is needed only for CPUs and EAS skip other devices */
237+
if (!_is_cpu_device(dev))
238+
return 0;
239+
236240
/* Compute the cost of each performance state. */
237241
for (i = nr_states - 1; i >= 0; i--) {
238242
unsigned long power_res, cost;
@@ -698,10 +702,12 @@ static int em_recalc_and_update(struct device *dev, struct em_perf_domain *pd,
698702
{
699703
int ret;
700704

701-
ret = em_compute_costs(dev, em_table->state, NULL, pd->nr_perf_states,
702-
pd->flags);
703-
if (ret)
704-
goto free_em_table;
705+
if (!em_is_artificial(pd)) {
706+
ret = em_compute_costs(dev, em_table->state, NULL,
707+
pd->nr_perf_states, pd->flags);
708+
if (ret)
709+
goto free_em_table;
710+
}
705711

706712
ret = em_dev_update_perf_domain(dev, em_table);
707713
if (ret)
@@ -721,10 +727,24 @@ static int em_recalc_and_update(struct device *dev, struct em_perf_domain *pd,
721727
* Adjustment of CPU performance values after boot, when all CPUs capacites
722728
* are correctly calculated.
723729
*/
724-
static void em_adjust_new_capacity(struct device *dev,
730+
static void em_adjust_new_capacity(unsigned int cpu, struct device *dev,
725731
struct em_perf_domain *pd)
726732
{
733+
unsigned long cpu_capacity = arch_scale_cpu_capacity(cpu);
727734
struct em_perf_table *em_table;
735+
struct em_perf_state *table;
736+
unsigned long em_max_perf;
737+
738+
rcu_read_lock();
739+
table = em_perf_state_from_pd(pd);
740+
em_max_perf = table[pd->nr_perf_states - 1].performance;
741+
rcu_read_unlock();
742+
743+
if (em_max_perf == cpu_capacity)
744+
return;
745+
746+
pr_debug("updating cpu%d cpu_cap=%lu old capacity=%lu\n", cpu,
747+
cpu_capacity, em_max_perf);
728748

729749
em_table = em_table_dup(pd);
730750
if (!em_table) {
@@ -737,12 +757,27 @@ static void em_adjust_new_capacity(struct device *dev,
737757
em_recalc_and_update(dev, pd, em_table);
738758
}
739759

760+
/**
761+
* em_adjust_cpu_capacity() - Adjust the EM for a CPU after a capacity update.
762+
* @cpu: Target CPU.
763+
*
764+
* Adjust the existing EM for @cpu after a capacity update under the assumption
765+
* that the capacity has been updated in the same way for all of the CPUs in
766+
* the same perf domain.
767+
*/
768+
void em_adjust_cpu_capacity(unsigned int cpu)
769+
{
770+
struct device *dev = get_cpu_device(cpu);
771+
struct em_perf_domain *pd;
772+
773+
pd = em_pd_get(dev);
774+
if (pd)
775+
em_adjust_new_capacity(cpu, dev, pd);
776+
}
777+
740778
static void em_check_capacity_update(void)
741779
{
742780
cpumask_var_t cpu_done_mask;
743-
struct em_perf_state *table;
744-
struct em_perf_domain *pd;
745-
unsigned long cpu_capacity;
746781
int cpu;
747782

748783
if (!zalloc_cpumask_var(&cpu_done_mask, GFP_KERNEL)) {
@@ -753,7 +788,7 @@ static void em_check_capacity_update(void)
753788
/* Check if CPUs capacity has changed than update EM */
754789
for_each_possible_cpu(cpu) {
755790
struct cpufreq_policy *policy;
756-
unsigned long em_max_perf;
791+
struct em_perf_domain *pd;
757792
struct device *dev;
758793

759794
if (cpumask_test_cpu(cpu, cpu_done_mask))
@@ -776,24 +811,7 @@ static void em_check_capacity_update(void)
776811
cpumask_or(cpu_done_mask, cpu_done_mask,
777812
em_span_cpus(pd));
778813

779-
cpu_capacity = arch_scale_cpu_capacity(cpu);
780-
781-
rcu_read_lock();
782-
table = em_perf_state_from_pd(pd);
783-
em_max_perf = table[pd->nr_perf_states - 1].performance;
784-
rcu_read_unlock();
785-
786-
/*
787-
* Check if the CPU capacity has been adjusted during boot
788-
* and trigger the update for new performance values.
789-
*/
790-
if (em_max_perf == cpu_capacity)
791-
continue;
792-
793-
pr_debug("updating cpu%d cpu_cap=%lu old capacity=%lu\n",
794-
cpu, cpu_capacity, em_max_perf);
795-
796-
em_adjust_new_capacity(dev, pd);
814+
em_adjust_new_capacity(cpu, dev, pd);
797815
}
798816

799817
free_cpumask_var(cpu_done_mask);

0 commit comments

Comments
 (0)