diff options
Diffstat (limited to 'drivers/base/bus.c')
| -rw-r--r-- | drivers/base/bus.c | 133 |
1 files changed, 79 insertions, 54 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2e954d07175a..12173d16bea7 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 | ||
| @@ -384,16 +392,24 @@ int bus_add_device(struct device * dev) | |||
| 384 | * bus_attach_device - add device to bus | 392 | * bus_attach_device - add device to bus |
| 385 | * @dev: device tried to attach to a driver | 393 | * @dev: device tried to attach to a driver |
| 386 | * | 394 | * |
| 395 | * - Add device to bus's list of devices. | ||
| 387 | * - Try to attach to driver. | 396 | * - Try to attach to driver. |
| 388 | */ | 397 | */ |
| 389 | void bus_attach_device(struct device * dev) | 398 | int bus_attach_device(struct device * dev) |
| 390 | { | 399 | { |
| 391 | struct bus_type * bus = dev->bus; | 400 | struct bus_type *bus = dev->bus; |
| 401 | int ret = 0; | ||
| 392 | 402 | ||
| 393 | if (bus) { | 403 | if (bus) { |
| 394 | device_attach(dev); | 404 | dev->is_registered = 1; |
| 395 | klist_add_tail(&dev->knode_bus, &bus->klist_devices); | 405 | ret = device_attach(dev); |
| 406 | if (ret >= 0) { | ||
| 407 | klist_add_tail(&dev->knode_bus, &bus->klist_devices); | ||
| 408 | ret = 0; | ||
| 409 | } else | ||
| 410 | dev->is_registered = 0; | ||
| 396 | } | 411 | } |
| 412 | return ret; | ||
| 397 | } | 413 | } |
| 398 | 414 | ||
| 399 | /** | 415 | /** |
| @@ -412,7 +428,8 @@ void bus_remove_device(struct device * dev) | |||
| 412 | sysfs_remove_link(&dev->kobj, "bus"); | 428 | sysfs_remove_link(&dev->kobj, "bus"); |
| 413 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); | 429 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); |
| 414 | device_remove_attrs(dev->bus, dev); | 430 | device_remove_attrs(dev->bus, dev); |
| 415 | klist_remove(&dev->knode_bus); | 431 | dev->is_registered = 0; |
| 432 | klist_del(&dev->knode_bus); | ||
| 416 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); | 433 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); |
| 417 | device_release_driver(dev); | 434 | device_release_driver(dev); |
| 418 | put_bus(dev->bus); | 435 | put_bus(dev->bus); |
| @@ -455,10 +472,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 | 472 | * Thanks to drivers making their tables __devinit, we can't allow manual |
| 456 | * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled. | 473 | * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled. |
| 457 | */ | 474 | */ |
| 458 | static void add_bind_files(struct device_driver *drv) | 475 | static int __must_check add_bind_files(struct device_driver *drv) |
| 459 | { | 476 | { |
| 460 | driver_create_file(drv, &driver_attr_unbind); | 477 | int ret; |
| 461 | driver_create_file(drv, &driver_attr_bind); | 478 | |
| 479 | ret = driver_create_file(drv, &driver_attr_unbind); | ||
| 480 | if (ret == 0) { | ||
| 481 | ret = driver_create_file(drv, &driver_attr_bind); | ||
| 482 | if (ret) | ||
| 483 | driver_remove_file(drv, &driver_attr_unbind); | ||
| 484 | } | ||
| 485 | return ret; | ||
| 462 | } | 486 | } |
| 463 | 487 | ||
| 464 | static void remove_bind_files(struct device_driver *drv) | 488 | static void remove_bind_files(struct device_driver *drv) |
| @@ -467,7 +491,7 @@ static void remove_bind_files(struct device_driver *drv) | |||
| 467 | driver_remove_file(drv, &driver_attr_unbind); | 491 | driver_remove_file(drv, &driver_attr_unbind); |
| 468 | } | 492 | } |
| 469 | #else | 493 | #else |
| 470 | static inline void add_bind_files(struct device_driver *drv) {} | 494 | static inline int add_bind_files(struct device_driver *drv) { return 0; } |
| 471 | static inline void remove_bind_files(struct device_driver *drv) {} | 495 | static inline void remove_bind_files(struct device_driver *drv) {} |
| 472 | #endif | 496 | #endif |
| 473 | 497 | ||
| @@ -476,7 +500,7 @@ static inline void remove_bind_files(struct device_driver *drv) {} | |||
| 476 | * @drv: driver. | 500 | * @drv: driver. |
| 477 | * | 501 | * |
| 478 | */ | 502 | */ |
| 479 | int bus_add_driver(struct device_driver * drv) | 503 | int bus_add_driver(struct device_driver *drv) |
| 480 | { | 504 | { |
| 481 | struct bus_type * bus = get_bus(drv->bus); | 505 | struct bus_type * bus = get_bus(drv->bus); |
| 482 | int error = 0; | 506 | int error = 0; |
| @@ -484,27 +508,39 @@ int bus_add_driver(struct device_driver * drv) | |||
| 484 | if (bus) { | 508 | if (bus) { |
| 485 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); | 509 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); |
| 486 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | 510 | error = kobject_set_name(&drv->kobj, "%s", drv->name); |
| 487 | if (error) { | 511 | if (error) |
| 488 | put_bus(bus); | 512 | goto out_put_bus; |
| 489 | return error; | ||
| 490 | } | ||
| 491 | drv->kobj.kset = &bus->drivers; | 513 | drv->kobj.kset = &bus->drivers; |
| 492 | if ((error = kobject_register(&drv->kobj))) { | 514 | if ((error = kobject_register(&drv->kobj))) |
| 493 | put_bus(bus); | 515 | goto out_put_bus; |
| 494 | return error; | ||
| 495 | } | ||
| 496 | 516 | ||
| 497 | driver_attach(drv); | 517 | error = driver_attach(drv); |
| 518 | if (error) | ||
| 519 | goto out_unregister; | ||
| 498 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | 520 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); |
| 499 | module_add_driver(drv->owner, drv); | 521 | module_add_driver(drv->owner, drv); |
| 500 | 522 | ||
| 501 | driver_add_attrs(bus, drv); | 523 | error = driver_add_attrs(bus, drv); |
| 502 | add_bind_files(drv); | 524 | if (error) { |
| 525 | /* How the hell do we get out of this pickle? Give up */ | ||
| 526 | printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", | ||
| 527 | __FUNCTION__, drv->name); | ||
| 528 | } | ||
| 529 | error = add_bind_files(drv); | ||
| 530 | if (error) { | ||
| 531 | /* Ditto */ | ||
| 532 | printk(KERN_ERR "%s: add_bind_files(%s) failed\n", | ||
| 533 | __FUNCTION__, drv->name); | ||
| 534 | } | ||
| 503 | } | 535 | } |
| 504 | return error; | 536 | return error; |
| 537 | out_unregister: | ||
| 538 | kobject_unregister(&drv->kobj); | ||
| 539 | out_put_bus: | ||
| 540 | put_bus(bus); | ||
| 541 | return error; | ||
| 505 | } | 542 | } |
| 506 | 543 | ||
| 507 | |||
| 508 | /** | 544 | /** |
| 509 | * bus_remove_driver - delete driver from bus's knowledge. | 545 | * bus_remove_driver - delete driver from bus's knowledge. |
| 510 | * @drv: driver. | 546 | * @drv: driver. |
| @@ -530,16 +566,21 @@ void bus_remove_driver(struct device_driver * drv) | |||
| 530 | 566 | ||
| 531 | 567 | ||
| 532 | /* Helper for bus_rescan_devices's iter */ | 568 | /* Helper for bus_rescan_devices's iter */ |
| 533 | static int bus_rescan_devices_helper(struct device *dev, void *data) | 569 | static int __must_check bus_rescan_devices_helper(struct device *dev, |
| 570 | void *data) | ||
| 534 | { | 571 | { |
| 572 | int ret = 0; | ||
| 573 | |||
| 535 | if (!dev->driver) { | 574 | if (!dev->driver) { |
| 536 | if (dev->parent) /* Needed for USB */ | 575 | if (dev->parent) /* Needed for USB */ |
| 537 | down(&dev->parent->sem); | 576 | down(&dev->parent->sem); |
| 538 | device_attach(dev); | 577 | ret = device_attach(dev); |
| 539 | if (dev->parent) | 578 | if (dev->parent) |
| 540 | up(&dev->parent->sem); | 579 | up(&dev->parent->sem); |
| 580 | if (ret > 0) | ||
| 581 | ret = 0; | ||
| 541 | } | 582 | } |
| 542 | return 0; | 583 | return ret < 0 ? ret : 0; |
| 543 | } | 584 | } |
| 544 | 585 | ||
| 545 | /** | 586 | /** |
| @@ -550,9 +591,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 | 591 | * attached and rescan it against existing drivers to see if it matches |
| 551 | * any by calling device_attach() for the unbound devices. | 592 | * any by calling device_attach() for the unbound devices. |
| 552 | */ | 593 | */ |
| 553 | void bus_rescan_devices(struct bus_type * bus) | 594 | int bus_rescan_devices(struct bus_type * bus) |
| 554 | { | 595 | { |
| 555 | bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); | 596 | return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); |
| 556 | } | 597 | } |
| 557 | 598 | ||
| 558 | /** | 599 | /** |
| @@ -564,7 +605,7 @@ void bus_rescan_devices(struct bus_type * bus) | |||
| 564 | * to use if probing criteria changed during a devices lifetime and | 605 | * to use if probing criteria changed during a devices lifetime and |
| 565 | * driver attachment should change accordingly. | 606 | * driver attachment should change accordingly. |
| 566 | */ | 607 | */ |
| 567 | void device_reprobe(struct device *dev) | 608 | int device_reprobe(struct device *dev) |
| 568 | { | 609 | { |
| 569 | if (dev->driver) { | 610 | if (dev->driver) { |
| 570 | if (dev->parent) /* Needed for USB */ | 611 | if (dev->parent) /* Needed for USB */ |
| @@ -573,14 +614,14 @@ void device_reprobe(struct device *dev) | |||
| 573 | if (dev->parent) | 614 | if (dev->parent) |
| 574 | up(&dev->parent->sem); | 615 | up(&dev->parent->sem); |
| 575 | } | 616 | } |
| 576 | 617 | return bus_rescan_devices_helper(dev, NULL); | |
| 577 | bus_rescan_devices_helper(dev, NULL); | ||
| 578 | } | 618 | } |
| 579 | EXPORT_SYMBOL_GPL(device_reprobe); | 619 | EXPORT_SYMBOL_GPL(device_reprobe); |
| 580 | 620 | ||
| 581 | struct bus_type * get_bus(struct bus_type * bus) | 621 | struct bus_type *get_bus(struct bus_type *bus) |
| 582 | { | 622 | { |
| 583 | return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL; | 623 | return bus ? container_of(subsys_get(&bus->subsys), |
| 624 | struct bus_type, subsys) : NULL; | ||
| 584 | } | 625 | } |
| 585 | 626 | ||
| 586 | void put_bus(struct bus_type * bus) | 627 | void put_bus(struct bus_type * bus) |
| @@ -655,22 +696,6 @@ static void klist_devices_put(struct klist_node *n) | |||
| 655 | put_device(dev); | 696 | put_device(dev); |
| 656 | } | 697 | } |
| 657 | 698 | ||
| 658 | static void klist_drivers_get(struct klist_node *n) | ||
| 659 | { | ||
| 660 | struct device_driver *drv = container_of(n, struct device_driver, | ||
| 661 | knode_bus); | ||
| 662 | |||
| 663 | get_driver(drv); | ||
| 664 | } | ||
| 665 | |||
| 666 | static void klist_drivers_put(struct klist_node *n) | ||
| 667 | { | ||
| 668 | struct device_driver *drv = container_of(n, struct device_driver, | ||
| 669 | knode_bus); | ||
| 670 | |||
| 671 | put_driver(drv); | ||
| 672 | } | ||
| 673 | |||
| 674 | /** | 699 | /** |
| 675 | * bus_register - register a bus with the system. | 700 | * bus_register - register a bus with the system. |
| 676 | * @bus: bus. | 701 | * @bus: bus. |
| @@ -706,7 +731,7 @@ int bus_register(struct bus_type * bus) | |||
| 706 | goto bus_drivers_fail; | 731 | goto bus_drivers_fail; |
| 707 | 732 | ||
| 708 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); | 733 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); |
| 709 | klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put); | 734 | klist_init(&bus->klist_drivers, NULL, NULL); |
| 710 | bus_add_attrs(bus); | 735 | bus_add_attrs(bus); |
| 711 | 736 | ||
| 712 | pr_debug("bus type '%s' registered\n", bus->name); | 737 | pr_debug("bus type '%s' registered\n", bus->name); |
