diff options
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r-- | drivers/base/bus.c | 107 |
1 files changed, 72 insertions, 35 deletions
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) |