Blame view

include/linux/energy_model.h 6.89 KB
27871f7a8   Quentin Perret   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   Lukasz Luba   PM / EM: introduc...
5
  #include <linux/device.h>
27871f7a8   Quentin Perret   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   Quentin Perret   PM: Introduce an ...
12
  /**
521b512b1   Lukasz Luba   PM / EM: change n...
13
   * em_perf_state - Performance state of a performance domain
1bc138c62   Lukasz Luba   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   Quentin Perret   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   Lukasz Luba   PM / EM: change n...
21
  struct em_perf_state {
27871f7a8   Quentin Perret   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   Lukasz Luba   PM / EM: change n...
29
30
   * @table:		List of performance states, in ascending order
   * @nr_perf_states:	Number of performance states
1bc138c62   Lukasz Luba   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   Quentin Perret   PM: Introduce an ...
35
   *
1bc138c62   Lukasz Luba   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   Quentin Perret   PM: Introduce an ...
41
42
   */
  struct em_perf_domain {
521b512b1   Lukasz Luba   PM / EM: change n...
43
44
  	struct em_perf_state *table;
  	int nr_perf_states;
beb69f15a   Gustavo A. R. Silva   energy_model.h: R...
45
  	unsigned long cpus[];
27871f7a8   Quentin Perret   PM: Introduce an ...
46
  };
521b512b1   Lukasz Luba   PM / EM: change n...
47
  #define em_span_cpus(em) (to_cpumask((em)->cpus))
27a47e422   Quentin Perret   PM / EM: Declare ...
48
  #ifdef CONFIG_ENERGY_MODEL
7d9895c7f   Lukasz Luba   PM / EM: introduc...
49
  #define EM_MAX_POWER 0xFFFF
27871f7a8   Quentin Perret   PM: Introduce an ...
50
51
52
  
  struct em_data_callback {
  	/**
521b512b1   Lukasz Luba   PM / EM: change n...
53
  	 * active_power() - Provide power at the next performance state of
d0351cc3b   Lukasz Luba   PM / EM: update c...
54
  	 *		a device
521b512b1   Lukasz Luba   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   Lukasz Luba   PM / EM: update c...
59
  	 * @dev		: Device for which we do this operation (can be a CPU)
27871f7a8   Quentin Perret   PM: Introduce an ...
60
  	 *
d0351cc3b   Lukasz Luba   PM / EM: update c...
61
  	 * active_power() must find the lowest performance state of 'dev' above
27871f7a8   Quentin Perret   PM: Introduce an ...
62
63
64
  	 * 'freq' and update 'power' and 'freq' to the matching active power
  	 * and frequency.
  	 *
d0351cc3b   Lukasz Luba   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   Quentin Perret   PM: Introduce an ...
68
69
70
  	 *
  	 * Return 0 on success.
  	 */
d0351cc3b   Lukasz Luba   PM / EM: update c...
71
72
  	int (*active_power)(unsigned long *power, unsigned long *freq,
  			    struct device *dev);
27871f7a8   Quentin Perret   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   Lukasz Luba   PM / EM: add supp...
77
  struct em_perf_domain *em_pd_get(struct device *dev);
7d9895c7f   Lukasz Luba   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   Lukasz Luba   PM / EM: add supp...
80
  void em_dev_unregister_perf_domain(struct device *dev);
27871f7a8   Quentin Perret   PM: Introduce an ...
81
82
  
  /**
f0b569479   Lukasz Luba   PM / EM: change n...
83
84
   * em_cpu_energy() - Estimates the energy consumed by the CPUs of a
  		performance domain
27871f7a8   Quentin Perret   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   Lukasz Luba   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   Quentin Perret   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   Lukasz Luba   PM / EM: change n...
96
  static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
27871f7a8   Quentin Perret   PM: Introduce an ...
97
98
99
  				unsigned long max_util, unsigned long sum_util)
  {
  	unsigned long freq, scale_cpu;
521b512b1   Lukasz Luba   PM / EM: change n...
100
  	struct em_perf_state *ps;
27871f7a8   Quentin Perret   PM: Introduce an ...
101
102
103
  	int i, cpu;
  
  	/*
521b512b1   Lukasz Luba   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   Quentin Perret   PM: Introduce an ...
107
108
  	 */
  	cpu = cpumask_first(to_cpumask(pd->cpus));
8ec59c0f5   Vincent Guittot   sched/topology: R...
109
  	scale_cpu = arch_scale_cpu_capacity(cpu);
521b512b1   Lukasz Luba   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   Quentin Perret   PM: Introduce an ...
112
113
  
  	/*
521b512b1   Lukasz Luba   PM / EM: change n...
114
  	 * Find the lowest performance state of the Energy Model above the
27871f7a8   Quentin Perret   PM: Introduce an ...
115
116
  	 * requested frequency.
  	 */
521b512b1   Lukasz Luba   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   Quentin Perret   PM: Introduce an ...
120
121
122
123
  			break;
  	}
  
  	/*
521b512b1   Lukasz Luba   PM / EM: change n...
124
  	 * The capacity of a CPU in the domain at the performance state (ps)
27871f7a8   Quentin Perret   PM: Introduce an ...
125
126
  	 * can be computed as:
  	 *
521b512b1   Lukasz Luba   PM / EM: change n...
127
128
  	 *             ps->freq * scale_cpu
  	 *   ps->cap = --------------------                          (1)
27871f7a8   Quentin Perret   PM: Introduce an ...
129
130
131
  	 *                 cpu_max_freq
  	 *
  	 * So, ignoring the costs of idle states (which are not available in
521b512b1   Lukasz Luba   PM / EM: change n...
132
133
  	 * the EM), the energy consumed by this CPU at that performance state
  	 * is estimated as:
27871f7a8   Quentin Perret   PM: Introduce an ...
134
  	 *
521b512b1   Lukasz Luba   PM / EM: change n...
135
  	 *             ps->power * cpu_util
27871f7a8   Quentin Perret   PM: Introduce an ...
136
  	 *   cpu_nrg = --------------------                          (2)
521b512b1   Lukasz Luba   PM / EM: change n...
137
  	 *                   ps->cap
27871f7a8   Quentin Perret   PM: Introduce an ...
138
  	 *
521b512b1   Lukasz Luba   PM / EM: change n...
139
  	 * since 'cpu_util / ps->cap' represents its percentage of busy time.
27871f7a8   Quentin Perret   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   Lukasz Luba   PM / EM: change n...
149
  	 *             ps->power * cpu_max_freq   cpu_util
27871f7a8   Quentin Perret   PM: Introduce an ...
150
  	 *   cpu_nrg = ------------------------ * ---------          (3)
521b512b1   Lukasz Luba   PM / EM: change n...
151
  	 *                    ps->freq            scale_cpu
27871f7a8   Quentin Perret   PM: Introduce an ...
152
  	 *
521b512b1   Lukasz Luba   PM / EM: change n...
153
154
  	 * The first term is static, and is stored in the em_perf_state struct
  	 * as 'ps->cost'.
27871f7a8   Quentin Perret   PM: Introduce an ...
155
156
  	 *
  	 * Since all CPUs of the domain have the same micro-architecture, they
521b512b1   Lukasz Luba   PM / EM: change n...
157
  	 * share the same 'ps->cost', and the same CPU capacity. Hence, the
27871f7a8   Quentin Perret   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   Lukasz Luba   PM / EM: change n...
161
  	 *            ps->cost * \Sum cpu_util
27871f7a8   Quentin Perret   PM: Introduce an ...
162
163
164
  	 *   pd_nrg = ------------------------                       (4)
  	 *                  scale_cpu
  	 */
521b512b1   Lukasz Luba   PM / EM: change n...
165
  	return ps->cost * sum_util / scale_cpu;
27871f7a8   Quentin Perret   PM: Introduce an ...
166
167
168
  }
  
  /**
521b512b1   Lukasz Luba   PM / EM: change n...
169
170
   * em_pd_nr_perf_states() - Get the number of performance states of a perf.
   *				domain
27871f7a8   Quentin Perret   PM: Introduce an ...
171
172
   * @pd		: performance domain for which this must be done
   *
521b512b1   Lukasz Luba   PM / EM: change n...
173
   * Return: the number of performance states in the performance domain table
27871f7a8   Quentin Perret   PM: Introduce an ...
174
   */
521b512b1   Lukasz Luba   PM / EM: change n...
175
  static inline int em_pd_nr_perf_states(struct em_perf_domain *pd)
27871f7a8   Quentin Perret   PM: Introduce an ...
176
  {
521b512b1   Lukasz Luba   PM / EM: change n...
177
  	return pd->nr_perf_states;
27871f7a8   Quentin Perret   PM: Introduce an ...
178
179
180
  }
  
  #else
27871f7a8   Quentin Perret   PM: Introduce an ...
181
182
  struct em_data_callback {};
  #define EM_DATA_CB(_active_power_cb) { }
7d9895c7f   Lukasz Luba   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   Lukasz Luba   PM / EM: add supp...
189
190
191
  static inline void em_dev_unregister_perf_domain(struct device *dev)
  {
  }
27871f7a8   Quentin Perret   PM: Introduce an ...
192
193
194
195
  static inline struct em_perf_domain *em_cpu_get(int cpu)
  {
  	return NULL;
  }
1bc138c62   Lukasz Luba   PM / EM: add supp...
196
197
198
199
  static inline struct em_perf_domain *em_pd_get(struct device *dev)
  {
  	return NULL;
  }
f0b569479   Lukasz Luba   PM / EM: change n...
200
  static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
27871f7a8   Quentin Perret   PM: Introduce an ...
201
202
203
204
  			unsigned long max_util, unsigned long sum_util)
  {
  	return 0;
  }
521b512b1   Lukasz Luba   PM / EM: change n...
205
  static inline int em_pd_nr_perf_states(struct em_perf_domain *pd)
27871f7a8   Quentin Perret   PM: Introduce an ...
206
207
208
209
210
211
  {
  	return 0;
  }
  #endif
  
  #endif