Blame view
drivers/base/bus.c
25.8 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 |
/* * bus.c - bus driver management * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs |
e5dd12784 Driver core: move... |
6 7 |
* Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (c) 2007 Novell Inc. |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 |
* * This file is released under the GPLv2 * */ |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
#include <linux/device.h> #include <linux/module.h> #include <linux/errno.h> |
5a0e3ad6a include cleanup: ... |
15 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 19 |
#include <linux/init.h> #include <linux/string.h> #include "base.h" #include "power/power.h" |
1da177e4c Linux-2.6.12-rc2 |
20 |
#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) |
c6f7e72a3 driver core: remo... |
21 |
#define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj) |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 25 26 27 |
/* * sysfs bindings for drivers */ #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr) |
1da177e4c Linux-2.6.12-rc2 |
28 |
|
b8c5cec23 Driver core: udev... |
29 30 |
static int __must_check bus_rescan_devices_helper(struct device *dev, void *data); |
5901d0145 Driver core: remo... |
31 32 |
static struct bus_type *bus_get(struct bus_type *bus) { |
c6f7e72a3 driver core: remo... |
33 34 35 36 37 |
if (bus) { kset_get(&bus->p->subsys); return bus; } return NULL; |
5901d0145 Driver core: remo... |
38 |
} |
fc1ede588 Driver core: remo... |
39 40 |
static void bus_put(struct bus_type *bus) { |
c6f7e72a3 driver core: remo... |
41 42 |
if (bus) kset_put(&bus->p->subsys); |
fc1ede588 Driver core: remo... |
43 |
} |
4a3ad20cc Driver core: codi... |
44 45 |
static ssize_t drv_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
46 |
{ |
4a3ad20cc Driver core: codi... |
47 |
struct driver_attribute *drv_attr = to_drv_attr(attr); |
e5dd12784 Driver core: move... |
48 |
struct driver_private *drv_priv = to_driver(kobj); |
4a0c20bf8 [PATCH] sysfs: (d... |
49 |
ssize_t ret = -EIO; |
1da177e4c Linux-2.6.12-rc2 |
50 51 |
if (drv_attr->show) |
e5dd12784 Driver core: move... |
52 |
ret = drv_attr->show(drv_priv->driver, buf); |
1da177e4c Linux-2.6.12-rc2 |
53 54 |
return ret; } |
4a3ad20cc Driver core: codi... |
55 56 |
static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
57 |
{ |
4a3ad20cc Driver core: codi... |
58 |
struct driver_attribute *drv_attr = to_drv_attr(attr); |
e5dd12784 Driver core: move... |
59 |
struct driver_private *drv_priv = to_driver(kobj); |
4a0c20bf8 [PATCH] sysfs: (d... |
60 |
ssize_t ret = -EIO; |
1da177e4c Linux-2.6.12-rc2 |
61 62 |
if (drv_attr->store) |
e5dd12784 Driver core: move... |
63 |
ret = drv_attr->store(drv_priv->driver, buf, count); |
1da177e4c Linux-2.6.12-rc2 |
64 65 |
return ret; } |
52cf25d0a Driver core: Cons... |
66 |
static const struct sysfs_ops driver_sysfs_ops = { |
1da177e4c Linux-2.6.12-rc2 |
67 68 69 |
.show = drv_attr_show, .store = drv_attr_store, }; |
e5dd12784 Driver core: move... |
70 |
static void driver_release(struct kobject *kobj) |
1da177e4c Linux-2.6.12-rc2 |
71 |
{ |
e5dd12784 Driver core: move... |
72 |
struct driver_private *drv_priv = to_driver(kobj); |
2b3a302a0 driver core: repl... |
73 74 |
pr_debug("driver: '%s': %s ", kobject_name(kobj), __func__); |
e5dd12784 Driver core: move... |
75 |
kfree(drv_priv); |
1da177e4c Linux-2.6.12-rc2 |
76 |
} |
a1148fb03 Driver core: rena... |
77 |
static struct kobj_type driver_ktype = { |
1da177e4c Linux-2.6.12-rc2 |
78 79 80 |
.sysfs_ops = &driver_sysfs_ops, .release = driver_release, }; |
1da177e4c Linux-2.6.12-rc2 |
81 82 83 |
/* * sysfs bindings for buses */ |
4a3ad20cc Driver core: codi... |
84 85 |
static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
86 |
{ |
4a3ad20cc Driver core: codi... |
87 |
struct bus_attribute *bus_attr = to_bus_attr(attr); |
c6f7e72a3 driver core: remo... |
88 |
struct bus_type_private *bus_priv = to_bus(kobj); |
1da177e4c Linux-2.6.12-rc2 |
89 90 91 |
ssize_t ret = 0; if (bus_attr->show) |
c6f7e72a3 driver core: remo... |
92 |
ret = bus_attr->show(bus_priv->bus, buf); |
1da177e4c Linux-2.6.12-rc2 |
93 94 |
return ret; } |
4a3ad20cc Driver core: codi... |
95 96 |
static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
97 |
{ |
4a3ad20cc Driver core: codi... |
98 |
struct bus_attribute *bus_attr = to_bus_attr(attr); |
c6f7e72a3 driver core: remo... |
99 |
struct bus_type_private *bus_priv = to_bus(kobj); |
1da177e4c Linux-2.6.12-rc2 |
100 101 102 |
ssize_t ret = 0; if (bus_attr->store) |
c6f7e72a3 driver core: remo... |
103 |
ret = bus_attr->store(bus_priv->bus, buf, count); |
1da177e4c Linux-2.6.12-rc2 |
104 105 |
return ret; } |
52cf25d0a Driver core: Cons... |
106 |
static const struct sysfs_ops bus_sysfs_ops = { |
1da177e4c Linux-2.6.12-rc2 |
107 108 109 |
.show = bus_attr_show, .store = bus_attr_store, }; |
4a3ad20cc Driver core: codi... |
110 |
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr) |
1da177e4c Linux-2.6.12-rc2 |
111 112 |
{ int error; |
5901d0145 Driver core: remo... |
113 |
if (bus_get(bus)) { |
c6f7e72a3 driver core: remo... |
114 |
error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr); |
fc1ede588 Driver core: remo... |
115 |
bus_put(bus); |
1da177e4c Linux-2.6.12-rc2 |
116 117 118 119 |
} else error = -EINVAL; return error; } |
4a3ad20cc Driver core: codi... |
120 |
EXPORT_SYMBOL_GPL(bus_create_file); |
1da177e4c Linux-2.6.12-rc2 |
121 |
|
4a3ad20cc Driver core: codi... |
122 |
void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr) |
1da177e4c Linux-2.6.12-rc2 |
123 |
{ |
5901d0145 Driver core: remo... |
124 |
if (bus_get(bus)) { |
c6f7e72a3 driver core: remo... |
125 |
sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr); |
fc1ede588 Driver core: remo... |
126 |
bus_put(bus); |
1da177e4c Linux-2.6.12-rc2 |
127 128 |
} } |
4a3ad20cc Driver core: codi... |
129 |
EXPORT_SYMBOL_GPL(bus_remove_file); |
1da177e4c Linux-2.6.12-rc2 |
130 |
|
80f03e349 Driver core: add ... |
131 |
static struct kobj_type bus_ktype = { |
1da177e4c Linux-2.6.12-rc2 |
132 |
.sysfs_ops = &bus_sysfs_ops, |
80f03e349 Driver core: add ... |
133 134 135 136 137 138 139 140 141 142 |
}; static int bus_uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); if (ktype == &bus_ktype) return 1; return 0; } |
1da177e4c Linux-2.6.12-rc2 |
143 |
|
9cd43611c kobject: Constify... |
144 |
static const struct kset_uevent_ops bus_uevent_ops = { |
80f03e349 Driver core: add ... |
145 |
.filter = bus_uevent_filter, |
1da177e4c Linux-2.6.12-rc2 |
146 |
}; |
59a548338 kset: convert dri... |
147 |
static struct kset *bus_kset; |
1da177e4c Linux-2.6.12-rc2 |
148 |
|
1da177e4c Linux-2.6.12-rc2 |
149 |
|
2139bdd5b [PATCH] drivers/b... |
150 |
#ifdef CONFIG_HOTPLUG |
2b08c8d04 [PATCH] Small fix... |
151 |
/* Manually detach a device from its associated driver. */ |
151ef38f7 [PATCH] driver co... |
152 153 154 |
static ssize_t driver_unbind(struct device_driver *drv, const char *buf, size_t count) { |
5901d0145 Driver core: remo... |
155 |
struct bus_type *bus = bus_get(drv->bus); |
151ef38f7 [PATCH] driver co... |
156 157 |
struct device *dev; int err = -ENODEV; |
1f9ffc049 Driver core: add ... |
158 |
dev = bus_find_device_by_name(bus, NULL, buf); |
2b08c8d04 [PATCH] Small fix... |
159 |
if (dev && dev->driver == drv) { |
bf74ad5bc [PATCH] Hold the ... |
160 |
if (dev->parent) /* Needed for USB */ |
8e9394ce2 Driver core: crea... |
161 |
device_lock(dev->parent); |
151ef38f7 [PATCH] driver co... |
162 |
device_release_driver(dev); |
bf74ad5bc [PATCH] Hold the ... |
163 |
if (dev->parent) |
8e9394ce2 Driver core: crea... |
164 |
device_unlock(dev->parent); |
151ef38f7 [PATCH] driver co... |
165 166 |
err = count; } |
2b08c8d04 [PATCH] Small fix... |
167 |
put_device(dev); |
fc1ede588 Driver core: remo... |
168 |
bus_put(bus); |
2b08c8d04 [PATCH] Small fix... |
169 |
return err; |
151ef38f7 [PATCH] driver co... |
170 171 |
} static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); |
afdce75f1 [PATCH] driver co... |
172 173 174 175 176 177 178 179 |
/* * Manually attach a device to a driver. * Note: the driver must want to bind to the device, * it is not possible to override the driver's id table. */ static ssize_t driver_bind(struct device_driver *drv, const char *buf, size_t count) { |
5901d0145 Driver core: remo... |
180 |
struct bus_type *bus = bus_get(drv->bus); |
afdce75f1 [PATCH] driver co... |
181 182 |
struct device *dev; int err = -ENODEV; |
1f9ffc049 Driver core: add ... |
183 |
dev = bus_find_device_by_name(bus, NULL, buf); |
49b420a13 driver core: chec... |
184 |
if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { |
bf74ad5bc [PATCH] Hold the ... |
185 |
if (dev->parent) /* Needed for USB */ |
8e9394ce2 Driver core: crea... |
186 187 |
device_lock(dev->parent); device_lock(dev); |
afdce75f1 [PATCH] driver co... |
188 |
err = driver_probe_device(drv, dev); |
8e9394ce2 Driver core: crea... |
189 |
device_unlock(dev); |
bf74ad5bc [PATCH] Hold the ... |
190 |
if (dev->parent) |
8e9394ce2 Driver core: crea... |
191 |
device_unlock(dev->parent); |
372254018 [PATCH] driver co... |
192 |
|
4a3ad20cc Driver core: codi... |
193 194 |
if (err > 0) { /* success */ |
372254018 [PATCH] driver co... |
195 |
err = count; |
4a3ad20cc Driver core: codi... |
196 197 |
} else if (err == 0) { /* driver didn't accept device */ |
372254018 [PATCH] driver co... |
198 |
err = -ENODEV; |
4a3ad20cc Driver core: codi... |
199 |
} |
afdce75f1 [PATCH] driver co... |
200 |
} |
2b08c8d04 [PATCH] Small fix... |
201 |
put_device(dev); |
fc1ede588 Driver core: remo... |
202 |
bus_put(bus); |
2b08c8d04 [PATCH] Small fix... |
203 |
return err; |
afdce75f1 [PATCH] driver co... |
204 205 |
} static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); |
b8c5cec23 Driver core: udev... |
206 207 |
static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf) { |
c6f7e72a3 driver core: remo... |
208 209 |
return sprintf(buf, "%d ", bus->p->drivers_autoprobe); |
b8c5cec23 Driver core: udev... |
210 211 212 213 214 215 |
} static ssize_t store_drivers_autoprobe(struct bus_type *bus, const char *buf, size_t count) { if (buf[0] == '0') |
c6f7e72a3 driver core: remo... |
216 |
bus->p->drivers_autoprobe = 0; |
b8c5cec23 Driver core: udev... |
217 |
else |
c6f7e72a3 driver core: remo... |
218 |
bus->p->drivers_autoprobe = 1; |
b8c5cec23 Driver core: udev... |
219 220 221 222 223 224 225 |
return count; } static ssize_t store_drivers_probe(struct bus_type *bus, const char *buf, size_t count) { struct device *dev; |
1f9ffc049 Driver core: add ... |
226 |
dev = bus_find_device_by_name(bus, NULL, buf); |
b8c5cec23 Driver core: udev... |
227 228 229 230 231 232 |
if (!dev) return -ENODEV; if (bus_rescan_devices_helper(dev, NULL) != 0) return -EINVAL; return count; } |
2139bdd5b [PATCH] drivers/b... |
233 |
#endif |
151ef38f7 [PATCH] driver co... |
234 |
|
4a3ad20cc Driver core: codi... |
235 |
static struct device *next_device(struct klist_iter *i) |
465c7a3a3 [PATCH] Add a kli... |
236 |
{ |
4a3ad20cc Driver core: codi... |
237 |
struct klist_node *n = klist_next(i); |
ae1b41715 driver core: move... |
238 239 240 241 242 243 244 245 |
struct device *dev = NULL; struct device_private *dev_prv; if (n) { dev_prv = to_device_private_bus(n); dev = dev_prv->device; } return dev; |
465c7a3a3 [PATCH] Add a kli... |
246 |
} |
1da177e4c Linux-2.6.12-rc2 |
247 |
/** |
4a3ad20cc Driver core: codi... |
248 249 250 251 252 |
* bus_for_each_dev - device iterator. * @bus: bus type. * @start: device to start iterating from. * @data: data for the callback. * @fn: function to be called for each device. |
1da177e4c Linux-2.6.12-rc2 |
253 |
* |
4a3ad20cc Driver core: codi... |
254 255 256 |
* Iterate over @bus's list of devices, and call @fn for each, * passing it @data. If @start is not NULL, we use that device to * begin iterating from. |
1da177e4c Linux-2.6.12-rc2 |
257 |
* |
4a3ad20cc Driver core: codi... |
258 259 |
* We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. |
1da177e4c Linux-2.6.12-rc2 |
260 |
* |
4a3ad20cc Driver core: codi... |
261 262 |
* NOTE: The device that returns a non-zero value is not retained * in any way, nor is its refcount incremented. If the caller needs |
0fa1b0a14 trivial: fix gram... |
263 |
* to retain this data, it should do so, and increment the reference |
4a3ad20cc Driver core: codi... |
264 |
* count in the supplied callback. |
1da177e4c Linux-2.6.12-rc2 |
265 |
*/ |
4a3ad20cc Driver core: codi... |
266 267 |
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *)) |
1da177e4c Linux-2.6.12-rc2 |
268 |
{ |
465c7a3a3 [PATCH] Add a kli... |
269 |
struct klist_iter i; |
4a3ad20cc Driver core: codi... |
270 |
struct device *dev; |
465c7a3a3 [PATCH] Add a kli... |
271 |
int error = 0; |
1da177e4c Linux-2.6.12-rc2 |
272 |
|
465c7a3a3 [PATCH] Add a kli... |
273 274 |
if (!bus) return -EINVAL; |
c6f7e72a3 driver core: remo... |
275 |
klist_iter_init_node(&bus->p->klist_devices, &i, |
ae1b41715 driver core: move... |
276 |
(start ? &start->p->knode_bus : NULL)); |
465c7a3a3 [PATCH] Add a kli... |
277 278 279 280 |
while ((dev = next_device(&i)) && !error) error = fn(dev, data); klist_iter_exit(&i); return error; |
1da177e4c Linux-2.6.12-rc2 |
281 |
} |
4a3ad20cc Driver core: codi... |
282 |
EXPORT_SYMBOL_GPL(bus_for_each_dev); |
1da177e4c Linux-2.6.12-rc2 |
283 |
|
0edb58604 [PATCH] driver co... |
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
/** * bus_find_device - device iterator for locating a particular device. * @bus: bus type * @start: Device to begin with * @data: Data to pass to match function * @match: Callback function to check device * * This is similar to the bus_for_each_dev() function above, but it * returns a reference to a device that is 'found' for later use, as * determined by the @match callback. * * The callback should return 0 if the device doesn't match and non-zero * if it does. If the callback returns non-zero, this function will * return to the caller and not iterate over any more devices. */ |
4a3ad20cc Driver core: codi... |
299 300 301 |
struct device *bus_find_device(struct bus_type *bus, struct device *start, void *data, int (*match)(struct device *dev, void *data)) |
0edb58604 [PATCH] driver co... |
302 303 304 305 306 307 |
{ struct klist_iter i; struct device *dev; if (!bus) return NULL; |
c6f7e72a3 driver core: remo... |
308 |
klist_iter_init_node(&bus->p->klist_devices, &i, |
ae1b41715 driver core: move... |
309 |
(start ? &start->p->knode_bus : NULL)); |
0edb58604 [PATCH] driver co... |
310 311 312 313 314 315 |
while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)) break; klist_iter_exit(&i); return dev; } |
4a3ad20cc Driver core: codi... |
316 |
EXPORT_SYMBOL_GPL(bus_find_device); |
38fdac3cd [PATCH] Add a kli... |
317 |
|
1f9ffc049 Driver core: add ... |
318 319 320 |
static int match_name(struct device *dev, void *data) { const char *name = data; |
1e0b2cf93 driver core: stru... |
321 |
return sysfs_streq(name, dev_name(dev)); |
1f9ffc049 Driver core: add ... |
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
} /** * bus_find_device_by_name - device iterator for locating a particular device of a specific name * @bus: bus type * @start: Device to begin with * @name: name of the device to match * * This is similar to the bus_find_device() function above, but it handles * searching by a name automatically, no need to write another strcmp matching * function. */ struct device *bus_find_device_by_name(struct bus_type *bus, struct device *start, const char *name) { return bus_find_device(bus, start, (void *)name, match_name); } EXPORT_SYMBOL_GPL(bus_find_device_by_name); |
4a3ad20cc Driver core: codi... |
340 |
static struct device_driver *next_driver(struct klist_iter *i) |
38fdac3cd [PATCH] Add a kli... |
341 |
{ |
4a3ad20cc Driver core: codi... |
342 |
struct klist_node *n = klist_next(i); |
e5dd12784 Driver core: move... |
343 344 345 346 347 348 349 |
struct driver_private *drv_priv; if (n) { drv_priv = container_of(n, struct driver_private, knode_bus); return drv_priv->driver; } return NULL; |
38fdac3cd [PATCH] Add a kli... |
350 |
} |
1da177e4c Linux-2.6.12-rc2 |
351 |
/** |
4a3ad20cc Driver core: codi... |
352 353 354 355 356 |
* bus_for_each_drv - driver iterator * @bus: bus we're dealing with. * @start: driver to start iterating on. * @data: data to pass to the callback. * @fn: function to call for each driver. |
1da177e4c Linux-2.6.12-rc2 |
357 |
* |
4a3ad20cc Driver core: codi... |
358 359 360 361 362 |
* This is nearly identical to the device iterator above. * We iterate over each driver that belongs to @bus, and call * @fn for each. If @fn returns anything but 0, we break out * and return it. If @start is not NULL, we use it as the head * of the list. |
1da177e4c Linux-2.6.12-rc2 |
363 |
* |
4a3ad20cc Driver core: codi... |
364 365 366 367 368 |
* NOTE: we don't return the driver that returns a non-zero * value, nor do we leave the reference count incremented for that * driver. If the caller needs to know that info, it must set it * in the callback. It must also be sure to increment the refcount * so it doesn't disappear before returning to the caller. |
1da177e4c Linux-2.6.12-rc2 |
369 |
*/ |
4a3ad20cc Driver core: codi... |
370 371 |
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *)) |
1da177e4c Linux-2.6.12-rc2 |
372 |
{ |
38fdac3cd [PATCH] Add a kli... |
373 |
struct klist_iter i; |
4a3ad20cc Driver core: codi... |
374 |
struct device_driver *drv; |
38fdac3cd [PATCH] Add a kli... |
375 |
int error = 0; |
1da177e4c Linux-2.6.12-rc2 |
376 |
|
38fdac3cd [PATCH] Add a kli... |
377 378 |
if (!bus) return -EINVAL; |
c6f7e72a3 driver core: remo... |
379 |
klist_iter_init_node(&bus->p->klist_drivers, &i, |
e5dd12784 Driver core: move... |
380 |
start ? &start->p->knode_bus : NULL); |
38fdac3cd [PATCH] Add a kli... |
381 382 383 384 |
while ((drv = next_driver(&i)) && !error) error = fn(drv, data); klist_iter_exit(&i); return error; |
1da177e4c Linux-2.6.12-rc2 |
385 |
} |
4a3ad20cc Driver core: codi... |
386 |
EXPORT_SYMBOL_GPL(bus_for_each_drv); |
1da177e4c Linux-2.6.12-rc2 |
387 |
|
4aca67e5f Driver core: devi... |
388 |
static int device_add_attrs(struct bus_type *bus, struct device *dev) |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 |
{ int error = 0; int i; |
4aca67e5f Driver core: devi... |
392 393 394 395 |
if (!bus->dev_attrs) return 0; for (i = 0; attr_name(bus->dev_attrs[i]); i++) { |
4a3ad20cc Driver core: codi... |
396 |
error = device_create_file(dev, &bus->dev_attrs[i]); |
4aca67e5f Driver core: devi... |
397 398 399 400 |
if (error) { while (--i >= 0) device_remove_file(dev, &bus->dev_attrs[i]); break; |
1da177e4c Linux-2.6.12-rc2 |
401 402 |
} } |
1da177e4c Linux-2.6.12-rc2 |
403 |
return error; |
1da177e4c Linux-2.6.12-rc2 |
404 |
} |
4a3ad20cc Driver core: codi... |
405 |
static void device_remove_attrs(struct bus_type *bus, struct device *dev) |
1da177e4c Linux-2.6.12-rc2 |
406 407 408 409 410 |
{ int i; if (bus->dev_attrs) { for (i = 0; attr_name(bus->dev_attrs[i]); i++) |
4a3ad20cc Driver core: codi... |
411 |
device_remove_file(dev, &bus->dev_attrs[i]); |
1da177e4c Linux-2.6.12-rc2 |
412 413 |
} } |
b9cafc7d5 CONFIG_SYSFS_DEPR... |
414 415 416 417 |
#ifdef CONFIG_SYSFS_DEPRECATED static int make_deprecated_bus_links(struct device *dev) { return sysfs_create_link(&dev->kobj, |
c6f7e72a3 driver core: remo... |
418 |
&dev->bus->p->subsys.kobj, "bus"); |
b9cafc7d5 CONFIG_SYSFS_DEPR... |
419 420 421 422 423 424 425 426 427 428 |
} static void remove_deprecated_bus_links(struct device *dev) { sysfs_remove_link(&dev->kobj, "bus"); } #else static inline int make_deprecated_bus_links(struct device *dev) { return 0; } static inline void remove_deprecated_bus_links(struct device *dev) { } #endif |
1da177e4c Linux-2.6.12-rc2 |
429 430 |
/** |
4a3ad20cc Driver core: codi... |
431 432 |
* bus_add_device - add device to bus * @dev: device being added |
1da177e4c Linux-2.6.12-rc2 |
433 |
* |
2023c610d Driver core: add ... |
434 435 |
* - Add device's bus attributes. * - Create links to device's bus. |
4a3ad20cc Driver core: codi... |
436 |
* - Add the device to its bus's list of devices. |
1da177e4c Linux-2.6.12-rc2 |
437 |
*/ |
4a3ad20cc Driver core: codi... |
438 |
int bus_add_device(struct device *dev) |
1da177e4c Linux-2.6.12-rc2 |
439 |
{ |
4a3ad20cc Driver core: codi... |
440 |
struct bus_type *bus = bus_get(dev->bus); |
1da177e4c Linux-2.6.12-rc2 |
441 442 443 |
int error = 0; if (bus) { |
1e0b2cf93 driver core: stru... |
444 445 |
pr_debug("bus: '%s': add device %s ", bus->name, dev_name(dev)); |
d377e85b5 [PATCH] driver co... |
446 |
error = device_add_attrs(bus, dev); |
f86db396f drivers/base: che... |
447 |
if (error) |
513e7337a driver core fixes... |
448 |
goto out_put; |
c6f7e72a3 driver core: remo... |
449 |
error = sysfs_create_link(&bus->p->devices_kset->kobj, |
1e0b2cf93 driver core: stru... |
450 |
&dev->kobj, dev_name(dev)); |
f86db396f drivers/base: che... |
451 |
if (error) |
513e7337a driver core fixes... |
452 |
goto out_id; |
f86db396f drivers/base: che... |
453 |
error = sysfs_create_link(&dev->kobj, |
c6f7e72a3 driver core: remo... |
454 |
&dev->bus->p->subsys.kobj, "subsystem"); |
f86db396f drivers/base: che... |
455 |
if (error) |
513e7337a driver core fixes... |
456 |
goto out_subsys; |
b9cafc7d5 CONFIG_SYSFS_DEPR... |
457 |
error = make_deprecated_bus_links(dev); |
513e7337a driver core fixes... |
458 459 |
if (error) goto out_deprecated; |
2023c610d Driver core: add ... |
460 |
klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices); |
1da177e4c Linux-2.6.12-rc2 |
461 |
} |
513e7337a driver core fixes... |
462 463 464 465 466 |
return 0; out_deprecated: sysfs_remove_link(&dev->kobj, "subsystem"); out_subsys: |
1e0b2cf93 driver core: stru... |
467 |
sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev)); |
513e7337a driver core fixes... |
468 469 470 |
out_id: device_remove_attrs(bus, dev); out_put: |
fc1ede588 Driver core: remo... |
471 |
bus_put(dev->bus); |
1da177e4c Linux-2.6.12-rc2 |
472 473 474 475 |
return error; } /** |
2023c610d Driver core: add ... |
476 477 |
* bus_probe_device - probe drivers for a new device * @dev: device to probe |
53877d06d [PATCH] Driver co... |
478 |
* |
2023c610d Driver core: add ... |
479 |
* - Automatically probe for a driver if the bus allows it. |
53877d06d [PATCH] Driver co... |
480 |
*/ |
2023c610d Driver core: add ... |
481 |
void bus_probe_device(struct device *dev) |
53877d06d [PATCH] Driver co... |
482 |
{ |
f86db396f drivers/base: che... |
483 |
struct bus_type *bus = dev->bus; |
2023c610d Driver core: add ... |
484 |
int ret; |
53877d06d [PATCH] Driver co... |
485 |
|
2023c610d Driver core: add ... |
486 487 |
if (bus && bus->p->drivers_autoprobe) { ret = device_attach(dev); |
c6a46696f driver core: don'... |
488 |
WARN_ON(ret < 0); |
53877d06d [PATCH] Driver co... |
489 490 491 492 |
} } /** |
4a3ad20cc Driver core: codi... |
493 494 |
* bus_remove_device - remove device from bus * @dev: device to be removed |
1da177e4c Linux-2.6.12-rc2 |
495 |
* |
4a3ad20cc Driver core: codi... |
496 497 498 499 |
* - Remove symlink from bus's directory. * - Delete device from bus's list. * - Detach from its driver. * - Drop reference taken in bus_add_device(). |
1da177e4c Linux-2.6.12-rc2 |
500 |
*/ |
4a3ad20cc Driver core: codi... |
501 |
void bus_remove_device(struct device *dev) |
1da177e4c Linux-2.6.12-rc2 |
502 503 |
{ if (dev->bus) { |
b9d9c82b4 [PATCH] Driver co... |
504 |
sysfs_remove_link(&dev->kobj, "subsystem"); |
b9cafc7d5 CONFIG_SYSFS_DEPR... |
505 |
remove_deprecated_bus_links(dev); |
4a3ad20cc Driver core: codi... |
506 |
sysfs_remove_link(&dev->bus->p->devices_kset->kobj, |
1e0b2cf93 driver core: stru... |
507 |
dev_name(dev)); |
1da177e4c Linux-2.6.12-rc2 |
508 |
device_remove_attrs(dev->bus, dev); |
ae1b41715 driver core: move... |
509 510 |
if (klist_node_attached(&dev->p->knode_bus)) klist_del(&dev->p->knode_bus); |
3f62e5700 Driver core: make... |
511 |
|
4a3ad20cc Driver core: codi... |
512 513 |
pr_debug("bus: '%s': remove device %s ", |
1e0b2cf93 driver core: stru... |
514 |
dev->bus->name, dev_name(dev)); |
1da177e4c Linux-2.6.12-rc2 |
515 |
device_release_driver(dev); |
fc1ede588 Driver core: remo... |
516 |
bus_put(dev->bus); |
1da177e4c Linux-2.6.12-rc2 |
517 518 |
} } |
4a3ad20cc Driver core: codi... |
519 |
static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) |
1da177e4c Linux-2.6.12-rc2 |
520 521 522 523 524 525 526 527 |
{ int error = 0; int i; if (bus->drv_attrs) { for (i = 0; attr_name(bus->drv_attrs[i]); i++) { error = driver_create_file(drv, &bus->drv_attrs[i]); if (error) |
4a3ad20cc Driver core: codi... |
528 |
goto err; |
1da177e4c Linux-2.6.12-rc2 |
529 530 |
} } |
4a3ad20cc Driver core: codi... |
531 |
done: |
1da177e4c Linux-2.6.12-rc2 |
532 |
return error; |
4a3ad20cc Driver core: codi... |
533 |
err: |
1da177e4c Linux-2.6.12-rc2 |
534 535 |
while (--i >= 0) driver_remove_file(drv, &bus->drv_attrs[i]); |
4a3ad20cc Driver core: codi... |
536 |
goto done; |
1da177e4c Linux-2.6.12-rc2 |
537 |
} |
4a3ad20cc Driver core: codi... |
538 539 |
static void driver_remove_attrs(struct bus_type *bus, struct device_driver *drv) |
1da177e4c Linux-2.6.12-rc2 |
540 541 542 543 544 545 546 547 |
{ int i; if (bus->drv_attrs) { for (i = 0; attr_name(bus->drv_attrs[i]); i++) driver_remove_file(drv, &bus->drv_attrs[i]); } } |
874c6241b [PATCH] Driver co... |
548 549 550 551 552 |
#ifdef CONFIG_HOTPLUG /* * Thanks to drivers making their tables __devinit, we can't allow manual * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled. */ |
f86db396f drivers/base: che... |
553 |
static int __must_check add_bind_files(struct device_driver *drv) |
874c6241b [PATCH] Driver co... |
554 |
{ |
f86db396f drivers/base: che... |
555 556 557 558 559 560 561 562 563 |
int ret; ret = driver_create_file(drv, &driver_attr_unbind); if (ret == 0) { ret = driver_create_file(drv, &driver_attr_bind); if (ret) driver_remove_file(drv, &driver_attr_unbind); } return ret; |
874c6241b [PATCH] Driver co... |
564 565 566 567 568 569 570 |
} static void remove_bind_files(struct device_driver *drv) { driver_remove_file(drv, &driver_attr_bind); driver_remove_file(drv, &driver_attr_unbind); } |
b8c5cec23 Driver core: udev... |
571 |
|
8380770c8 Driver core: make... |
572 573 574 |
static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe); static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO, show_drivers_autoprobe, store_drivers_autoprobe); |
b8c5cec23 Driver core: udev... |
575 576 577 |
static int add_probe_files(struct bus_type *bus) { int retval; |
8380770c8 Driver core: make... |
578 |
retval = bus_create_file(bus, &bus_attr_drivers_probe); |
b8c5cec23 Driver core: udev... |
579 580 |
if (retval) goto out; |
8380770c8 Driver core: make... |
581 |
retval = bus_create_file(bus, &bus_attr_drivers_autoprobe); |
b8c5cec23 Driver core: udev... |
582 |
if (retval) |
8380770c8 Driver core: make... |
583 |
bus_remove_file(bus, &bus_attr_drivers_probe); |
b8c5cec23 Driver core: udev... |
584 585 586 587 588 589 |
out: return retval; } static void remove_probe_files(struct bus_type *bus) { |
8380770c8 Driver core: make... |
590 591 |
bus_remove_file(bus, &bus_attr_drivers_autoprobe); bus_remove_file(bus, &bus_attr_drivers_probe); |
b8c5cec23 Driver core: udev... |
592 |
} |
874c6241b [PATCH] Driver co... |
593 |
#else |
35acfdd72 Driver core: fixe... |
594 |
static inline int add_bind_files(struct device_driver *drv) { return 0; } |
874c6241b [PATCH] Driver co... |
595 |
static inline void remove_bind_files(struct device_driver *drv) {} |
b8c5cec23 Driver core: udev... |
596 597 |
static inline int add_probe_files(struct bus_type *bus) { return 0; } static inline void remove_probe_files(struct bus_type *bus) {} |
874c6241b [PATCH] Driver co... |
598 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
599 |
|
7ac1cf4a8 Driver core: add ... |
600 601 602 603 604 605 |
static ssize_t driver_uevent_store(struct device_driver *drv, const char *buf, size_t count) { enum kobject_action action; if (kobject_action_type(buf, count, &action) == 0) |
e5dd12784 Driver core: move... |
606 |
kobject_uevent(&drv->p->kobj, action); |
7ac1cf4a8 Driver core: add ... |
607 608 609 |
return count; } static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store); |
1da177e4c Linux-2.6.12-rc2 |
610 |
/** |
4a3ad20cc Driver core: codi... |
611 612 |
* bus_add_driver - Add a driver to the bus. * @drv: driver. |
1da177e4c Linux-2.6.12-rc2 |
613 |
*/ |
f86db396f drivers/base: che... |
614 |
int bus_add_driver(struct device_driver *drv) |
1da177e4c Linux-2.6.12-rc2 |
615 |
{ |
e5dd12784 Driver core: move... |
616 617 |
struct bus_type *bus; struct driver_private *priv; |
1da177e4c Linux-2.6.12-rc2 |
618 |
int error = 0; |
e5dd12784 Driver core: move... |
619 |
bus = bus_get(drv->bus); |
d9fd4d3b3 Driver core: bus:... |
620 |
if (!bus) |
4f6e1945f driver core: bus_... |
621 |
return -EINVAL; |
d9fd4d3b3 Driver core: bus:... |
622 |
|
7dc72b284 Driver core: clea... |
623 624 |
pr_debug("bus: '%s': add driver %s ", bus->name, drv->name); |
e5dd12784 Driver core: move... |
625 626 |
priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
076344642 Driver core: Fix ... |
627 628 629 630 |
if (!priv) { error = -ENOMEM; goto out_put_bus; } |
e5dd12784 Driver core: move... |
631 632 633 |
klist_init(&priv->klist_devices, NULL, NULL); priv->driver = drv; drv->p = priv; |
c8e90d822 Kobject: change d... |
634 635 636 |
priv->kobj.kset = bus->p->drivers_kset; error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name); |
dc0afa838 Driver core: codi... |
637 |
if (error) |
076344642 Driver core: Fix ... |
638 |
goto out_unregister; |
d9fd4d3b3 Driver core: bus:... |
639 |
|
c6f7e72a3 driver core: remo... |
640 |
if (drv->bus->p->drivers_autoprobe) { |
b8c5cec23 Driver core: udev... |
641 642 643 644 |
error = driver_attach(drv); if (error) goto out_unregister; } |
e5dd12784 Driver core: move... |
645 |
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); |
d9fd4d3b3 Driver core: bus:... |
646 |
module_add_driver(drv->owner, drv); |
7ac1cf4a8 Driver core: add ... |
647 648 649 650 |
error = driver_create_file(drv, &driver_attr_uevent); if (error) { printk(KERN_ERR "%s: uevent attr (%s) failed ", |
2b3a302a0 driver core: repl... |
651 |
__func__, drv->name); |
7ac1cf4a8 Driver core: add ... |
652 |
} |
d9fd4d3b3 Driver core: bus:... |
653 654 655 656 657 |
error = driver_add_attrs(bus, drv); if (error) { /* How the hell do we get out of this pickle? Give up */ printk(KERN_ERR "%s: driver_add_attrs(%s) failed ", |
2b3a302a0 driver core: repl... |
658 |
__func__, drv->name); |
d9fd4d3b3 Driver core: bus:... |
659 |
} |
1a6f2a751 Driver core: allo... |
660 661 662 663 664 665 666 667 668 |
if (!drv->suppress_bind_attrs) { error = add_bind_files(drv); if (error) { /* Ditto */ printk(KERN_ERR "%s: add_bind_files(%s) failed ", __func__, drv->name); } |
1da177e4c Linux-2.6.12-rc2 |
669 |
} |
d9fd4d3b3 Driver core: bus:... |
670 |
|
c8e90d822 Kobject: change d... |
671 |
kobject_uevent(&priv->kobj, KOBJ_ADD); |
5c8563d77 Driver Core: do n... |
672 |
return 0; |
1a6f2a751 Driver core: allo... |
673 |
|
f86db396f drivers/base: che... |
674 |
out_unregister: |
99b28f1b4 driver core: Prev... |
675 |
kobject_put(&priv->kobj); |
5c8563d77 Driver Core: do n... |
676 677 |
kfree(drv->p); drv->p = NULL; |
f86db396f drivers/base: che... |
678 |
out_put_bus: |
fc1ede588 Driver core: remo... |
679 |
bus_put(bus); |
f86db396f drivers/base: che... |
680 |
return error; |
1da177e4c Linux-2.6.12-rc2 |
681 |
} |
1da177e4c Linux-2.6.12-rc2 |
682 |
/** |
4a3ad20cc Driver core: codi... |
683 684 |
* bus_remove_driver - delete driver from bus's knowledge. * @drv: driver. |
1da177e4c Linux-2.6.12-rc2 |
685 |
* |
4a3ad20cc Driver core: codi... |
686 687 688 |
* Detach the driver from the devices it controls, and remove * it from its bus's list of drivers. Finally, we drop the reference * to the bus we took in bus_add_driver(). |
1da177e4c Linux-2.6.12-rc2 |
689 |
*/ |
4a3ad20cc Driver core: codi... |
690 |
void bus_remove_driver(struct device_driver *drv) |
1da177e4c Linux-2.6.12-rc2 |
691 |
{ |
d9fd4d3b3 Driver core: bus:... |
692 693 |
if (!drv->bus) return; |
1a6f2a751 Driver core: allo... |
694 695 |
if (!drv->suppress_bind_attrs) remove_bind_files(drv); |
d9fd4d3b3 Driver core: bus:... |
696 |
driver_remove_attrs(drv->bus, drv); |
7ac1cf4a8 Driver core: add ... |
697 |
driver_remove_file(drv, &driver_attr_uevent); |
e5dd12784 Driver core: move... |
698 |
klist_remove(&drv->p->knode_bus); |
7dc72b284 Driver core: clea... |
699 700 |
pr_debug("bus: '%s': remove driver %s ", drv->bus->name, drv->name); |
d9fd4d3b3 Driver core: bus:... |
701 702 |
driver_detach(drv); module_remove_driver(drv); |
c10997f65 Kobject: convert ... |
703 |
kobject_put(&drv->p->kobj); |
fc1ede588 Driver core: remo... |
704 |
bus_put(drv->bus); |
1da177e4c Linux-2.6.12-rc2 |
705 |
} |
1da177e4c Linux-2.6.12-rc2 |
706 |
/* Helper for bus_rescan_devices's iter */ |
f86db396f drivers/base: che... |
707 |
static int __must_check bus_rescan_devices_helper(struct device *dev, |
4a3ad20cc Driver core: codi... |
708 |
void *data) |
1da177e4c Linux-2.6.12-rc2 |
709 |
{ |
f86db396f drivers/base: che... |
710 |
int ret = 0; |
bf74ad5bc [PATCH] Hold the ... |
711 712 |
if (!dev->driver) { if (dev->parent) /* Needed for USB */ |
8e9394ce2 Driver core: crea... |
713 |
device_lock(dev->parent); |
f86db396f drivers/base: che... |
714 |
ret = device_attach(dev); |
bf74ad5bc [PATCH] Hold the ... |
715 |
if (dev->parent) |
8e9394ce2 Driver core: crea... |
716 |
device_unlock(dev->parent); |
bf74ad5bc [PATCH] Hold the ... |
717 |
} |
f86db396f drivers/base: che... |
718 |
return ret < 0 ? ret : 0; |
1da177e4c Linux-2.6.12-rc2 |
719 |
} |
1da177e4c Linux-2.6.12-rc2 |
720 |
/** |
23d3d602c [PATCH] driver co... |
721 722 |
* bus_rescan_devices - rescan devices on the bus for possible drivers * @bus: the bus to scan. |
1da177e4c Linux-2.6.12-rc2 |
723 |
* |
23d3d602c [PATCH] driver co... |
724 725 726 |
* This function will look for devices on the bus with no driver * attached and rescan it against existing drivers to see if it matches * any by calling device_attach() for the unbound devices. |
1da177e4c Linux-2.6.12-rc2 |
727 |
*/ |
4a3ad20cc Driver core: codi... |
728 |
int bus_rescan_devices(struct bus_type *bus) |
1da177e4c Linux-2.6.12-rc2 |
729 |
{ |
f86db396f drivers/base: che... |
730 |
return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); |
1da177e4c Linux-2.6.12-rc2 |
731 |
} |
4a3ad20cc Driver core: codi... |
732 |
EXPORT_SYMBOL_GPL(bus_rescan_devices); |
1da177e4c Linux-2.6.12-rc2 |
733 |
|
e935d5da8 [SCSI] drivers/ba... |
734 735 736 737 738 739 740 741 742 |
/** * device_reprobe - remove driver for a device and probe for a new driver * @dev: the device to reprobe * * This function detaches the attached driver (if any) for the given * device and restarts the driver probing process. It is intended * to use if probing criteria changed during a devices lifetime and * driver attachment should change accordingly. */ |
f86db396f drivers/base: che... |
743 |
int device_reprobe(struct device *dev) |
e935d5da8 [SCSI] drivers/ba... |
744 745 746 |
{ if (dev->driver) { if (dev->parent) /* Needed for USB */ |
8e9394ce2 Driver core: crea... |
747 |
device_lock(dev->parent); |
e935d5da8 [SCSI] drivers/ba... |
748 749 |
device_release_driver(dev); if (dev->parent) |
8e9394ce2 Driver core: crea... |
750 |
device_unlock(dev->parent); |
e935d5da8 [SCSI] drivers/ba... |
751 |
} |
f86db396f drivers/base: che... |
752 |
return bus_rescan_devices_helper(dev, NULL); |
e935d5da8 [SCSI] drivers/ba... |
753 754 |
} EXPORT_SYMBOL_GPL(device_reprobe); |
1da177e4c Linux-2.6.12-rc2 |
755 |
|
1da177e4c Linux-2.6.12-rc2 |
756 |
/** |
4a3ad20cc Driver core: codi... |
757 758 |
* find_bus - locate bus by name. * @name: name of bus. |
1da177e4c Linux-2.6.12-rc2 |
759 |
* |
4a3ad20cc Driver core: codi... |
760 761 |
* Call kset_find_obj() to iterate over list of buses to * find a bus by name. Return bus if found. |
1da177e4c Linux-2.6.12-rc2 |
762 |
* |
4a3ad20cc Driver core: codi... |
763 |
* Note that kset_find_obj increments bus' reference count. |
1da177e4c Linux-2.6.12-rc2 |
764 |
*/ |
7e4ef085e [PATCH] Driver co... |
765 |
#if 0 |
4a3ad20cc Driver core: codi... |
766 |
struct bus_type *find_bus(char *name) |
1da177e4c Linux-2.6.12-rc2 |
767 |
{ |
4a3ad20cc Driver core: codi... |
768 |
struct kobject *k = kset_find_obj(bus_kset, name); |
1da177e4c Linux-2.6.12-rc2 |
769 770 |
return k ? to_bus(k) : NULL; } |
7e4ef085e [PATCH] Driver co... |
771 |
#endif /* 0 */ |
1da177e4c Linux-2.6.12-rc2 |
772 773 774 |
/** |
4a3ad20cc Driver core: codi... |
775 776 |
* bus_add_attrs - Add default attributes for this bus. * @bus: Bus that has just been registered. |
1da177e4c Linux-2.6.12-rc2 |
777 |
*/ |
4a3ad20cc Driver core: codi... |
778 |
static int bus_add_attrs(struct bus_type *bus) |
1da177e4c Linux-2.6.12-rc2 |
779 780 781 782 783 784 |
{ int error = 0; int i; if (bus->bus_attrs) { for (i = 0; attr_name(bus->bus_attrs[i]); i++) { |
4a3ad20cc Driver core: codi... |
785 |
error = bus_create_file(bus, &bus->bus_attrs[i]); |
dc0afa838 Driver core: codi... |
786 |
if (error) |
4a3ad20cc Driver core: codi... |
787 |
goto err; |
1da177e4c Linux-2.6.12-rc2 |
788 789 |
} } |
4a3ad20cc Driver core: codi... |
790 |
done: |
1da177e4c Linux-2.6.12-rc2 |
791 |
return error; |
4a3ad20cc Driver core: codi... |
792 |
err: |
1da177e4c Linux-2.6.12-rc2 |
793 |
while (--i >= 0) |
4a3ad20cc Driver core: codi... |
794 795 |
bus_remove_file(bus, &bus->bus_attrs[i]); goto done; |
1da177e4c Linux-2.6.12-rc2 |
796 |
} |
4a3ad20cc Driver core: codi... |
797 |
static void bus_remove_attrs(struct bus_type *bus) |
1da177e4c Linux-2.6.12-rc2 |
798 799 800 801 802 |
{ int i; if (bus->bus_attrs) { for (i = 0; attr_name(bus->bus_attrs[i]); i++) |
4a3ad20cc Driver core: codi... |
803 |
bus_remove_file(bus, &bus->bus_attrs[i]); |
1da177e4c Linux-2.6.12-rc2 |
804 805 |
} } |
34bb61f9d [PATCH] fix klist... |
806 807 |
static void klist_devices_get(struct klist_node *n) { |
ae1b41715 driver core: move... |
808 809 |
struct device_private *dev_prv = to_device_private_bus(n); struct device *dev = dev_prv->device; |
34bb61f9d [PATCH] fix klist... |
810 811 812 813 814 815 |
get_device(dev); } static void klist_devices_put(struct klist_node *n) { |
ae1b41715 driver core: move... |
816 817 |
struct device_private *dev_prv = to_device_private_bus(n); struct device *dev = dev_prv->device; |
34bb61f9d [PATCH] fix klist... |
818 819 820 |
put_device(dev); } |
7ac1cf4a8 Driver core: add ... |
821 822 823 824 825 826 |
static ssize_t bus_uevent_store(struct bus_type *bus, const char *buf, size_t count) { enum kobject_action action; if (kobject_action_type(buf, count, &action) == 0) |
c6f7e72a3 driver core: remo... |
827 |
kobject_uevent(&bus->p->subsys.kobj, action); |
7ac1cf4a8 Driver core: add ... |
828 829 830 |
return count; } static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); |
1da177e4c Linux-2.6.12-rc2 |
831 |
/** |
4a3ad20cc Driver core: codi... |
832 833 |
* bus_register - register a bus with the system. * @bus: bus. |
1da177e4c Linux-2.6.12-rc2 |
834 |
* |
4a3ad20cc Driver core: codi... |
835 836 837 |
* Once we have that, we registered the bus with the kobject * infrastructure, then register the children subsystems it has: * the devices and drivers that belong to the bus. |
1da177e4c Linux-2.6.12-rc2 |
838 |
*/ |
4a3ad20cc Driver core: codi... |
839 |
int bus_register(struct bus_type *bus) |
1da177e4c Linux-2.6.12-rc2 |
840 841 |
{ int retval; |
c6f7e72a3 driver core: remo... |
842 843 844 845 846 847 848 849 |
struct bus_type_private *priv; priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL); if (!priv) return -ENOMEM; priv->bus = bus; bus->p = priv; |
1da177e4c Linux-2.6.12-rc2 |
850 |
|
c6f7e72a3 driver core: remo... |
851 |
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); |
116af3782 Driver core: add ... |
852 |
|
c6f7e72a3 driver core: remo... |
853 |
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); |
1da177e4c Linux-2.6.12-rc2 |
854 855 |
if (retval) goto out; |
c6f7e72a3 driver core: remo... |
856 857 858 |
priv->subsys.kobj.kset = bus_kset; priv->subsys.kobj.ktype = &bus_ktype; priv->drivers_autoprobe = 1; |
d6b05b84e Driver core: remo... |
859 |
|
c6f7e72a3 driver core: remo... |
860 |
retval = kset_register(&priv->subsys); |
1da177e4c Linux-2.6.12-rc2 |
861 862 |
if (retval) goto out; |
7ac1cf4a8 Driver core: add ... |
863 864 865 |
retval = bus_create_file(bus, &bus_attr_uevent); if (retval) goto bus_uevent_fail; |
c6f7e72a3 driver core: remo... |
866 867 868 |
priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj); if (!priv->devices_kset) { |
3d8995963 kset: convert str... |
869 |
retval = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
870 |
goto bus_devices_fail; |
3d8995963 kset: convert str... |
871 |
} |
1da177e4c Linux-2.6.12-rc2 |
872 |
|
c6f7e72a3 driver core: remo... |
873 874 875 |
priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj); if (!priv->drivers_kset) { |
6dcec2511 kset: convert str... |
876 |
retval = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
877 |
goto bus_drivers_fail; |
6dcec2511 kset: convert str... |
878 |
} |
465c7a3a3 [PATCH] Add a kli... |
879 |
|
c6f7e72a3 driver core: remo... |
880 881 |
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); klist_init(&priv->klist_drivers, NULL, NULL); |
b8c5cec23 Driver core: udev... |
882 |
|
b8c5cec23 Driver core: udev... |
883 884 885 |
retval = add_probe_files(bus); if (retval) goto bus_probe_files_fail; |
1bb6881ac driver core fixes... |
886 887 888 |
retval = bus_add_attrs(bus); if (retval) goto bus_attrs_fail; |
1da177e4c Linux-2.6.12-rc2 |
889 |
|
7dc72b284 Driver core: clea... |
890 891 |
pr_debug("bus: '%s': registered ", bus->name); |
1da177e4c Linux-2.6.12-rc2 |
892 |
return 0; |
1bb6881ac driver core fixes... |
893 |
bus_attrs_fail: |
b8c5cec23 Driver core: udev... |
894 895 |
remove_probe_files(bus); bus_probe_files_fail: |
c6f7e72a3 driver core: remo... |
896 |
kset_unregister(bus->p->drivers_kset); |
1da177e4c Linux-2.6.12-rc2 |
897 |
bus_drivers_fail: |
c6f7e72a3 driver core: remo... |
898 |
kset_unregister(bus->p->devices_kset); |
1da177e4c Linux-2.6.12-rc2 |
899 |
bus_devices_fail: |
7ac1cf4a8 Driver core: add ... |
900 901 |
bus_remove_file(bus, &bus_attr_uevent); bus_uevent_fail: |
c6f7e72a3 driver core: remo... |
902 |
kset_unregister(&bus->p->subsys); |
1da177e4c Linux-2.6.12-rc2 |
903 |
out: |
600c20f34 driver core: fix ... |
904 |
kfree(bus->p); |
f48f3febb driver-core: do n... |
905 |
bus->p = NULL; |
1da177e4c Linux-2.6.12-rc2 |
906 907 |
return retval; } |
4a3ad20cc Driver core: codi... |
908 |
EXPORT_SYMBOL_GPL(bus_register); |
1da177e4c Linux-2.6.12-rc2 |
909 |
|
1da177e4c Linux-2.6.12-rc2 |
910 |
/** |
4a3ad20cc Driver core: codi... |
911 912 |
* bus_unregister - remove a bus from the system * @bus: bus. |
1da177e4c Linux-2.6.12-rc2 |
913 |
* |
4a3ad20cc Driver core: codi... |
914 915 |
* Unregister the child subsystems and the bus itself. * Finally, we call bus_put() to release the refcount |
1da177e4c Linux-2.6.12-rc2 |
916 |
*/ |
4a3ad20cc Driver core: codi... |
917 |
void bus_unregister(struct bus_type *bus) |
1da177e4c Linux-2.6.12-rc2 |
918 |
{ |
7dc72b284 Driver core: clea... |
919 920 |
pr_debug("bus: '%s': unregistering ", bus->name); |
1da177e4c Linux-2.6.12-rc2 |
921 |
bus_remove_attrs(bus); |
b8c5cec23 Driver core: udev... |
922 |
remove_probe_files(bus); |
c6f7e72a3 driver core: remo... |
923 924 |
kset_unregister(bus->p->drivers_kset); kset_unregister(bus->p->devices_kset); |
7ac1cf4a8 Driver core: add ... |
925 |
bus_remove_file(bus, &bus_attr_uevent); |
c6f7e72a3 driver core: remo... |
926 927 |
kset_unregister(&bus->p->subsys); kfree(bus->p); |
f48f3febb driver-core: do n... |
928 |
bus->p = NULL; |
1da177e4c Linux-2.6.12-rc2 |
929 |
} |
4a3ad20cc Driver core: codi... |
930 |
EXPORT_SYMBOL_GPL(bus_unregister); |
1da177e4c Linux-2.6.12-rc2 |
931 |
|
116af3782 Driver core: add ... |
932 933 |
int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb) { |
c6f7e72a3 driver core: remo... |
934 |
return blocking_notifier_chain_register(&bus->p->bus_notifier, nb); |
116af3782 Driver core: add ... |
935 936 937 938 939 |
} EXPORT_SYMBOL_GPL(bus_register_notifier); int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb) { |
c6f7e72a3 driver core: remo... |
940 |
return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb); |
116af3782 Driver core: add ... |
941 942 |
} EXPORT_SYMBOL_GPL(bus_unregister_notifier); |
0fed80f7a driver core: add ... |
943 944 |
struct kset *bus_get_kset(struct bus_type *bus) { |
c6f7e72a3 driver core: remo... |
945 |
return &bus->p->subsys; |
0fed80f7a driver core: add ... |
946 947 |
} EXPORT_SYMBOL_GPL(bus_get_kset); |
b249072ee driver core: add ... |
948 949 |
struct klist *bus_get_device_klist(struct bus_type *bus) { |
c6f7e72a3 driver core: remo... |
950 |
return &bus->p->klist_devices; |
b249072ee driver core: add ... |
951 952 |
} EXPORT_SYMBOL_GPL(bus_get_device_klist); |
99178b036 Driver core: add ... |
953 954 955 956 957 958 959 960 961 962 963 964 965 |
/* * Yes, this forcably breaks the klist abstraction temporarily. It * just wants to sort the klist, not change reference counts and * take/drop locks rapidly in the process. It does all this while * holding the lock for the list, so objects can't otherwise be * added/removed while we're swizzling. */ static void device_insertion_sort_klist(struct device *a, struct list_head *list, int (*compare)(const struct device *a, const struct device *b)) { struct list_head *pos; struct klist_node *n; |
ae1b41715 driver core: move... |
966 |
struct device_private *dev_prv; |
99178b036 Driver core: add ... |
967 968 969 970 |
struct device *b; list_for_each(pos, list) { n = container_of(pos, struct klist_node, n_node); |
ae1b41715 driver core: move... |
971 972 |
dev_prv = to_device_private_bus(n); b = dev_prv->device; |
99178b036 Driver core: add ... |
973 |
if (compare(a, b) <= 0) { |
ae1b41715 driver core: move... |
974 975 |
list_move_tail(&a->p->knode_bus.n_node, &b->p->knode_bus.n_node); |
99178b036 Driver core: add ... |
976 977 978 |
return; } } |
ae1b41715 driver core: move... |
979 |
list_move_tail(&a->p->knode_bus.n_node, list); |
99178b036 Driver core: add ... |
980 981 982 983 984 985 986 987 988 |
} void bus_sort_breadthfirst(struct bus_type *bus, int (*compare)(const struct device *a, const struct device *b)) { LIST_HEAD(sorted_devices); struct list_head *pos, *tmp; struct klist_node *n; |
ae1b41715 driver core: move... |
989 |
struct device_private *dev_prv; |
99178b036 Driver core: add ... |
990 991 992 993 994 995 996 997 |
struct device *dev; struct klist *device_klist; device_klist = bus_get_device_klist(bus); spin_lock(&device_klist->k_lock); list_for_each_safe(pos, tmp, &device_klist->k_list) { n = container_of(pos, struct klist_node, n_node); |
ae1b41715 driver core: move... |
998 999 |
dev_prv = to_device_private_bus(n); dev = dev_prv->device; |
99178b036 Driver core: add ... |
1000 1001 1002 1003 1004 1005 |
device_insertion_sort_klist(dev, &sorted_devices, compare); } list_splice(&sorted_devices, &device_klist->k_list); spin_unlock(&device_klist->k_lock); } EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); |
1da177e4c Linux-2.6.12-rc2 |
1006 1007 |
int __init buses_init(void) { |
59a548338 kset: convert dri... |
1008 1009 1010 1011 |
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); if (!bus_kset) return -ENOMEM; return 0; |
1da177e4c Linux-2.6.12-rc2 |
1012 |
} |