blob: c8da37230b3ec81465f8264e4ae1d22851f1ce5b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * bus.c - bus driver management
3 *
4 * Copyright (c) 2002-3 Patrick Mochel
5 * Copyright (c) 2002-3 Open Source Development Labs
6 *
7 * This file is released under the GPLv2
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/device.h>
13#include <linux/module.h>
14#include <linux/errno.h>
15#include <linux/init.h>
16#include <linux/string.h>
17#include "base.h"
18#include "power/power.h"
19
20#define to_dev(node) container_of(node, struct device, bus_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
22#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
23#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)
24
25/*
26 * sysfs bindings for drivers
27 */
28
29#define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
30#define to_driver(obj) container_of(obj, struct device_driver, kobj)
31
32
33static ssize_t
34drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
35{
36 struct driver_attribute * drv_attr = to_drv_attr(attr);
37 struct device_driver * drv = to_driver(kobj);
Dmitry Torokhov4a0c20b2005-04-29 01:23:47 -050038 ssize_t ret = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40 if (drv_attr->show)
41 ret = drv_attr->show(drv, buf);
42 return ret;
43}
44
45static ssize_t
46drv_attr_store(struct kobject * kobj, struct attribute * attr,
47 const char * buf, size_t count)
48{
49 struct driver_attribute * drv_attr = to_drv_attr(attr);
50 struct device_driver * drv = to_driver(kobj);
Dmitry Torokhov4a0c20b2005-04-29 01:23:47 -050051 ssize_t ret = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
53 if (drv_attr->store)
54 ret = drv_attr->store(drv, buf, count);
55 return ret;
56}
57
58static struct sysfs_ops driver_sysfs_ops = {
59 .show = drv_attr_show,
60 .store = drv_attr_store,
61};
62
63
64static void driver_release(struct kobject * kobj)
65{
66 struct device_driver * drv = to_driver(kobj);
67 complete(&drv->unloaded);
68}
69
70static struct kobj_type ktype_driver = {
71 .sysfs_ops = &driver_sysfs_ops,
72 .release = driver_release,
73};
74
75
76/*
77 * sysfs bindings for buses
78 */
79
80
81static ssize_t
82bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
83{
84 struct bus_attribute * bus_attr = to_bus_attr(attr);
85 struct bus_type * bus = to_bus(kobj);
86 ssize_t ret = 0;
87
88 if (bus_attr->show)
89 ret = bus_attr->show(bus, buf);
90 return ret;
91}
92
93static ssize_t
94bus_attr_store(struct kobject * kobj, struct attribute * attr,
95 const char * buf, size_t count)
96{
97 struct bus_attribute * bus_attr = to_bus_attr(attr);
98 struct bus_type * bus = to_bus(kobj);
99 ssize_t ret = 0;
100
101 if (bus_attr->store)
102 ret = bus_attr->store(bus, buf, count);
103 return ret;
104}
105
106static struct sysfs_ops bus_sysfs_ops = {
107 .show = bus_attr_show,
108 .store = bus_attr_store,
109};
110
111int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
112{
113 int error;
114 if (get_bus(bus)) {
115 error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr);
116 put_bus(bus);
117 } else
118 error = -EINVAL;
119 return error;
120}
121
122void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
123{
124 if (get_bus(bus)) {
125 sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr);
126 put_bus(bus);
127 }
128}
129
130static struct kobj_type ktype_bus = {
131 .sysfs_ops = &bus_sysfs_ops,
132
133};
134
135decl_subsys(bus, &ktype_bus, NULL);
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
139 void * data, int (*fn)(struct device_driver *, void *))
140{
141 struct list_head *head;
142 struct device_driver *drv;
143 int error = 0;
144
145 if (!(bus = get_bus(bus)))
146 return -EINVAL;
147
148 head = &bus->drivers.list;
149 drv = list_prepare_entry(start, head, kobj.entry);
150 list_for_each_entry_continue(drv, head, kobj.entry) {
151 get_driver(drv);
152 error = fn(drv, data);
153 put_driver(drv);
154 if (error)
155 break;
156 }
157 put_bus(bus);
158 return error;
159}
160
mochel@digitalimplant.org465c7a32005-03-21 11:49:14 -0800161
162static struct device * next_device(struct klist_iter * i)
163{
164 struct klist_node * n = klist_next(i);
165 return n ? container_of(n, struct device, knode_bus) : NULL;
166}
167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168/**
169 * bus_for_each_dev - device iterator.
170 * @bus: bus type.
171 * @start: device to start iterating from.
172 * @data: data for the callback.
173 * @fn: function to be called for each device.
174 *
175 * Iterate over @bus's list of devices, and call @fn for each,
176 * passing it @data. If @start is not NULL, we use that device to
177 * begin iterating from.
178 *
179 * We check the return of @fn each time. If it returns anything
180 * other than 0, we break out and return that value.
181 *
182 * NOTE: The device that returns a non-zero value is not retained
183 * in any way, nor is its refcount incremented. If the caller needs
184 * to retain this data, it should do, and increment the reference
185 * count in the supplied callback.
186 */
187
188int bus_for_each_dev(struct bus_type * bus, struct device * start,
189 void * data, int (*fn)(struct device *, void *))
190{
mochel@digitalimplant.org465c7a32005-03-21 11:49:14 -0800191 struct klist_iter i;
192 struct device * dev;
193 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194
mochel@digitalimplant.org465c7a32005-03-21 11:49:14 -0800195 if (!bus)
196 return -EINVAL;
197
198 klist_iter_init_node(&bus->klist_devices, &i,
199 (start ? &start->knode_bus : NULL));
200 while ((dev = next_device(&i)) && !error)
201 error = fn(dev, data);
202 klist_iter_exit(&i);
203 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204}
205
206/**
207 * bus_for_each_drv - driver iterator
208 * @bus: bus we're dealing with.
209 * @start: driver to start iterating on.
210 * @data: data to pass to the callback.
211 * @fn: function to call for each driver.
212 *
213 * This is nearly identical to the device iterator above.
214 * We iterate over each driver that belongs to @bus, and call
215 * @fn for each. If @fn returns anything but 0, we break out
216 * and return it. If @start is not NULL, we use it as the head
217 * of the list.
218 *
219 * NOTE: we don't return the driver that returns a non-zero
220 * value, nor do we leave the reference count incremented for that
221 * driver. If the caller needs to know that info, it must set it
222 * in the callback. It must also be sure to increment the refcount
223 * so it doesn't disappear before returning to the caller.
224 */
225
226int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
227 void * data, int (*fn)(struct device_driver *, void *))
228{
229 int ret;
230
231 down_read(&bus->subsys.rwsem);
232 ret = __bus_for_each_drv(bus, start, data, fn);
233 up_read(&bus->subsys.rwsem);
234 return ret;
235}
236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237static int device_add_attrs(struct bus_type * bus, struct device * dev)
238{
239 int error = 0;
240 int i;
241
242 if (bus->dev_attrs) {
243 for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
244 error = device_create_file(dev,&bus->dev_attrs[i]);
245 if (error)
246 goto Err;
247 }
248 }
249 Done:
250 return error;
251 Err:
252 while (--i >= 0)
253 device_remove_file(dev,&bus->dev_attrs[i]);
254 goto Done;
255}
256
257
258static void device_remove_attrs(struct bus_type * bus, struct device * dev)
259{
260 int i;
261
262 if (bus->dev_attrs) {
263 for (i = 0; attr_name(bus->dev_attrs[i]); i++)
264 device_remove_file(dev,&bus->dev_attrs[i]);
265 }
266}
267
268
269/**
270 * bus_add_device - add device to bus
271 * @dev: device being added
272 *
273 * - Add the device to its bus's list of devices.
274 * - Try to attach to driver.
275 * - Create link to device's physical location.
276 */
277int bus_add_device(struct device * dev)
278{
279 struct bus_type * bus = get_bus(dev->bus);
280 int error = 0;
281
282 if (bus) {
283 down_write(&dev->bus->subsys.rwsem);
284 pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
285 list_add_tail(&dev->bus_list, &dev->bus->devices.list);
286 device_attach(dev);
287 up_write(&dev->bus->subsys.rwsem);
mochel@digitalimplant.org465c7a32005-03-21 11:49:14 -0800288 klist_add_tail(&bus->klist_devices, &dev->knode_bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 device_add_attrs(bus, dev);
290 sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
291 sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
292 }
293 return error;
294}
295
296/**
297 * bus_remove_device - remove device from bus
298 * @dev: device to be removed
299 *
300 * - Remove symlink from bus's directory.
301 * - Delete device from bus's list.
302 * - Detach from its driver.
303 * - Drop reference taken in bus_add_device().
304 */
305void bus_remove_device(struct device * dev)
306{
307 if (dev->bus) {
308 sysfs_remove_link(&dev->kobj, "bus");
309 sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
310 device_remove_attrs(dev->bus, dev);
mochel@digitalimplant.org465c7a32005-03-21 11:49:14 -0800311 klist_remove(&dev->knode_bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 down_write(&dev->bus->subsys.rwsem);
313 pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
314 device_release_driver(dev);
315 list_del_init(&dev->bus_list);
316 up_write(&dev->bus->subsys.rwsem);
317 put_bus(dev->bus);
318 }
319}
320
321static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
322{
323 int error = 0;
324 int i;
325
326 if (bus->drv_attrs) {
327 for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
328 error = driver_create_file(drv, &bus->drv_attrs[i]);
329 if (error)
330 goto Err;
331 }
332 }
333 Done:
334 return error;
335 Err:
336 while (--i >= 0)
337 driver_remove_file(drv, &bus->drv_attrs[i]);
338 goto Done;
339}
340
341
342static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv)
343{
344 int i;
345
346 if (bus->drv_attrs) {
347 for (i = 0; attr_name(bus->drv_attrs[i]); i++)
348 driver_remove_file(drv, &bus->drv_attrs[i]);
349 }
350}
351
352
353/**
354 * bus_add_driver - Add a driver to the bus.
355 * @drv: driver.
356 *
357 */
358int bus_add_driver(struct device_driver * drv)
359{
360 struct bus_type * bus = get_bus(drv->bus);
361 int error = 0;
362
363 if (bus) {
364 pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
365 error = kobject_set_name(&drv->kobj, "%s", drv->name);
366 if (error) {
367 put_bus(bus);
368 return error;
369 }
370 drv->kobj.kset = &bus->drivers;
371 if ((error = kobject_register(&drv->kobj))) {
372 put_bus(bus);
373 return error;
374 }
375
376 down_write(&bus->subsys.rwsem);
377 driver_attach(drv);
378 up_write(&bus->subsys.rwsem);
379 module_add_driver(drv->owner, drv);
380
381 driver_add_attrs(bus, drv);
382 }
383 return error;
384}
385
386
387/**
388 * bus_remove_driver - delete driver from bus's knowledge.
389 * @drv: driver.
390 *
391 * Detach the driver from the devices it controls, and remove
392 * it from its bus's list of drivers. Finally, we drop the reference
393 * to the bus we took in bus_add_driver().
394 */
395
396void bus_remove_driver(struct device_driver * drv)
397{
398 if (drv->bus) {
399 driver_remove_attrs(drv->bus, drv);
400 down_write(&drv->bus->subsys.rwsem);
401 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
402 driver_detach(drv);
403 up_write(&drv->bus->subsys.rwsem);
404 module_remove_driver(drv);
405 kobject_unregister(&drv->kobj);
406 put_bus(drv->bus);
407 }
408}
409
410
411/* Helper for bus_rescan_devices's iter */
412static int bus_rescan_devices_helper(struct device *dev, void *data)
413{
414 int *count = data;
415
416 if (!dev->driver && device_attach(dev))
417 (*count)++;
418
419 return 0;
420}
421
422
423/**
424 * bus_rescan_devices - rescan devices on the bus for possible drivers
425 * @bus: the bus to scan.
426 *
427 * This function will look for devices on the bus with no driver
428 * attached and rescan it against existing drivers to see if it
429 * matches any. Calls device_attach(). Returns the number of devices
430 * that were sucessfully bound to a driver.
431 */
432int bus_rescan_devices(struct bus_type * bus)
433{
434 int count = 0;
435
mochel@digitalimplant.org465c7a32005-03-21 11:49:14 -0800436 bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
438 return count;
439}
440
441
442struct bus_type * get_bus(struct bus_type * bus)
443{
444 return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL;
445}
446
447void put_bus(struct bus_type * bus)
448{
449 subsys_put(&bus->subsys);
450}
451
452
453/**
454 * find_bus - locate bus by name.
455 * @name: name of bus.
456 *
457 * Call kset_find_obj() to iterate over list of buses to
458 * find a bus by name. Return bus if found.
459 *
460 * Note that kset_find_obj increments bus' reference count.
461 */
462
463struct bus_type * find_bus(char * name)
464{
465 struct kobject * k = kset_find_obj(&bus_subsys.kset, name);
466 return k ? to_bus(k) : NULL;
467}
468
469
470/**
471 * bus_add_attrs - Add default attributes for this bus.
472 * @bus: Bus that has just been registered.
473 */
474
475static int bus_add_attrs(struct bus_type * bus)
476{
477 int error = 0;
478 int i;
479
480 if (bus->bus_attrs) {
481 for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
482 if ((error = bus_create_file(bus,&bus->bus_attrs[i])))
483 goto Err;
484 }
485 }
486 Done:
487 return error;
488 Err:
489 while (--i >= 0)
490 bus_remove_file(bus,&bus->bus_attrs[i]);
491 goto Done;
492}
493
494static void bus_remove_attrs(struct bus_type * bus)
495{
496 int i;
497
498 if (bus->bus_attrs) {
499 for (i = 0; attr_name(bus->bus_attrs[i]); i++)
500 bus_remove_file(bus,&bus->bus_attrs[i]);
501 }
502}
503
504/**
505 * bus_register - register a bus with the system.
506 * @bus: bus.
507 *
508 * Once we have that, we registered the bus with the kobject
509 * infrastructure, then register the children subsystems it has:
510 * the devices and drivers that belong to the bus.
511 */
512int bus_register(struct bus_type * bus)
513{
514 int retval;
515
516 retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
517 if (retval)
518 goto out;
519
520 subsys_set_kset(bus, bus_subsys);
521 retval = subsystem_register(&bus->subsys);
522 if (retval)
523 goto out;
524
525 kobject_set_name(&bus->devices.kobj, "devices");
526 bus->devices.subsys = &bus->subsys;
527 retval = kset_register(&bus->devices);
528 if (retval)
529 goto bus_devices_fail;
530
531 kobject_set_name(&bus->drivers.kobj, "drivers");
532 bus->drivers.subsys = &bus->subsys;
533 bus->drivers.ktype = &ktype_driver;
534 retval = kset_register(&bus->drivers);
535 if (retval)
536 goto bus_drivers_fail;
mochel@digitalimplant.org465c7a32005-03-21 11:49:14 -0800537
538 klist_init(&bus->klist_devices);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 bus_add_attrs(bus);
540
541 pr_debug("bus type '%s' registered\n", bus->name);
542 return 0;
543
544bus_drivers_fail:
545 kset_unregister(&bus->devices);
546bus_devices_fail:
547 subsystem_unregister(&bus->subsys);
548out:
549 return retval;
550}
551
552
553/**
554 * bus_unregister - remove a bus from the system
555 * @bus: bus.
556 *
557 * Unregister the child subsystems and the bus itself.
558 * Finally, we call put_bus() to release the refcount
559 */
560void bus_unregister(struct bus_type * bus)
561{
562 pr_debug("bus %s: unregistering\n", bus->name);
563 bus_remove_attrs(bus);
564 kset_unregister(&bus->drivers);
565 kset_unregister(&bus->devices);
566 subsystem_unregister(&bus->subsys);
567}
568
569int __init buses_init(void)
570{
571 return subsystem_register(&bus_subsys);
572}
573
574
575EXPORT_SYMBOL_GPL(bus_for_each_dev);
576EXPORT_SYMBOL_GPL(bus_for_each_drv);
577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578EXPORT_SYMBOL_GPL(bus_add_device);
579EXPORT_SYMBOL_GPL(bus_remove_device);
580EXPORT_SYMBOL_GPL(bus_register);
581EXPORT_SYMBOL_GPL(bus_unregister);
582EXPORT_SYMBOL_GPL(bus_rescan_devices);
583EXPORT_SYMBOL_GPL(get_bus);
584EXPORT_SYMBOL_GPL(put_bus);
585EXPORT_SYMBOL_GPL(find_bus);
586
587EXPORT_SYMBOL_GPL(bus_create_file);
588EXPORT_SYMBOL_GPL(bus_remove_file);