diff options
author | Andrew Morton <akpm@osdl.org> | 2006-08-15 01:43:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-26 00:08:39 -0400 |
commit | f86db396ff455ed586751d21816a1ebd431264e5 (patch) | |
tree | dfbeb27206b673ed46482b18ee6d779786be7ed1 | |
parent | 370226449ced358e52d198081120826ef52c166b (diff) |
drivers/base: check errors
Add lots of return-value checking.
<pcornelia.huck@de.ibm.com>: fix bus_rescan_devices()]
Cc: "Randy.Dunlap" <rdunlap@xenotime.net>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/base/base.h | 2 | ||||
-rw-r--r-- | drivers/base/bus.c | 107 | ||||
-rw-r--r-- | drivers/base/dd.c | 37 | ||||
-rw-r--r-- | include/linux/device.h | 8 |
4 files changed, 104 insertions, 50 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h index c3b8dc98b8a7..d26644a59537 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -16,7 +16,7 @@ extern int cpu_dev_init(void); | |||
16 | extern int attribute_container_init(void); | 16 | extern int attribute_container_init(void); |
17 | 17 | ||
18 | extern int bus_add_device(struct device * dev); | 18 | extern int bus_add_device(struct device * dev); |
19 | extern void bus_attach_device(struct device * dev); | 19 | extern int bus_attach_device(struct device * dev); |
20 | extern void bus_remove_device(struct device * dev); | 20 | extern void bus_remove_device(struct device * dev); |
21 | extern struct bus_type *get_bus(struct bus_type * bus); | 21 | extern struct bus_type *get_bus(struct bus_type * bus); |
22 | extern void put_bus(struct bus_type * bus); | 22 | extern void put_bus(struct bus_type * bus); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 4d22a1d10a1c..aa685a20b649 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -371,12 +371,20 @@ int bus_add_device(struct device * dev) | |||
371 | if (bus) { | 371 | if (bus) { |
372 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); | 372 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); |
373 | error = device_add_attrs(bus, dev); | 373 | error = device_add_attrs(bus, dev); |
374 | if (!error) { | 374 | if (error) |
375 | sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); | 375 | goto out; |
376 | sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem"); | 376 | error = sysfs_create_link(&bus->devices.kobj, |
377 | sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); | 377 | &dev->kobj, dev->bus_id); |
378 | } | 378 | if (error) |
379 | goto out; | ||
380 | error = sysfs_create_link(&dev->kobj, | ||
381 | &dev->bus->subsys.kset.kobj, "subsystem"); | ||
382 | if (error) | ||
383 | goto out; | ||
384 | error = sysfs_create_link(&dev->kobj, | ||
385 | &dev->bus->subsys.kset.kobj, "bus"); | ||
379 | } | 386 | } |
387 | out: | ||
380 | return error; | 388 | return error; |
381 | } | 389 | } |
382 | 390 | ||
@@ -386,14 +394,19 @@ int bus_add_device(struct device * dev) | |||
386 | * | 394 | * |
387 | * - Try to attach to driver. | 395 | * - Try to attach to driver. |
388 | */ | 396 | */ |
389 | void bus_attach_device(struct device * dev) | 397 | int bus_attach_device(struct device * dev) |
390 | { | 398 | { |
391 | struct bus_type * bus = dev->bus; | 399 | struct bus_type *bus = dev->bus; |
400 | int ret = 0; | ||
392 | 401 | ||
393 | if (bus) { | 402 | if (bus) { |
394 | device_attach(dev); | 403 | ret = device_attach(dev); |
395 | klist_add_tail(&dev->knode_bus, &bus->klist_devices); | 404 | if (ret >= 0) { |
405 | klist_add_tail(&dev->knode_bus, &bus->klist_devices); | ||
406 | ret = 0; | ||
407 | } | ||
396 | } | 408 | } |
409 | return ret; | ||
397 | } | 410 | } |
398 | 411 | ||
399 | /** | 412 | /** |
@@ -455,10 +468,17 @@ static void driver_remove_attrs(struct bus_type * bus, struct device_driver * dr | |||
455 | * Thanks to drivers making their tables __devinit, we can't allow manual | 468 | * Thanks to drivers making their tables __devinit, we can't allow manual |
456 | * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled. | 469 | * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled. |
457 | */ | 470 | */ |
458 | static void add_bind_files(struct device_driver *drv) | 471 | static int __must_check add_bind_files(struct device_driver *drv) |
459 | { | 472 | { |
460 | driver_create_file(drv, &driver_attr_unbind); | 473 | int ret; |
461 | driver_create_file(drv, &driver_attr_bind); | 474 | |
475 | ret = driver_create_file(drv, &driver_attr_unbind); | ||
476 | if (ret == 0) { | ||
477 | ret = driver_create_file(drv, &driver_attr_bind); | ||
478 | if (ret) | ||
479 | driver_remove_file(drv, &driver_attr_unbind); | ||
480 | } | ||
481 | return ret; | ||
462 | } | 482 | } |
463 | 483 | ||
464 | static void remove_bind_files(struct device_driver *drv) | 484 | static void remove_bind_files(struct device_driver *drv) |
@@ -476,7 +496,7 @@ static inline void remove_bind_files(struct device_driver *drv) {} | |||
476 | * @drv: driver. | 496 | * @drv: driver. |
477 | * | 497 | * |
478 | */ | 498 | */ |
479 | int bus_add_driver(struct device_driver * drv) | 499 | int bus_add_driver(struct device_driver *drv) |
480 | { | 500 | { |
481 | struct bus_type * bus = get_bus(drv->bus); | 501 | struct bus_type * bus = get_bus(drv->bus); |
482 | int error = 0; | 502 | int error = 0; |
@@ -484,27 +504,39 @@ int bus_add_driver(struct device_driver * drv) | |||
484 | if (bus) { | 504 | if (bus) { |
485 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); | 505 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); |
486 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | 506 | error = kobject_set_name(&drv->kobj, "%s", drv->name); |
487 | if (error) { | 507 | if (error) |
488 | put_bus(bus); | 508 | goto out_put_bus; |
489 | return error; | ||
490 | } | ||
491 | drv->kobj.kset = &bus->drivers; | 509 | drv->kobj.kset = &bus->drivers; |
492 | if ((error = kobject_register(&drv->kobj))) { | 510 | if ((error = kobject_register(&drv->kobj))) |
493 | put_bus(bus); | 511 | goto out_put_bus; |
494 | return error; | ||
495 | } | ||
496 | 512 | ||
497 | driver_attach(drv); | 513 | error = driver_attach(drv); |
514 | if (error) | ||
515 | goto out_unregister; | ||
498 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | 516 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); |
499 | module_add_driver(drv->owner, drv); | 517 | module_add_driver(drv->owner, drv); |
500 | 518 | ||
501 | driver_add_attrs(bus, drv); | 519 | error = driver_add_attrs(bus, drv); |
502 | add_bind_files(drv); | 520 | if (error) { |
521 | /* How the hell do we get out of this pickle? Give up */ | ||
522 | printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", | ||
523 | __FUNCTION__, drv->name); | ||
524 | } | ||
525 | error = add_bind_files(drv); | ||
526 | if (error) { | ||
527 | /* Ditto */ | ||
528 | printk(KERN_ERR "%s: add_bind_files(%s) failed\n", | ||
529 | __FUNCTION__, drv->name); | ||
530 | } | ||
503 | } | 531 | } |
504 | return error; | 532 | return error; |
533 | out_unregister: | ||
534 | kobject_unregister(&drv->kobj); | ||
535 | out_put_bus: | ||
536 | put_bus(bus); | ||
537 | return error; | ||
505 | } | 538 | } |
506 | 539 | ||
507 | |||
508 | /** | 540 | /** |
509 | * bus_remove_driver - delete driver from bus's knowledge. | 541 | * bus_remove_driver - delete driver from bus's knowledge. |
510 | * @drv: driver. | 542 | * @drv: driver. |
@@ -530,16 +562,21 @@ void bus_remove_driver(struct device_driver * drv) | |||
530 | 562 | ||
531 | 563 | ||
532 | /* Helper for bus_rescan_devices's iter */ | 564 | /* Helper for bus_rescan_devices's iter */ |
533 | static int bus_rescan_devices_helper(struct device *dev, void *data) | 565 | static int __must_check bus_rescan_devices_helper(struct device *dev, |
566 | void *data) | ||
534 | { | 567 | { |
568 | int ret = 0; | ||
569 | |||
535 | if (!dev->driver) { | 570 | if (!dev->driver) { |
536 | if (dev->parent) /* Needed for USB */ | 571 | if (dev->parent) /* Needed for USB */ |
537 | down(&dev->parent->sem); | 572 | down(&dev->parent->sem); |
538 | device_attach(dev); | 573 | ret = device_attach(dev); |
539 | if (dev->parent) | 574 | if (dev->parent) |
540 | up(&dev->parent->sem); | 575 | up(&dev->parent->sem); |
576 | if (ret > 0) | ||
577 | ret = 0; | ||
541 | } | 578 | } |
542 | return 0; | 579 | return ret < 0 ? ret : 0; |
543 | } | 580 | } |
544 | 581 | ||
545 | /** | 582 | /** |
@@ -550,9 +587,9 @@ static int bus_rescan_devices_helper(struct device *dev, void *data) | |||
550 | * attached and rescan it against existing drivers to see if it matches | 587 | * attached and rescan it against existing drivers to see if it matches |
551 | * any by calling device_attach() for the unbound devices. | 588 | * any by calling device_attach() for the unbound devices. |
552 | */ | 589 | */ |
553 | void bus_rescan_devices(struct bus_type * bus) | 590 | int bus_rescan_devices(struct bus_type * bus) |
554 | { | 591 | { |
555 | bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); | 592 | return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); |
556 | } | 593 | } |
557 | 594 | ||
558 | /** | 595 | /** |
@@ -564,7 +601,7 @@ void bus_rescan_devices(struct bus_type * bus) | |||
564 | * to use if probing criteria changed during a devices lifetime and | 601 | * to use if probing criteria changed during a devices lifetime and |
565 | * driver attachment should change accordingly. | 602 | * driver attachment should change accordingly. |
566 | */ | 603 | */ |
567 | void device_reprobe(struct device *dev) | 604 | int device_reprobe(struct device *dev) |
568 | { | 605 | { |
569 | if (dev->driver) { | 606 | if (dev->driver) { |
570 | if (dev->parent) /* Needed for USB */ | 607 | if (dev->parent) /* Needed for USB */ |
@@ -573,14 +610,14 @@ void device_reprobe(struct device *dev) | |||
573 | if (dev->parent) | 610 | if (dev->parent) |
574 | up(&dev->parent->sem); | 611 | up(&dev->parent->sem); |
575 | } | 612 | } |
576 | 613 | return bus_rescan_devices_helper(dev, NULL); | |
577 | bus_rescan_devices_helper(dev, NULL); | ||
578 | } | 614 | } |
579 | EXPORT_SYMBOL_GPL(device_reprobe); | 615 | EXPORT_SYMBOL_GPL(device_reprobe); |
580 | 616 | ||
581 | struct bus_type * get_bus(struct bus_type * bus) | 617 | struct bus_type *get_bus(struct bus_type *bus) |
582 | { | 618 | { |
583 | return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL; | 619 | return bus ? container_of(subsys_get(&bus->subsys), |
620 | struct bus_type, subsys) : NULL; | ||
584 | } | 621 | } |
585 | 622 | ||
586 | void put_bus(struct bus_type * bus) | 623 | void put_bus(struct bus_type * bus) |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 889c71111239..9f6f11ca0ab6 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -38,17 +38,29 @@ | |||
38 | * | 38 | * |
39 | * This function must be called with @dev->sem held. | 39 | * This function must be called with @dev->sem held. |
40 | */ | 40 | */ |
41 | void device_bind_driver(struct device * dev) | 41 | int device_bind_driver(struct device *dev) |
42 | { | 42 | { |
43 | if (klist_node_attached(&dev->knode_driver)) | 43 | int ret; |
44 | return; | 44 | |
45 | if (klist_node_attached(&dev->knode_driver)) { | ||
46 | printk(KERN_WARNING "%s: device %s already bound\n", | ||
47 | __FUNCTION__, kobject_name(&dev->kobj)); | ||
48 | return 0; | ||
49 | } | ||
45 | 50 | ||
46 | pr_debug("bound device '%s' to driver '%s'\n", | 51 | pr_debug("bound device '%s' to driver '%s'\n", |
47 | dev->bus_id, dev->driver->name); | 52 | dev->bus_id, dev->driver->name); |
48 | klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); | 53 | klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); |
49 | sysfs_create_link(&dev->driver->kobj, &dev->kobj, | 54 | ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, |
50 | kobject_name(&dev->kobj)); | 55 | kobject_name(&dev->kobj)); |
51 | sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver"); | 56 | if (ret == 0) { |
57 | ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj, | ||
58 | "driver"); | ||
59 | if (ret) | ||
60 | sysfs_remove_link(&dev->driver->kobj, | ||
61 | kobject_name(&dev->kobj)); | ||
62 | } | ||
63 | return ret; | ||
52 | } | 64 | } |
53 | 65 | ||
54 | /** | 66 | /** |
@@ -91,7 +103,11 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
91 | goto ProbeFailed; | 103 | goto ProbeFailed; |
92 | } | 104 | } |
93 | } | 105 | } |
94 | device_bind_driver(dev); | 106 | if (device_bind_driver(dev)) { |
107 | printk(KERN_ERR "%s: device_bind_driver(%s) failed\n", | ||
108 | __FUNCTION__, dev->bus_id); | ||
109 | /* How does undo a ->probe? We're screwed. */ | ||
110 | } | ||
95 | ret = 1; | 111 | ret = 1; |
96 | pr_debug("%s: Bound Device %s to Driver %s\n", | 112 | pr_debug("%s: Bound Device %s to Driver %s\n", |
97 | drv->bus->name, dev->bus_id, drv->name); | 113 | drv->bus->name, dev->bus_id, drv->name); |
@@ -139,8 +155,9 @@ int device_attach(struct device * dev) | |||
139 | 155 | ||
140 | down(&dev->sem); | 156 | down(&dev->sem); |
141 | if (dev->driver) { | 157 | if (dev->driver) { |
142 | device_bind_driver(dev); | 158 | ret = device_bind_driver(dev); |
143 | ret = 1; | 159 | if (ret == 0) |
160 | ret = 1; | ||
144 | } else | 161 | } else |
145 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); | 162 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); |
146 | up(&dev->sem); | 163 | up(&dev->sem); |
@@ -182,9 +199,9 @@ static int __driver_attach(struct device * dev, void * data) | |||
182 | * returns 0 and the @dev->driver is set, we've found a | 199 | * returns 0 and the @dev->driver is set, we've found a |
183 | * compatible pair. | 200 | * compatible pair. |
184 | */ | 201 | */ |
185 | void driver_attach(struct device_driver * drv) | 202 | int driver_attach(struct device_driver * drv) |
186 | { | 203 | { |
187 | bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); | 204 | return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); |
188 | } | 205 | } |
189 | 206 | ||
190 | /** | 207 | /** |
diff --git a/include/linux/device.h b/include/linux/device.h index ad4db72f5733..b3da9a870cfc 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -62,7 +62,7 @@ struct bus_type { | |||
62 | extern int __must_check bus_register(struct bus_type * bus); | 62 | extern int __must_check bus_register(struct bus_type * bus); |
63 | extern void bus_unregister(struct bus_type * bus); | 63 | extern void bus_unregister(struct bus_type * bus); |
64 | 64 | ||
65 | extern void bus_rescan_devices(struct bus_type * bus); | 65 | extern int __must_check bus_rescan_devices(struct bus_type * bus); |
66 | 66 | ||
67 | /* iterator helpers for buses */ | 67 | /* iterator helpers for buses */ |
68 | 68 | ||
@@ -397,11 +397,11 @@ extern int device_rename(struct device *dev, char *new_name); | |||
397 | * Manual binding of a device to driver. See drivers/base/bus.c | 397 | * Manual binding of a device to driver. See drivers/base/bus.c |
398 | * for information on use. | 398 | * for information on use. |
399 | */ | 399 | */ |
400 | extern void device_bind_driver(struct device * dev); | 400 | extern int __must_check device_bind_driver(struct device *dev); |
401 | extern void device_release_driver(struct device * dev); | 401 | extern void device_release_driver(struct device * dev); |
402 | extern int __must_check device_attach(struct device * dev); | 402 | extern int __must_check device_attach(struct device * dev); |
403 | extern void driver_attach(struct device_driver * drv); | 403 | extern int __must_check driver_attach(struct device_driver *drv); |
404 | extern void device_reprobe(struct device *dev); | 404 | extern int __must_check device_reprobe(struct device *dev); |
405 | 405 | ||
406 | /* | 406 | /* |
407 | * Easy functions for dynamically creating devices on the fly | 407 | * Easy functions for dynamically creating devices on the fly |