PM / EM: introduce em_dev_register_perf_domain function
[platform/kernel/linux-starfive.git] / kernel / power / energy_model.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Energy Model of CPUs
4  *
5  * Copyright (c) 2018, Arm ltd.
6  * Written by: Quentin Perret, Arm ltd.
7  */
8
9 #define pr_fmt(fmt) "energy_model: " fmt
10
11 #include <linux/cpu.h>
12 #include <linux/cpumask.h>
13 #include <linux/debugfs.h>
14 #include <linux/energy_model.h>
15 #include <linux/sched/topology.h>
16 #include <linux/slab.h>
17
18 /* Mapping of each CPU to the performance domain to which it belongs. */
19 static DEFINE_PER_CPU(struct em_perf_domain *, em_data);
20
21 /*
22  * Mutex serializing the registrations of performance domains and letting
23  * callbacks defined by drivers sleep.
24  */
25 static DEFINE_MUTEX(em_pd_mutex);
26
27 #ifdef CONFIG_DEBUG_FS
28 static struct dentry *rootdir;
29
30 static void em_debug_create_ps(struct em_perf_state *ps, struct dentry *pd)
31 {
32         struct dentry *d;
33         char name[24];
34
35         snprintf(name, sizeof(name), "ps:%lu", ps->frequency);
36
37         /* Create per-ps directory */
38         d = debugfs_create_dir(name, pd);
39         debugfs_create_ulong("frequency", 0444, d, &ps->frequency);
40         debugfs_create_ulong("power", 0444, d, &ps->power);
41         debugfs_create_ulong("cost", 0444, d, &ps->cost);
42 }
43
44 static int em_debug_cpus_show(struct seq_file *s, void *unused)
45 {
46         seq_printf(s, "%*pbl\n", cpumask_pr_args(to_cpumask(s->private)));
47
48         return 0;
49 }
50 DEFINE_SHOW_ATTRIBUTE(em_debug_cpus);
51
52 static void em_debug_create_pd(struct em_perf_domain *pd, int cpu)
53 {
54         struct dentry *d;
55         char name[8];
56         int i;
57
58         snprintf(name, sizeof(name), "pd%d", cpu);
59
60         /* Create the directory of the performance domain */
61         d = debugfs_create_dir(name, rootdir);
62
63         debugfs_create_file("cpus", 0444, d, pd->cpus, &em_debug_cpus_fops);
64
65         /* Create a sub-directory for each performance state */
66         for (i = 0; i < pd->nr_perf_states; i++)
67                 em_debug_create_ps(&pd->table[i], d);
68 }
69
70 static int __init em_debug_init(void)
71 {
72         /* Create /sys/kernel/debug/energy_model directory */
73         rootdir = debugfs_create_dir("energy_model", NULL);
74
75         return 0;
76 }
77 core_initcall(em_debug_init);
78 #else /* CONFIG_DEBUG_FS */
79 static void em_debug_create_pd(struct em_perf_domain *pd, int cpu) {}
80 #endif
81 static struct em_perf_domain *em_create_pd(cpumask_t *span, int nr_states,
82                                                 struct em_data_callback *cb)
83 {
84         unsigned long opp_eff, prev_opp_eff = ULONG_MAX;
85         unsigned long power, freq, prev_freq = 0;
86         int i, ret, cpu = cpumask_first(span);
87         struct em_perf_state *table;
88         struct em_perf_domain *pd;
89         u64 fmax;
90
91         if (!cb->active_power)
92                 return NULL;
93
94         pd = kzalloc(sizeof(*pd) + cpumask_size(), GFP_KERNEL);
95         if (!pd)
96                 return NULL;
97
98         table = kcalloc(nr_states, sizeof(*table), GFP_KERNEL);
99         if (!table)
100                 goto free_pd;
101
102         /* Build the list of performance states for this performance domain */
103         for (i = 0, freq = 0; i < nr_states; i++, freq++) {
104                 /*
105                  * active_power() is a driver callback which ceils 'freq' to
106                  * lowest performance state of 'cpu' above 'freq' and updates
107                  * 'power' and 'freq' accordingly.
108                  */
109                 ret = cb->active_power(&power, &freq, cpu);
110                 if (ret) {
111                         pr_err("pd%d: invalid perf. state: %d\n", cpu, ret);
112                         goto free_ps_table;
113                 }
114
115                 /*
116                  * We expect the driver callback to increase the frequency for
117                  * higher performance states.
118                  */
119                 if (freq <= prev_freq) {
120                         pr_err("pd%d: non-increasing freq: %lu\n", cpu, freq);
121                         goto free_ps_table;
122                 }
123
124                 /*
125                  * The power returned by active_state() is expected to be
126                  * positive, in milli-watts and to fit into 16 bits.
127                  */
128                 if (!power || power > EM_MAX_POWER) {
129                         pr_err("pd%d: invalid power: %lu\n", cpu, power);
130                         goto free_ps_table;
131                 }
132
133                 table[i].power = power;
134                 table[i].frequency = prev_freq = freq;
135
136                 /*
137                  * The hertz/watts efficiency ratio should decrease as the
138                  * frequency grows on sane platforms. But this isn't always
139                  * true in practice so warn the user if a higher OPP is more
140                  * power efficient than a lower one.
141                  */
142                 opp_eff = freq / power;
143                 if (opp_eff >= prev_opp_eff)
144                         pr_warn("pd%d: hertz/watts ratio non-monotonically decreasing: em_perf_state %d >= em_perf_state%d\n",
145                                         cpu, i, i - 1);
146                 prev_opp_eff = opp_eff;
147         }
148
149         /* Compute the cost of each performance state. */
150         fmax = (u64) table[nr_states - 1].frequency;
151         for (i = 0; i < nr_states; i++) {
152                 table[i].cost = div64_u64(fmax * table[i].power,
153                                           table[i].frequency);
154         }
155
156         pd->table = table;
157         pd->nr_perf_states = nr_states;
158         cpumask_copy(to_cpumask(pd->cpus), span);
159
160         em_debug_create_pd(pd, cpu);
161
162         return pd;
163
164 free_ps_table:
165         kfree(table);
166 free_pd:
167         kfree(pd);
168
169         return NULL;
170 }
171
172 /**
173  * em_cpu_get() - Return the performance domain for a CPU
174  * @cpu : CPU to find the performance domain for
175  *
176  * Return: the performance domain to which 'cpu' belongs, or NULL if it doesn't
177  * exist.
178  */
179 struct em_perf_domain *em_cpu_get(int cpu)
180 {
181         return READ_ONCE(per_cpu(em_data, cpu));
182 }
183 EXPORT_SYMBOL_GPL(em_cpu_get);
184
185 /**
186  * em_dev_register_perf_domain() - Register the Energy Model (EM) for a device
187  * @dev         : Device for which the EM is to register
188  * @nr_states   : Number of performance states to register
189  * @cb          : Callback functions providing the data of the Energy Model
190  * @span        : Pointer to cpumask_t, which in case of a CPU device is
191  *              obligatory. It can be taken from i.e. 'policy->cpus'. For other
192  *              type of devices this should be set to NULL.
193  *
194  * Create Energy Model tables for a performance domain using the callbacks
195  * defined in cb.
196  *
197  * If multiple clients register the same performance domain, all but the first
198  * registration will be ignored.
199  *
200  * Return 0 on success
201  */
202 int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
203                                 struct em_data_callback *cb, cpumask_t *span)
204 {
205         unsigned long cap, prev_cap = 0;
206         struct em_perf_domain *pd;
207         int cpu, ret = 0;
208
209         if (!dev || !span || !nr_states || !cb)
210                 return -EINVAL;
211
212         /*
213          * Use a mutex to serialize the registration of performance domains and
214          * let the driver-defined callback functions sleep.
215          */
216         mutex_lock(&em_pd_mutex);
217
218         for_each_cpu(cpu, span) {
219                 /* Make sure we don't register again an existing domain. */
220                 if (READ_ONCE(per_cpu(em_data, cpu))) {
221                         ret = -EEXIST;
222                         goto unlock;
223                 }
224
225                 /*
226                  * All CPUs of a domain must have the same micro-architecture
227                  * since they all share the same table.
228                  */
229                 cap = arch_scale_cpu_capacity(cpu);
230                 if (prev_cap && prev_cap != cap) {
231                         pr_err("CPUs of %*pbl must have the same capacity\n",
232                                                         cpumask_pr_args(span));
233                         ret = -EINVAL;
234                         goto unlock;
235                 }
236                 prev_cap = cap;
237         }
238
239         /* Create the performance domain and add it to the Energy Model. */
240         pd = em_create_pd(span, nr_states, cb);
241         if (!pd) {
242                 ret = -EINVAL;
243                 goto unlock;
244         }
245
246         for_each_cpu(cpu, span) {
247                 /*
248                  * The per-cpu array can be read concurrently from em_cpu_get().
249                  * The barrier enforces the ordering needed to make sure readers
250                  * can only access well formed em_perf_domain structs.
251                  */
252                 smp_store_release(per_cpu_ptr(&em_data, cpu), pd);
253         }
254
255         pr_debug("Created perf domain %*pbl\n", cpumask_pr_args(span));
256 unlock:
257         mutex_unlock(&em_pd_mutex);
258
259         return ret;
260 }
261 EXPORT_SYMBOL_GPL(em_dev_register_perf_domain);
262
263 /**
264  * em_register_perf_domain() - Register the Energy Model of a performance domain
265  * @span        : Mask of CPUs in the performance domain
266  * @nr_states   : Number of capacity states to register
267  * @cb          : Callback functions providing the data of the Energy Model
268  *
269  * Create Energy Model tables for a performance domain using the callbacks
270  * defined in cb.
271  *
272  * If multiple clients register the same performance domain, all but the first
273  * registration will be ignored.
274  *
275  * Return 0 on success
276  */
277 int em_register_perf_domain(cpumask_t *span, unsigned int nr_states,
278                                                 struct em_data_callback *cb)
279 {
280         struct device *cpu_dev;
281
282         cpu_dev = get_cpu_device(cpumask_first(span));
283
284         return em_dev_register_perf_domain(cpu_dev, nr_states, cb, span);
285 }
286 EXPORT_SYMBOL_GPL(em_register_perf_domain);