]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/cpuidle/sysfs.c
rt2x00: do not generate seqno in h/w if QOS is disabled
[karo-tx-linux.git] / drivers / cpuidle / sysfs.c
1 /*
2  * sysfs.c - sysfs support
3  *
4  * (C) 2006-2007 Shaohua Li <shaohua.li@intel.com>
5  *
6  * This code is licenced under the GPL.
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/cpuidle.h>
11 #include <linux/sysfs.h>
12 #include <linux/slab.h>
13 #include <linux/cpu.h>
14
15 #include "cpuidle.h"
16
17 static unsigned int sysfs_switch;
18 static int __init cpuidle_sysfs_setup(char *unused)
19 {
20         sysfs_switch = 1;
21         return 1;
22 }
23 __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
24
25 static ssize_t show_available_governors(struct device *dev,
26                                         struct device_attribute *attr,
27                                         char *buf)
28 {
29         ssize_t i = 0;
30         struct cpuidle_governor *tmp;
31
32         mutex_lock(&cpuidle_lock);
33         list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
34                 if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
35                         goto out;
36                 i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
37         }
38
39 out:
40         i+= sprintf(&buf[i], "\n");
41         mutex_unlock(&cpuidle_lock);
42         return i;
43 }
44
45 static ssize_t show_current_driver(struct device *dev,
46                                    struct device_attribute *attr,
47                                    char *buf)
48 {
49         ssize_t ret;
50         struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
51
52         spin_lock(&cpuidle_driver_lock);
53         if (cpuidle_driver)
54                 ret = sprintf(buf, "%s\n", cpuidle_driver->name);
55         else
56                 ret = sprintf(buf, "none\n");
57         spin_unlock(&cpuidle_driver_lock);
58
59         return ret;
60 }
61
62 static ssize_t show_current_governor(struct device *dev,
63                                      struct device_attribute *attr,
64                                      char *buf)
65 {
66         ssize_t ret;
67
68         mutex_lock(&cpuidle_lock);
69         if (cpuidle_curr_governor)
70                 ret = sprintf(buf, "%s\n", cpuidle_curr_governor->name);
71         else
72                 ret = sprintf(buf, "none\n");
73         mutex_unlock(&cpuidle_lock);
74
75         return ret;
76 }
77
78 static ssize_t store_current_governor(struct device *dev,
79                                       struct device_attribute *attr,
80                                       const char *buf, size_t count)
81 {
82         char gov_name[CPUIDLE_NAME_LEN];
83         int ret = -EINVAL;
84         size_t len = count;
85         struct cpuidle_governor *gov;
86
87         if (!len || len >= sizeof(gov_name))
88                 return -EINVAL;
89
90         memcpy(gov_name, buf, len);
91         gov_name[len] = '\0';
92         if (gov_name[len - 1] == '\n')
93                 gov_name[--len] = '\0';
94
95         mutex_lock(&cpuidle_lock);
96
97         list_for_each_entry(gov, &cpuidle_governors, governor_list) {
98                 if (strlen(gov->name) == len && !strcmp(gov->name, gov_name)) {
99                         ret = cpuidle_switch_governor(gov);
100                         break;
101                 }
102         }
103
104         mutex_unlock(&cpuidle_lock);
105
106         if (ret)
107                 return ret;
108         else
109                 return count;
110 }
111
112 static DEVICE_ATTR(current_driver, 0444, show_current_driver, NULL);
113 static DEVICE_ATTR(current_governor_ro, 0444, show_current_governor, NULL);
114
115 static struct attribute *cpuidle_default_attrs[] = {
116         &dev_attr_current_driver.attr,
117         &dev_attr_current_governor_ro.attr,
118         NULL
119 };
120
121 static DEVICE_ATTR(available_governors, 0444, show_available_governors, NULL);
122 static DEVICE_ATTR(current_governor, 0644, show_current_governor,
123                    store_current_governor);
124
125 static struct attribute *cpuidle_switch_attrs[] = {
126         &dev_attr_available_governors.attr,
127         &dev_attr_current_driver.attr,
128         &dev_attr_current_governor.attr,
129         NULL
130 };
131
132 static struct attribute_group cpuidle_attr_group = {
133         .attrs = cpuidle_default_attrs,
134         .name = "cpuidle",
135 };
136
137 /**
138  * cpuidle_add_interface - add CPU global sysfs attributes
139  */
140 int cpuidle_add_interface(struct device *dev)
141 {
142         if (sysfs_switch)
143                 cpuidle_attr_group.attrs = cpuidle_switch_attrs;
144
145         return sysfs_create_group(&dev->kobj, &cpuidle_attr_group);
146 }
147
148 /**
149  * cpuidle_remove_interface - remove CPU global sysfs attributes
150  */
151 void cpuidle_remove_interface(struct device *dev)
152 {
153         sysfs_remove_group(&dev->kobj, &cpuidle_attr_group);
154 }
155
156 struct cpuidle_attr {
157         struct attribute attr;
158         ssize_t (*show)(struct cpuidle_device *, char *);
159         ssize_t (*store)(struct cpuidle_device *, const char *, size_t count);
160 };
161
162 #define define_one_ro(_name, show) \
163         static struct cpuidle_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
164 #define define_one_rw(_name, show, store) \
165         static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
166
167 #define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
168 #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
169 static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf)
170 {
171         int ret = -EIO;
172         struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
173         struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
174
175         if (cattr->show) {
176                 mutex_lock(&cpuidle_lock);
177                 ret = cattr->show(dev, buf);
178                 mutex_unlock(&cpuidle_lock);
179         }
180         return ret;
181 }
182
183 static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
184                      const char * buf, size_t count)
185 {
186         int ret = -EIO;
187         struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
188         struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
189
190         if (cattr->store) {
191                 mutex_lock(&cpuidle_lock);
192                 ret = cattr->store(dev, buf, count);
193                 mutex_unlock(&cpuidle_lock);
194         }
195         return ret;
196 }
197
198 static const struct sysfs_ops cpuidle_sysfs_ops = {
199         .show = cpuidle_show,
200         .store = cpuidle_store,
201 };
202
203 static void cpuidle_sysfs_release(struct kobject *kobj)
204 {
205         struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
206
207         complete(&dev->kobj_unregister);
208 }
209
210 static struct kobj_type ktype_cpuidle = {
211         .sysfs_ops = &cpuidle_sysfs_ops,
212         .release = cpuidle_sysfs_release,
213 };
214
215 struct cpuidle_state_attr {
216         struct attribute attr;
217         ssize_t (*show)(struct cpuidle_state *, \
218                                         struct cpuidle_state_usage *, char *);
219         ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
220 };
221
222 #define define_one_state_ro(_name, show) \
223 static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
224
225 #define define_show_state_function(_name) \
226 static ssize_t show_state_##_name(struct cpuidle_state *state, \
227                          struct cpuidle_state_usage *state_usage, char *buf) \
228 { \
229         return sprintf(buf, "%u\n", state->_name);\
230 }
231
232 #define define_show_state_ull_function(_name) \
233 static ssize_t show_state_##_name(struct cpuidle_state *state, \
234                         struct cpuidle_state_usage *state_usage, char *buf) \
235 { \
236         return sprintf(buf, "%llu\n", state_usage->_name);\
237 }
238
239 #define define_show_state_str_function(_name) \
240 static ssize_t show_state_##_name(struct cpuidle_state *state, \
241                         struct cpuidle_state_usage *state_usage, char *buf) \
242 { \
243         if (state->_name[0] == '\0')\
244                 return sprintf(buf, "<null>\n");\
245         return sprintf(buf, "%s\n", state->_name);\
246 }
247
248 define_show_state_function(exit_latency)
249 define_show_state_function(power_usage)
250 define_show_state_ull_function(usage)
251 define_show_state_ull_function(time)
252 define_show_state_str_function(name)
253 define_show_state_str_function(desc)
254
255 define_one_state_ro(name, show_state_name);
256 define_one_state_ro(desc, show_state_desc);
257 define_one_state_ro(latency, show_state_exit_latency);
258 define_one_state_ro(power, show_state_power_usage);
259 define_one_state_ro(usage, show_state_usage);
260 define_one_state_ro(time, show_state_time);
261
262 static struct attribute *cpuidle_state_default_attrs[] = {
263         &attr_name.attr,
264         &attr_desc.attr,
265         &attr_latency.attr,
266         &attr_power.attr,
267         &attr_usage.attr,
268         &attr_time.attr,
269         NULL
270 };
271
272 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
273 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
274 #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
275 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
276 static ssize_t cpuidle_state_show(struct kobject * kobj,
277         struct attribute * attr ,char * buf)
278 {
279         int ret = -EIO;
280         struct cpuidle_state *state = kobj_to_state(kobj);
281         struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
282         struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
283
284         if (cattr->show)
285                 ret = cattr->show(state, state_usage, buf);
286
287         return ret;
288 }
289
290 static const struct sysfs_ops cpuidle_state_sysfs_ops = {
291         .show = cpuidle_state_show,
292 };
293
294 static void cpuidle_state_sysfs_release(struct kobject *kobj)
295 {
296         struct cpuidle_state_kobj *state_obj = kobj_to_state_obj(kobj);
297
298         complete(&state_obj->kobj_unregister);
299 }
300
301 static struct kobj_type ktype_state_cpuidle = {
302         .sysfs_ops = &cpuidle_state_sysfs_ops,
303         .default_attrs = cpuidle_state_default_attrs,
304         .release = cpuidle_state_sysfs_release,
305 };
306
307 static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
308 {
309         kobject_put(&device->kobjs[i]->kobj);
310         wait_for_completion(&device->kobjs[i]->kobj_unregister);
311         kfree(device->kobjs[i]);
312         device->kobjs[i] = NULL;
313 }
314
315 /**
316  * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
317  * @device: the target device
318  */
319 int cpuidle_add_state_sysfs(struct cpuidle_device *device)
320 {
321         int i, ret = -ENOMEM;
322         struct cpuidle_state_kobj *kobj;
323         struct cpuidle_driver *drv = cpuidle_get_driver();
324
325         /* state statistics */
326         for (i = 0; i < device->state_count; i++) {
327                 kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
328                 if (!kobj)
329                         goto error_state;
330                 kobj->state = &drv->states[i];
331                 kobj->state_usage = &device->states_usage[i];
332                 init_completion(&kobj->kobj_unregister);
333
334                 ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
335                                            "state%d", i);
336                 if (ret) {
337                         kfree(kobj);
338                         goto error_state;
339                 }
340                 kobject_uevent(&kobj->kobj, KOBJ_ADD);
341                 device->kobjs[i] = kobj;
342         }
343
344         return 0;
345
346 error_state:
347         for (i = i - 1; i >= 0; i--)
348                 cpuidle_free_state_kobj(device, i);
349         return ret;
350 }
351
352 /**
353  * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
354  * @device: the target device
355  */
356 void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
357 {
358         int i;
359
360         for (i = 0; i < device->state_count; i++)
361                 cpuidle_free_state_kobj(device, i);
362 }
363
364 /**
365  * cpuidle_add_sysfs - creates a sysfs instance for the target device
366  * @dev: the target device
367  */
368 int cpuidle_add_sysfs(struct device *cpu_dev)
369 {
370         int cpu = cpu_dev->id;
371         struct cpuidle_device *dev;
372         int error;
373
374         dev = per_cpu(cpuidle_devices, cpu);
375         error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
376                                      "cpuidle");
377         if (!error)
378                 kobject_uevent(&dev->kobj, KOBJ_ADD);
379         return error;
380 }
381
382 /**
383  * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
384  * @dev: the target device
385  */
386 void cpuidle_remove_sysfs(struct device *cpu_dev)
387 {
388         int cpu = cpu_dev->id;
389         struct cpuidle_device *dev;
390
391         dev = per_cpu(cpuidle_devices, cpu);
392         kobject_put(&dev->kobj);
393 }