Blame view
include/linux/energy_model.h
6.89 KB
27871f7a8 PM: Introduce an ... |
1 2 3 4 |
/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_ENERGY_MODEL_H #define _LINUX_ENERGY_MODEL_H #include <linux/cpumask.h> |
7d9895c7f PM / EM: introduc... |
5 |
#include <linux/device.h> |
27871f7a8 PM: Introduce an ... |
6 7 8 9 10 11 |
#include <linux/jump_label.h> #include <linux/kobject.h> #include <linux/rcupdate.h> #include <linux/sched/cpufreq.h> #include <linux/sched/topology.h> #include <linux/types.h> |
27871f7a8 PM: Introduce an ... |
12 |
/** |
521b512b1 PM / EM: change n... |
13 |
* em_perf_state - Performance state of a performance domain |
1bc138c62 PM / EM: add supp... |
14 15 16 17 |
* @frequency: The frequency in KHz, for consistency with CPUFreq * @power: The power consumed at this level, in milli-watts (by 1 CPU or by a registered device). It can be a total power: static and dynamic. |
27871f7a8 PM: Introduce an ... |
18 19 20 |
* @cost: The cost coefficient associated with this level, used during * energy calculation. Equal to: power * max_frequency / frequency */ |
521b512b1 PM / EM: change n... |
21 |
struct em_perf_state { |
27871f7a8 PM: Introduce an ... |
22 23 24 25 26 27 28 |
unsigned long frequency; unsigned long power; unsigned long cost; }; /** * em_perf_domain - Performance domain |
521b512b1 PM / EM: change n... |
29 30 |
* @table: List of performance states, in ascending order * @nr_perf_states: Number of performance states |
1bc138c62 PM / EM: add supp... |
31 32 33 34 |
* @cpus: Cpumask covering the CPUs of the domain. It's here * for performance reasons to avoid potential cache * misses during energy calculations in the scheduler * and simplifies allocating/freeing that memory region. |
27871f7a8 PM: Introduce an ... |
35 |
* |
1bc138c62 PM / EM: add supp... |
36 37 38 39 40 |
* In case of CPU device, a "performance domain" represents a group of CPUs * whose performance is scaled together. All CPUs of a performance domain * must have the same micro-architecture. Performance domains often have * a 1-to-1 mapping with CPUFreq policies. In case of other devices the @cpus * field is unused. |
27871f7a8 PM: Introduce an ... |
41 42 |
*/ struct em_perf_domain { |
521b512b1 PM / EM: change n... |
43 44 |
struct em_perf_state *table; int nr_perf_states; |
beb69f15a energy_model.h: R... |
45 |
unsigned long cpus[]; |
27871f7a8 PM: Introduce an ... |
46 |
}; |
521b512b1 PM / EM: change n... |
47 |
#define em_span_cpus(em) (to_cpumask((em)->cpus)) |
27a47e422 PM / EM: Declare ... |
48 |
#ifdef CONFIG_ENERGY_MODEL |
7d9895c7f PM / EM: introduc... |
49 |
#define EM_MAX_POWER 0xFFFF |
27871f7a8 PM: Introduce an ... |
50 51 52 |
struct em_data_callback { /** |
521b512b1 PM / EM: change n... |
53 |
* active_power() - Provide power at the next performance state of |
d0351cc3b PM / EM: update c... |
54 |
* a device |
521b512b1 PM / EM: change n... |
55 56 57 58 |
* @power : Active power at the performance state in mW * (modified) * @freq : Frequency at the performance state in kHz * (modified) |
d0351cc3b PM / EM: update c... |
59 |
* @dev : Device for which we do this operation (can be a CPU) |
27871f7a8 PM: Introduce an ... |
60 |
* |
d0351cc3b PM / EM: update c... |
61 |
* active_power() must find the lowest performance state of 'dev' above |
27871f7a8 PM: Introduce an ... |
62 63 64 |
* 'freq' and update 'power' and 'freq' to the matching active power * and frequency. * |
d0351cc3b PM / EM: update c... |
65 66 67 |
* In case of CPUs, the power is the one of a single CPU in the domain, * expressed in milli-watts. It is expected to fit in the * [0, EM_MAX_POWER] range. |
27871f7a8 PM: Introduce an ... |
68 69 70 |
* * Return 0 on success. */ |
d0351cc3b PM / EM: update c... |
71 72 |
int (*active_power)(unsigned long *power, unsigned long *freq, struct device *dev); |
27871f7a8 PM: Introduce an ... |
73 74 75 76 |
}; #define EM_DATA_CB(_active_power_cb) { .active_power = &_active_power_cb } struct em_perf_domain *em_cpu_get(int cpu); |
1bc138c62 PM / EM: add supp... |
77 |
struct em_perf_domain *em_pd_get(struct device *dev); |
7d9895c7f PM / EM: introduc... |
78 79 |
int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, struct em_data_callback *cb, cpumask_t *span); |
1bc138c62 PM / EM: add supp... |
80 |
void em_dev_unregister_perf_domain(struct device *dev); |
27871f7a8 PM: Introduce an ... |
81 82 |
/** |
f0b569479 PM / EM: change n... |
83 84 |
* em_cpu_energy() - Estimates the energy consumed by the CPUs of a performance domain |
27871f7a8 PM: Introduce an ... |
85 86 87 88 |
* @pd : performance domain for which energy has to be estimated * @max_util : highest utilization among CPUs of the domain * @sum_util : sum of the utilization of all CPUs in the domain * |
f0b569479 PM / EM: change n... |
89 90 91 92 |
* This function must be used only for CPU devices. There is no validation, * i.e. if the EM is a CPU type and has cpumask allocated. It is called from * the scheduler code quite frequently and that is why there is not checks. * |
27871f7a8 PM: Introduce an ... |
93 94 95 |
* Return: the sum of the energy consumed by the CPUs of the domain assuming * a capacity state satisfying the max utilization of the domain. */ |
f0b569479 PM / EM: change n... |
96 |
static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, |
27871f7a8 PM: Introduce an ... |
97 98 99 |
unsigned long max_util, unsigned long sum_util) { unsigned long freq, scale_cpu; |
521b512b1 PM / EM: change n... |
100 |
struct em_perf_state *ps; |
27871f7a8 PM: Introduce an ... |
101 102 103 |
int i, cpu; /* |
521b512b1 PM / EM: change n... |
104 105 106 |
* In order to predict the performance state, map the utilization of * the most utilized CPU of the performance domain to a requested * frequency, like schedutil. |
27871f7a8 PM: Introduce an ... |
107 108 |
*/ cpu = cpumask_first(to_cpumask(pd->cpus)); |
8ec59c0f5 sched/topology: R... |
109 |
scale_cpu = arch_scale_cpu_capacity(cpu); |
521b512b1 PM / EM: change n... |
110 111 |
ps = &pd->table[pd->nr_perf_states - 1]; freq = map_util_freq(max_util, ps->frequency, scale_cpu); |
27871f7a8 PM: Introduce an ... |
112 113 |
/* |
521b512b1 PM / EM: change n... |
114 |
* Find the lowest performance state of the Energy Model above the |
27871f7a8 PM: Introduce an ... |
115 116 |
* requested frequency. */ |
521b512b1 PM / EM: change n... |
117 118 119 |
for (i = 0; i < pd->nr_perf_states; i++) { ps = &pd->table[i]; if (ps->frequency >= freq) |
27871f7a8 PM: Introduce an ... |
120 121 122 123 |
break; } /* |
521b512b1 PM / EM: change n... |
124 |
* The capacity of a CPU in the domain at the performance state (ps) |
27871f7a8 PM: Introduce an ... |
125 126 |
* can be computed as: * |
521b512b1 PM / EM: change n... |
127 128 |
* ps->freq * scale_cpu * ps->cap = -------------------- (1) |
27871f7a8 PM: Introduce an ... |
129 130 131 |
* cpu_max_freq * * So, ignoring the costs of idle states (which are not available in |
521b512b1 PM / EM: change n... |
132 133 |
* the EM), the energy consumed by this CPU at that performance state * is estimated as: |
27871f7a8 PM: Introduce an ... |
134 |
* |
521b512b1 PM / EM: change n... |
135 |
* ps->power * cpu_util |
27871f7a8 PM: Introduce an ... |
136 |
* cpu_nrg = -------------------- (2) |
521b512b1 PM / EM: change n... |
137 |
* ps->cap |
27871f7a8 PM: Introduce an ... |
138 |
* |
521b512b1 PM / EM: change n... |
139 |
* since 'cpu_util / ps->cap' represents its percentage of busy time. |
27871f7a8 PM: Introduce an ... |
140 141 142 143 144 145 146 147 148 |
* * NOTE: Although the result of this computation actually is in * units of power, it can be manipulated as an energy value * over a scheduling period, since it is assumed to be * constant during that interval. * * By injecting (1) in (2), 'cpu_nrg' can be re-expressed as a product * of two terms: * |
521b512b1 PM / EM: change n... |
149 |
* ps->power * cpu_max_freq cpu_util |
27871f7a8 PM: Introduce an ... |
150 |
* cpu_nrg = ------------------------ * --------- (3) |
521b512b1 PM / EM: change n... |
151 |
* ps->freq scale_cpu |
27871f7a8 PM: Introduce an ... |
152 |
* |
521b512b1 PM / EM: change n... |
153 154 |
* The first term is static, and is stored in the em_perf_state struct * as 'ps->cost'. |
27871f7a8 PM: Introduce an ... |
155 156 |
* * Since all CPUs of the domain have the same micro-architecture, they |
521b512b1 PM / EM: change n... |
157 |
* share the same 'ps->cost', and the same CPU capacity. Hence, the |
27871f7a8 PM: Introduce an ... |
158 159 160 |
* total energy of the domain (which is the simple sum of the energy of * all of its CPUs) can be factorized as: * |
521b512b1 PM / EM: change n... |
161 |
* ps->cost * \Sum cpu_util |
27871f7a8 PM: Introduce an ... |
162 163 164 |
* pd_nrg = ------------------------ (4) * scale_cpu */ |
521b512b1 PM / EM: change n... |
165 |
return ps->cost * sum_util / scale_cpu; |
27871f7a8 PM: Introduce an ... |
166 167 168 |
} /** |
521b512b1 PM / EM: change n... |
169 170 |
* em_pd_nr_perf_states() - Get the number of performance states of a perf. * domain |
27871f7a8 PM: Introduce an ... |
171 172 |
* @pd : performance domain for which this must be done * |
521b512b1 PM / EM: change n... |
173 |
* Return: the number of performance states in the performance domain table |
27871f7a8 PM: Introduce an ... |
174 |
*/ |
521b512b1 PM / EM: change n... |
175 |
static inline int em_pd_nr_perf_states(struct em_perf_domain *pd) |
27871f7a8 PM: Introduce an ... |
176 |
{ |
521b512b1 PM / EM: change n... |
177 |
return pd->nr_perf_states; |
27871f7a8 PM: Introduce an ... |
178 179 180 |
} #else |
27871f7a8 PM: Introduce an ... |
181 182 |
struct em_data_callback {}; #define EM_DATA_CB(_active_power_cb) { } |
7d9895c7f PM / EM: introduc... |
183 184 185 186 187 188 |
static inline int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, struct em_data_callback *cb, cpumask_t *span) { return -EINVAL; } |
1bc138c62 PM / EM: add supp... |
189 190 191 |
static inline void em_dev_unregister_perf_domain(struct device *dev) { } |
27871f7a8 PM: Introduce an ... |
192 193 194 195 |
static inline struct em_perf_domain *em_cpu_get(int cpu) { return NULL; } |
1bc138c62 PM / EM: add supp... |
196 197 198 199 |
static inline struct em_perf_domain *em_pd_get(struct device *dev) { return NULL; } |
f0b569479 PM / EM: change n... |
200 |
static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, |
27871f7a8 PM: Introduce an ... |
201 202 203 204 |
unsigned long max_util, unsigned long sum_util) { return 0; } |
521b512b1 PM / EM: change n... |
205 |
static inline int em_pd_nr_perf_states(struct em_perf_domain *pd) |
27871f7a8 PM: Introduce an ... |
206 207 208 209 210 211 |
{ return 0; } #endif #endif |