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 |
