fix rga2 soft reset may cause rga status uncorrect
[firefly-linux-kernel-4.4.55.git] / drivers / cpuquiet / 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
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that 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 along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16  *
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/sysfs.h>
21 #include <linux/slab.h>
22 #include <linux/cpuquiet.h>
23
24 #include "cpuquiet.h"
25
26 struct cpuquiet_dev {
27         unsigned int cpu;
28         struct kobject kobj;
29 };
30
31 struct cpuquiet_sysfs_attr {
32         struct attribute attr;
33         ssize_t (*show)(char *);
34         ssize_t (*store)(const char *, size_t count);
35 };
36
37 static struct kobject *cpuquiet_global_kobject;
38 struct cpuquiet_dev *cpuquiet_cpu_devices[CONFIG_NR_CPUS];
39
40 static ssize_t show_current_governor(char *buf)
41 {
42         ssize_t ret;
43
44         mutex_lock(&cpuquiet_lock);
45
46         if (cpuquiet_curr_governor)
47                 ret = sprintf(buf, "%s\n", cpuquiet_curr_governor->name);
48         else
49                 ret = sprintf(buf, "none\n");
50
51         mutex_unlock(&cpuquiet_lock);
52
53         return ret;
54
55 }
56
57 static ssize_t store_current_governor(const char *buf, size_t count)
58 {
59         char name[CPUQUIET_NAME_LEN];
60         struct cpuquiet_governor *gov;
61         int len = count, ret = -EINVAL;
62
63         if (!len || len >= sizeof(name))
64                 return -EINVAL;
65
66         memcpy(name, buf, count);
67         name[len] = '\0';
68         if (name[len - 1] == '\n')
69                 name[--len] = '\0';
70
71         mutex_lock(&cpuquiet_lock);
72         gov = cpuquiet_find_governor(name);
73
74         if (gov)
75                 ret = cpuquiet_switch_governor(gov);
76         mutex_unlock(&cpuquiet_lock);
77
78         if (ret)
79                 return ret;
80         else
81                 return count;
82 }
83
84 static ssize_t available_governors_show(char *buf)
85 {
86         ssize_t ret = 0, len;
87         struct cpuquiet_governor *gov;
88
89         mutex_lock(&cpuquiet_lock);
90         if (!list_empty(&cpuquiet_governors)) {
91                 list_for_each_entry(gov, &cpuquiet_governors, governor_list) {
92                         len = sprintf(buf, "%s ", gov->name);
93                         buf += len;
94                         ret += len;
95                 }
96                 buf--;
97                 *buf = '\n';
98         } else
99                 ret = sprintf(buf, "none\n");
100
101         mutex_unlock(&cpuquiet_lock);
102
103         return ret;
104 }
105
106 struct cpuquiet_sysfs_attr attr_current_governor = __ATTR(current_governor,
107                         0644, show_current_governor, store_current_governor);
108 struct cpuquiet_sysfs_attr attr_governors = __ATTR_RO(available_governors);
109
110
111 static struct attribute *cpuquiet_default_attrs[] = {
112         &attr_current_governor.attr,
113         &attr_governors.attr,
114         NULL
115 };
116
117 static ssize_t cpuquiet_sysfs_show(struct kobject *kobj,
118                         struct attribute *attr, char *buf)
119 {
120         struct cpuquiet_sysfs_attr *cattr =
121                         container_of(attr, struct cpuquiet_sysfs_attr, attr);
122
123         return cattr->show(buf);
124 }
125
126 static ssize_t cpuquiet_sysfs_store(struct kobject *kobj,
127                         struct attribute *attr, const char *buf, size_t count)
128 {
129         struct cpuquiet_sysfs_attr *cattr =
130                         container_of(attr, struct cpuquiet_sysfs_attr, attr);
131
132         if (cattr->store)
133                 return cattr->store(buf, count);
134
135         return -EINVAL;
136 }
137
138 static const struct sysfs_ops cpuquiet_sysfs_ops = {
139         .show = cpuquiet_sysfs_show,
140         .store = cpuquiet_sysfs_store,
141 };
142
143 static struct kobj_type ktype_cpuquiet_sysfs = {
144         .sysfs_ops = &cpuquiet_sysfs_ops,
145         .default_attrs = cpuquiet_default_attrs,
146 };
147
148 int cpuquiet_add_group(struct attribute_group *attrs)
149 {
150         return sysfs_create_group(cpuquiet_global_kobject, attrs);
151 }
152
153 void cpuquiet_remove_group(struct attribute_group *attrs)
154 {
155         sysfs_remove_group(cpuquiet_global_kobject, attrs);
156 }
157
158 int cpuquiet_kobject_init(struct kobject *kobj, struct kobj_type *type,
159                                 char *name)
160 {
161         int err;
162
163         err = kobject_init_and_add(kobj, type, cpuquiet_global_kobject, name);
164         if (!err)
165                 kobject_uevent(kobj, KOBJ_ADD);
166
167         return err;
168 }
169
170 int cpuquiet_cpu_kobject_init(struct kobject *kobj, struct kobj_type *type,
171                                 char *name, int cpu)
172 {
173         int err;
174
175         err = kobject_init_and_add(kobj, type, &cpuquiet_cpu_devices[cpu]->kobj,
176                                         name);
177         if (!err)
178                 kobject_uevent(kobj, KOBJ_ADD);
179
180         return err;
181 }
182
183 int cpuquiet_add_interface(struct device *dev)
184 {
185         int err;
186
187         cpuquiet_global_kobject = kzalloc(sizeof(*cpuquiet_global_kobject),
188                                                 GFP_KERNEL);
189         if (!cpuquiet_global_kobject)
190                 return -ENOMEM;
191
192         err = kobject_init_and_add(cpuquiet_global_kobject,
193                         &ktype_cpuquiet_sysfs, &dev->kobj, "cpuquiet");
194         if (!err)
195                 kobject_uevent(cpuquiet_global_kobject, KOBJ_ADD);
196
197         return err;
198 }
199
200
201 struct cpuquiet_attr {
202         struct attribute attr;
203         ssize_t (*show)(unsigned int, char *);
204         ssize_t (*store)(unsigned int, const char *, size_t count);
205 };
206
207
208 static ssize_t cpuquiet_state_show(struct kobject *kobj,
209         struct attribute *attr, char *buf)
210 {
211         struct cpuquiet_attr *cattr = container_of(attr,
212                                         struct cpuquiet_attr, attr);
213         struct cpuquiet_dev *dev = container_of(kobj,
214                                         struct cpuquiet_dev, kobj);
215
216         return cattr->show(dev->cpu, buf);
217 }
218
219 static ssize_t cpuquiet_state_store(struct kobject *kobj,
220         struct attribute *attr, const char *buf, size_t count)
221 {
222         struct cpuquiet_attr *cattr = container_of(attr,
223                                         struct cpuquiet_attr, attr);
224         struct cpuquiet_dev *dev = container_of(kobj,
225                                         struct cpuquiet_dev, kobj);
226
227         if (cattr->store)
228                 return cattr->store(dev->cpu, buf, count);
229
230         return -EINVAL;
231 }
232
233 static ssize_t show_active(unsigned int cpu, char *buf)
234 {
235         return sprintf(buf, "%u\n", cpu_online(cpu));
236 }
237
238 static ssize_t store_active(unsigned int cpu, const char *value, size_t count)
239 {
240         unsigned int active;
241         int ret;
242
243         if (!cpuquiet_curr_governor->store_active)
244                 return -EINVAL;
245
246         ret = sscanf(value, "%u", &active);
247         if (ret != 1)
248                 return -EINVAL;
249
250         cpuquiet_curr_governor->store_active(cpu, active);
251
252         return count;
253 }
254
255 struct cpuquiet_attr attr_active = __ATTR(active, 0644, show_active,
256                                                 store_active);
257
258 static struct attribute *cpuquiet_default_cpu_attrs[] = {
259         &attr_active.attr,
260         NULL
261 };
262
263 static const struct sysfs_ops cpuquiet_cpu_sysfs_ops = {
264         .show = cpuquiet_state_show,
265         .store = cpuquiet_state_store,
266 };
267
268 static struct kobj_type ktype_cpuquiet = {
269         .sysfs_ops = &cpuquiet_cpu_sysfs_ops,
270         .default_attrs = cpuquiet_default_cpu_attrs,
271 };
272
273 void cpuquiet_add_dev(struct device *device, unsigned int cpu)
274 {
275         struct cpuquiet_dev *dev;
276         int err;
277
278         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
279         dev->cpu = cpu;
280         cpuquiet_cpu_devices[cpu] = dev;
281         err = kobject_init_and_add(&dev->kobj, &ktype_cpuquiet,
282                                 &device->kobj, "cpuquiet");
283         if (!err)
284                 kobject_uevent(&dev->kobj, KOBJ_ADD);
285 }
286
287 void cpuquiet_remove_dev(unsigned int cpu)
288 {
289         if (cpu < CONFIG_NR_CPUS && cpuquiet_cpu_devices[cpu])
290                 kobject_put(&cpuquiet_cpu_devices[cpu]->kobj);
291 }