Revert "ARM: tegra: tegratab: dummy change"
[linux-2.6.git] / drivers / edp / edp_sysfs.c
1 /*
2  * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/edp.h>
20 #include <linux/slab.h>
21 #include "edp_internal.h"
22
23 static struct kobject edp_kobj;
24
25 struct manager_entry {
26         struct edp_manager *manager;
27         struct kobject kobj;
28 };
29
30 struct manager_attr {
31         struct attribute attr;
32         ssize_t (*show)(struct edp_manager *, char *);
33         ssize_t (*store)(struct edp_manager *, const char *, size_t);
34 };
35
36 static ssize_t cap_show(struct edp_manager *m, char *s)
37 {
38         return scnprintf(s, PAGE_SIZE, "%u\n", m->max);
39 }
40
41 static ssize_t remaining_show(struct edp_manager *m, char *s)
42 {
43         return scnprintf(s, PAGE_SIZE, "%u\n", m->remaining);
44 }
45
46 static ssize_t denied_show(struct edp_manager *m, char *s)
47 {
48         return scnprintf(s, PAGE_SIZE, "%u\n", m->num_denied);
49 }
50
51 static ssize_t manager_governor_show(struct edp_manager *m, char *s)
52 {
53         return scnprintf(s, PAGE_SIZE, "%s\n", m->gov ? m->gov->name : "");
54 }
55
56 static ssize_t manager_governor_store(struct edp_manager *m, const char *s,
57                 size_t count)
58 {
59         char name[EDP_NAME_LEN];
60         struct edp_governor *gov;
61
62         if (!count || count >= sizeof(name))
63                 return -EINVAL;
64
65         memcpy(name, s, count);
66         name[count] = 0;
67         strim(name);
68         gov = edp_find_governor_unlocked(name);
69         if (!gov)
70                 return -EINVAL;
71
72         return edp_set_governor_unlocked(m, gov) ?: count;
73 }
74
75 struct manager_attr attr_cap = __ATTR_RO(cap);
76 struct manager_attr attr_remaining = __ATTR_RO(remaining);
77 struct manager_attr attr_denied = __ATTR_RO(denied);
78 struct manager_attr attr_mgr_gov = __ATTR(governor, 0644,
79                 manager_governor_show, manager_governor_store);
80
81 static struct attribute *manager_attrs[] = {
82         &attr_cap.attr,
83         &attr_remaining.attr,
84         &attr_denied.attr,
85         &attr_mgr_gov.attr,
86         NULL
87 };
88
89 static struct edp_manager *to_manager(struct kobject *kobj)
90 {
91         struct manager_entry *me = container_of(kobj, struct manager_entry,
92                         kobj);
93         return me ? me->manager : NULL;
94 }
95
96 static ssize_t manager_state_show(struct kobject *kobj,
97                 struct attribute *attr, char *buf)
98 {
99         ssize_t r;
100         struct edp_manager *m;
101         struct manager_attr *mattr;
102
103         mutex_lock(&edp_lock);
104         m = to_manager(kobj);
105         mattr = container_of(attr, struct manager_attr, attr);
106         r = m && mattr ? mattr->show(m, buf) : -EINVAL;
107         mutex_unlock(&edp_lock);
108
109         return r;
110 }
111
112 static ssize_t manager_state_store(struct kobject *kobj,
113                 struct attribute *attr, const char *buf, size_t count)
114 {
115         ssize_t r;
116         struct edp_manager *m;
117         struct manager_attr *mattr;
118
119         mutex_lock(&edp_lock);
120         m = to_manager(kobj);
121         mattr = container_of(attr, struct manager_attr, attr);
122         r = m && mattr ? mattr->store(m, buf, count) : -EINVAL;
123         mutex_unlock(&edp_lock);
124
125         return r;
126 }
127
128 static const struct sysfs_ops manager_sysfs_ops = {
129         .show = manager_state_show,
130         .store = manager_state_store
131 };
132
133 static struct kobj_type ktype_manager = {
134         .sysfs_ops = &manager_sysfs_ops,
135         .default_attrs = manager_attrs
136 };
137
138 void edp_manager_add_kobject(struct edp_manager *mgr)
139 {
140         struct manager_entry *me;
141
142         me = kzalloc(sizeof(*me), GFP_KERNEL);
143         if (!me) {
144                 pr_err("%s: failed to alloc sysfs manager entry\n",
145                                 mgr->name);
146                 return;
147         }
148
149         if (kobject_init_and_add(&me->kobj, &ktype_manager, &edp_kobj,
150                                 mgr->name)) {
151                 pr_err("%s: failed to init & add sysfs manager entry\n",
152                                 mgr->name);
153                 kfree(me);
154                 return;
155         }
156
157         me->manager = mgr;
158         mgr->kobj = &me->kobj;
159         kobject_uevent(&me->kobj, KOBJ_ADD);
160         return;
161 }
162
163 void edp_manager_remove_kobject(struct edp_manager *mgr)
164 {
165         struct manager_entry *me;
166
167         if (!mgr->kobj)
168                 return;
169
170         me = container_of(mgr->kobj, struct manager_entry, kobj);
171         mgr->kobj = NULL;
172         kobject_put(&me->kobj);
173         kfree(me);
174 }
175
176 struct client_entry {
177         struct edp_client *client;
178         struct kobject kobj;
179 };
180
181 static ssize_t states_show(struct edp_client *c,
182                 struct edp_client_attribute *attr, char *s)
183 {
184         unsigned int i;
185         int cnt = 0;
186         const int sz = sizeof(*c->states) * 3 + 2;
187
188         for (i = 0; i < c->num_states && (cnt + sz) < PAGE_SIZE; i++)
189                 cnt += sprintf(s + cnt, "%s%u", i ? " " : "", c->states[i]);
190
191         cnt += sprintf(s + cnt, "\n");
192         return cnt;
193 }
194
195 static ssize_t num_states_show(struct edp_client *c,
196                 struct edp_client_attribute *attr, char *s)
197 {
198         return scnprintf(s, PAGE_SIZE, "%u\n", c->num_states);
199 }
200
201 static ssize_t e0_show(struct edp_client *c,
202                 struct edp_client_attribute *attr, char *s)
203 {
204         return scnprintf(s, PAGE_SIZE, "%u\n", c->states[c->e0_index]);
205 }
206
207 static ssize_t max_borrowers_show(struct edp_client *c,
208                 struct edp_client_attribute *attr, char *s)
209 {
210         return scnprintf(s, PAGE_SIZE, "%u\n", c->max_borrowers);
211 }
212
213 static ssize_t priority_show(struct edp_client *c,
214                 struct edp_client_attribute *attr, char *s)
215 {
216         return scnprintf(s, PAGE_SIZE, "%d\n", c->priority);
217 }
218
219 static ssize_t request_show(struct edp_client *c,
220                 struct edp_client_attribute *attr, char *s)
221 {
222         return scnprintf(s, PAGE_SIZE, "%u\n", req_level(c));
223 }
224
225 /* Allow only updates that are guaranteed to succeed */
226 static ssize_t request_store(struct edp_client *c,
227                 struct edp_client_attribute *attr, const char *s, size_t count)
228 {
229         unsigned int id;
230         int r;
231
232         if (sscanf(s, "%u", &id) != 1)
233                 return -EINVAL;
234
235         mutex_lock(&edp_lock);
236
237         if (id >= c->num_states) {
238                 r = -EINVAL;
239                 goto out;
240         }
241
242         if (id < c->e0_index && id < req_index(c)) {
243                 r = -EPERM;
244                 goto out;
245         }
246
247         r = edp_update_client_request_unlocked(c, id, NULL);
248
249 out:
250         mutex_unlock(&edp_lock);
251         return r ?: count;
252 }
253
254 static ssize_t current_show(struct edp_client *c,
255                 struct edp_client_attribute *attr, char *s)
256 {
257         return scnprintf(s, PAGE_SIZE, "%u\n", cur_level(c));
258 }
259
260 static ssize_t threshold_show(struct edp_client *c,
261                 struct edp_client_attribute *attr, char *s)
262 {
263         return scnprintf(s, PAGE_SIZE, "%u\n", c->ithreshold);
264 }
265
266 static ssize_t threshold_store(struct edp_client *c,
267                 struct edp_client_attribute *attr, const char *s, size_t count)
268 {
269         unsigned int tv;
270         int r;
271
272         if (sscanf(s, "%u", &tv) != 1)
273                 return -EINVAL;
274
275         r = edp_update_loan_threshold(c, tv);
276         return r ?: count;
277 }
278
279 static ssize_t borrowers_show(struct edp_client *c,
280                 struct edp_client_attribute *attr, char *s)
281 {
282         return scnprintf(s, PAGE_SIZE, "%u\n", c->num_borrowers);
283 }
284
285 static ssize_t loans_show(struct edp_client *c,
286                 struct edp_client_attribute *attr, char *s)
287 {
288         return scnprintf(s, PAGE_SIZE, "%u\n", c->num_loans);
289 }
290
291 static ssize_t notify_show(struct edp_client *c,
292                 struct edp_client_attribute *attr, char *s)
293 {
294         return scnprintf(s, PAGE_SIZE, "%u\n", c->notify_ui);
295 }
296
297 static ssize_t notify_store(struct edp_client *c,
298                 struct edp_client_attribute *attr, const char *s, size_t count)
299 {
300         unsigned int f;
301
302         if (sscanf(s, "%u", &f) != 1)
303                 return -EINVAL;
304         c->notify_ui = f;
305         return count;
306 }
307
308 struct edp_client_attribute attr_states = __ATTR_RO(states);
309 struct edp_client_attribute attr_num_states = __ATTR_RO(num_states);
310 struct edp_client_attribute attr_e0 = __ATTR_RO(e0);
311 struct edp_client_attribute attr_max_borrowers = __ATTR_RO(max_borrowers);
312 struct edp_client_attribute attr_priority = __ATTR_RO(priority);
313 struct edp_client_attribute attr_request = __ATTR(request, 0644, request_show,
314                 request_store);
315 struct edp_client_attribute attr_threshold = __ATTR(threshold, 0644,
316                 threshold_show, threshold_store);
317 struct edp_client_attribute attr_borrowers = __ATTR_RO(borrowers);
318 struct edp_client_attribute attr_loans = __ATTR_RO(loans);
319 struct edp_client_attribute attr_current = {
320         .attr = { .name = "current", .mode = 0444 },
321         .show = current_show
322 };
323 struct edp_client_attribute attr_notify = __ATTR(notify, 0644, notify_show,
324                 notify_store);
325
326 static struct attribute *client_attrs[] = {
327         &attr_states.attr,
328         &attr_num_states.attr,
329         &attr_e0.attr,
330         &attr_max_borrowers.attr,
331         &attr_priority.attr,
332         &attr_request.attr,
333         &attr_current.attr,
334         &attr_threshold.attr,
335         &attr_borrowers.attr,
336         &attr_loans.attr,
337         &attr_notify.attr,
338         NULL
339 };
340
341 static struct edp_client *to_client(struct kobject *kobj)
342 {
343         struct client_entry *ce = container_of(kobj, struct client_entry,
344                         kobj);
345         return ce ? ce->client : NULL;
346 }
347
348 static ssize_t client_state_show(struct kobject *kobj,
349                 struct attribute *attr, char *buf)
350 {
351         ssize_t r = -EINVAL;
352         struct edp_client *c;
353         struct edp_client_attribute *cattr;
354
355         c = to_client(kobj);
356         cattr = container_of(attr, struct edp_client_attribute, attr);
357         if (c && cattr) {
358                 if (cattr->show)
359                         r = cattr->show(c, cattr, buf);
360         }
361
362         return r;
363 }
364
365 static ssize_t client_state_store(struct kobject *kobj,
366                 struct attribute *attr, const char *buf, size_t count)
367 {
368         ssize_t r = -EINVAL;
369         struct edp_client *c;
370         struct edp_client_attribute *cattr;
371
372         c = to_client(kobj);
373         cattr = container_of(attr, struct edp_client_attribute, attr);
374         if (c && cattr) {
375                 if (cattr->store)
376                         r = cattr->store(c, cattr, buf, count);
377         }
378
379         return r;
380 }
381
382 static const struct sysfs_ops client_sysfs_ops = {
383         .show = client_state_show,
384         .store = client_state_store
385 };
386
387 static struct kobj_type ktype_client = {
388         .sysfs_ops = &client_sysfs_ops,
389         .default_attrs = client_attrs
390 };
391
392 static void create_driver_attrs(struct edp_client *c)
393 {
394         struct edp_client_attribute *p;
395         int r;
396
397         if (!c->attrs)
398                 return;
399
400         for (p = c->attrs; attr_name(*p); p++) {
401                 r = sysfs_create_file(c->kobj, &p->attr);
402                 WARN_ON(r);
403         }
404 }
405
406 static void remove_driver_attrs(struct edp_client *c)
407 {
408         struct edp_client_attribute *p;
409
410         if (!c->attrs)
411                 return;
412
413         for (p = c->attrs; attr_name(*p); p++)
414                 sysfs_remove_file(c->kobj, &p->attr);
415 }
416
417 void edp_client_add_kobject(struct edp_client *client)
418 {
419         struct client_entry *ce;
420         struct kobject *parent = client->manager->kobj;
421
422         if (!parent)
423                 return;
424
425         ce = kzalloc(sizeof(*ce), GFP_KERNEL);
426         if (!ce) {
427                 pr_err("%s: failed to alloc sysfs client entry\n",
428                                 client->name);
429                 return;
430         }
431
432         if (kobject_init_and_add(&ce->kobj, &ktype_client, parent,
433                                 client->name)) {
434                 pr_err("%s: failed to init & add sysfs client entry\n",
435                                 client->name);
436                 kfree(ce);
437                 return;
438         }
439
440         ce->client = client;
441         client->kobj = &ce->kobj;
442         create_driver_attrs(client);
443         kobject_uevent(&ce->kobj, KOBJ_ADD);
444 }
445
446 void edp_client_remove_kobject(struct edp_client *client)
447 {
448         struct client_entry *ce;
449
450         if (!client->kobj)
451                 return;
452
453         ce = container_of(client->kobj, struct client_entry, kobj);
454
455         remove_driver_attrs(client);
456         client->kobj = NULL;
457         kobject_put(&ce->kobj);
458         kfree(ce);
459 }
460
461 static ssize_t governors_show(struct kobject *kobj, struct attribute *attr,
462                 char *s)
463 {
464         struct edp_governor *g;
465         int cnt = 0;
466
467         mutex_lock(&edp_lock);
468
469         list_for_each_entry(g, &edp_governors, link) {
470                 if (cnt + EDP_NAME_LEN + 2 >= PAGE_SIZE)
471                         break;
472                 cnt += sprintf(s + cnt, "%s%s", cnt ? " " : "", g->name);
473         }
474
475         cnt += sprintf(s + cnt, "\n");
476
477         mutex_unlock(&edp_lock);
478
479         return cnt;
480 }
481
482 static const struct sysfs_ops edp_sysfs_ops = {
483         .show = governors_show
484 };
485
486 static struct attribute attr_governors = {
487         .name = "governors",
488         .mode = 0444
489 };
490
491 static struct attribute *edp_attrs[] = {
492         &attr_governors,
493         NULL
494 };
495
496 static struct kobj_type ktype_edp = {
497         .sysfs_ops = &edp_sysfs_ops,
498         .default_attrs = edp_attrs
499 };
500
501 static int __init edp_sysfs_init(void)
502 {
503         struct kobject *parent = NULL;
504
505 #ifdef CONFIG_PM
506         parent = power_kobj;
507 #endif
508
509         return kobject_init_and_add(&edp_kobj, &ktype_edp, parent, "edp");
510 }
511 postcore_initcall(edp_sysfs_init);