Commit | Line | Data |
---|---|---|
27871f7a QP |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _LINUX_ENERGY_MODEL_H | |
3 | #define _LINUX_ENERGY_MODEL_H | |
4 | #include <linux/cpumask.h> | |
5 | #include <linux/jump_label.h> | |
6 | #include <linux/kobject.h> | |
7 | #include <linux/rcupdate.h> | |
8 | #include <linux/sched/cpufreq.h> | |
9 | #include <linux/sched/topology.h> | |
10 | #include <linux/types.h> | |
11 | ||
12 | #ifdef CONFIG_ENERGY_MODEL | |
13 | /** | |
14 | * em_cap_state - Capacity state of a performance domain | |
15 | * @frequency: The CPU frequency in KHz, for consistency with CPUFreq | |
16 | * @power: The power consumed by 1 CPU at this level, in milli-watts | |
17 | * @cost: The cost coefficient associated with this level, used during | |
18 | * energy calculation. Equal to: power * max_frequency / frequency | |
19 | */ | |
20 | struct em_cap_state { | |
21 | unsigned long frequency; | |
22 | unsigned long power; | |
23 | unsigned long cost; | |
24 | }; | |
25 | ||
26 | /** | |
27 | * em_perf_domain - Performance domain | |
28 | * @table: List of capacity states, in ascending order | |
29 | * @nr_cap_states: Number of capacity states | |
30 | * @cpus: Cpumask covering the CPUs of the domain | |
31 | * | |
32 | * A "performance domain" represents a group of CPUs whose performance is | |
33 | * scaled together. All CPUs of a performance domain must have the same | |
34 | * micro-architecture. Performance domains often have a 1-to-1 mapping with | |
35 | * CPUFreq policies. | |
36 | */ | |
37 | struct em_perf_domain { | |
38 | struct em_cap_state *table; | |
39 | int nr_cap_states; | |
40 | unsigned long cpus[0]; | |
41 | }; | |
42 | ||
43 | #define EM_CPU_MAX_POWER 0xFFFF | |
44 | ||
45 | struct em_data_callback { | |
46 | /** | |
47 | * active_power() - Provide power at the next capacity state of a CPU | |
48 | * @power : Active power at the capacity state in mW (modified) | |
49 | * @freq : Frequency at the capacity state in kHz (modified) | |
50 | * @cpu : CPU for which we do this operation | |
51 | * | |
52 | * active_power() must find the lowest capacity state of 'cpu' above | |
53 | * 'freq' and update 'power' and 'freq' to the matching active power | |
54 | * and frequency. | |
55 | * | |
56 | * The power is the one of a single CPU in the domain, expressed in | |
57 | * milli-watts. It is expected to fit in the [0, EM_CPU_MAX_POWER] | |
58 | * range. | |
59 | * | |
60 | * Return 0 on success. | |
61 | */ | |
62 | int (*active_power)(unsigned long *power, unsigned long *freq, int cpu); | |
63 | }; | |
64 | #define EM_DATA_CB(_active_power_cb) { .active_power = &_active_power_cb } | |
65 | ||
66 | struct em_perf_domain *em_cpu_get(int cpu); | |
67 | int em_register_perf_domain(cpumask_t *span, unsigned int nr_states, | |
68 | struct em_data_callback *cb); | |
69 | ||
70 | /** | |
71 | * em_pd_energy() - Estimates the energy consumed by the CPUs of a perf. domain | |
72 | * @pd : performance domain for which energy has to be estimated | |
73 | * @max_util : highest utilization among CPUs of the domain | |
74 | * @sum_util : sum of the utilization of all CPUs in the domain | |
75 | * | |
76 | * Return: the sum of the energy consumed by the CPUs of the domain assuming | |
77 | * a capacity state satisfying the max utilization of the domain. | |
78 | */ | |
79 | static inline unsigned long em_pd_energy(struct em_perf_domain *pd, | |
80 | unsigned long max_util, unsigned long sum_util) | |
81 | { | |
82 | unsigned long freq, scale_cpu; | |
83 | struct em_cap_state *cs; | |
84 | int i, cpu; | |
85 | ||
86 | /* | |
87 | * In order to predict the capacity state, map the utilization of the | |
88 | * most utilized CPU of the performance domain to a requested frequency, | |
89 | * like schedutil. | |
90 | */ | |
91 | cpu = cpumask_first(to_cpumask(pd->cpus)); | |
92 | scale_cpu = arch_scale_cpu_capacity(NULL, cpu); | |
93 | cs = &pd->table[pd->nr_cap_states - 1]; | |
94 | freq = map_util_freq(max_util, cs->frequency, scale_cpu); | |
95 | ||
96 | /* | |
97 | * Find the lowest capacity state of the Energy Model above the | |
98 | * requested frequency. | |
99 | */ | |
100 | for (i = 0; i < pd->nr_cap_states; i++) { | |
101 | cs = &pd->table[i]; | |
102 | if (cs->frequency >= freq) | |
103 | break; | |
104 | } | |
105 | ||
106 | /* | |
107 | * The capacity of a CPU in the domain at that capacity state (cs) | |
108 | * can be computed as: | |
109 | * | |
110 | * cs->freq * scale_cpu | |
111 | * cs->cap = -------------------- (1) | |
112 | * cpu_max_freq | |
113 | * | |
114 | * So, ignoring the costs of idle states (which are not available in | |
115 | * the EM), the energy consumed by this CPU at that capacity state is | |
116 | * estimated as: | |
117 | * | |
118 | * cs->power * cpu_util | |
119 | * cpu_nrg = -------------------- (2) | |
120 | * cs->cap | |
121 | * | |
122 | * since 'cpu_util / cs->cap' represents its percentage of busy time. | |
123 | * | |
124 | * NOTE: Although the result of this computation actually is in | |
125 | * units of power, it can be manipulated as an energy value | |
126 | * over a scheduling period, since it is assumed to be | |
127 | * constant during that interval. | |
128 | * | |
129 | * By injecting (1) in (2), 'cpu_nrg' can be re-expressed as a product | |
130 | * of two terms: | |
131 | * | |
132 | * cs->power * cpu_max_freq cpu_util | |
133 | * cpu_nrg = ------------------------ * --------- (3) | |
134 | * cs->freq scale_cpu | |
135 | * | |
136 | * The first term is static, and is stored in the em_cap_state struct | |
137 | * as 'cs->cost'. | |
138 | * | |
139 | * Since all CPUs of the domain have the same micro-architecture, they | |
140 | * share the same 'cs->cost', and the same CPU capacity. Hence, the | |
141 | * total energy of the domain (which is the simple sum of the energy of | |
142 | * all of its CPUs) can be factorized as: | |
143 | * | |
144 | * cs->cost * \Sum cpu_util | |
145 | * pd_nrg = ------------------------ (4) | |
146 | * scale_cpu | |
147 | */ | |
148 | return cs->cost * sum_util / scale_cpu; | |
149 | } | |
150 | ||
151 | /** | |
152 | * em_pd_nr_cap_states() - Get the number of capacity states of a perf. domain | |
153 | * @pd : performance domain for which this must be done | |
154 | * | |
155 | * Return: the number of capacity states in the performance domain table | |
156 | */ | |
157 | static inline int em_pd_nr_cap_states(struct em_perf_domain *pd) | |
158 | { | |
159 | return pd->nr_cap_states; | |
160 | } | |
161 | ||
162 | #else | |
163 | struct em_perf_domain {}; | |
164 | struct em_data_callback {}; | |
165 | #define EM_DATA_CB(_active_power_cb) { } | |
166 | ||
167 | static inline int em_register_perf_domain(cpumask_t *span, | |
168 | unsigned int nr_states, struct em_data_callback *cb) | |
169 | { | |
170 | return -EINVAL; | |
171 | } | |
172 | static inline struct em_perf_domain *em_cpu_get(int cpu) | |
173 | { | |
174 | return NULL; | |
175 | } | |
176 | static inline unsigned long em_pd_energy(struct em_perf_domain *pd, | |
177 | unsigned long max_util, unsigned long sum_util) | |
178 | { | |
179 | return 0; | |
180 | } | |
181 | static inline int em_pd_nr_cap_states(struct em_perf_domain *pd) | |
182 | { | |
183 | return 0; | |
184 | } | |
185 | #endif | |
186 | ||
187 | #endif |