platform/x86: intel-uncore-freq: Fix types in sysfs callbacks
[sfrench/cifs-2.6.git] / drivers / platform / x86 / intel / uncore-frequency / uncore-frequency-common.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Uncore Frequency Control: Common code implementation
4  * Copyright (c) 2022, Intel Corporation.
5  * All rights reserved.
6  *
7  */
8 #include <linux/cpu.h>
9 #include <linux/module.h>
10 #include "uncore-frequency-common.h"
11
12 /* Mutex to control all mutual exclusions */
13 static DEFINE_MUTEX(uncore_lock);
14 /* Root of the all uncore sysfs kobjs */
15 static struct kobject *uncore_root_kobj;
16 /* uncore instance count */
17 static int uncore_instance_count;
18
19 static DEFINE_IDA(intel_uncore_ida);
20
21 /* callbacks for actual HW read/write */
22 static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max);
23 static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max);
24 static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq);
25
26 static ssize_t show_domain_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
27 {
28         struct uncore_data *data = container_of(attr, struct uncore_data, domain_id_kobj_attr);
29
30         return sprintf(buf, "%u\n", data->domain_id);
31 }
32
33 static ssize_t show_fabric_cluster_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
34 {
35         struct uncore_data *data = container_of(attr, struct uncore_data, fabric_cluster_id_kobj_attr);
36
37         return sprintf(buf, "%u\n", data->cluster_id);
38 }
39
40 static ssize_t show_package_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
41 {
42         struct uncore_data *data = container_of(attr, struct uncore_data, package_id_kobj_attr);
43
44         return sprintf(buf, "%u\n", data->package_id);
45 }
46
47 static ssize_t show_min_max_freq_khz(struct uncore_data *data,
48                                       char *buf, int min_max)
49 {
50         unsigned int min, max;
51         int ret;
52
53         mutex_lock(&uncore_lock);
54         ret = uncore_read(data, &min, &max);
55         mutex_unlock(&uncore_lock);
56         if (ret)
57                 return ret;
58
59         if (min_max)
60                 return sprintf(buf, "%u\n", max);
61
62         return sprintf(buf, "%u\n", min);
63 }
64
65 static ssize_t store_min_max_freq_khz(struct uncore_data *data,
66                                       const char *buf, ssize_t count,
67                                       int min_max)
68 {
69         unsigned int input;
70         int ret;
71
72         if (kstrtouint(buf, 10, &input))
73                 return -EINVAL;
74
75         mutex_lock(&uncore_lock);
76         ret = uncore_write(data, input, min_max);
77         mutex_unlock(&uncore_lock);
78
79         if (ret)
80                 return ret;
81
82         return count;
83 }
84
85 static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf)
86 {
87         unsigned int freq;
88         int ret;
89
90         mutex_lock(&uncore_lock);
91         ret = uncore_read_freq(data, &freq);
92         mutex_unlock(&uncore_lock);
93         if (ret)
94                 return ret;
95
96         return sprintf(buf, "%u\n", freq);
97 }
98
99 #define store_uncore_min_max(name, min_max)                             \
100         static ssize_t store_##name(struct kobject *kobj,               \
101                                      struct kobj_attribute *attr,       \
102                                      const char *buf, size_t count)     \
103         {                                                               \
104                 struct uncore_data *data = container_of(attr, struct uncore_data, name##_kobj_attr);\
105                                                                         \
106                 return store_min_max_freq_khz(data, buf, count, \
107                                               min_max);         \
108         }
109
110 #define show_uncore_min_max(name, min_max)                              \
111         static ssize_t show_##name(struct kobject *kobj,                \
112                                     struct kobj_attribute *attr, char *buf)\
113         {                                                               \
114                 struct uncore_data *data = container_of(attr, struct uncore_data, name##_kobj_attr);\
115                                                                         \
116                 return show_min_max_freq_khz(data, buf, min_max);       \
117         }
118
119 #define show_uncore_perf_status(name)                                   \
120         static ssize_t show_##name(struct kobject *kobj,                \
121                                    struct kobj_attribute *attr, char *buf)\
122         {                                                               \
123                 struct uncore_data *data = container_of(attr, struct uncore_data, name##_kobj_attr);\
124                                                                         \
125                 return show_perf_status_freq_khz(data, buf); \
126         }
127
128 store_uncore_min_max(min_freq_khz, 0);
129 store_uncore_min_max(max_freq_khz, 1);
130
131 show_uncore_min_max(min_freq_khz, 0);
132 show_uncore_min_max(max_freq_khz, 1);
133
134 show_uncore_perf_status(current_freq_khz);
135
136 #define show_uncore_data(member_name)                                   \
137         static ssize_t show_##member_name(struct kobject *kobj, \
138                                            struct kobj_attribute *attr, char *buf)\
139         {                                                               \
140                 struct uncore_data *data = container_of(attr, struct uncore_data,\
141                                                           member_name##_kobj_attr);\
142                                                                         \
143                 return sysfs_emit(buf, "%u\n",                          \
144                                  data->member_name);                    \
145         }                                                               \
146
147 show_uncore_data(initial_min_freq_khz);
148 show_uncore_data(initial_max_freq_khz);
149
150 #define init_attribute_rw(_name)                                        \
151         do {                                                            \
152                 sysfs_attr_init(&data->_name##_kobj_attr.attr); \
153                 data->_name##_kobj_attr.show = show_##_name;            \
154                 data->_name##_kobj_attr.store = store_##_name;          \
155                 data->_name##_kobj_attr.attr.name = #_name;             \
156                 data->_name##_kobj_attr.attr.mode = 0644;               \
157         } while (0)
158
159 #define init_attribute_ro(_name)                                        \
160         do {                                                            \
161                 sysfs_attr_init(&data->_name##_kobj_attr.attr); \
162                 data->_name##_kobj_attr.show = show_##_name;            \
163                 data->_name##_kobj_attr.store = NULL;                   \
164                 data->_name##_kobj_attr.attr.name = #_name;             \
165                 data->_name##_kobj_attr.attr.mode = 0444;               \
166         } while (0)
167
168 #define init_attribute_root_ro(_name)                                   \
169         do {                                                            \
170                 sysfs_attr_init(&data->_name##_kobj_attr.attr); \
171                 data->_name##_kobj_attr.show = show_##_name;            \
172                 data->_name##_kobj_attr.store = NULL;                   \
173                 data->_name##_kobj_attr.attr.name = #_name;             \
174                 data->_name##_kobj_attr.attr.mode = 0400;               \
175         } while (0)
176
177 static int create_attr_group(struct uncore_data *data, char *name)
178 {
179         int ret, freq, index = 0;
180
181         init_attribute_rw(max_freq_khz);
182         init_attribute_rw(min_freq_khz);
183         init_attribute_ro(initial_min_freq_khz);
184         init_attribute_ro(initial_max_freq_khz);
185         init_attribute_root_ro(current_freq_khz);
186
187         if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) {
188                 init_attribute_root_ro(domain_id);
189                 data->uncore_attrs[index++] = &data->domain_id_kobj_attr.attr;
190                 init_attribute_root_ro(fabric_cluster_id);
191                 data->uncore_attrs[index++] = &data->fabric_cluster_id_kobj_attr.attr;
192                 init_attribute_root_ro(package_id);
193                 data->uncore_attrs[index++] = &data->package_id_kobj_attr.attr;
194         }
195
196         data->uncore_attrs[index++] = &data->max_freq_khz_kobj_attr.attr;
197         data->uncore_attrs[index++] = &data->min_freq_khz_kobj_attr.attr;
198         data->uncore_attrs[index++] = &data->initial_min_freq_khz_kobj_attr.attr;
199         data->uncore_attrs[index++] = &data->initial_max_freq_khz_kobj_attr.attr;
200
201         ret = uncore_read_freq(data, &freq);
202         if (!ret)
203                 data->uncore_attrs[index++] = &data->current_freq_khz_kobj_attr.attr;
204
205         data->uncore_attrs[index] = NULL;
206
207         data->uncore_attr_group.name = name;
208         data->uncore_attr_group.attrs = data->uncore_attrs;
209         ret = sysfs_create_group(uncore_root_kobj, &data->uncore_attr_group);
210
211         return ret;
212 }
213
214 static void delete_attr_group(struct uncore_data *data, char *name)
215 {
216         sysfs_remove_group(uncore_root_kobj, &data->uncore_attr_group);
217 }
218
219 int uncore_freq_add_entry(struct uncore_data *data, int cpu)
220 {
221         int ret = 0;
222
223         mutex_lock(&uncore_lock);
224         if (data->valid) {
225                 /* control cpu changed */
226                 data->control_cpu = cpu;
227                 goto uncore_unlock;
228         }
229
230         if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) {
231                 ret = ida_alloc(&intel_uncore_ida, GFP_KERNEL);
232                 if (ret < 0)
233                         goto uncore_unlock;
234
235                 data->instance_id = ret;
236                 sprintf(data->name, "uncore%02d", ret);
237         } else {
238                 sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
239         }
240
241         uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz);
242
243         ret = create_attr_group(data, data->name);
244         if (ret) {
245                 if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
246                         ida_free(&intel_uncore_ida, data->instance_id);
247         } else {
248                 data->control_cpu = cpu;
249                 data->valid = true;
250         }
251
252 uncore_unlock:
253         mutex_unlock(&uncore_lock);
254
255         return ret;
256 }
257 EXPORT_SYMBOL_NS_GPL(uncore_freq_add_entry, INTEL_UNCORE_FREQUENCY);
258
259 void uncore_freq_remove_die_entry(struct uncore_data *data)
260 {
261         mutex_lock(&uncore_lock);
262         delete_attr_group(data, data->name);
263         data->control_cpu = -1;
264         data->valid = false;
265         if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
266                 ida_free(&intel_uncore_ida, data->instance_id);
267
268         mutex_unlock(&uncore_lock);
269 }
270 EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY);
271
272 int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max),
273                              int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int set_max),
274                              int (*read_freq)(struct uncore_data *data, unsigned int *freq))
275 {
276         mutex_lock(&uncore_lock);
277
278         uncore_read = read_control_freq;
279         uncore_write = write_control_freq;
280         uncore_read_freq = read_freq;
281
282         if (!uncore_root_kobj) {
283                 struct device *dev_root = bus_get_dev_root(&cpu_subsys);
284
285                 if (dev_root) {
286                         uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency",
287                                                                   &dev_root->kobj);
288                         put_device(dev_root);
289                 }
290         }
291         if (uncore_root_kobj)
292                 ++uncore_instance_count;
293         mutex_unlock(&uncore_lock);
294
295         return uncore_root_kobj ? 0 : -ENOMEM;
296 }
297 EXPORT_SYMBOL_NS_GPL(uncore_freq_common_init, INTEL_UNCORE_FREQUENCY);
298
299 void uncore_freq_common_exit(void)
300 {
301         mutex_lock(&uncore_lock);
302         --uncore_instance_count;
303         if (!uncore_instance_count) {
304                 kobject_put(uncore_root_kobj);
305                 uncore_root_kobj = NULL;
306         }
307         mutex_unlock(&uncore_lock);
308 }
309 EXPORT_SYMBOL_NS_GPL(uncore_freq_common_exit, INTEL_UNCORE_FREQUENCY);
310
311
312 MODULE_LICENSE("GPL v2");
313 MODULE_DESCRIPTION("Intel Uncore Frequency Common Module");