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(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