aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/driver.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-25 11:34:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-25 11:35:13 -0500
commitdf8dc74e8a383eaf2d9b44b80a71ec6f0e52b42e (patch)
treebc3799a43e8b94fa84b32e37b1c124d5e4868f50 /drivers/base/driver.c
parent556a169dab38b5100df6f4a45b655dddd3db94c1 (diff)
parent4a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6
This can be broken down into these major areas: - Documentation updates (language translations and fixes, as well as kobject and kset documenatation updates.) - major kset/kobject/ktype rework and fixes. This cleans up the kset and kobject and ktype relationship and architecture, making sense of things now, and good documenation and samples are provided for others to use. Also the attributes for kobjects are much easier to handle now. This cleaned up a LOT of code all through the kernel, making kobjects easier to use if you want to. - struct bus_type has been reworked to now handle the lifetime rules properly, as the kobject is properly dynamic. - struct driver has also been reworked, and now the lifetime issues are resolved. - the block subsystem has been converted to use struct device now, and not "raw" kobjects. This patch has been in the -mm tree for over a year now, and finally all the issues are worked out with it. Older distros now properly work with new kernels, and no userspace updates are needed at all. - nozomi driver is added. This has also been in -mm for a long time, and many people have asked for it to go in. It is now in good enough shape to do so. - lots of class_device conversions to use struct device instead. The tree is almost all cleaned up now, only SCSI and IB is the remaining code to fix up... * git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6: (196 commits) Driver core: coding style fixes Kobject: fix coding style issues in kobject c files Kobject: fix coding style issues in kobject.h Driver core: fix coding style issues in device.h spi: use class iteration api scsi: use class iteration api rtc: use class iteration api power supply : use class iteration api ieee1394: use class iteration api Driver Core: add class iteration api Driver core: Cleanup get_device_parent() in device_add() and device_move() UIO: constify function pointer tables Driver Core: constify the name passed to platform_device_register_simple driver core: fix build with SYSFS=n sysfs: make SYSFS_DEPRECATED depend on SYSFS Driver core: use LIST_HEAD instead of call to INIT_LIST_HEAD in __init kobject: add sample code for how to use ksets/ktypes/kobjects kobject: add sample code for how to use kobjects in a simple manner. kobject: update the kobject/kset documentation kobject: remove old, outdated documentation. ...
Diffstat (limited to 'drivers/base/driver.c')
-rw-r--r--drivers/base/driver.c216
1 files changed, 141 insertions, 75 deletions
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index eb11475293ed..a35f04121a00 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * Copyright (c) 2002-3 Patrick Mochel 4 * Copyright (c) 2002-3 Patrick Mochel
5 * Copyright (c) 2002-3 Open Source Development Labs 5 * Copyright (c) 2002-3 Open Source Development Labs
6 * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
7 * Copyright (c) 2007 Novell Inc.
6 * 8 *
7 * This file is released under the GPLv2 9 * This file is released under the GPLv2
8 * 10 *
@@ -15,46 +17,42 @@
15#include "base.h" 17#include "base.h"
16 18
17#define to_dev(node) container_of(node, struct device, driver_list) 19#define to_dev(node) container_of(node, struct device, driver_list)
18#define to_drv(obj) container_of(obj, struct device_driver, kobj)
19 20
20 21
21static struct device * next_device(struct klist_iter * i) 22static struct device *next_device(struct klist_iter *i)
22{ 23{
23 struct klist_node * n = klist_next(i); 24 struct klist_node *n = klist_next(i);
24 return n ? container_of(n, struct device, knode_driver) : NULL; 25 return n ? container_of(n, struct device, knode_driver) : NULL;
25} 26}
26 27
27/** 28/**
28 * driver_for_each_device - Iterator for devices bound to a driver. 29 * driver_for_each_device - Iterator for devices bound to a driver.
29 * @drv: Driver we're iterating. 30 * @drv: Driver we're iterating.
30 * @start: Device to begin with 31 * @start: Device to begin with
31 * @data: Data to pass to the callback. 32 * @data: Data to pass to the callback.
32 * @fn: Function to call for each device. 33 * @fn: Function to call for each device.
33 * 34 *
34 * Iterate over the @drv's list of devices calling @fn for each one. 35 * Iterate over the @drv's list of devices calling @fn for each one.
35 */ 36 */
36 37int driver_for_each_device(struct device_driver *drv, struct device *start,
37int driver_for_each_device(struct device_driver * drv, struct device * start, 38 void *data, int (*fn)(struct device *, void *))
38 void * data, int (*fn)(struct device *, void *))
39{ 39{
40 struct klist_iter i; 40 struct klist_iter i;
41 struct device * dev; 41 struct device *dev;
42 int error = 0; 42 int error = 0;
43 43
44 if (!drv) 44 if (!drv)
45 return -EINVAL; 45 return -EINVAL;
46 46
47 klist_iter_init_node(&drv->klist_devices, &i, 47 klist_iter_init_node(&drv->p->klist_devices, &i,
48 start ? &start->knode_driver : NULL); 48 start ? &start->knode_driver : NULL);
49 while ((dev = next_device(&i)) && !error) 49 while ((dev = next_device(&i)) && !error)
50 error = fn(dev, data); 50 error = fn(dev, data);
51 klist_iter_exit(&i); 51 klist_iter_exit(&i);
52 return error; 52 return error;
53} 53}
54
55EXPORT_SYMBOL_GPL(driver_for_each_device); 54EXPORT_SYMBOL_GPL(driver_for_each_device);
56 55
57
58/** 56/**
59 * driver_find_device - device iterator for locating a particular device. 57 * driver_find_device - device iterator for locating a particular device.
60 * @drv: The device's driver 58 * @drv: The device's driver
@@ -70,9 +68,9 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
70 * if it does. If the callback returns non-zero, this function will 68 * if it does. If the callback returns non-zero, this function will
71 * return to the caller and not iterate over any more devices. 69 * return to the caller and not iterate over any more devices.
72 */ 70 */
73struct device * driver_find_device(struct device_driver *drv, 71struct device *driver_find_device(struct device_driver *drv,
74 struct device * start, void * data, 72 struct device *start, void *data,
75 int (*match)(struct device *, void *)) 73 int (*match)(struct device *dev, void *data))
76{ 74{
77 struct klist_iter i; 75 struct klist_iter i;
78 struct device *dev; 76 struct device *dev;
@@ -80,7 +78,7 @@ struct device * driver_find_device(struct device_driver *drv,
80 if (!drv) 78 if (!drv)
81 return NULL; 79 return NULL;
82 80
83 klist_iter_init_node(&drv->klist_devices, &i, 81 klist_iter_init_node(&drv->p->klist_devices, &i,
84 (start ? &start->knode_driver : NULL)); 82 (start ? &start->knode_driver : NULL));
85 while ((dev = next_device(&i))) 83 while ((dev = next_device(&i)))
86 if (match(dev, data) && get_device(dev)) 84 if (match(dev, data) && get_device(dev))
@@ -91,111 +89,179 @@ struct device * driver_find_device(struct device_driver *drv,
91EXPORT_SYMBOL_GPL(driver_find_device); 89EXPORT_SYMBOL_GPL(driver_find_device);
92 90
93/** 91/**
94 * driver_create_file - create sysfs file for driver. 92 * driver_create_file - create sysfs file for driver.
95 * @drv: driver. 93 * @drv: driver.
96 * @attr: driver attribute descriptor. 94 * @attr: driver attribute descriptor.
97 */ 95 */
98 96int driver_create_file(struct device_driver *drv,
99int driver_create_file(struct device_driver * drv, struct driver_attribute * attr) 97 struct driver_attribute *attr)
100{ 98{
101 int error; 99 int error;
102 if (get_driver(drv)) { 100 if (get_driver(drv)) {
103 error = sysfs_create_file(&drv->kobj, &attr->attr); 101 error = sysfs_create_file(&drv->p->kobj, &attr->attr);
104 put_driver(drv); 102 put_driver(drv);
105 } else 103 } else
106 error = -EINVAL; 104 error = -EINVAL;
107 return error; 105 return error;
108} 106}
109 107EXPORT_SYMBOL_GPL(driver_create_file);
110 108
111/** 109/**
112 * driver_remove_file - remove sysfs file for driver. 110 * driver_remove_file - remove sysfs file for driver.
113 * @drv: driver. 111 * @drv: driver.
114 * @attr: driver attribute descriptor. 112 * @attr: driver attribute descriptor.
115 */ 113 */
116 114void driver_remove_file(struct device_driver *drv,
117void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) 115 struct driver_attribute *attr)
118{ 116{
119 if (get_driver(drv)) { 117 if (get_driver(drv)) {
120 sysfs_remove_file(&drv->kobj, &attr->attr); 118 sysfs_remove_file(&drv->p->kobj, &attr->attr);
121 put_driver(drv); 119 put_driver(drv);
122 } 120 }
123} 121}
124 122EXPORT_SYMBOL_GPL(driver_remove_file);
125 123
126/** 124/**
127 * get_driver - increment driver reference count. 125 * driver_add_kobj - add a kobject below the specified driver
128 * @drv: driver. 126 *
127 * You really don't want to do this, this is only here due to one looney
128 * iseries driver, go poke those developers if you are annoyed about
129 * this...
129 */ 130 */
130struct device_driver * get_driver(struct device_driver * drv) 131int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
132 const char *fmt, ...)
131{ 133{
132 return drv ? to_drv(kobject_get(&drv->kobj)) : NULL; 134 va_list args;
135 char *name;
136
137 va_start(args, fmt);
138 name = kvasprintf(GFP_KERNEL, fmt, args);
139 va_end(args);
140
141 if (!name)
142 return -ENOMEM;
143
144 return kobject_add(kobj, &drv->p->kobj, "%s", name);
133} 145}
146EXPORT_SYMBOL_GPL(driver_add_kobj);
147
148/**
149 * get_driver - increment driver reference count.
150 * @drv: driver.
151 */
152struct device_driver *get_driver(struct device_driver *drv)
153{
154 if (drv) {
155 struct driver_private *priv;
156 struct kobject *kobj;
134 157
158 kobj = kobject_get(&drv->p->kobj);
159 priv = to_driver(kobj);
160 return priv->driver;
161 }
162 return NULL;
163}
164EXPORT_SYMBOL_GPL(get_driver);
135 165
136/** 166/**
137 * put_driver - decrement driver's refcount. 167 * put_driver - decrement driver's refcount.
138 * @drv: driver. 168 * @drv: driver.
139 */ 169 */
140void put_driver(struct device_driver * drv) 170void put_driver(struct device_driver *drv)
171{
172 kobject_put(&drv->p->kobj);
173}
174EXPORT_SYMBOL_GPL(put_driver);
175
176static int driver_add_groups(struct device_driver *drv,
177 struct attribute_group **groups)
141{ 178{
142 kobject_put(&drv->kobj); 179 int error = 0;
180 int i;
181
182 if (groups) {
183 for (i = 0; groups[i]; i++) {
184 error = sysfs_create_group(&drv->p->kobj, groups[i]);
185 if (error) {
186 while (--i >= 0)
187 sysfs_remove_group(&drv->p->kobj,
188 groups[i]);
189 break;
190 }
191 }
192 }
193 return error;
194}
195
196static void driver_remove_groups(struct device_driver *drv,
197 struct attribute_group **groups)
198{
199 int i;
200
201 if (groups)
202 for (i = 0; groups[i]; i++)
203 sysfs_remove_group(&drv->p->kobj, groups[i]);
143} 204}
144 205
145/** 206/**
146 * driver_register - register driver with bus 207 * driver_register - register driver with bus
147 * @drv: driver to register 208 * @drv: driver to register
148 * 209 *
149 * We pass off most of the work to the bus_add_driver() call, 210 * We pass off most of the work to the bus_add_driver() call,
150 * since most of the things we have to do deal with the bus 211 * since most of the things we have to do deal with the bus
151 * structures. 212 * structures.
152 */ 213 */
153int driver_register(struct device_driver * drv) 214int driver_register(struct device_driver *drv)
154{ 215{
216 int ret;
217
155 if ((drv->bus->probe && drv->probe) || 218 if ((drv->bus->probe && drv->probe) ||
156 (drv->bus->remove && drv->remove) || 219 (drv->bus->remove && drv->remove) ||
157 (drv->bus->shutdown && drv->shutdown)) { 220 (drv->bus->shutdown && drv->shutdown))
158 printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); 221 printk(KERN_WARNING "Driver '%s' needs updating - please use "
159 } 222 "bus_type methods\n", drv->name);
160 klist_init(&drv->klist_devices, NULL, NULL); 223 ret = bus_add_driver(drv);
161 return bus_add_driver(drv); 224 if (ret)
225 return ret;
226 ret = driver_add_groups(drv, drv->groups);
227 if (ret)
228 bus_remove_driver(drv);
229 return ret;
162} 230}
231EXPORT_SYMBOL_GPL(driver_register);
163 232
164/** 233/**
165 * driver_unregister - remove driver from system. 234 * driver_unregister - remove driver from system.
166 * @drv: driver. 235 * @drv: driver.
167 * 236 *
168 * Again, we pass off most of the work to the bus-level call. 237 * Again, we pass off most of the work to the bus-level call.
169 */ 238 */
170 239void driver_unregister(struct device_driver *drv)
171void driver_unregister(struct device_driver * drv)
172{ 240{
241 driver_remove_groups(drv, drv->groups);
173 bus_remove_driver(drv); 242 bus_remove_driver(drv);
174} 243}
244EXPORT_SYMBOL_GPL(driver_unregister);
175 245
176/** 246/**
177 * driver_find - locate driver on a bus by its name. 247 * driver_find - locate driver on a bus by its name.
178 * @name: name of the driver. 248 * @name: name of the driver.
179 * @bus: bus to scan for the driver. 249 * @bus: bus to scan for the driver.
180 * 250 *
181 * Call kset_find_obj() to iterate over list of drivers on 251 * Call kset_find_obj() to iterate over list of drivers on
182 * a bus to find driver by name. Return driver if found. 252 * a bus to find driver by name. Return driver if found.
183 * 253 *
184 * Note that kset_find_obj increments driver's reference count. 254 * Note that kset_find_obj increments driver's reference count.
185 */ 255 */
186struct device_driver *driver_find(const char *name, struct bus_type *bus) 256struct device_driver *driver_find(const char *name, struct bus_type *bus)
187{ 257{
188 struct kobject *k = kset_find_obj(&bus->drivers, name); 258 struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
189 if (k) 259 struct driver_private *priv;
190 return to_drv(k); 260
261 if (k) {
262 priv = to_driver(k);
263 return priv->driver;
264 }
191 return NULL; 265 return NULL;
192} 266}
193
194EXPORT_SYMBOL_GPL(driver_register);
195EXPORT_SYMBOL_GPL(driver_unregister);
196EXPORT_SYMBOL_GPL(get_driver);
197EXPORT_SYMBOL_GPL(put_driver);
198EXPORT_SYMBOL_GPL(driver_find); 267EXPORT_SYMBOL_GPL(driver_find);
199
200EXPORT_SYMBOL_GPL(driver_create_file);
201EXPORT_SYMBOL_GPL(driver_remove_file);