]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/x86/kernel/ksysfs.c
x86: Constify attribute_group structures
[karo-tx-linux.git] / arch / x86 / kernel / ksysfs.c
1 /*
2  * Architecture specific sysfs attributes in /sys/kernel
3  *
4  * Copyright (C) 2007, Intel Corp.
5  *      Huang Ying <ying.huang@intel.com>
6  * Copyright (C) 2013, 2013 Red Hat, Inc.
7  *      Dave Young <dyoung@redhat.com>
8  *
9  * This file is released under the GPLv2
10  */
11
12 #include <linux/kobject.h>
13 #include <linux/string.h>
14 #include <linux/sysfs.h>
15 #include <linux/init.h>
16 #include <linux/stat.h>
17 #include <linux/slab.h>
18 #include <linux/mm.h>
19
20 #include <asm/io.h>
21 #include <asm/setup.h>
22
23 static ssize_t version_show(struct kobject *kobj,
24                             struct kobj_attribute *attr, char *buf)
25 {
26         return sprintf(buf, "0x%04x\n", boot_params.hdr.version);
27 }
28
29 static struct kobj_attribute boot_params_version_attr = __ATTR_RO(version);
30
31 static ssize_t boot_params_data_read(struct file *fp, struct kobject *kobj,
32                                      struct bin_attribute *bin_attr,
33                                      char *buf, loff_t off, size_t count)
34 {
35         memcpy(buf, (void *)&boot_params + off, count);
36         return count;
37 }
38
39 static struct bin_attribute boot_params_data_attr = {
40         .attr = {
41                 .name = "data",
42                 .mode = S_IRUGO,
43         },
44         .read = boot_params_data_read,
45         .size = sizeof(boot_params),
46 };
47
48 static struct attribute *boot_params_version_attrs[] = {
49         &boot_params_version_attr.attr,
50         NULL,
51 };
52
53 static struct bin_attribute *boot_params_data_attrs[] = {
54         &boot_params_data_attr,
55         NULL,
56 };
57
58 static const struct attribute_group boot_params_attr_group = {
59         .attrs = boot_params_version_attrs,
60         .bin_attrs = boot_params_data_attrs,
61 };
62
63 static int kobj_to_setup_data_nr(struct kobject *kobj, int *nr)
64 {
65         const char *name;
66
67         name = kobject_name(kobj);
68         return kstrtoint(name, 10, nr);
69 }
70
71 static int get_setup_data_paddr(int nr, u64 *paddr)
72 {
73         int i = 0;
74         struct setup_data *data;
75         u64 pa_data = boot_params.hdr.setup_data;
76
77         while (pa_data) {
78                 if (nr == i) {
79                         *paddr = pa_data;
80                         return 0;
81                 }
82                 data = ioremap_cache(pa_data, sizeof(*data));
83                 if (!data)
84                         return -ENOMEM;
85
86                 pa_data = data->next;
87                 iounmap(data);
88                 i++;
89         }
90         return -EINVAL;
91 }
92
93 static int __init get_setup_data_size(int nr, size_t *size)
94 {
95         int i = 0;
96         struct setup_data *data;
97         u64 pa_data = boot_params.hdr.setup_data;
98
99         while (pa_data) {
100                 data = ioremap_cache(pa_data, sizeof(*data));
101                 if (!data)
102                         return -ENOMEM;
103                 if (nr == i) {
104                         *size = data->len;
105                         iounmap(data);
106                         return 0;
107                 }
108
109                 pa_data = data->next;
110                 iounmap(data);
111                 i++;
112         }
113         return -EINVAL;
114 }
115
116 static ssize_t type_show(struct kobject *kobj,
117                          struct kobj_attribute *attr, char *buf)
118 {
119         int nr, ret;
120         u64 paddr;
121         struct setup_data *data;
122
123         ret = kobj_to_setup_data_nr(kobj, &nr);
124         if (ret)
125                 return ret;
126
127         ret = get_setup_data_paddr(nr, &paddr);
128         if (ret)
129                 return ret;
130         data = ioremap_cache(paddr, sizeof(*data));
131         if (!data)
132                 return -ENOMEM;
133
134         ret = sprintf(buf, "0x%x\n", data->type);
135         iounmap(data);
136         return ret;
137 }
138
139 static ssize_t setup_data_data_read(struct file *fp,
140                                     struct kobject *kobj,
141                                     struct bin_attribute *bin_attr,
142                                     char *buf,
143                                     loff_t off, size_t count)
144 {
145         int nr, ret = 0;
146         u64 paddr;
147         struct setup_data *data;
148         void *p;
149
150         ret = kobj_to_setup_data_nr(kobj, &nr);
151         if (ret)
152                 return ret;
153
154         ret = get_setup_data_paddr(nr, &paddr);
155         if (ret)
156                 return ret;
157         data = ioremap_cache(paddr, sizeof(*data));
158         if (!data)
159                 return -ENOMEM;
160
161         if (off > data->len) {
162                 ret = -EINVAL;
163                 goto out;
164         }
165
166         if (count > data->len - off)
167                 count = data->len - off;
168
169         if (!count)
170                 goto out;
171
172         ret = count;
173         p = ioremap_cache(paddr + sizeof(*data), data->len);
174         if (!p) {
175                 ret = -ENOMEM;
176                 goto out;
177         }
178         memcpy(buf, p + off, count);
179         iounmap(p);
180 out:
181         iounmap(data);
182         return ret;
183 }
184
185 static struct kobj_attribute type_attr = __ATTR_RO(type);
186
187 static struct bin_attribute data_attr __ro_after_init = {
188         .attr = {
189                 .name = "data",
190                 .mode = S_IRUGO,
191         },
192         .read = setup_data_data_read,
193 };
194
195 static struct attribute *setup_data_type_attrs[] = {
196         &type_attr.attr,
197         NULL,
198 };
199
200 static struct bin_attribute *setup_data_data_attrs[] = {
201         &data_attr,
202         NULL,
203 };
204
205 static const struct attribute_group setup_data_attr_group = {
206         .attrs = setup_data_type_attrs,
207         .bin_attrs = setup_data_data_attrs,
208 };
209
210 static int __init create_setup_data_node(struct kobject *parent,
211                                          struct kobject **kobjp, int nr)
212 {
213         int ret = 0;
214         size_t size;
215         struct kobject *kobj;
216         char name[16]; /* should be enough for setup_data nodes numbers */
217         snprintf(name, 16, "%d", nr);
218
219         kobj = kobject_create_and_add(name, parent);
220         if (!kobj)
221                 return -ENOMEM;
222
223         ret = get_setup_data_size(nr, &size);
224         if (ret)
225                 goto out_kobj;
226
227         data_attr.size = size;
228         ret = sysfs_create_group(kobj, &setup_data_attr_group);
229         if (ret)
230                 goto out_kobj;
231         *kobjp = kobj;
232
233         return 0;
234 out_kobj:
235         kobject_put(kobj);
236         return ret;
237 }
238
239 static void __init cleanup_setup_data_node(struct kobject *kobj)
240 {
241         sysfs_remove_group(kobj, &setup_data_attr_group);
242         kobject_put(kobj);
243 }
244
245 static int __init get_setup_data_total_num(u64 pa_data, int *nr)
246 {
247         int ret = 0;
248         struct setup_data *data;
249
250         *nr = 0;
251         while (pa_data) {
252                 *nr += 1;
253                 data = ioremap_cache(pa_data, sizeof(*data));
254                 if (!data) {
255                         ret = -ENOMEM;
256                         goto out;
257                 }
258                 pa_data = data->next;
259                 iounmap(data);
260         }
261
262 out:
263         return ret;
264 }
265
266 static int __init create_setup_data_nodes(struct kobject *parent)
267 {
268         struct kobject *setup_data_kobj, **kobjp;
269         u64 pa_data;
270         int i, j, nr, ret = 0;
271
272         pa_data = boot_params.hdr.setup_data;
273         if (!pa_data)
274                 return 0;
275
276         setup_data_kobj = kobject_create_and_add("setup_data", parent);
277         if (!setup_data_kobj) {
278                 ret = -ENOMEM;
279                 goto out;
280         }
281
282         ret = get_setup_data_total_num(pa_data, &nr);
283         if (ret)
284                 goto out_setup_data_kobj;
285
286         kobjp = kmalloc(sizeof(*kobjp) * nr, GFP_KERNEL);
287         if (!kobjp) {
288                 ret = -ENOMEM;
289                 goto out_setup_data_kobj;
290         }
291
292         for (i = 0; i < nr; i++) {
293                 ret = create_setup_data_node(setup_data_kobj, kobjp + i, i);
294                 if (ret)
295                         goto out_clean_nodes;
296         }
297
298         kfree(kobjp);
299         return 0;
300
301 out_clean_nodes:
302         for (j = i - 1; j > 0; j--)
303                 cleanup_setup_data_node(*(kobjp + j));
304         kfree(kobjp);
305 out_setup_data_kobj:
306         kobject_put(setup_data_kobj);
307 out:
308         return ret;
309 }
310
311 static int __init boot_params_ksysfs_init(void)
312 {
313         int ret;
314         struct kobject *boot_params_kobj;
315
316         boot_params_kobj = kobject_create_and_add("boot_params",
317                                                   kernel_kobj);
318         if (!boot_params_kobj) {
319                 ret = -ENOMEM;
320                 goto out;
321         }
322
323         ret = sysfs_create_group(boot_params_kobj, &boot_params_attr_group);
324         if (ret)
325                 goto out_boot_params_kobj;
326
327         ret = create_setup_data_nodes(boot_params_kobj);
328         if (ret)
329                 goto out_create_group;
330
331         return 0;
332 out_create_group:
333         sysfs_remove_group(boot_params_kobj, &boot_params_attr_group);
334 out_boot_params_kobj:
335         kobject_put(boot_params_kobj);
336 out:
337         return ret;
338 }
339
340 arch_initcall(boot_params_ksysfs_init);