diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Kconfig | 4 | ||||
-rw-r--r-- | drivers/base/bus.c | 142 | ||||
-rw-r--r-- | drivers/base/class.c | 171 | ||||
-rw-r--r-- | drivers/base/core.c | 267 | ||||
-rw-r--r-- | drivers/base/dd.c | 126 | ||||
-rw-r--r-- | drivers/base/dmapool.c | 13 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 119 | ||||
-rw-r--r-- | drivers/base/platform.c | 48 | ||||
-rw-r--r-- | drivers/base/topology.c | 56 |
9 files changed, 681 insertions, 265 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 0b4e22436935..1429f3a2629e 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -37,8 +37,8 @@ config DEBUG_DRIVER | |||
37 | 37 | ||
38 | If you are unsure about this, say N here. | 38 | If you are unsure about this, say N here. |
39 | 39 | ||
40 | endmenu | ||
41 | |||
42 | config SYS_HYPERVISOR | 40 | config SYS_HYPERVISOR |
43 | bool | 41 | bool |
44 | default n | 42 | default n |
43 | |||
44 | endmenu | ||
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 12173d16bea7..472810f8e6e7 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -355,6 +355,21 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev) | |||
355 | } | 355 | } |
356 | } | 356 | } |
357 | 357 | ||
358 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
359 | static int make_deprecated_bus_links(struct device *dev) | ||
360 | { | ||
361 | return sysfs_create_link(&dev->kobj, | ||
362 | &dev->bus->subsys.kset.kobj, "bus"); | ||
363 | } | ||
364 | |||
365 | static void remove_deprecated_bus_links(struct device *dev) | ||
366 | { | ||
367 | sysfs_remove_link(&dev->kobj, "bus"); | ||
368 | } | ||
369 | #else | ||
370 | static inline int make_deprecated_bus_links(struct device *dev) { return 0; } | ||
371 | static inline void remove_deprecated_bus_links(struct device *dev) { } | ||
372 | #endif | ||
358 | 373 | ||
359 | /** | 374 | /** |
360 | * bus_add_device - add device to bus | 375 | * bus_add_device - add device to bus |
@@ -372,19 +387,29 @@ int bus_add_device(struct device * dev) | |||
372 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); | 387 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); |
373 | error = device_add_attrs(bus, dev); | 388 | error = device_add_attrs(bus, dev); |
374 | if (error) | 389 | if (error) |
375 | goto out; | 390 | goto out_put; |
376 | error = sysfs_create_link(&bus->devices.kobj, | 391 | error = sysfs_create_link(&bus->devices.kobj, |
377 | &dev->kobj, dev->bus_id); | 392 | &dev->kobj, dev->bus_id); |
378 | if (error) | 393 | if (error) |
379 | goto out; | 394 | goto out_id; |
380 | error = sysfs_create_link(&dev->kobj, | 395 | error = sysfs_create_link(&dev->kobj, |
381 | &dev->bus->subsys.kset.kobj, "subsystem"); | 396 | &dev->bus->subsys.kset.kobj, "subsystem"); |
382 | if (error) | 397 | if (error) |
383 | goto out; | 398 | goto out_subsys; |
384 | error = sysfs_create_link(&dev->kobj, | 399 | error = make_deprecated_bus_links(dev); |
385 | &dev->bus->subsys.kset.kobj, "bus"); | 400 | if (error) |
401 | goto out_deprecated; | ||
386 | } | 402 | } |
387 | out: | 403 | return 0; |
404 | |||
405 | out_deprecated: | ||
406 | sysfs_remove_link(&dev->kobj, "subsystem"); | ||
407 | out_subsys: | ||
408 | sysfs_remove_link(&bus->devices.kobj, dev->bus_id); | ||
409 | out_id: | ||
410 | device_remove_attrs(bus, dev); | ||
411 | out_put: | ||
412 | put_bus(dev->bus); | ||
388 | return error; | 413 | return error; |
389 | } | 414 | } |
390 | 415 | ||
@@ -425,11 +450,13 @@ void bus_remove_device(struct device * dev) | |||
425 | { | 450 | { |
426 | if (dev->bus) { | 451 | if (dev->bus) { |
427 | sysfs_remove_link(&dev->kobj, "subsystem"); | 452 | sysfs_remove_link(&dev->kobj, "subsystem"); |
428 | sysfs_remove_link(&dev->kobj, "bus"); | 453 | remove_deprecated_bus_links(dev); |
429 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); | 454 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); |
430 | device_remove_attrs(dev->bus, dev); | 455 | device_remove_attrs(dev->bus, dev); |
431 | dev->is_registered = 0; | 456 | if (dev->is_registered) { |
432 | klist_del(&dev->knode_bus); | 457 | dev->is_registered = 0; |
458 | klist_del(&dev->knode_bus); | ||
459 | } | ||
433 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); | 460 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); |
434 | device_release_driver(dev); | 461 | device_release_driver(dev); |
435 | put_bus(dev->bus); | 462 | put_bus(dev->bus); |
@@ -505,34 +532,36 @@ int bus_add_driver(struct device_driver *drv) | |||
505 | struct bus_type * bus = get_bus(drv->bus); | 532 | struct bus_type * bus = get_bus(drv->bus); |
506 | int error = 0; | 533 | int error = 0; |
507 | 534 | ||
508 | if (bus) { | 535 | if (!bus) |
509 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); | 536 | return 0; |
510 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | 537 | |
511 | if (error) | 538 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); |
512 | goto out_put_bus; | 539 | error = kobject_set_name(&drv->kobj, "%s", drv->name); |
513 | drv->kobj.kset = &bus->drivers; | 540 | if (error) |
514 | if ((error = kobject_register(&drv->kobj))) | 541 | goto out_put_bus; |
515 | goto out_put_bus; | 542 | drv->kobj.kset = &bus->drivers; |
516 | 543 | if ((error = kobject_register(&drv->kobj))) | |
517 | error = driver_attach(drv); | 544 | goto out_put_bus; |
518 | if (error) | 545 | |
519 | goto out_unregister; | 546 | error = driver_attach(drv); |
520 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | 547 | if (error) |
521 | module_add_driver(drv->owner, drv); | 548 | goto out_unregister; |
522 | 549 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | |
523 | error = driver_add_attrs(bus, drv); | 550 | module_add_driver(drv->owner, drv); |
524 | if (error) { | 551 | |
525 | /* How the hell do we get out of this pickle? Give up */ | 552 | error = driver_add_attrs(bus, drv); |
526 | printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", | 553 | if (error) { |
527 | __FUNCTION__, drv->name); | 554 | /* How the hell do we get out of this pickle? Give up */ |
528 | } | 555 | printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", |
529 | error = add_bind_files(drv); | 556 | __FUNCTION__, drv->name); |
530 | if (error) { | ||
531 | /* Ditto */ | ||
532 | printk(KERN_ERR "%s: add_bind_files(%s) failed\n", | ||
533 | __FUNCTION__, drv->name); | ||
534 | } | ||
535 | } | 557 | } |
558 | error = add_bind_files(drv); | ||
559 | if (error) { | ||
560 | /* Ditto */ | ||
561 | printk(KERN_ERR "%s: add_bind_files(%s) failed\n", | ||
562 | __FUNCTION__, drv->name); | ||
563 | } | ||
564 | |||
536 | return error; | 565 | return error; |
537 | out_unregister: | 566 | out_unregister: |
538 | kobject_unregister(&drv->kobj); | 567 | kobject_unregister(&drv->kobj); |
@@ -552,16 +581,17 @@ out_put_bus: | |||
552 | 581 | ||
553 | void bus_remove_driver(struct device_driver * drv) | 582 | void bus_remove_driver(struct device_driver * drv) |
554 | { | 583 | { |
555 | if (drv->bus) { | 584 | if (!drv->bus) |
556 | remove_bind_files(drv); | 585 | return; |
557 | driver_remove_attrs(drv->bus, drv); | 586 | |
558 | klist_remove(&drv->knode_bus); | 587 | remove_bind_files(drv); |
559 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); | 588 | driver_remove_attrs(drv->bus, drv); |
560 | driver_detach(drv); | 589 | klist_remove(&drv->knode_bus); |
561 | module_remove_driver(drv); | 590 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); |
562 | kobject_unregister(&drv->kobj); | 591 | driver_detach(drv); |
563 | put_bus(drv->bus); | 592 | module_remove_driver(drv); |
564 | } | 593 | kobject_unregister(&drv->kobj); |
594 | put_bus(drv->bus); | ||
565 | } | 595 | } |
566 | 596 | ||
567 | 597 | ||
@@ -708,6 +738,8 @@ int bus_register(struct bus_type * bus) | |||
708 | { | 738 | { |
709 | int retval; | 739 | int retval; |
710 | 740 | ||
741 | BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier); | ||
742 | |||
711 | retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); | 743 | retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); |
712 | if (retval) | 744 | if (retval) |
713 | goto out; | 745 | goto out; |
@@ -732,11 +764,15 @@ int bus_register(struct bus_type * bus) | |||
732 | 764 | ||
733 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); | 765 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); |
734 | klist_init(&bus->klist_drivers, NULL, NULL); | 766 | klist_init(&bus->klist_drivers, NULL, NULL); |
735 | bus_add_attrs(bus); | 767 | retval = bus_add_attrs(bus); |
768 | if (retval) | ||
769 | goto bus_attrs_fail; | ||
736 | 770 | ||
737 | pr_debug("bus type '%s' registered\n", bus->name); | 771 | pr_debug("bus type '%s' registered\n", bus->name); |
738 | return 0; | 772 | return 0; |
739 | 773 | ||
774 | bus_attrs_fail: | ||
775 | kset_unregister(&bus->drivers); | ||
740 | bus_drivers_fail: | 776 | bus_drivers_fail: |
741 | kset_unregister(&bus->devices); | 777 | kset_unregister(&bus->devices); |
742 | bus_devices_fail: | 778 | bus_devices_fail: |
@@ -762,6 +798,18 @@ void bus_unregister(struct bus_type * bus) | |||
762 | subsystem_unregister(&bus->subsys); | 798 | subsystem_unregister(&bus->subsys); |
763 | } | 799 | } |
764 | 800 | ||
801 | int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb) | ||
802 | { | ||
803 | return blocking_notifier_chain_register(&bus->bus_notifier, nb); | ||
804 | } | ||
805 | EXPORT_SYMBOL_GPL(bus_register_notifier); | ||
806 | |||
807 | int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb) | ||
808 | { | ||
809 | return blocking_notifier_chain_unregister(&bus->bus_notifier, nb); | ||
810 | } | ||
811 | EXPORT_SYMBOL_GPL(bus_unregister_notifier); | ||
812 | |||
765 | int __init buses_init(void) | 813 | int __init buses_init(void) |
766 | { | 814 | { |
767 | return subsystem_register(&bus_subsys); | 815 | return subsystem_register(&bus_subsys); |
diff --git a/drivers/base/class.c b/drivers/base/class.c index b32b77ff2dcd..f098881f45b2 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -352,6 +352,92 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj) | |||
352 | return class_dev->class->name; | 352 | return class_dev->class->name; |
353 | } | 353 | } |
354 | 354 | ||
355 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
356 | char *make_class_name(const char *name, struct kobject *kobj) | ||
357 | { | ||
358 | char *class_name; | ||
359 | int size; | ||
360 | |||
361 | size = strlen(name) + strlen(kobject_name(kobj)) + 2; | ||
362 | |||
363 | class_name = kmalloc(size, GFP_KERNEL); | ||
364 | if (!class_name) | ||
365 | return ERR_PTR(-ENOMEM); | ||
366 | |||
367 | strcpy(class_name, name); | ||
368 | strcat(class_name, ":"); | ||
369 | strcat(class_name, kobject_name(kobj)); | ||
370 | return class_name; | ||
371 | } | ||
372 | |||
373 | static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index, | ||
374 | char *buffer, int buffer_size, | ||
375 | int *cur_len, | ||
376 | struct class_device *class_dev) | ||
377 | { | ||
378 | struct device *dev = class_dev->dev; | ||
379 | char *path; | ||
380 | |||
381 | if (!dev) | ||
382 | return 0; | ||
383 | |||
384 | /* add device, backing this class device (deprecated) */ | ||
385 | path = kobject_get_path(&dev->kobj, GFP_KERNEL); | ||
386 | |||
387 | add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size, | ||
388 | cur_len, "PHYSDEVPATH=%s", path); | ||
389 | kfree(path); | ||
390 | |||
391 | if (dev->bus) | ||
392 | add_uevent_var(envp, num_envp, cur_index, | ||
393 | buffer, buffer_size, cur_len, | ||
394 | "PHYSDEVBUS=%s", dev->bus->name); | ||
395 | |||
396 | if (dev->driver) | ||
397 | add_uevent_var(envp, num_envp, cur_index, | ||
398 | buffer, buffer_size, cur_len, | ||
399 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int make_deprecated_class_device_links(struct class_device *class_dev) | ||
404 | { | ||
405 | char *class_name; | ||
406 | int error; | ||
407 | |||
408 | if (!class_dev->dev) | ||
409 | return 0; | ||
410 | |||
411 | class_name = make_class_name(class_dev->class->name, &class_dev->kobj); | ||
412 | error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, | ||
413 | class_name); | ||
414 | kfree(class_name); | ||
415 | return error; | ||
416 | } | ||
417 | |||
418 | static void remove_deprecated_class_device_links(struct class_device *class_dev) | ||
419 | { | ||
420 | char *class_name; | ||
421 | |||
422 | if (!class_dev->dev) | ||
423 | return; | ||
424 | |||
425 | class_name = make_class_name(class_dev->class->name, &class_dev->kobj); | ||
426 | sysfs_remove_link(&class_dev->dev->kobj, class_name); | ||
427 | kfree(class_name); | ||
428 | } | ||
429 | #else | ||
430 | static inline int deprecated_class_uevent(char **envp, int num_envp, | ||
431 | int *cur_index, char *buffer, | ||
432 | int buffer_size, int *cur_len, | ||
433 | struct class_device *class_dev) | ||
434 | { return 0; } | ||
435 | static inline int make_deprecated_class_device_links(struct class_device *cd) | ||
436 | { return 0; } | ||
437 | static void remove_deprecated_class_device_links(struct class_device *cd) | ||
438 | { } | ||
439 | #endif | ||
440 | |||
355 | static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, | 441 | static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, |
356 | int num_envp, char *buffer, int buffer_size) | 442 | int num_envp, char *buffer, int buffer_size) |
357 | { | 443 | { |
@@ -362,25 +448,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, | |||
362 | 448 | ||
363 | pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); | 449 | pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); |
364 | 450 | ||
365 | if (class_dev->dev) { | 451 | deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size, |
366 | /* add device, backing this class device (deprecated) */ | 452 | &length, class_dev); |
367 | struct device *dev = class_dev->dev; | ||
368 | char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); | ||
369 | |||
370 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | ||
371 | &length, "PHYSDEVPATH=%s", path); | ||
372 | kfree(path); | ||
373 | |||
374 | if (dev->bus) | ||
375 | add_uevent_var(envp, num_envp, &i, | ||
376 | buffer, buffer_size, &length, | ||
377 | "PHYSDEVBUS=%s", dev->bus->name); | ||
378 | |||
379 | if (dev->driver) | ||
380 | add_uevent_var(envp, num_envp, &i, | ||
381 | buffer, buffer_size, &length, | ||
382 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
383 | } | ||
384 | 453 | ||
385 | if (MAJOR(class_dev->devt)) { | 454 | if (MAJOR(class_dev->devt)) { |
386 | add_uevent_var(envp, num_envp, &i, | 455 | add_uevent_var(envp, num_envp, &i, |
@@ -506,29 +575,11 @@ void class_device_initialize(struct class_device *class_dev) | |||
506 | INIT_LIST_HEAD(&class_dev->node); | 575 | INIT_LIST_HEAD(&class_dev->node); |
507 | } | 576 | } |
508 | 577 | ||
509 | char *make_class_name(const char *name, struct kobject *kobj) | ||
510 | { | ||
511 | char *class_name; | ||
512 | int size; | ||
513 | |||
514 | size = strlen(name) + strlen(kobject_name(kobj)) + 2; | ||
515 | |||
516 | class_name = kmalloc(size, GFP_KERNEL); | ||
517 | if (!class_name) | ||
518 | return ERR_PTR(-ENOMEM); | ||
519 | |||
520 | strcpy(class_name, name); | ||
521 | strcat(class_name, ":"); | ||
522 | strcat(class_name, kobject_name(kobj)); | ||
523 | return class_name; | ||
524 | } | ||
525 | |||
526 | int class_device_add(struct class_device *class_dev) | 578 | int class_device_add(struct class_device *class_dev) |
527 | { | 579 | { |
528 | struct class *parent_class = NULL; | 580 | struct class *parent_class = NULL; |
529 | struct class_device *parent_class_dev = NULL; | 581 | struct class_device *parent_class_dev = NULL; |
530 | struct class_interface *class_intf; | 582 | struct class_interface *class_intf; |
531 | char *class_name = NULL; | ||
532 | int error = -EINVAL; | 583 | int error = -EINVAL; |
533 | 584 | ||
534 | class_dev = class_device_get(class_dev); | 585 | class_dev = class_device_get(class_dev); |
@@ -562,7 +613,10 @@ int class_device_add(struct class_device *class_dev) | |||
562 | goto out2; | 613 | goto out2; |
563 | 614 | ||
564 | /* add the needed attributes to this device */ | 615 | /* add the needed attributes to this device */ |
565 | sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem"); | 616 | error = sysfs_create_link(&class_dev->kobj, |
617 | &parent_class->subsys.kset.kobj, "subsystem"); | ||
618 | if (error) | ||
619 | goto out3; | ||
566 | class_dev->uevent_attr.attr.name = "uevent"; | 620 | class_dev->uevent_attr.attr.name = "uevent"; |
567 | class_dev->uevent_attr.attr.mode = S_IWUSR; | 621 | class_dev->uevent_attr.attr.mode = S_IWUSR; |
568 | class_dev->uevent_attr.attr.owner = parent_class->owner; | 622 | class_dev->uevent_attr.attr.owner = parent_class->owner; |
@@ -596,20 +650,18 @@ int class_device_add(struct class_device *class_dev) | |||
596 | goto out5; | 650 | goto out5; |
597 | 651 | ||
598 | if (class_dev->dev) { | 652 | if (class_dev->dev) { |
599 | class_name = make_class_name(class_dev->class->name, | ||
600 | &class_dev->kobj); | ||
601 | error = sysfs_create_link(&class_dev->kobj, | 653 | error = sysfs_create_link(&class_dev->kobj, |
602 | &class_dev->dev->kobj, "device"); | 654 | &class_dev->dev->kobj, "device"); |
603 | if (error) | 655 | if (error) |
604 | goto out6; | 656 | goto out6; |
605 | error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, | ||
606 | class_name); | ||
607 | if (error) | ||
608 | goto out7; | ||
609 | } | 657 | } |
610 | 658 | ||
611 | error = class_device_add_groups(class_dev); | 659 | error = class_device_add_groups(class_dev); |
612 | if (error) | 660 | if (error) |
661 | goto out7; | ||
662 | |||
663 | error = make_deprecated_class_device_links(class_dev); | ||
664 | if (error) | ||
613 | goto out8; | 665 | goto out8; |
614 | 666 | ||
615 | kobject_uevent(&class_dev->kobj, KOBJ_ADD); | 667 | kobject_uevent(&class_dev->kobj, KOBJ_ADD); |
@@ -626,8 +678,7 @@ int class_device_add(struct class_device *class_dev) | |||
626 | goto out1; | 678 | goto out1; |
627 | 679 | ||
628 | out8: | 680 | out8: |
629 | if (class_dev->dev) | 681 | class_device_remove_groups(class_dev); |
630 | sysfs_remove_link(&class_dev->kobj, class_name); | ||
631 | out7: | 682 | out7: |
632 | if (class_dev->dev) | 683 | if (class_dev->dev) |
633 | sysfs_remove_link(&class_dev->kobj, "device"); | 684 | sysfs_remove_link(&class_dev->kobj, "device"); |
@@ -646,7 +697,6 @@ int class_device_add(struct class_device *class_dev) | |||
646 | class_put(parent_class); | 697 | class_put(parent_class); |
647 | out1: | 698 | out1: |
648 | class_device_put(class_dev); | 699 | class_device_put(class_dev); |
649 | kfree(class_name); | ||
650 | return error; | 700 | return error; |
651 | } | 701 | } |
652 | 702 | ||
@@ -723,7 +773,6 @@ void class_device_del(struct class_device *class_dev) | |||
723 | struct class *parent_class = class_dev->class; | 773 | struct class *parent_class = class_dev->class; |
724 | struct class_device *parent_device = class_dev->parent; | 774 | struct class_device *parent_device = class_dev->parent; |
725 | struct class_interface *class_intf; | 775 | struct class_interface *class_intf; |
726 | char *class_name = NULL; | ||
727 | 776 | ||
728 | if (parent_class) { | 777 | if (parent_class) { |
729 | down(&parent_class->sem); | 778 | down(&parent_class->sem); |
@@ -735,10 +784,8 @@ void class_device_del(struct class_device *class_dev) | |||
735 | } | 784 | } |
736 | 785 | ||
737 | if (class_dev->dev) { | 786 | if (class_dev->dev) { |
738 | class_name = make_class_name(class_dev->class->name, | 787 | remove_deprecated_class_device_links(class_dev); |
739 | &class_dev->kobj); | ||
740 | sysfs_remove_link(&class_dev->kobj, "device"); | 788 | sysfs_remove_link(&class_dev->kobj, "device"); |
741 | sysfs_remove_link(&class_dev->dev->kobj, class_name); | ||
742 | } | 789 | } |
743 | sysfs_remove_link(&class_dev->kobj, "subsystem"); | 790 | sysfs_remove_link(&class_dev->kobj, "subsystem"); |
744 | class_device_remove_file(class_dev, &class_dev->uevent_attr); | 791 | class_device_remove_file(class_dev, &class_dev->uevent_attr); |
@@ -752,7 +799,6 @@ void class_device_del(struct class_device *class_dev) | |||
752 | 799 | ||
753 | class_device_put(parent_device); | 800 | class_device_put(parent_device); |
754 | class_put(parent_class); | 801 | class_put(parent_class); |
755 | kfree(class_name); | ||
756 | } | 802 | } |
757 | 803 | ||
758 | void class_device_unregister(struct class_device *class_dev) | 804 | void class_device_unregister(struct class_device *class_dev) |
@@ -801,14 +847,17 @@ int class_device_rename(struct class_device *class_dev, char *new_name) | |||
801 | pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, | 847 | pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, |
802 | new_name); | 848 | new_name); |
803 | 849 | ||
850 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
804 | if (class_dev->dev) | 851 | if (class_dev->dev) |
805 | old_class_name = make_class_name(class_dev->class->name, | 852 | old_class_name = make_class_name(class_dev->class->name, |
806 | &class_dev->kobj); | 853 | &class_dev->kobj); |
854 | #endif | ||
807 | 855 | ||
808 | strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); | 856 | strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); |
809 | 857 | ||
810 | error = kobject_rename(&class_dev->kobj, new_name); | 858 | error = kobject_rename(&class_dev->kobj, new_name); |
811 | 859 | ||
860 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
812 | if (class_dev->dev) { | 861 | if (class_dev->dev) { |
813 | new_class_name = make_class_name(class_dev->class->name, | 862 | new_class_name = make_class_name(class_dev->class->name, |
814 | &class_dev->kobj); | 863 | &class_dev->kobj); |
@@ -816,6 +865,7 @@ int class_device_rename(struct class_device *class_dev, char *new_name) | |||
816 | new_class_name); | 865 | new_class_name); |
817 | sysfs_remove_link(&class_dev->dev->kobj, old_class_name); | 866 | sysfs_remove_link(&class_dev->dev->kobj, old_class_name); |
818 | } | 867 | } |
868 | #endif | ||
819 | class_device_put(class_dev); | 869 | class_device_put(class_dev); |
820 | 870 | ||
821 | kfree(old_class_name); | 871 | kfree(old_class_name); |
@@ -890,23 +940,6 @@ void class_interface_unregister(struct class_interface *class_intf) | |||
890 | class_put(parent); | 940 | class_put(parent); |
891 | } | 941 | } |
892 | 942 | ||
893 | int virtual_device_parent(struct device *dev) | ||
894 | { | ||
895 | if (!dev->class) | ||
896 | return -ENODEV; | ||
897 | |||
898 | if (!dev->class->virtual_dir) { | ||
899 | static struct kobject *virtual_dir = NULL; | ||
900 | |||
901 | if (!virtual_dir) | ||
902 | virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual"); | ||
903 | dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); | ||
904 | } | ||
905 | |||
906 | dev->kobj.parent = dev->class->virtual_dir; | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | int __init classes_init(void) | 943 | int __init classes_init(void) |
911 | { | 944 | { |
912 | int retval; | 945 | int retval; |
diff --git a/drivers/base/core.c b/drivers/base/core.c index b224bb43ff63..e4b530ef757d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/kdev_t.h> | 19 | #include <linux/kdev_t.h> |
20 | #include <linux/notifier.h> | ||
20 | 21 | ||
21 | #include <asm/semaphore.h> | 22 | #include <asm/semaphore.h> |
22 | 23 | ||
@@ -44,7 +45,7 @@ const char *dev_driver_string(struct device *dev) | |||
44 | return dev->driver ? dev->driver->name : | 45 | return dev->driver ? dev->driver->name : |
45 | (dev->bus ? dev->bus->name : ""); | 46 | (dev->bus ? dev->bus->name : ""); |
46 | } | 47 | } |
47 | EXPORT_SYMBOL_GPL(dev_driver_string); | 48 | EXPORT_SYMBOL(dev_driver_string); |
48 | 49 | ||
49 | #define to_dev(obj) container_of(obj, struct device, kobj) | 50 | #define to_dev(obj) container_of(obj, struct device, kobj) |
50 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | 51 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) |
@@ -153,20 +154,24 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | |||
153 | "MINOR=%u", MINOR(dev->devt)); | 154 | "MINOR=%u", MINOR(dev->devt)); |
154 | } | 155 | } |
155 | 156 | ||
157 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
156 | /* add bus name (same as SUBSYSTEM, deprecated) */ | 158 | /* add bus name (same as SUBSYSTEM, deprecated) */ |
157 | if (dev->bus) | 159 | if (dev->bus) |
158 | add_uevent_var(envp, num_envp, &i, | 160 | add_uevent_var(envp, num_envp, &i, |
159 | buffer, buffer_size, &length, | 161 | buffer, buffer_size, &length, |
160 | "PHYSDEVBUS=%s", dev->bus->name); | 162 | "PHYSDEVBUS=%s", dev->bus->name); |
163 | #endif | ||
161 | 164 | ||
162 | /* add driver name (PHYSDEV* values are deprecated)*/ | 165 | /* add driver name (PHYSDEV* values are deprecated)*/ |
163 | if (dev->driver) { | 166 | if (dev->driver) { |
164 | add_uevent_var(envp, num_envp, &i, | 167 | add_uevent_var(envp, num_envp, &i, |
165 | buffer, buffer_size, &length, | 168 | buffer, buffer_size, &length, |
166 | "DRIVER=%s", dev->driver->name); | 169 | "DRIVER=%s", dev->driver->name); |
170 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
167 | add_uevent_var(envp, num_envp, &i, | 171 | add_uevent_var(envp, num_envp, &i, |
168 | buffer, buffer_size, &length, | 172 | buffer, buffer_size, &length, |
169 | "PHYSDEVDRIVER=%s", dev->driver->name); | 173 | "PHYSDEVDRIVER=%s", dev->driver->name); |
174 | #endif | ||
170 | } | 175 | } |
171 | 176 | ||
172 | /* terminate, set to next free slot, shrink available space */ | 177 | /* terminate, set to next free slot, shrink available space */ |
@@ -383,6 +388,52 @@ void device_initialize(struct device *dev) | |||
383 | device_init_wakeup(dev, 0); | 388 | device_init_wakeup(dev, 0); |
384 | } | 389 | } |
385 | 390 | ||
391 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
392 | static int setup_parent(struct device *dev, struct device *parent) | ||
393 | { | ||
394 | /* Set the parent to the class, not the parent device */ | ||
395 | /* this keeps sysfs from having a symlink to make old udevs happy */ | ||
396 | if (dev->class) | ||
397 | dev->kobj.parent = &dev->class->subsys.kset.kobj; | ||
398 | else if (parent) | ||
399 | dev->kobj.parent = &parent->kobj; | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | #else | ||
404 | static int virtual_device_parent(struct device *dev) | ||
405 | { | ||
406 | if (!dev->class) | ||
407 | return -ENODEV; | ||
408 | |||
409 | if (!dev->class->virtual_dir) { | ||
410 | static struct kobject *virtual_dir = NULL; | ||
411 | |||
412 | if (!virtual_dir) | ||
413 | virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual"); | ||
414 | dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); | ||
415 | } | ||
416 | |||
417 | dev->kobj.parent = dev->class->virtual_dir; | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int setup_parent(struct device *dev, struct device *parent) | ||
422 | { | ||
423 | int error; | ||
424 | |||
425 | /* if this is a class device, and has no parent, create one */ | ||
426 | if ((dev->class) && (parent == NULL)) { | ||
427 | error = virtual_device_parent(dev); | ||
428 | if (error) | ||
429 | return error; | ||
430 | } else if (parent) | ||
431 | dev->kobj.parent = &parent->kobj; | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | #endif | ||
436 | |||
386 | /** | 437 | /** |
387 | * device_add - add device to device hierarchy. | 438 | * device_add - add device to device hierarchy. |
388 | * @dev: device. | 439 | * @dev: device. |
@@ -405,42 +456,44 @@ int device_add(struct device *dev) | |||
405 | if (!dev || !strlen(dev->bus_id)) | 456 | if (!dev || !strlen(dev->bus_id)) |
406 | goto Error; | 457 | goto Error; |
407 | 458 | ||
408 | /* if this is a class device, and has no parent, create one */ | 459 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); |
409 | if ((dev->class) && (dev->parent == NULL)) { | ||
410 | error = virtual_device_parent(dev); | ||
411 | if (error) | ||
412 | goto Error; | ||
413 | } | ||
414 | 460 | ||
415 | parent = get_device(dev->parent); | 461 | parent = get_device(dev->parent); |
416 | 462 | ||
417 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); | 463 | error = setup_parent(dev, parent); |
464 | if (error) | ||
465 | goto Error; | ||
418 | 466 | ||
419 | /* first, register with generic layer. */ | 467 | /* first, register with generic layer. */ |
420 | kobject_set_name(&dev->kobj, "%s", dev->bus_id); | 468 | kobject_set_name(&dev->kobj, "%s", dev->bus_id); |
421 | if (parent) | 469 | error = kobject_add(&dev->kobj); |
422 | dev->kobj.parent = &parent->kobj; | 470 | if (error) |
423 | |||
424 | if ((error = kobject_add(&dev->kobj))) | ||
425 | goto Error; | 471 | goto Error; |
426 | 472 | ||
427 | /* notify platform of device entry */ | 473 | /* notify platform of device entry */ |
428 | if (platform_notify) | 474 | if (platform_notify) |
429 | platform_notify(dev); | 475 | platform_notify(dev); |
430 | 476 | ||
477 | /* notify clients of device entry (new way) */ | ||
478 | if (dev->bus) | ||
479 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | ||
480 | BUS_NOTIFY_ADD_DEVICE, dev); | ||
481 | |||
431 | dev->uevent_attr.attr.name = "uevent"; | 482 | dev->uevent_attr.attr.name = "uevent"; |
432 | dev->uevent_attr.attr.mode = S_IWUSR; | 483 | dev->uevent_attr.attr.mode = S_IWUSR; |
433 | if (dev->driver) | 484 | if (dev->driver) |
434 | dev->uevent_attr.attr.owner = dev->driver->owner; | 485 | dev->uevent_attr.attr.owner = dev->driver->owner; |
435 | dev->uevent_attr.store = store_uevent; | 486 | dev->uevent_attr.store = store_uevent; |
436 | device_create_file(dev, &dev->uevent_attr); | 487 | error = device_create_file(dev, &dev->uevent_attr); |
488 | if (error) | ||
489 | goto attrError; | ||
437 | 490 | ||
438 | if (MAJOR(dev->devt)) { | 491 | if (MAJOR(dev->devt)) { |
439 | struct device_attribute *attr; | 492 | struct device_attribute *attr; |
440 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); | 493 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); |
441 | if (!attr) { | 494 | if (!attr) { |
442 | error = -ENOMEM; | 495 | error = -ENOMEM; |
443 | goto PMError; | 496 | goto ueventattrError; |
444 | } | 497 | } |
445 | attr->attr.name = "dev"; | 498 | attr->attr.name = "dev"; |
446 | attr->attr.mode = S_IRUGO; | 499 | attr->attr.mode = S_IRUGO; |
@@ -450,7 +503,7 @@ int device_add(struct device *dev) | |||
450 | error = device_create_file(dev, attr); | 503 | error = device_create_file(dev, attr); |
451 | if (error) { | 504 | if (error) { |
452 | kfree(attr); | 505 | kfree(attr); |
453 | goto attrError; | 506 | goto ueventattrError; |
454 | } | 507 | } |
455 | 508 | ||
456 | dev->devt_attr = attr; | 509 | dev->devt_attr = attr; |
@@ -459,13 +512,18 @@ int device_add(struct device *dev) | |||
459 | if (dev->class) { | 512 | if (dev->class) { |
460 | sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, | 513 | sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, |
461 | "subsystem"); | 514 | "subsystem"); |
462 | sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, | 515 | /* If this is not a "fake" compatible device, then create the |
463 | dev->bus_id); | 516 | * symlink from the class to the device. */ |
517 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | ||
518 | sysfs_create_link(&dev->class->subsys.kset.kobj, | ||
519 | &dev->kobj, dev->bus_id); | ||
520 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
464 | if (parent) { | 521 | if (parent) { |
465 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); | 522 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); |
466 | class_name = make_class_name(dev->class->name, &dev->kobj); | 523 | class_name = make_class_name(dev->class->name, &dev->kobj); |
467 | sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); | 524 | sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); |
468 | } | 525 | } |
526 | #endif | ||
469 | } | 527 | } |
470 | 528 | ||
471 | if ((error = device_add_attrs(dev))) | 529 | if ((error = device_add_attrs(dev))) |
@@ -477,7 +535,8 @@ int device_add(struct device *dev) | |||
477 | if ((error = bus_add_device(dev))) | 535 | if ((error = bus_add_device(dev))) |
478 | goto BusError; | 536 | goto BusError; |
479 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 537 | kobject_uevent(&dev->kobj, KOBJ_ADD); |
480 | bus_attach_device(dev); | 538 | if ((error = bus_attach_device(dev))) |
539 | goto AttachError; | ||
481 | if (parent) | 540 | if (parent) |
482 | klist_add_tail(&dev->knode_parent, &parent->klist_children); | 541 | klist_add_tail(&dev->knode_parent, &parent->klist_children); |
483 | 542 | ||
@@ -496,9 +555,14 @@ int device_add(struct device *dev) | |||
496 | kfree(class_name); | 555 | kfree(class_name); |
497 | put_device(dev); | 556 | put_device(dev); |
498 | return error; | 557 | return error; |
558 | AttachError: | ||
559 | bus_remove_device(dev); | ||
499 | BusError: | 560 | BusError: |
500 | device_pm_remove(dev); | 561 | device_pm_remove(dev); |
501 | PMError: | 562 | PMError: |
563 | if (dev->bus) | ||
564 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | ||
565 | BUS_NOTIFY_DEL_DEVICE, dev); | ||
502 | device_remove_groups(dev); | 566 | device_remove_groups(dev); |
503 | GroupError: | 567 | GroupError: |
504 | device_remove_attrs(dev); | 568 | device_remove_attrs(dev); |
@@ -507,6 +571,8 @@ int device_add(struct device *dev) | |||
507 | device_remove_file(dev, dev->devt_attr); | 571 | device_remove_file(dev, dev->devt_attr); |
508 | kfree(dev->devt_attr); | 572 | kfree(dev->devt_attr); |
509 | } | 573 | } |
574 | ueventattrError: | ||
575 | device_remove_file(dev, &dev->uevent_attr); | ||
510 | attrError: | 576 | attrError: |
511 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 577 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |
512 | kobject_del(&dev->kobj); | 578 | kobject_del(&dev->kobj); |
@@ -579,22 +645,31 @@ void put_device(struct device * dev) | |||
579 | void device_del(struct device * dev) | 645 | void device_del(struct device * dev) |
580 | { | 646 | { |
581 | struct device * parent = dev->parent; | 647 | struct device * parent = dev->parent; |
582 | char *class_name = NULL; | ||
583 | struct class_interface *class_intf; | 648 | struct class_interface *class_intf; |
584 | 649 | ||
585 | if (parent) | 650 | if (parent) |
586 | klist_del(&dev->knode_parent); | 651 | klist_del(&dev->knode_parent); |
587 | if (dev->devt_attr) | 652 | if (dev->devt_attr) { |
588 | device_remove_file(dev, dev->devt_attr); | 653 | device_remove_file(dev, dev->devt_attr); |
654 | kfree(dev->devt_attr); | ||
655 | } | ||
589 | if (dev->class) { | 656 | if (dev->class) { |
590 | sysfs_remove_link(&dev->kobj, "subsystem"); | 657 | sysfs_remove_link(&dev->kobj, "subsystem"); |
591 | sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); | 658 | /* If this is not a "fake" compatible device, remove the |
592 | class_name = make_class_name(dev->class->name, &dev->kobj); | 659 | * symlink from the class to the device. */ |
660 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | ||
661 | sysfs_remove_link(&dev->class->subsys.kset.kobj, | ||
662 | dev->bus_id); | ||
663 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
593 | if (parent) { | 664 | if (parent) { |
594 | sysfs_remove_link(&dev->kobj, "device"); | 665 | char *class_name = make_class_name(dev->class->name, |
666 | &dev->kobj); | ||
595 | sysfs_remove_link(&dev->parent->kobj, class_name); | 667 | sysfs_remove_link(&dev->parent->kobj, class_name); |
668 | kfree(class_name); | ||
669 | sysfs_remove_link(&dev->kobj, "device"); | ||
596 | } | 670 | } |
597 | kfree(class_name); | 671 | #endif |
672 | |||
598 | down(&dev->class->sem); | 673 | down(&dev->class->sem); |
599 | /* notify any interfaces that the device is now gone */ | 674 | /* notify any interfaces that the device is now gone */ |
600 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | 675 | list_for_each_entry(class_intf, &dev->class->interfaces, node) |
@@ -607,13 +682,16 @@ void device_del(struct device * dev) | |||
607 | device_remove_file(dev, &dev->uevent_attr); | 682 | device_remove_file(dev, &dev->uevent_attr); |
608 | device_remove_groups(dev); | 683 | device_remove_groups(dev); |
609 | device_remove_attrs(dev); | 684 | device_remove_attrs(dev); |
685 | bus_remove_device(dev); | ||
610 | 686 | ||
611 | /* Notify the platform of the removal, in case they | 687 | /* Notify the platform of the removal, in case they |
612 | * need to do anything... | 688 | * need to do anything... |
613 | */ | 689 | */ |
614 | if (platform_notify_remove) | 690 | if (platform_notify_remove) |
615 | platform_notify_remove(dev); | 691 | platform_notify_remove(dev); |
616 | bus_remove_device(dev); | 692 | if (dev->bus) |
693 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | ||
694 | BUS_NOTIFY_DEL_DEVICE, dev); | ||
617 | device_pm_remove(dev); | 695 | device_pm_remove(dev); |
618 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 696 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |
619 | kobject_del(&dev->kobj); | 697 | kobject_del(&dev->kobj); |
@@ -672,12 +750,45 @@ int device_for_each_child(struct device * parent, void * data, | |||
672 | return error; | 750 | return error; |
673 | } | 751 | } |
674 | 752 | ||
753 | /** | ||
754 | * device_find_child - device iterator for locating a particular device. | ||
755 | * @parent: parent struct device | ||
756 | * @data: Data to pass to match function | ||
757 | * @match: Callback function to check device | ||
758 | * | ||
759 | * This is similar to the device_for_each_child() function above, but it | ||
760 | * returns a reference to a device that is 'found' for later use, as | ||
761 | * determined by the @match callback. | ||
762 | * | ||
763 | * The callback should return 0 if the device doesn't match and non-zero | ||
764 | * if it does. If the callback returns non-zero and a reference to the | ||
765 | * current device can be obtained, this function will return to the caller | ||
766 | * and not iterate over any more devices. | ||
767 | */ | ||
768 | struct device * device_find_child(struct device *parent, void *data, | ||
769 | int (*match)(struct device *, void *)) | ||
770 | { | ||
771 | struct klist_iter i; | ||
772 | struct device *child; | ||
773 | |||
774 | if (!parent) | ||
775 | return NULL; | ||
776 | |||
777 | klist_iter_init(&parent->klist_children, &i); | ||
778 | while ((child = next_device(&i))) | ||
779 | if (match(child, data) && get_device(child)) | ||
780 | break; | ||
781 | klist_iter_exit(&i); | ||
782 | return child; | ||
783 | } | ||
784 | |||
675 | int __init devices_init(void) | 785 | int __init devices_init(void) |
676 | { | 786 | { |
677 | return subsystem_register(&devices_subsys); | 787 | return subsystem_register(&devices_subsys); |
678 | } | 788 | } |
679 | 789 | ||
680 | EXPORT_SYMBOL_GPL(device_for_each_child); | 790 | EXPORT_SYMBOL_GPL(device_for_each_child); |
791 | EXPORT_SYMBOL_GPL(device_find_child); | ||
681 | 792 | ||
682 | EXPORT_SYMBOL_GPL(device_initialize); | 793 | EXPORT_SYMBOL_GPL(device_initialize); |
683 | EXPORT_SYMBOL_GPL(device_add); | 794 | EXPORT_SYMBOL_GPL(device_add); |
@@ -800,13 +911,17 @@ int device_rename(struct device *dev, char *new_name) | |||
800 | 911 | ||
801 | pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name); | 912 | pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name); |
802 | 913 | ||
914 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
803 | if ((dev->class) && (dev->parent)) | 915 | if ((dev->class) && (dev->parent)) |
804 | old_class_name = make_class_name(dev->class->name, &dev->kobj); | 916 | old_class_name = make_class_name(dev->class->name, &dev->kobj); |
917 | #endif | ||
805 | 918 | ||
806 | if (dev->class) { | 919 | if (dev->class) { |
807 | old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); | 920 | old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); |
808 | if (!old_symlink_name) | 921 | if (!old_symlink_name) { |
809 | return -ENOMEM; | 922 | error = -ENOMEM; |
923 | goto out_free_old_class; | ||
924 | } | ||
810 | strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE); | 925 | strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE); |
811 | } | 926 | } |
812 | 927 | ||
@@ -814,6 +929,7 @@ int device_rename(struct device *dev, char *new_name) | |||
814 | 929 | ||
815 | error = kobject_rename(&dev->kobj, new_name); | 930 | error = kobject_rename(&dev->kobj, new_name); |
816 | 931 | ||
932 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
817 | if (old_class_name) { | 933 | if (old_class_name) { |
818 | new_class_name = make_class_name(dev->class->name, &dev->kobj); | 934 | new_class_name = make_class_name(dev->class->name, &dev->kobj); |
819 | if (new_class_name) { | 935 | if (new_class_name) { |
@@ -822,6 +938,8 @@ int device_rename(struct device *dev, char *new_name) | |||
822 | sysfs_remove_link(&dev->parent->kobj, old_class_name); | 938 | sysfs_remove_link(&dev->parent->kobj, old_class_name); |
823 | } | 939 | } |
824 | } | 940 | } |
941 | #endif | ||
942 | |||
825 | if (dev->class) { | 943 | if (dev->class) { |
826 | sysfs_remove_link(&dev->class->subsys.kset.kobj, | 944 | sysfs_remove_link(&dev->class->subsys.kset.kobj, |
827 | old_symlink_name); | 945 | old_symlink_name); |
@@ -830,9 +948,102 @@ int device_rename(struct device *dev, char *new_name) | |||
830 | } | 948 | } |
831 | put_device(dev); | 949 | put_device(dev); |
832 | 950 | ||
833 | kfree(old_class_name); | ||
834 | kfree(new_class_name); | 951 | kfree(new_class_name); |
835 | kfree(old_symlink_name); | 952 | kfree(old_symlink_name); |
953 | out_free_old_class: | ||
954 | kfree(old_class_name); | ||
836 | 955 | ||
837 | return error; | 956 | return error; |
838 | } | 957 | } |
958 | |||
959 | |||
960 | static int device_move_class_links(struct device *dev, | ||
961 | struct device *old_parent, | ||
962 | struct device *new_parent) | ||
963 | { | ||
964 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
965 | int error; | ||
966 | char *class_name; | ||
967 | |||
968 | class_name = make_class_name(dev->class->name, &dev->kobj); | ||
969 | if (!class_name) { | ||
970 | error = PTR_ERR(class_name); | ||
971 | class_name = NULL; | ||
972 | goto out; | ||
973 | } | ||
974 | if (old_parent) { | ||
975 | sysfs_remove_link(&dev->kobj, "device"); | ||
976 | sysfs_remove_link(&old_parent->kobj, class_name); | ||
977 | } | ||
978 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device"); | ||
979 | if (error) | ||
980 | goto out; | ||
981 | error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name); | ||
982 | if (error) | ||
983 | sysfs_remove_link(&dev->kobj, "device"); | ||
984 | out: | ||
985 | kfree(class_name); | ||
986 | return error; | ||
987 | #else | ||
988 | return 0; | ||
989 | #endif | ||
990 | } | ||
991 | |||
992 | /** | ||
993 | * device_move - moves a device to a new parent | ||
994 | * @dev: the pointer to the struct device to be moved | ||
995 | * @new_parent: the new parent of the device | ||
996 | */ | ||
997 | int device_move(struct device *dev, struct device *new_parent) | ||
998 | { | ||
999 | int error; | ||
1000 | struct device *old_parent; | ||
1001 | |||
1002 | dev = get_device(dev); | ||
1003 | if (!dev) | ||
1004 | return -EINVAL; | ||
1005 | |||
1006 | if (!device_is_registered(dev)) { | ||
1007 | error = -EINVAL; | ||
1008 | goto out; | ||
1009 | } | ||
1010 | new_parent = get_device(new_parent); | ||
1011 | if (!new_parent) { | ||
1012 | error = -EINVAL; | ||
1013 | goto out; | ||
1014 | } | ||
1015 | pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id, | ||
1016 | new_parent->bus_id); | ||
1017 | error = kobject_move(&dev->kobj, &new_parent->kobj); | ||
1018 | if (error) { | ||
1019 | put_device(new_parent); | ||
1020 | goto out; | ||
1021 | } | ||
1022 | old_parent = dev->parent; | ||
1023 | dev->parent = new_parent; | ||
1024 | if (old_parent) | ||
1025 | klist_remove(&dev->knode_parent); | ||
1026 | klist_add_tail(&dev->knode_parent, &new_parent->klist_children); | ||
1027 | if (!dev->class) | ||
1028 | goto out_put; | ||
1029 | error = device_move_class_links(dev, old_parent, new_parent); | ||
1030 | if (error) { | ||
1031 | /* We ignore errors on cleanup since we're hosed anyway... */ | ||
1032 | device_move_class_links(dev, new_parent, old_parent); | ||
1033 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { | ||
1034 | klist_remove(&dev->knode_parent); | ||
1035 | if (old_parent) | ||
1036 | klist_add_tail(&dev->knode_parent, | ||
1037 | &old_parent->klist_children); | ||
1038 | } | ||
1039 | put_device(new_parent); | ||
1040 | goto out; | ||
1041 | } | ||
1042 | out_put: | ||
1043 | put_device(old_parent); | ||
1044 | out: | ||
1045 | put_device(dev); | ||
1046 | return error; | ||
1047 | } | ||
1048 | |||
1049 | EXPORT_SYMBOL_GPL(device_move); | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index b5f43c3e44fa..510e7884975f 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/device.h> | 18 | #include <linux/device.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/kthread.h> | 20 | #include <linux/kthread.h> |
21 | #include <linux/wait.h> | ||
21 | 22 | ||
22 | #include "base.h" | 23 | #include "base.h" |
23 | #include "power/power.h" | 24 | #include "power/power.h" |
@@ -25,33 +26,28 @@ | |||
25 | #define to_drv(node) container_of(node, struct device_driver, kobj.entry) | 26 | #define to_drv(node) container_of(node, struct device_driver, kobj.entry) |
26 | 27 | ||
27 | 28 | ||
28 | /** | 29 | static void driver_bound(struct device *dev) |
29 | * device_bind_driver - bind a driver to one device. | ||
30 | * @dev: device. | ||
31 | * | ||
32 | * Allow manual attachment of a driver to a device. | ||
33 | * Caller must have already set @dev->driver. | ||
34 | * | ||
35 | * Note that this does not modify the bus reference count | ||
36 | * nor take the bus's rwsem. Please verify those are accounted | ||
37 | * for before calling this. (It is ok to call with no other effort | ||
38 | * from a driver's probe() method.) | ||
39 | * | ||
40 | * This function must be called with @dev->sem held. | ||
41 | */ | ||
42 | int device_bind_driver(struct device *dev) | ||
43 | { | 30 | { |
44 | int ret; | ||
45 | |||
46 | if (klist_node_attached(&dev->knode_driver)) { | 31 | if (klist_node_attached(&dev->knode_driver)) { |
47 | printk(KERN_WARNING "%s: device %s already bound\n", | 32 | printk(KERN_WARNING "%s: device %s already bound\n", |
48 | __FUNCTION__, kobject_name(&dev->kobj)); | 33 | __FUNCTION__, kobject_name(&dev->kobj)); |
49 | return 0; | 34 | return; |
50 | } | 35 | } |
51 | 36 | ||
52 | pr_debug("bound device '%s' to driver '%s'\n", | 37 | pr_debug("bound device '%s' to driver '%s'\n", |
53 | dev->bus_id, dev->driver->name); | 38 | dev->bus_id, dev->driver->name); |
39 | |||
40 | if (dev->bus) | ||
41 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | ||
42 | BUS_NOTIFY_BOUND_DRIVER, dev); | ||
43 | |||
54 | klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); | 44 | klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); |
45 | } | ||
46 | |||
47 | static int driver_sysfs_add(struct device *dev) | ||
48 | { | ||
49 | int ret; | ||
50 | |||
55 | ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, | 51 | ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, |
56 | kobject_name(&dev->kobj)); | 52 | kobject_name(&dev->kobj)); |
57 | if (ret == 0) { | 53 | if (ret == 0) { |
@@ -64,12 +60,44 @@ int device_bind_driver(struct device *dev) | |||
64 | return ret; | 60 | return ret; |
65 | } | 61 | } |
66 | 62 | ||
63 | static void driver_sysfs_remove(struct device *dev) | ||
64 | { | ||
65 | struct device_driver *drv = dev->driver; | ||
66 | |||
67 | if (drv) { | ||
68 | sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); | ||
69 | sysfs_remove_link(&dev->kobj, "driver"); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * device_bind_driver - bind a driver to one device. | ||
75 | * @dev: device. | ||
76 | * | ||
77 | * Allow manual attachment of a driver to a device. | ||
78 | * Caller must have already set @dev->driver. | ||
79 | * | ||
80 | * Note that this does not modify the bus reference count | ||
81 | * nor take the bus's rwsem. Please verify those are accounted | ||
82 | * for before calling this. (It is ok to call with no other effort | ||
83 | * from a driver's probe() method.) | ||
84 | * | ||
85 | * This function must be called with @dev->sem held. | ||
86 | */ | ||
87 | int device_bind_driver(struct device *dev) | ||
88 | { | ||
89 | driver_bound(dev); | ||
90 | return driver_sysfs_add(dev); | ||
91 | } | ||
92 | |||
67 | struct stupid_thread_structure { | 93 | struct stupid_thread_structure { |
68 | struct device_driver *drv; | 94 | struct device_driver *drv; |
69 | struct device *dev; | 95 | struct device *dev; |
70 | }; | 96 | }; |
71 | 97 | ||
72 | static atomic_t probe_count = ATOMIC_INIT(0); | 98 | static atomic_t probe_count = ATOMIC_INIT(0); |
99 | static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); | ||
100 | |||
73 | static int really_probe(void *void_data) | 101 | static int really_probe(void *void_data) |
74 | { | 102 | { |
75 | struct stupid_thread_structure *data = void_data; | 103 | struct stupid_thread_structure *data = void_data; |
@@ -82,30 +110,32 @@ static int really_probe(void *void_data) | |||
82 | drv->bus->name, drv->name, dev->bus_id); | 110 | drv->bus->name, drv->name, dev->bus_id); |
83 | 111 | ||
84 | dev->driver = drv; | 112 | dev->driver = drv; |
113 | if (driver_sysfs_add(dev)) { | ||
114 | printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", | ||
115 | __FUNCTION__, dev->bus_id); | ||
116 | goto probe_failed; | ||
117 | } | ||
118 | |||
85 | if (dev->bus->probe) { | 119 | if (dev->bus->probe) { |
86 | ret = dev->bus->probe(dev); | 120 | ret = dev->bus->probe(dev); |
87 | if (ret) { | 121 | if (ret) |
88 | dev->driver = NULL; | ||
89 | goto probe_failed; | 122 | goto probe_failed; |
90 | } | ||
91 | } else if (drv->probe) { | 123 | } else if (drv->probe) { |
92 | ret = drv->probe(dev); | 124 | ret = drv->probe(dev); |
93 | if (ret) { | 125 | if (ret) |
94 | dev->driver = NULL; | ||
95 | goto probe_failed; | 126 | goto probe_failed; |
96 | } | ||
97 | } | ||
98 | if (device_bind_driver(dev)) { | ||
99 | printk(KERN_ERR "%s: device_bind_driver(%s) failed\n", | ||
100 | __FUNCTION__, dev->bus_id); | ||
101 | /* How does undo a ->probe? We're screwed. */ | ||
102 | } | 127 | } |
128 | |||
129 | driver_bound(dev); | ||
103 | ret = 1; | 130 | ret = 1; |
104 | pr_debug("%s: Bound Device %s to Driver %s\n", | 131 | pr_debug("%s: Bound Device %s to Driver %s\n", |
105 | drv->bus->name, dev->bus_id, drv->name); | 132 | drv->bus->name, dev->bus_id, drv->name); |
106 | goto done; | 133 | goto done; |
107 | 134 | ||
108 | probe_failed: | 135 | probe_failed: |
136 | driver_sysfs_remove(dev); | ||
137 | dev->driver = NULL; | ||
138 | |||
109 | if (ret == -ENODEV || ret == -ENXIO) { | 139 | if (ret == -ENODEV || ret == -ENXIO) { |
110 | /* Driver matched, but didn't support device | 140 | /* Driver matched, but didn't support device |
111 | * or device not found. | 141 | * or device not found. |
@@ -121,6 +151,7 @@ probe_failed: | |||
121 | done: | 151 | done: |
122 | kfree(data); | 152 | kfree(data); |
123 | atomic_dec(&probe_count); | 153 | atomic_dec(&probe_count); |
154 | wake_up(&probe_waitqueue); | ||
124 | return ret; | 155 | return ret; |
125 | } | 156 | } |
126 | 157 | ||
@@ -171,6 +202,8 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
171 | drv->bus->name, dev->bus_id, drv->name); | 202 | drv->bus->name, dev->bus_id, drv->name); |
172 | 203 | ||
173 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 204 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
205 | if (!data) | ||
206 | return -ENOMEM; | ||
174 | data->drv = drv; | 207 | data->drv = drv; |
175 | data->dev = dev; | 208 | data->dev = dev; |
176 | 209 | ||
@@ -178,7 +211,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
178 | probe_task = kthread_run(really_probe, data, | 211 | probe_task = kthread_run(really_probe, data, |
179 | "probe-%s", dev->bus_id); | 212 | "probe-%s", dev->bus_id); |
180 | if (IS_ERR(probe_task)) | 213 | if (IS_ERR(probe_task)) |
181 | ret = PTR_ERR(probe_task); | 214 | ret = really_probe(data); |
182 | } else | 215 | } else |
183 | ret = really_probe(data); | 216 | ret = really_probe(data); |
184 | 217 | ||
@@ -278,10 +311,15 @@ static void __device_release_driver(struct device * dev) | |||
278 | drv = dev->driver; | 311 | drv = dev->driver; |
279 | if (drv) { | 312 | if (drv) { |
280 | get_driver(drv); | 313 | get_driver(drv); |
281 | sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); | 314 | driver_sysfs_remove(dev); |
282 | sysfs_remove_link(&dev->kobj, "driver"); | 315 | sysfs_remove_link(&dev->kobj, "driver"); |
283 | klist_remove(&dev->knode_driver); | 316 | klist_remove(&dev->knode_driver); |
284 | 317 | ||
318 | if (dev->bus) | ||
319 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | ||
320 | BUS_NOTIFY_UNBIND_DRIVER, | ||
321 | dev); | ||
322 | |||
285 | if (dev->bus && dev->bus->remove) | 323 | if (dev->bus && dev->bus->remove) |
286 | dev->bus->remove(dev); | 324 | dev->bus->remove(dev); |
287 | else if (drv->remove) | 325 | else if (drv->remove) |
@@ -335,6 +373,32 @@ void driver_detach(struct device_driver * drv) | |||
335 | } | 373 | } |
336 | } | 374 | } |
337 | 375 | ||
376 | #ifdef CONFIG_PCI_MULTITHREAD_PROBE | ||
377 | static int __init wait_for_probes(void) | ||
378 | { | ||
379 | DEFINE_WAIT(wait); | ||
380 | |||
381 | printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__, | ||
382 | atomic_read(&probe_count)); | ||
383 | if (!atomic_read(&probe_count)) | ||
384 | return 0; | ||
385 | while (atomic_read(&probe_count)) { | ||
386 | prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE); | ||
387 | if (atomic_read(&probe_count)) | ||
388 | schedule(); | ||
389 | } | ||
390 | finish_wait(&probe_waitqueue, &wait); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | core_initcall_sync(wait_for_probes); | ||
395 | postcore_initcall_sync(wait_for_probes); | ||
396 | arch_initcall_sync(wait_for_probes); | ||
397 | subsys_initcall_sync(wait_for_probes); | ||
398 | fs_initcall_sync(wait_for_probes); | ||
399 | device_initcall_sync(wait_for_probes); | ||
400 | late_initcall_sync(wait_for_probes); | ||
401 | #endif | ||
338 | 402 | ||
339 | EXPORT_SYMBOL_GPL(device_bind_driver); | 403 | EXPORT_SYMBOL_GPL(device_bind_driver); |
340 | EXPORT_SYMBOL_GPL(device_release_driver); | 404 | EXPORT_SYMBOL_GPL(device_release_driver); |
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index 33c5cce1560b..b2efbd4cf710 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c | |||
@@ -141,11 +141,20 @@ dma_pool_create (const char *name, struct device *dev, | |||
141 | init_waitqueue_head (&retval->waitq); | 141 | init_waitqueue_head (&retval->waitq); |
142 | 142 | ||
143 | if (dev) { | 143 | if (dev) { |
144 | int ret; | ||
145 | |||
144 | down (&pools_lock); | 146 | down (&pools_lock); |
145 | if (list_empty (&dev->dma_pools)) | 147 | if (list_empty (&dev->dma_pools)) |
146 | device_create_file (dev, &dev_attr_pools); | 148 | ret = device_create_file (dev, &dev_attr_pools); |
149 | else | ||
150 | ret = 0; | ||
147 | /* note: not currently insisting "name" be unique */ | 151 | /* note: not currently insisting "name" be unique */ |
148 | list_add (&retval->pools, &dev->dma_pools); | 152 | if (!ret) |
153 | list_add (&retval->pools, &dev->dma_pools); | ||
154 | else { | ||
155 | kfree(retval); | ||
156 | retval = NULL; | ||
157 | } | ||
149 | up (&pools_lock); | 158 | up (&pools_lock); |
150 | } else | 159 | } else |
151 | INIT_LIST_HEAD (&retval->pools); | 160 | INIT_LIST_HEAD (&retval->pools); |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 14615694ae9a..4bad2870c485 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
22 | #include "base.h" | 22 | #include "base.h" |
23 | 23 | ||
24 | #define to_dev(obj) container_of(obj, struct device, kobj) | ||
25 | |||
24 | MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>"); | 26 | MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>"); |
25 | MODULE_DESCRIPTION("Multi purpose firmware loading support"); | 27 | MODULE_DESCRIPTION("Multi purpose firmware loading support"); |
26 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
@@ -86,12 +88,12 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count) | |||
86 | 88 | ||
87 | static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); | 89 | static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); |
88 | 90 | ||
89 | static void fw_class_dev_release(struct class_device *class_dev); | 91 | static void fw_dev_release(struct device *dev); |
90 | 92 | ||
91 | static int firmware_class_uevent(struct class_device *class_dev, char **envp, | 93 | static int firmware_uevent(struct device *dev, char **envp, int num_envp, |
92 | int num_envp, char *buffer, int buffer_size) | 94 | char *buffer, int buffer_size) |
93 | { | 95 | { |
94 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | 96 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
95 | int i = 0, len = 0; | 97 | int i = 0, len = 0; |
96 | 98 | ||
97 | if (!test_bit(FW_STATUS_READY, &fw_priv->status)) | 99 | if (!test_bit(FW_STATUS_READY, &fw_priv->status)) |
@@ -110,21 +112,21 @@ static int firmware_class_uevent(struct class_device *class_dev, char **envp, | |||
110 | 112 | ||
111 | static struct class firmware_class = { | 113 | static struct class firmware_class = { |
112 | .name = "firmware", | 114 | .name = "firmware", |
113 | .uevent = firmware_class_uevent, | 115 | .dev_uevent = firmware_uevent, |
114 | .release = fw_class_dev_release, | 116 | .dev_release = fw_dev_release, |
115 | }; | 117 | }; |
116 | 118 | ||
117 | static ssize_t | 119 | static ssize_t firmware_loading_show(struct device *dev, |
118 | firmware_loading_show(struct class_device *class_dev, char *buf) | 120 | struct device_attribute *attr, char *buf) |
119 | { | 121 | { |
120 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | 122 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
121 | int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); | 123 | int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); |
122 | return sprintf(buf, "%d\n", loading); | 124 | return sprintf(buf, "%d\n", loading); |
123 | } | 125 | } |
124 | 126 | ||
125 | /** | 127 | /** |
126 | * firmware_loading_store - set value in the 'loading' control file | 128 | * firmware_loading_store - set value in the 'loading' control file |
127 | * @class_dev: class_device pointer | 129 | * @dev: device pointer |
128 | * @buf: buffer to scan for loading control value | 130 | * @buf: buffer to scan for loading control value |
129 | * @count: number of bytes in @buf | 131 | * @count: number of bytes in @buf |
130 | * | 132 | * |
@@ -134,11 +136,11 @@ firmware_loading_show(struct class_device *class_dev, char *buf) | |||
134 | * 0: Conclude the load and hand the data to the driver code. | 136 | * 0: Conclude the load and hand the data to the driver code. |
135 | * -1: Conclude the load with an error and discard any written data. | 137 | * -1: Conclude the load with an error and discard any written data. |
136 | **/ | 138 | **/ |
137 | static ssize_t | 139 | static ssize_t firmware_loading_store(struct device *dev, |
138 | firmware_loading_store(struct class_device *class_dev, | 140 | struct device_attribute *attr, |
139 | const char *buf, size_t count) | 141 | const char *buf, size_t count) |
140 | { | 142 | { |
141 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | 143 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
142 | int loading = simple_strtol(buf, NULL, 10); | 144 | int loading = simple_strtol(buf, NULL, 10); |
143 | 145 | ||
144 | switch (loading) { | 146 | switch (loading) { |
@@ -174,15 +176,14 @@ firmware_loading_store(struct class_device *class_dev, | |||
174 | return count; | 176 | return count; |
175 | } | 177 | } |
176 | 178 | ||
177 | static CLASS_DEVICE_ATTR(loading, 0644, | 179 | static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); |
178 | firmware_loading_show, firmware_loading_store); | ||
179 | 180 | ||
180 | static ssize_t | 181 | static ssize_t |
181 | firmware_data_read(struct kobject *kobj, | 182 | firmware_data_read(struct kobject *kobj, |
182 | char *buffer, loff_t offset, size_t count) | 183 | char *buffer, loff_t offset, size_t count) |
183 | { | 184 | { |
184 | struct class_device *class_dev = to_class_dev(kobj); | 185 | struct device *dev = to_dev(kobj); |
185 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | 186 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
186 | struct firmware *fw; | 187 | struct firmware *fw; |
187 | ssize_t ret_count = count; | 188 | ssize_t ret_count = count; |
188 | 189 | ||
@@ -234,7 +235,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) | |||
234 | 235 | ||
235 | /** | 236 | /** |
236 | * firmware_data_write - write method for firmware | 237 | * firmware_data_write - write method for firmware |
237 | * @kobj: kobject for the class_device | 238 | * @kobj: kobject for the device |
238 | * @buffer: buffer being written | 239 | * @buffer: buffer being written |
239 | * @offset: buffer offset for write in total data store area | 240 | * @offset: buffer offset for write in total data store area |
240 | * @count: buffer size | 241 | * @count: buffer size |
@@ -246,8 +247,8 @@ static ssize_t | |||
246 | firmware_data_write(struct kobject *kobj, | 247 | firmware_data_write(struct kobject *kobj, |
247 | char *buffer, loff_t offset, size_t count) | 248 | char *buffer, loff_t offset, size_t count) |
248 | { | 249 | { |
249 | struct class_device *class_dev = to_class_dev(kobj); | 250 | struct device *dev = to_dev(kobj); |
250 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | 251 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
251 | struct firmware *fw; | 252 | struct firmware *fw; |
252 | ssize_t retval; | 253 | ssize_t retval; |
253 | 254 | ||
@@ -280,13 +281,12 @@ static struct bin_attribute firmware_attr_data_tmpl = { | |||
280 | .write = firmware_data_write, | 281 | .write = firmware_data_write, |
281 | }; | 282 | }; |
282 | 283 | ||
283 | static void | 284 | static void fw_dev_release(struct device *dev) |
284 | fw_class_dev_release(struct class_device *class_dev) | ||
285 | { | 285 | { |
286 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | 286 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
287 | 287 | ||
288 | kfree(fw_priv); | 288 | kfree(fw_priv); |
289 | kfree(class_dev); | 289 | kfree(dev); |
290 | 290 | ||
291 | module_put(THIS_MODULE); | 291 | module_put(THIS_MODULE); |
292 | } | 292 | } |
@@ -298,26 +298,23 @@ firmware_class_timeout(u_long data) | |||
298 | fw_load_abort(fw_priv); | 298 | fw_load_abort(fw_priv); |
299 | } | 299 | } |
300 | 300 | ||
301 | static inline void | 301 | static inline void fw_setup_device_id(struct device *f_dev, struct device *dev) |
302 | fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) | ||
303 | { | 302 | { |
304 | /* XXX warning we should watch out for name collisions */ | 303 | /* XXX warning we should watch out for name collisions */ |
305 | strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); | 304 | strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE); |
306 | } | 305 | } |
307 | 306 | ||
308 | static int | 307 | static int fw_register_device(struct device **dev_p, const char *fw_name, |
309 | fw_register_class_device(struct class_device **class_dev_p, | 308 | struct device *device) |
310 | const char *fw_name, struct device *device) | ||
311 | { | 309 | { |
312 | int retval; | 310 | int retval; |
313 | struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv), | 311 | struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv), |
314 | GFP_KERNEL); | 312 | GFP_KERNEL); |
315 | struct class_device *class_dev = kzalloc(sizeof(*class_dev), | 313 | struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL); |
316 | GFP_KERNEL); | ||
317 | 314 | ||
318 | *class_dev_p = NULL; | 315 | *dev_p = NULL; |
319 | 316 | ||
320 | if (!fw_priv || !class_dev) { | 317 | if (!fw_priv || !f_dev) { |
321 | printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__); | 318 | printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__); |
322 | retval = -ENOMEM; | 319 | retval = -ENOMEM; |
323 | goto error_kfree; | 320 | goto error_kfree; |
@@ -331,55 +328,54 @@ fw_register_class_device(struct class_device **class_dev_p, | |||
331 | fw_priv->timeout.data = (u_long) fw_priv; | 328 | fw_priv->timeout.data = (u_long) fw_priv; |
332 | init_timer(&fw_priv->timeout); | 329 | init_timer(&fw_priv->timeout); |
333 | 330 | ||
334 | fw_setup_class_device_id(class_dev, device); | 331 | fw_setup_device_id(f_dev, device); |
335 | class_dev->dev = device; | 332 | f_dev->parent = device; |
336 | class_dev->class = &firmware_class; | 333 | f_dev->class = &firmware_class; |
337 | class_set_devdata(class_dev, fw_priv); | 334 | dev_set_drvdata(f_dev, fw_priv); |
338 | retval = class_device_register(class_dev); | 335 | retval = device_register(f_dev); |
339 | if (retval) { | 336 | if (retval) { |
340 | printk(KERN_ERR "%s: class_device_register failed\n", | 337 | printk(KERN_ERR "%s: device_register failed\n", |
341 | __FUNCTION__); | 338 | __FUNCTION__); |
342 | goto error_kfree; | 339 | goto error_kfree; |
343 | } | 340 | } |
344 | *class_dev_p = class_dev; | 341 | *dev_p = f_dev; |
345 | return 0; | 342 | return 0; |
346 | 343 | ||
347 | error_kfree: | 344 | error_kfree: |
348 | kfree(fw_priv); | 345 | kfree(fw_priv); |
349 | kfree(class_dev); | 346 | kfree(f_dev); |
350 | return retval; | 347 | return retval; |
351 | } | 348 | } |
352 | 349 | ||
353 | static int | 350 | static int fw_setup_device(struct firmware *fw, struct device **dev_p, |
354 | fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, | 351 | const char *fw_name, struct device *device, |
355 | const char *fw_name, struct device *device, int uevent) | 352 | int uevent) |
356 | { | 353 | { |
357 | struct class_device *class_dev; | 354 | struct device *f_dev; |
358 | struct firmware_priv *fw_priv; | 355 | struct firmware_priv *fw_priv; |
359 | int retval; | 356 | int retval; |
360 | 357 | ||
361 | *class_dev_p = NULL; | 358 | *dev_p = NULL; |
362 | retval = fw_register_class_device(&class_dev, fw_name, device); | 359 | retval = fw_register_device(&f_dev, fw_name, device); |
363 | if (retval) | 360 | if (retval) |
364 | goto out; | 361 | goto out; |
365 | 362 | ||
366 | /* Need to pin this module until class device is destroyed */ | 363 | /* Need to pin this module until class device is destroyed */ |
367 | __module_get(THIS_MODULE); | 364 | __module_get(THIS_MODULE); |
368 | 365 | ||
369 | fw_priv = class_get_devdata(class_dev); | 366 | fw_priv = dev_get_drvdata(f_dev); |
370 | 367 | ||
371 | fw_priv->fw = fw; | 368 | fw_priv->fw = fw; |
372 | retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data); | 369 | retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); |
373 | if (retval) { | 370 | if (retval) { |
374 | printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", | 371 | printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", |
375 | __FUNCTION__); | 372 | __FUNCTION__); |
376 | goto error_unreg; | 373 | goto error_unreg; |
377 | } | 374 | } |
378 | 375 | ||
379 | retval = class_device_create_file(class_dev, | 376 | retval = device_create_file(f_dev, &dev_attr_loading); |
380 | &class_device_attr_loading); | ||
381 | if (retval) { | 377 | if (retval) { |
382 | printk(KERN_ERR "%s: class_device_create_file failed\n", | 378 | printk(KERN_ERR "%s: device_create_file failed\n", |
383 | __FUNCTION__); | 379 | __FUNCTION__); |
384 | goto error_unreg; | 380 | goto error_unreg; |
385 | } | 381 | } |
@@ -388,11 +384,11 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, | |||
388 | set_bit(FW_STATUS_READY, &fw_priv->status); | 384 | set_bit(FW_STATUS_READY, &fw_priv->status); |
389 | else | 385 | else |
390 | set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); | 386 | set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); |
391 | *class_dev_p = class_dev; | 387 | *dev_p = f_dev; |
392 | goto out; | 388 | goto out; |
393 | 389 | ||
394 | error_unreg: | 390 | error_unreg: |
395 | class_device_unregister(class_dev); | 391 | device_unregister(f_dev); |
396 | out: | 392 | out: |
397 | return retval; | 393 | return retval; |
398 | } | 394 | } |
@@ -401,7 +397,7 @@ static int | |||
401 | _request_firmware(const struct firmware **firmware_p, const char *name, | 397 | _request_firmware(const struct firmware **firmware_p, const char *name, |
402 | struct device *device, int uevent) | 398 | struct device *device, int uevent) |
403 | { | 399 | { |
404 | struct class_device *class_dev; | 400 | struct device *f_dev; |
405 | struct firmware_priv *fw_priv; | 401 | struct firmware_priv *fw_priv; |
406 | struct firmware *firmware; | 402 | struct firmware *firmware; |
407 | int retval; | 403 | int retval; |
@@ -417,12 +413,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
417 | goto out; | 413 | goto out; |
418 | } | 414 | } |
419 | 415 | ||
420 | retval = fw_setup_class_device(firmware, &class_dev, name, device, | 416 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); |
421 | uevent); | ||
422 | if (retval) | 417 | if (retval) |
423 | goto error_kfree_fw; | 418 | goto error_kfree_fw; |
424 | 419 | ||
425 | fw_priv = class_get_devdata(class_dev); | 420 | fw_priv = dev_get_drvdata(f_dev); |
426 | 421 | ||
427 | if (uevent) { | 422 | if (uevent) { |
428 | if (loading_timeout > 0) { | 423 | if (loading_timeout > 0) { |
@@ -430,7 +425,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
430 | add_timer(&fw_priv->timeout); | 425 | add_timer(&fw_priv->timeout); |
431 | } | 426 | } |
432 | 427 | ||
433 | kobject_uevent(&class_dev->kobj, KOBJ_ADD); | 428 | kobject_uevent(&f_dev->kobj, KOBJ_ADD); |
434 | wait_for_completion(&fw_priv->completion); | 429 | wait_for_completion(&fw_priv->completion); |
435 | set_bit(FW_STATUS_DONE, &fw_priv->status); | 430 | set_bit(FW_STATUS_DONE, &fw_priv->status); |
436 | del_timer_sync(&fw_priv->timeout); | 431 | del_timer_sync(&fw_priv->timeout); |
@@ -445,7 +440,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
445 | } | 440 | } |
446 | fw_priv->fw = NULL; | 441 | fw_priv->fw = NULL; |
447 | mutex_unlock(&fw_lock); | 442 | mutex_unlock(&fw_lock); |
448 | class_device_unregister(class_dev); | 443 | device_unregister(f_dev); |
449 | goto out; | 444 | goto out; |
450 | 445 | ||
451 | error_kfree_fw: | 446 | error_kfree_fw: |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 940ce41f1887..d1df4a087924 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev) | |||
388 | return drv->probe(dev); | 388 | return drv->probe(dev); |
389 | } | 389 | } |
390 | 390 | ||
391 | static int platform_drv_probe_fail(struct device *_dev) | ||
392 | { | ||
393 | return -ENXIO; | ||
394 | } | ||
395 | |||
391 | static int platform_drv_remove(struct device *_dev) | 396 | static int platform_drv_remove(struct device *_dev) |
392 | { | 397 | { |
393 | struct platform_driver *drv = to_platform_driver(_dev->driver); | 398 | struct platform_driver *drv = to_platform_driver(_dev->driver); |
@@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv) | |||
451 | } | 456 | } |
452 | EXPORT_SYMBOL_GPL(platform_driver_unregister); | 457 | EXPORT_SYMBOL_GPL(platform_driver_unregister); |
453 | 458 | ||
459 | /** | ||
460 | * platform_driver_probe - register driver for non-hotpluggable device | ||
461 | * @drv: platform driver structure | ||
462 | * @probe: the driver probe routine, probably from an __init section | ||
463 | * | ||
464 | * Use this instead of platform_driver_register() when you know the device | ||
465 | * is not hotpluggable and has already been registered, and you want to | ||
466 | * remove its run-once probe() infrastructure from memory after the driver | ||
467 | * has bound to the device. | ||
468 | * | ||
469 | * One typical use for this would be with drivers for controllers integrated | ||
470 | * into system-on-chip processors, where the controller devices have been | ||
471 | * configured as part of board setup. | ||
472 | * | ||
473 | * Returns zero if the driver registered and bound to a device, else returns | ||
474 | * a negative error code and with the driver not registered. | ||
475 | */ | ||
476 | int platform_driver_probe(struct platform_driver *drv, | ||
477 | int (*probe)(struct platform_device *)) | ||
478 | { | ||
479 | int retval, code; | ||
480 | |||
481 | /* temporary section violation during probe() */ | ||
482 | drv->probe = probe; | ||
483 | retval = code = platform_driver_register(drv); | ||
484 | |||
485 | /* Fixup that section violation, being paranoid about code scanning | ||
486 | * the list of drivers in order to probe new devices. Check to see | ||
487 | * if the probe was successful, and make sure any forced probes of | ||
488 | * new devices fail. | ||
489 | */ | ||
490 | spin_lock(&platform_bus_type.klist_drivers.k_lock); | ||
491 | drv->probe = NULL; | ||
492 | if (code == 0 && list_empty(&drv->driver.klist_devices.k_list)) | ||
493 | retval = -ENODEV; | ||
494 | drv->driver.probe = platform_drv_probe_fail; | ||
495 | spin_unlock(&platform_bus_type.klist_drivers.k_lock); | ||
496 | |||
497 | if (code != retval) | ||
498 | platform_driver_unregister(drv); | ||
499 | return retval; | ||
500 | } | ||
501 | EXPORT_SYMBOL_GPL(platform_driver_probe); | ||
454 | 502 | ||
455 | /* modalias support enables more hands-off userspace setup: | 503 | /* modalias support enables more hands-off userspace setup: |
456 | * (a) environment variable lets new-style hotplug events work once system is | 504 | * (a) environment variable lets new-style hotplug events work once system is |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 3ef9d514b916..3d12b85b0962 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -94,55 +94,63 @@ static struct attribute_group topology_attr_group = { | |||
94 | .name = "topology" | 94 | .name = "topology" |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static cpumask_t topology_dev_map = CPU_MASK_NONE; | ||
98 | |||
97 | /* Add/Remove cpu_topology interface for CPU device */ | 99 | /* Add/Remove cpu_topology interface for CPU device */ |
98 | static int __cpuinit topology_add_dev(struct sys_device * sys_dev) | 100 | static int __cpuinit topology_add_dev(unsigned int cpu) |
99 | { | 101 | { |
100 | sysfs_create_group(&sys_dev->kobj, &topology_attr_group); | 102 | int rc; |
101 | return 0; | 103 | struct sys_device *sys_dev = get_cpu_sysdev(cpu); |
104 | |||
105 | rc = sysfs_create_group(&sys_dev->kobj, &topology_attr_group); | ||
106 | if (!rc) | ||
107 | cpu_set(cpu, topology_dev_map); | ||
108 | return rc; | ||
102 | } | 109 | } |
103 | 110 | ||
104 | static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) | 111 | #ifdef CONFIG_HOTPLUG_CPU |
112 | static void __cpuinit topology_remove_dev(unsigned int cpu) | ||
105 | { | 113 | { |
114 | struct sys_device *sys_dev = get_cpu_sysdev(cpu); | ||
115 | |||
116 | if (!cpu_isset(cpu, topology_dev_map)) | ||
117 | return; | ||
118 | cpu_clear(cpu, topology_dev_map); | ||
106 | sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); | 119 | sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); |
107 | return 0; | ||
108 | } | 120 | } |
109 | 121 | ||
110 | static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, | 122 | static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, |
111 | unsigned long action, void *hcpu) | 123 | unsigned long action, void *hcpu) |
112 | { | 124 | { |
113 | unsigned int cpu = (unsigned long)hcpu; | 125 | unsigned int cpu = (unsigned long)hcpu; |
114 | struct sys_device *sys_dev; | 126 | int rc = 0; |
115 | 127 | ||
116 | sys_dev = get_cpu_sysdev(cpu); | ||
117 | switch (action) { | 128 | switch (action) { |
118 | case CPU_ONLINE: | 129 | case CPU_UP_PREPARE: |
119 | topology_add_dev(sys_dev); | 130 | rc = topology_add_dev(cpu); |
120 | break; | 131 | break; |
132 | case CPU_UP_CANCELED: | ||
121 | case CPU_DEAD: | 133 | case CPU_DEAD: |
122 | topology_remove_dev(sys_dev); | 134 | topology_remove_dev(cpu); |
123 | break; | 135 | break; |
124 | } | 136 | } |
125 | return NOTIFY_OK; | 137 | return rc ? NOTIFY_BAD : NOTIFY_OK; |
126 | } | 138 | } |
127 | 139 | #endif | |
128 | static struct notifier_block __cpuinitdata topology_cpu_notifier = | ||
129 | { | ||
130 | .notifier_call = topology_cpu_callback, | ||
131 | }; | ||
132 | 140 | ||
133 | static int __cpuinit topology_sysfs_init(void) | 141 | static int __cpuinit topology_sysfs_init(void) |
134 | { | 142 | { |
135 | int i; | 143 | int cpu; |
144 | int rc; | ||
136 | 145 | ||
137 | for_each_online_cpu(i) { | 146 | for_each_online_cpu(cpu) { |
138 | topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE, | 147 | rc = topology_add_dev(cpu); |
139 | (void *)(long)i); | 148 | if (rc) |
149 | return rc; | ||
140 | } | 150 | } |
141 | 151 | hotcpu_notifier(topology_cpu_callback, 0); | |
142 | register_hotcpu_notifier(&topology_cpu_notifier); | ||
143 | 152 | ||
144 | return 0; | 153 | return 0; |
145 | } | 154 | } |
146 | 155 | ||
147 | device_initcall(topology_sysfs_init); | 156 | device_initcall(topology_sysfs_init); |
148 | |||