aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-28 21:20:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-28 21:20:48 -0500
commit0a9626575400879d1d5e6bc8768188b938d7c501 (patch)
tree131242645033de27d549d9cb5d97f0043914b6d2
parente3b8369ca8f2fd756031dd972224bc70c2364ec2 (diff)
parentce597919361dcec97341151690e780eade2a9cf4 (diff)
Merge tag 'driver-core-3.3-rc1-bugfixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Here are some patches for the 3.3-rc1 tree. It contains the removal of the sysdev code, now that all users of it are gone, as well as some sysfs bugfixes that have been reported by users. There are also some documentation updates here as well. * tag 'driver-core-3.3-rc1-bugfixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: sysfs: Complain bitterly about attempts to remove files from nonexistent directories. stable: update documentation to ask for kernel version base/core.c:fix typo in comment in function device_add Documentation: devres: add allocation functions to list of supported calls Documentation update for the driver model core kernel-doc: fix new warnings in driver-core kernel-doc: fix new warnings in debugfs kernel-doc: fix new warnings in device.h driver core: remove drivers/base/sys.c and include/linux/sysdev.h
-rw-r--r--Documentation/driver-model/devres.txt4
-rw-r--r--Documentation/stable_kernel_rules.txt3
-rw-r--r--drivers/base/Makefile2
-rw-r--r--drivers/base/core.c17
-rw-r--r--drivers/base/sys.c383
-rw-r--r--fs/sysfs/file.c6
-rw-r--r--fs/sysfs/inode.c5
-rw-r--r--include/linux/sysdev.h164
8 files changed, 33 insertions, 551 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 10c64c8a13d4..41c0c5d1ba14 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -233,6 +233,10 @@ certainly invest a bit more effort into libata core layer).
233 6. List of managed interfaces 233 6. List of managed interfaces
234 ----------------------------- 234 -----------------------------
235 235
236MEM
237 devm_kzalloc()
238 devm_kfree()
239
236IO region 240IO region
237 devm_request_region() 241 devm_request_region()
238 devm_request_mem_region() 242 devm_request_mem_region()
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index 21fd05c28e73..f0ab5cf28fca 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -25,7 +25,8 @@ Procedure for submitting patches to the -stable tree:
25 25
26 - Send the patch, after verifying that it follows the above rules, to 26 - Send the patch, after verifying that it follows the above rules, to
27 stable@vger.kernel.org. You must note the upstream commit ID in the 27 stable@vger.kernel.org. You must note the upstream commit ID in the
28 changelog of your submission. 28 changelog of your submission, as well as the kernel version you wish
29 it to be applied to.
29 - To have the patch automatically included in the stable tree, add the tag 30 - To have the patch automatically included in the stable tree, add the tag
30 Cc: stable@vger.kernel.org 31 Cc: stable@vger.kernel.org
31 in the sign-off area. Once the patch is merged it will be applied to 32 in the sign-off area. Once the patch is merged it will be applied to
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/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
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 62f4fb37789e..00012e31829d 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -493,6 +493,12 @@ int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
493 const void *ns = NULL; 493 const void *ns = NULL;
494 int err; 494 int err;
495 495
496 if (!dir_sd) {
497 WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n",
498 kobject_name(kobj));
499 return -ENOENT;
500 }
501
496 err = 0; 502 err = 0;
497 if (!sysfs_ns_type(dir_sd)) 503 if (!sysfs_ns_type(dir_sd))
498 goto out; 504 goto out;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4a802b4a9056..85eb81683a29 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -318,8 +318,11 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const cha
318 struct sysfs_addrm_cxt acxt; 318 struct sysfs_addrm_cxt acxt;
319 struct sysfs_dirent *sd; 319 struct sysfs_dirent *sd;
320 320
321 if (!dir_sd) 321 if (!dir_sd) {
322 WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
323 name);
322 return -ENOENT; 324 return -ENOENT;
325 }
323 326
324 sysfs_addrm_start(&acxt, dir_sd); 327 sysfs_addrm_start(&acxt, dir_sd);
325 328
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
deleted file mode 100644
index 20f63d3e6144..000000000000
--- a/include/linux/sysdev.h
+++ /dev/null
@@ -1,164 +0,0 @@
1/**
2 * System devices follow a slightly different driver model.
3 * They don't need to do dynammic driver binding, can't be probed,
4 * and don't reside on any type of peripheral bus.
5 * So, we represent and treat them a little differently.
6 *
7 * We still have a notion of a driver for a system device, because we still
8 * want to perform basic operations on these devices.
9 *
10 * We also support auxiliary drivers binding to devices of a certain class.
11 *
12 * This allows configurable drivers to register themselves for devices of
13 * a certain type. And, it allows class definitions to reside in generic
14 * code while arch-specific code can register specific drivers.
15 *
16 * Auxiliary drivers registered with a NULL cls are registered as drivers
17 * for all system devices, and get notification calls for each device.
18 */
19
20
21#ifndef _SYSDEV_H_
22#define _SYSDEV_H_
23
24#include <linux/kobject.h>
25#include <linux/pm.h>
26
27
28struct sys_device;
29struct sysdev_class_attribute;
30
31struct sysdev_class {
32 const char *name;
33 struct list_head drivers;
34 struct sysdev_class_attribute **attrs;
35 struct kset kset;
36};
37
38struct sysdev_class_attribute {
39 struct attribute attr;
40 ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *,
41 char *);
42 ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *,
43 const char *, size_t);
44};
45
46#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
47{ \
48 .attr = {.name = __stringify(_name), .mode = _mode }, \
49 .show = _show, \
50 .store = _store, \
51}
52
53#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
54 struct sysdev_class_attribute attr_##_name = \
55 _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)
56
57
58extern int sysdev_class_register(struct sysdev_class *);
59extern void sysdev_class_unregister(struct sysdev_class *);
60
61extern int sysdev_class_create_file(struct sysdev_class *,
62 struct sysdev_class_attribute *);
63extern void sysdev_class_remove_file(struct sysdev_class *,
64 struct sysdev_class_attribute *);
65/**
66 * Auxiliary system device drivers.
67 */
68
69struct sysdev_driver {
70 struct list_head entry;
71 int (*add)(struct sys_device *);
72 int (*remove)(struct sys_device *);
73};
74
75
76extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *);
77extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *);
78
79
80/**
81 * sys_devices can be simplified a lot from regular devices, because they're
82 * simply not as versatile.
83 */
84
85struct sys_device {
86 u32 id;
87 struct sysdev_class * cls;
88 struct kobject kobj;
89};
90
91extern int sysdev_register(struct sys_device *);
92extern void sysdev_unregister(struct sys_device *);
93
94
95struct sysdev_attribute {
96 struct attribute attr;
97 ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *);
98 ssize_t (*store)(struct sys_device *, struct sysdev_attribute *,
99 const char *, size_t);
100};
101
102
103#define _SYSDEV_ATTR(_name, _mode, _show, _store) \
104{ \
105 .attr = { .name = __stringify(_name), .mode = _mode }, \
106 .show = _show, \
107 .store = _store, \
108}
109
110#define SYSDEV_ATTR(_name, _mode, _show, _store) \
111 struct sysdev_attribute attr_##_name = \
112 _SYSDEV_ATTR(_name, _mode, _show, _store);
113
114extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
115extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
116
117/* Create/remove NULL terminated attribute list */
118static inline int
119sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a)
120{
121 return sysfs_create_files(&d->kobj, (const struct attribute **)a);
122}
123
124static inline void
125sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a)
126{
127 return sysfs_remove_files(&d->kobj, (const struct attribute **)a);
128}
129
130struct sysdev_ext_attribute {
131 struct sysdev_attribute attr;
132 void *var;
133};
134
135/*
136 * Support for simple variable sysdev attributes.
137 * The pointer to the variable is stored in a sysdev_ext_attribute
138 */
139
140/* Add more types as needed */
141
142extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
143 char *);
144extern ssize_t sysdev_store_ulong(struct sys_device *,
145 struct sysdev_attribute *, const char *, size_t);
146extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
147 char *);
148extern ssize_t sysdev_store_int(struct sys_device *,
149 struct sysdev_attribute *, const char *, size_t);
150
151#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \
152 { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
153 &(_var) }
154#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \
155 struct sysdev_ext_attribute attr_##_name = \
156 _SYSDEV_ULONG_ATTR(_name, _mode, _var);
157#define _SYSDEV_INT_ATTR(_name, _mode, _var) \
158 { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
159 &(_var) }
160#define SYSDEV_INT_ATTR(_name, _mode, _var) \
161 struct sysdev_ext_attribute attr_##_name = \
162 _SYSDEV_INT_ATTR(_name, _mode, _var);
163
164#endif /* _SYSDEV_H_ */