aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2012-03-14 02:44:11 -0400
committerIngo Molnar <mingo@elte.hu>2012-03-14 02:44:11 -0400
commitcd593accdcc27ccbe6498d9ad1c2b6cc8e1d830d (patch)
tree9424d3ac86e753706cc6c3d7e6072d2a73711e29 /drivers/base
parent11b91d6fe7272452c999573bab33c15c2f03dc31 (diff)
parentfde7d9049e55ab85a390be7f415d74c9f62dd0f9 (diff)
Merge tag 'v3.3-rc7' into x86/mce
Merge reason: Update from an ancient -rc1 base to an almost-final stable kernel. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/Makefile2
-rw-r--r--drivers/base/core.c17
-rw-r--r--drivers/base/cpu.c21
-rw-r--r--drivers/base/memory.c31
-rw-r--r--drivers/base/node.c8
-rw-r--r--drivers/base/regmap/regcache.c4
-rw-r--r--drivers/base/sys.c383
7 files changed, 74 insertions, 392 deletions
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 2c8272dd93c4..610f9997a403 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -1,6 +1,6 @@
1# Makefile for the Linux device tree 1# Makefile for the Linux device tree
2 2
3obj-y := core.o sys.o bus.o dd.o syscore.o \ 3obj-y := core.o bus.o dd.o syscore.o \
4 driver.o class.o platform.o \ 4 driver.o class.o platform.o \
5 cpu.o firmware.o init.o map.o devres.o \ 5 cpu.o firmware.o init.o map.o devres.o \
6 attribute_container.o transport_class.o \ 6 attribute_container.o transport_class.o \
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 4a67cc0c8b37..74dda4f697f9 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -632,6 +632,11 @@ static void klist_children_put(struct klist_node *n)
632 * may be used for reference counting of @dev after calling this 632 * may be used for reference counting of @dev after calling this
633 * function. 633 * function.
634 * 634 *
635 * All fields in @dev must be initialized by the caller to 0, except
636 * for those explicitly set to some other value. The simplest
637 * approach is to use kzalloc() to allocate the structure containing
638 * @dev.
639 *
635 * NOTE: Use put_device() to give up your reference instead of freeing 640 * NOTE: Use put_device() to give up your reference instead of freeing
636 * @dev directly once you have called this function. 641 * @dev directly once you have called this function.
637 */ 642 */
@@ -930,6 +935,13 @@ int device_private_init(struct device *dev)
930 * to the global and sibling lists for the device, then 935 * to the global and sibling lists for the device, then
931 * adds it to the other relevant subsystems of the driver model. 936 * adds it to the other relevant subsystems of the driver model.
932 * 937 *
938 * Do not call this routine or device_register() more than once for
939 * any device structure. The driver model core is not designed to work
940 * with devices that get unregistered and then spring back to life.
941 * (Among other things, it's very hard to guarantee that all references
942 * to the previous incarnation of @dev have been dropped.) Allocate
943 * and register a fresh new struct device instead.
944 *
933 * NOTE: _Never_ directly free @dev after calling this function, even 945 * NOTE: _Never_ directly free @dev after calling this function, even
934 * if it returned an error! Always use put_device() to give up your 946 * if it returned an error! Always use put_device() to give up your
935 * reference instead. 947 * reference instead.
@@ -1022,7 +1034,7 @@ int device_add(struct device *dev)
1022 device_pm_add(dev); 1034 device_pm_add(dev);
1023 1035
1024 /* Notify clients of device addition. This call must come 1036 /* Notify clients of device addition. This call must come
1025 * after dpm_sysf_add() and before kobject_uevent(). 1037 * after dpm_sysfs_add() and before kobject_uevent().
1026 */ 1038 */
1027 if (dev->bus) 1039 if (dev->bus)
1028 blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 1040 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
@@ -1090,6 +1102,9 @@ name_error:
1090 * have a clearly defined need to use and refcount the device 1102 * have a clearly defined need to use and refcount the device
1091 * before it is added to the hierarchy. 1103 * before it is added to the hierarchy.
1092 * 1104 *
1105 * For more information, see the kerneldoc for device_initialize()
1106 * and device_add().
1107 *
1093 * NOTE: _Never_ directly free @dev after calling this function, even 1108 * NOTE: _Never_ directly free @dev after calling this function, even
1094 * if it returned an error! Always use put_device() to give up the 1109 * if it returned an error! Always use put_device() to give up the
1095 * reference initialized in this function instead. 1110 * reference initialized in this function instead.
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index db87e78d7459..4dabf5077c48 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -208,6 +208,25 @@ static ssize_t print_cpus_offline(struct device *dev,
208} 208}
209static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); 209static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
210 210
211static void cpu_device_release(struct device *dev)
212{
213 /*
214 * This is an empty function to prevent the driver core from spitting a
215 * warning at us. Yes, I know this is directly opposite of what the
216 * documentation for the driver core and kobjects say, and the author
217 * of this code has already been publically ridiculed for doing
218 * something as foolish as this. However, at this point in time, it is
219 * the only way to handle the issue of statically allocated cpu
220 * devices. The different architectures will have their cpu device
221 * code reworked to properly handle this in the near future, so this
222 * function will then be changed to correctly free up the memory held
223 * by the cpu device.
224 *
225 * Never copy this way of doing things, or you too will be made fun of
226 * on the linux-kerenl list, you have been warned.
227 */
228}
229
211/* 230/*
212 * register_cpu - Setup a sysfs device for a CPU. 231 * register_cpu - Setup a sysfs device for a CPU.
213 * @cpu - cpu->hotpluggable field set to 1 will generate a control file in 232 * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
@@ -221,8 +240,10 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
221 int error; 240 int error;
222 241
223 cpu->node_id = cpu_to_node(num); 242 cpu->node_id = cpu_to_node(num);
243 memset(&cpu->dev, 0x00, sizeof(struct device));
224 cpu->dev.id = num; 244 cpu->dev.id = num;
225 cpu->dev.bus = &cpu_subsys; 245 cpu->dev.bus = &cpu_subsys;
246 cpu->dev.release = cpu_device_release;
226 error = device_register(&cpu->dev); 247 error = device_register(&cpu->dev);
227 if (!error && cpu->hotpluggable) 248 if (!error && cpu->hotpluggable)
228 register_cpu_control(cpu); 249 register_cpu_control(cpu);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 9b3a71e391f4..7dda4f790f00 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -572,19 +572,36 @@ static int init_memory_block(struct memory_block **memory,
572} 572}
573 573
574static int add_memory_section(int nid, struct mem_section *section, 574static int add_memory_section(int nid, struct mem_section *section,
575 struct memory_block **mem_p,
575 unsigned long state, enum mem_add_context context) 576 unsigned long state, enum mem_add_context context)
576{ 577{
577 struct memory_block *mem; 578 struct memory_block *mem = NULL;
579 int scn_nr = __section_nr(section);
578 int ret = 0; 580 int ret = 0;
579 581
580 mutex_lock(&mem_sysfs_mutex); 582 mutex_lock(&mem_sysfs_mutex);
581 583
582 mem = find_memory_block(section); 584 if (context == BOOT) {
585 /* same memory block ? */
586 if (mem_p && *mem_p)
587 if (scn_nr >= (*mem_p)->start_section_nr &&
588 scn_nr <= (*mem_p)->end_section_nr) {
589 mem = *mem_p;
590 kobject_get(&mem->dev.kobj);
591 }
592 } else
593 mem = find_memory_block(section);
594
583 if (mem) { 595 if (mem) {
584 mem->section_count++; 596 mem->section_count++;
585 kobject_put(&mem->dev.kobj); 597 kobject_put(&mem->dev.kobj);
586 } else 598 } else {
587 ret = init_memory_block(&mem, section, state); 599 ret = init_memory_block(&mem, section, state);
600 /* store memory_block pointer for next loop */
601 if (!ret && context == BOOT)
602 if (mem_p)
603 *mem_p = mem;
604 }
588 605
589 if (!ret) { 606 if (!ret) {
590 if (context == HOTPLUG && 607 if (context == HOTPLUG &&
@@ -627,7 +644,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
627 */ 644 */
628int register_new_memory(int nid, struct mem_section *section) 645int register_new_memory(int nid, struct mem_section *section)
629{ 646{
630 return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG); 647 return add_memory_section(nid, section, NULL, MEM_OFFLINE, HOTPLUG);
631} 648}
632 649
633int unregister_memory_section(struct mem_section *section) 650int unregister_memory_section(struct mem_section *section)
@@ -647,6 +664,7 @@ int __init memory_dev_init(void)
647 int ret; 664 int ret;
648 int err; 665 int err;
649 unsigned long block_sz; 666 unsigned long block_sz;
667 struct memory_block *mem = NULL;
650 668
651 ret = subsys_system_register(&memory_subsys, NULL); 669 ret = subsys_system_register(&memory_subsys, NULL);
652 if (ret) 670 if (ret)
@@ -662,7 +680,10 @@ int __init memory_dev_init(void)
662 for (i = 0; i < NR_MEM_SECTIONS; i++) { 680 for (i = 0; i < NR_MEM_SECTIONS; i++) {
663 if (!present_section_nr(i)) 681 if (!present_section_nr(i))
664 continue; 682 continue;
665 err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE, 683 /* don't need to reuse memory_block if only one per block */
684 err = add_memory_section(0, __nr_to_section(i),
685 (sections_per_block == 1) ? NULL : &mem,
686 MEM_ONLINE,
666 BOOT); 687 BOOT);
667 if (!ret) 688 if (!ret)
668 ret = err; 689 ret = err;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 44f427a66117..90aa2a11a933 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -456,7 +456,15 @@ static int link_mem_sections(int nid)
456 if (!present_section_nr(section_nr)) 456 if (!present_section_nr(section_nr))
457 continue; 457 continue;
458 mem_sect = __nr_to_section(section_nr); 458 mem_sect = __nr_to_section(section_nr);
459
460 /* same memblock ? */
461 if (mem_blk)
462 if ((section_nr >= mem_blk->start_section_nr) &&
463 (section_nr <= mem_blk->end_section_nr))
464 continue;
465
459 mem_blk = find_memory_block_hinted(mem_sect, mem_blk); 466 mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
467
460 ret = register_mem_sect_under_node(mem_blk, nid); 468 ret = register_mem_sect_under_node(mem_blk, nid);
461 if (!err) 469 if (!err)
462 err = ret; 470 err = ret;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 1ead66186b7c..d1daa5e9fadf 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -53,7 +53,7 @@ static int regcache_hw_init(struct regmap *map)
53 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) { 53 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
54 val = regcache_get_val(map->reg_defaults_raw, 54 val = regcache_get_val(map->reg_defaults_raw,
55 i, map->cache_word_size); 55 i, map->cache_word_size);
56 if (!val) 56 if (regmap_volatile(map, i))
57 continue; 57 continue;
58 count++; 58 count++;
59 } 59 }
@@ -70,7 +70,7 @@ static int regcache_hw_init(struct regmap *map)
70 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { 70 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
71 val = regcache_get_val(map->reg_defaults_raw, 71 val = regcache_get_val(map->reg_defaults_raw,
72 i, map->cache_word_size); 72 i, map->cache_word_size);
73 if (!val) 73 if (regmap_volatile(map, i))
74 continue; 74 continue;
75 map->reg_defaults[j].reg = i; 75 map->reg_defaults[j].reg = i;
76 map->reg_defaults[j].def = val; 76 map->reg_defaults[j].def = val;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
deleted file mode 100644
index 409f5ce78829..000000000000
--- a/drivers/base/sys.c
+++ /dev/null
@@ -1,383 +0,0 @@
1/*
2 * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc)
3 *
4 * Copyright (c) 2002-3 Patrick Mochel
5 * 2002-3 Open Source Development Lab
6 *
7 * This file is released under the GPLv2
8 *
9 * This exports a 'system' bus type.
10 * By default, a 'sys' bus gets added to the root of the system. There will
11 * always be core system devices. Devices can use sysdev_register() to
12 * add themselves as children of the system bus.
13 */
14
15#include <linux/sysdev.h>
16#include <linux/err.h>
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/string.h>
21#include <linux/pm.h>
22#include <linux/device.h>
23#include <linux/mutex.h>
24#include <linux/interrupt.h>
25
26#include "base.h"
27
28#define to_sysdev(k) container_of(k, struct sys_device, kobj)
29#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
30
31
32static ssize_t
33sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
34{
35 struct sys_device *sysdev = to_sysdev(kobj);
36 struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
37
38 if (sysdev_attr->show)
39 return sysdev_attr->show(sysdev, sysdev_attr, buffer);
40 return -EIO;
41}
42
43
44static ssize_t
45sysdev_store(struct kobject *kobj, struct attribute *attr,
46 const char *buffer, size_t count)
47{
48 struct sys_device *sysdev = to_sysdev(kobj);
49 struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
50
51 if (sysdev_attr->store)
52 return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
53 return -EIO;
54}
55
56static const struct sysfs_ops sysfs_ops = {
57 .show = sysdev_show,
58 .store = sysdev_store,
59};
60
61static struct kobj_type ktype_sysdev = {
62 .sysfs_ops = &sysfs_ops,
63};
64
65
66int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a)
67{
68 return sysfs_create_file(&s->kobj, &a->attr);
69}
70
71
72void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a)
73{
74 sysfs_remove_file(&s->kobj, &a->attr);
75}
76
77EXPORT_SYMBOL_GPL(sysdev_create_file);
78EXPORT_SYMBOL_GPL(sysdev_remove_file);
79
80#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj)
81#define to_sysdev_class_attr(a) container_of(a, \
82 struct sysdev_class_attribute, attr)
83
84static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
85 char *buffer)
86{
87 struct sysdev_class *class = to_sysdev_class(kobj);
88 struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
89
90 if (class_attr->show)
91 return class_attr->show(class, class_attr, buffer);
92 return -EIO;
93}
94
95static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
96 const char *buffer, size_t count)
97{
98 struct sysdev_class *class = to_sysdev_class(kobj);
99 struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
100
101 if (class_attr->store)
102 return class_attr->store(class, class_attr, buffer, count);
103 return -EIO;
104}
105
106static const struct sysfs_ops sysfs_class_ops = {
107 .show = sysdev_class_show,
108 .store = sysdev_class_store,
109};
110
111static struct kobj_type ktype_sysdev_class = {
112 .sysfs_ops = &sysfs_class_ops,
113};
114
115int sysdev_class_create_file(struct sysdev_class *c,
116 struct sysdev_class_attribute *a)
117{
118 return sysfs_create_file(&c->kset.kobj, &a->attr);
119}
120EXPORT_SYMBOL_GPL(sysdev_class_create_file);
121
122void sysdev_class_remove_file(struct sysdev_class *c,
123 struct sysdev_class_attribute *a)
124{
125 sysfs_remove_file(&c->kset.kobj, &a->attr);
126}
127EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
128
129extern struct kset *system_kset;
130
131int sysdev_class_register(struct sysdev_class *cls)
132{
133 int retval;
134
135 pr_debug("Registering sysdev class '%s'\n", cls->name);
136
137 INIT_LIST_HEAD(&cls->drivers);
138 memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
139 cls->kset.kobj.parent = &system_kset->kobj;
140 cls->kset.kobj.ktype = &ktype_sysdev_class;
141 cls->kset.kobj.kset = system_kset;
142
143 retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name);
144 if (retval)
145 return retval;
146
147 retval = kset_register(&cls->kset);
148 if (!retval && cls->attrs)
149 retval = sysfs_create_files(&cls->kset.kobj,
150 (const struct attribute **)cls->attrs);
151 return retval;
152}
153
154void sysdev_class_unregister(struct sysdev_class *cls)
155{
156 pr_debug("Unregistering sysdev class '%s'\n",
157 kobject_name(&cls->kset.kobj));
158 if (cls->attrs)
159 sysfs_remove_files(&cls->kset.kobj,
160 (const struct attribute **)cls->attrs);
161 kset_unregister(&cls->kset);
162}
163
164EXPORT_SYMBOL_GPL(sysdev_class_register);
165EXPORT_SYMBOL_GPL(sysdev_class_unregister);
166
167static DEFINE_MUTEX(sysdev_drivers_lock);
168
169/*
170 * @dev != NULL means that we're unwinding because some drv->add()
171 * failed for some reason. You need to grab sysdev_drivers_lock before
172 * calling this.
173 */
174static void __sysdev_driver_remove(struct sysdev_class *cls,
175 struct sysdev_driver *drv,
176 struct sys_device *from_dev)
177{
178 struct sys_device *dev = from_dev;
179
180 list_del_init(&drv->entry);
181 if (!cls)
182 return;
183
184 if (!drv->remove)
185 goto kset_put;
186
187 if (dev)
188 list_for_each_entry_continue_reverse(dev, &cls->kset.list,
189 kobj.entry)
190 drv->remove(dev);
191 else
192 list_for_each_entry(dev, &cls->kset.list, kobj.entry)
193 drv->remove(dev);
194
195kset_put:
196 kset_put(&cls->kset);
197}
198
199/**
200 * sysdev_driver_register - Register auxiliary driver
201 * @cls: Device class driver belongs to.
202 * @drv: Driver.
203 *
204 * @drv is inserted into @cls->drivers to be
205 * called on each operation on devices of that class. The refcount
206 * of @cls is incremented.
207 */
208int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
209{
210 struct sys_device *dev = NULL;
211 int err = 0;
212
213 if (!cls) {
214 WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n",
215 __func__);
216 return -EINVAL;
217 }
218
219 /* Check whether this driver has already been added to a class. */
220 if (drv->entry.next && !list_empty(&drv->entry))
221 WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already"
222 " been registered to a class, something is wrong, but "
223 "will forge on!\n", cls->name, drv);
224
225 mutex_lock(&sysdev_drivers_lock);
226 if (cls && kset_get(&cls->kset)) {
227 list_add_tail(&drv->entry, &cls->drivers);
228
229 /* If devices of this class already exist, tell the driver */
230 if (drv->add) {
231 list_for_each_entry(dev, &cls->kset.list, kobj.entry) {
232 err = drv->add(dev);
233 if (err)
234 goto unwind;
235 }
236 }
237 } else {
238 err = -EINVAL;
239 WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
240 }
241
242 goto unlock;
243
244unwind:
245 __sysdev_driver_remove(cls, drv, dev);
246
247unlock:
248 mutex_unlock(&sysdev_drivers_lock);
249 return err;
250}
251
252/**
253 * sysdev_driver_unregister - Remove an auxiliary driver.
254 * @cls: Class driver belongs to.
255 * @drv: Driver.
256 */
257void sysdev_driver_unregister(struct sysdev_class *cls,
258 struct sysdev_driver *drv)
259{
260 mutex_lock(&sysdev_drivers_lock);
261 __sysdev_driver_remove(cls, drv, NULL);
262 mutex_unlock(&sysdev_drivers_lock);
263}
264EXPORT_SYMBOL_GPL(sysdev_driver_register);
265EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
266
267/**
268 * sysdev_register - add a system device to the tree
269 * @sysdev: device in question
270 *
271 */
272int sysdev_register(struct sys_device *sysdev)
273{
274 int error;
275 struct sysdev_class *cls = sysdev->cls;
276
277 if (!cls)
278 return -EINVAL;
279
280 pr_debug("Registering sys device of class '%s'\n",
281 kobject_name(&cls->kset.kobj));
282
283 /* initialize the kobject to 0, in case it had previously been used */
284 memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
285
286 /* Make sure the kset is set */
287 sysdev->kobj.kset = &cls->kset;
288
289 /* Register the object */
290 error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL,
291 "%s%d", kobject_name(&cls->kset.kobj),
292 sysdev->id);
293
294 if (!error) {
295 struct sysdev_driver *drv;
296
297 pr_debug("Registering sys device '%s'\n",
298 kobject_name(&sysdev->kobj));
299
300 mutex_lock(&sysdev_drivers_lock);
301 /* Generic notification is implicit, because it's that
302 * code that should have called us.
303 */
304
305 /* Notify class auxiliary drivers */
306 list_for_each_entry(drv, &cls->drivers, entry) {
307 if (drv->add)
308 drv->add(sysdev);
309 }
310 mutex_unlock(&sysdev_drivers_lock);
311 kobject_uevent(&sysdev->kobj, KOBJ_ADD);
312 }
313
314 return error;
315}
316
317void sysdev_unregister(struct sys_device *sysdev)
318{
319 struct sysdev_driver *drv;
320
321 mutex_lock(&sysdev_drivers_lock);
322 list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
323 if (drv->remove)
324 drv->remove(sysdev);
325 }
326 mutex_unlock(&sysdev_drivers_lock);
327
328 kobject_put(&sysdev->kobj);
329}
330
331EXPORT_SYMBOL_GPL(sysdev_register);
332EXPORT_SYMBOL_GPL(sysdev_unregister);
333
334#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
335
336ssize_t sysdev_store_ulong(struct sys_device *sysdev,
337 struct sysdev_attribute *attr,
338 const char *buf, size_t size)
339{
340 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
341 char *end;
342 unsigned long new = simple_strtoul(buf, &end, 0);
343 if (end == buf)
344 return -EINVAL;
345 *(unsigned long *)(ea->var) = new;
346 /* Always return full write size even if we didn't consume all */
347 return size;
348}
349EXPORT_SYMBOL_GPL(sysdev_store_ulong);
350
351ssize_t sysdev_show_ulong(struct sys_device *sysdev,
352 struct sysdev_attribute *attr,
353 char *buf)
354{
355 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
356 return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
357}
358EXPORT_SYMBOL_GPL(sysdev_show_ulong);
359
360ssize_t sysdev_store_int(struct sys_device *sysdev,
361 struct sysdev_attribute *attr,
362 const char *buf, size_t size)
363{
364 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
365 char *end;
366 long new = simple_strtol(buf, &end, 0);
367 if (end == buf || new > INT_MAX || new < INT_MIN)
368 return -EINVAL;
369 *(int *)(ea->var) = new;
370 /* Always return full write size even if we didn't consume all */
371 return size;
372}
373EXPORT_SYMBOL_GPL(sysdev_store_int);
374
375ssize_t sysdev_show_int(struct sys_device *sysdev,
376 struct sysdev_attribute *attr,
377 char *buf)
378{
379 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
380 return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
381}
382EXPORT_SYMBOL_GPL(sysdev_show_int);
383