diff options
56 files changed, 854 insertions, 544 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 6da663607f7b..ec0b4843b1cb 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -134,15 +134,6 @@ Who: Arjan van de Ven <arjan@linux.intel.com> | |||
134 | 134 | ||
135 | --------------------------- | 135 | --------------------------- |
136 | 136 | ||
137 | What: mount/umount uevents | ||
138 | When: February 2007 | ||
139 | Why: These events are not correct, and do not properly let userspace know | ||
140 | when a file system has been mounted or unmounted. Userspace should | ||
141 | poll the /proc/mounts file instead to detect this properly. | ||
142 | Who: Greg Kroah-Hartman <gregkh@suse.de> | ||
143 | |||
144 | --------------------------- | ||
145 | |||
146 | What: USB driver API moves to EXPORT_SYMBOL_GPL | 137 | What: USB driver API moves to EXPORT_SYMBOL_GPL |
147 | When: February 2008 | 138 | When: February 2008 |
148 | Files: include/linux/usb.h, drivers/usb/core/driver.c | 139 | Files: include/linux/usb.h, drivers/usb/core/driver.c |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index b7345176b399..9e7a4d249f03 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
@@ -475,9 +475,6 @@ static struct of_platform_driver of_pci_phb_driver = { | |||
475 | .name = "of-pci", | 475 | .name = "of-pci", |
476 | .match_table = of_pci_phb_ids, | 476 | .match_table = of_pci_phb_ids, |
477 | .probe = of_pci_phb_probe, | 477 | .probe = of_pci_phb_probe, |
478 | .driver = { | ||
479 | .multithread_probe = 1, | ||
480 | }, | ||
481 | }; | 478 | }; |
482 | 479 | ||
483 | static __init int of_pci_phb_init(void) | 480 | static __init int of_pci_phb_init(void) |
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index fd5475071acc..268e301775fc 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -47,14 +47,13 @@ static int amba_match(struct device *dev, struct device_driver *drv) | |||
47 | static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) | 47 | static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) |
48 | { | 48 | { |
49 | struct amba_device *pcdev = to_amba_device(dev); | 49 | struct amba_device *pcdev = to_amba_device(dev); |
50 | int retval = 0, i = 0, len = 0; | ||
50 | 51 | ||
51 | if (nr_env < 2) | 52 | retval = add_uevent_var(envp, nr_env, &i, |
52 | return -ENOMEM; | 53 | buf, bufsz, &len, |
53 | 54 | "AMBA_ID=%08x", pcdev->periphid); | |
54 | snprintf(buf, bufsz, "AMBA_ID=%08x", pcdev->periphid); | 55 | envp[i] = NULL; |
55 | *envp++ = buf; | 56 | return retval; |
56 | *envp++ = NULL; | ||
57 | return 0; | ||
58 | } | 57 | } |
59 | #else | 58 | #else |
60 | #define amba_uevent NULL | 59 | #define amba_uevent NULL |
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 22220733f76f..1ec0654665cf 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c | |||
@@ -62,7 +62,7 @@ EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container); | |||
62 | 62 | ||
63 | static struct list_head attribute_container_list; | 63 | static struct list_head attribute_container_list; |
64 | 64 | ||
65 | static DECLARE_MUTEX(attribute_container_mutex); | 65 | static DEFINE_MUTEX(attribute_container_mutex); |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * attribute_container_register - register an attribute container | 68 | * attribute_container_register - register an attribute container |
@@ -77,9 +77,9 @@ attribute_container_register(struct attribute_container *cont) | |||
77 | klist_init(&cont->containers,internal_container_klist_get, | 77 | klist_init(&cont->containers,internal_container_klist_get, |
78 | internal_container_klist_put); | 78 | internal_container_klist_put); |
79 | 79 | ||
80 | down(&attribute_container_mutex); | 80 | mutex_lock(&attribute_container_mutex); |
81 | list_add_tail(&cont->node, &attribute_container_list); | 81 | list_add_tail(&cont->node, &attribute_container_list); |
82 | up(&attribute_container_mutex); | 82 | mutex_unlock(&attribute_container_mutex); |
83 | 83 | ||
84 | return 0; | 84 | return 0; |
85 | } | 85 | } |
@@ -94,7 +94,7 @@ int | |||
94 | attribute_container_unregister(struct attribute_container *cont) | 94 | attribute_container_unregister(struct attribute_container *cont) |
95 | { | 95 | { |
96 | int retval = -EBUSY; | 96 | int retval = -EBUSY; |
97 | down(&attribute_container_mutex); | 97 | mutex_lock(&attribute_container_mutex); |
98 | spin_lock(&cont->containers.k_lock); | 98 | spin_lock(&cont->containers.k_lock); |
99 | if (!list_empty(&cont->containers.k_list)) | 99 | if (!list_empty(&cont->containers.k_list)) |
100 | goto out; | 100 | goto out; |
@@ -102,7 +102,7 @@ attribute_container_unregister(struct attribute_container *cont) | |||
102 | list_del(&cont->node); | 102 | list_del(&cont->node); |
103 | out: | 103 | out: |
104 | spin_unlock(&cont->containers.k_lock); | 104 | spin_unlock(&cont->containers.k_lock); |
105 | up(&attribute_container_mutex); | 105 | mutex_unlock(&attribute_container_mutex); |
106 | return retval; | 106 | return retval; |
107 | 107 | ||
108 | } | 108 | } |
@@ -145,7 +145,7 @@ attribute_container_add_device(struct device *dev, | |||
145 | { | 145 | { |
146 | struct attribute_container *cont; | 146 | struct attribute_container *cont; |
147 | 147 | ||
148 | down(&attribute_container_mutex); | 148 | mutex_lock(&attribute_container_mutex); |
149 | list_for_each_entry(cont, &attribute_container_list, node) { | 149 | list_for_each_entry(cont, &attribute_container_list, node) { |
150 | struct internal_container *ic; | 150 | struct internal_container *ic; |
151 | 151 | ||
@@ -173,7 +173,7 @@ attribute_container_add_device(struct device *dev, | |||
173 | attribute_container_add_class_device(&ic->classdev); | 173 | attribute_container_add_class_device(&ic->classdev); |
174 | klist_add_tail(&ic->node, &cont->containers); | 174 | klist_add_tail(&ic->node, &cont->containers); |
175 | } | 175 | } |
176 | up(&attribute_container_mutex); | 176 | mutex_unlock(&attribute_container_mutex); |
177 | } | 177 | } |
178 | 178 | ||
179 | /* FIXME: can't break out of this unless klist_iter_exit is also | 179 | /* FIXME: can't break out of this unless klist_iter_exit is also |
@@ -211,7 +211,7 @@ attribute_container_remove_device(struct device *dev, | |||
211 | { | 211 | { |
212 | struct attribute_container *cont; | 212 | struct attribute_container *cont; |
213 | 213 | ||
214 | down(&attribute_container_mutex); | 214 | mutex_lock(&attribute_container_mutex); |
215 | list_for_each_entry(cont, &attribute_container_list, node) { | 215 | list_for_each_entry(cont, &attribute_container_list, node) { |
216 | struct internal_container *ic; | 216 | struct internal_container *ic; |
217 | struct klist_iter iter; | 217 | struct klist_iter iter; |
@@ -234,7 +234,7 @@ attribute_container_remove_device(struct device *dev, | |||
234 | } | 234 | } |
235 | } | 235 | } |
236 | } | 236 | } |
237 | up(&attribute_container_mutex); | 237 | mutex_unlock(&attribute_container_mutex); |
238 | } | 238 | } |
239 | 239 | ||
240 | /** | 240 | /** |
@@ -255,7 +255,7 @@ attribute_container_device_trigger(struct device *dev, | |||
255 | { | 255 | { |
256 | struct attribute_container *cont; | 256 | struct attribute_container *cont; |
257 | 257 | ||
258 | down(&attribute_container_mutex); | 258 | mutex_lock(&attribute_container_mutex); |
259 | list_for_each_entry(cont, &attribute_container_list, node) { | 259 | list_for_each_entry(cont, &attribute_container_list, node) { |
260 | struct internal_container *ic; | 260 | struct internal_container *ic; |
261 | struct klist_iter iter; | 261 | struct klist_iter iter; |
@@ -273,7 +273,7 @@ attribute_container_device_trigger(struct device *dev, | |||
273 | fn(cont, dev, &ic->classdev); | 273 | fn(cont, dev, &ic->classdev); |
274 | } | 274 | } |
275 | } | 275 | } |
276 | up(&attribute_container_mutex); | 276 | mutex_unlock(&attribute_container_mutex); |
277 | } | 277 | } |
278 | 278 | ||
279 | /** | 279 | /** |
@@ -295,12 +295,12 @@ attribute_container_trigger(struct device *dev, | |||
295 | { | 295 | { |
296 | struct attribute_container *cont; | 296 | struct attribute_container *cont; |
297 | 297 | ||
298 | down(&attribute_container_mutex); | 298 | mutex_lock(&attribute_container_mutex); |
299 | list_for_each_entry(cont, &attribute_container_list, node) { | 299 | list_for_each_entry(cont, &attribute_container_list, node) { |
300 | if (cont->match(cont, dev)) | 300 | if (cont->match(cont, dev)) |
301 | fn(cont, dev); | 301 | fn(cont, dev); |
302 | } | 302 | } |
303 | up(&attribute_container_mutex); | 303 | mutex_unlock(&attribute_container_mutex); |
304 | } | 304 | } |
305 | 305 | ||
306 | /** | 306 | /** |
diff --git a/drivers/base/base.h b/drivers/base/base.h index de7e1442ce60..d597f2659b23 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -16,7 +16,7 @@ extern int cpu_dev_init(void); | |||
16 | extern int attribute_container_init(void); | 16 | extern int attribute_container_init(void); |
17 | 17 | ||
18 | extern int bus_add_device(struct device * dev); | 18 | extern int bus_add_device(struct device * dev); |
19 | extern int bus_attach_device(struct device * dev); | 19 | extern void bus_attach_device(struct device * dev); |
20 | extern void bus_remove_device(struct device * dev); | 20 | extern void bus_remove_device(struct device * dev); |
21 | extern struct bus_type *get_bus(struct bus_type * bus); | 21 | extern struct bus_type *get_bus(struct bus_type * bus); |
22 | extern void put_bus(struct bus_type * bus); | 22 | extern void put_bus(struct bus_type * bus); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 253868e03c70..1d76e2349654 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #define to_driver(obj) container_of(obj, struct device_driver, kobj) | 27 | #define to_driver(obj) container_of(obj, struct device_driver, kobj) |
28 | 28 | ||
29 | 29 | ||
30 | static int __must_check bus_rescan_devices_helper(struct device *dev, | ||
31 | void *data); | ||
32 | |||
30 | static ssize_t | 33 | static ssize_t |
31 | drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | 34 | drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) |
32 | { | 35 | { |
@@ -60,8 +63,19 @@ static struct sysfs_ops driver_sysfs_ops = { | |||
60 | 63 | ||
61 | static void driver_release(struct kobject * kobj) | 64 | static void driver_release(struct kobject * kobj) |
62 | { | 65 | { |
63 | struct device_driver * drv = to_driver(kobj); | 66 | /* |
64 | complete(&drv->unloaded); | 67 | * Yes this is an empty release function, it is this way because struct |
68 | * device is always a static object, not a dynamic one. Yes, this is | ||
69 | * not nice and bad, but remember, drivers are code, reference counted | ||
70 | * by the module count, not a device, which is really data. And yes, | ||
71 | * in the future I do want to have all drivers be created dynamically, | ||
72 | * and am working toward that goal, but it will take a bit longer... | ||
73 | * | ||
74 | * But do not let this example give _anyone_ the idea that they can | ||
75 | * create a release function without any code in it at all, to do that | ||
76 | * is almost always wrong. If you have any questions about this, | ||
77 | * please send an email to <greg@kroah.com> | ||
78 | */ | ||
65 | } | 79 | } |
66 | 80 | ||
67 | static struct kobj_type ktype_driver = { | 81 | static struct kobj_type ktype_driver = { |
@@ -133,7 +147,6 @@ static decl_subsys(bus, &ktype_bus, NULL); | |||
133 | 147 | ||
134 | 148 | ||
135 | #ifdef CONFIG_HOTPLUG | 149 | #ifdef CONFIG_HOTPLUG |
136 | |||
137 | /* Manually detach a device from its associated driver. */ | 150 | /* Manually detach a device from its associated driver. */ |
138 | static int driver_helper(struct device *dev, void *data) | 151 | static int driver_helper(struct device *dev, void *data) |
139 | { | 152 | { |
@@ -199,6 +212,33 @@ static ssize_t driver_bind(struct device_driver *drv, | |||
199 | } | 212 | } |
200 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); | 213 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); |
201 | 214 | ||
215 | static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf) | ||
216 | { | ||
217 | return sprintf(buf, "%d\n", bus->drivers_autoprobe); | ||
218 | } | ||
219 | |||
220 | static ssize_t store_drivers_autoprobe(struct bus_type *bus, | ||
221 | const char *buf, size_t count) | ||
222 | { | ||
223 | if (buf[0] == '0') | ||
224 | bus->drivers_autoprobe = 0; | ||
225 | else | ||
226 | bus->drivers_autoprobe = 1; | ||
227 | return count; | ||
228 | } | ||
229 | |||
230 | static ssize_t store_drivers_probe(struct bus_type *bus, | ||
231 | const char *buf, size_t count) | ||
232 | { | ||
233 | struct device *dev; | ||
234 | |||
235 | dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); | ||
236 | if (!dev) | ||
237 | return -ENODEV; | ||
238 | if (bus_rescan_devices_helper(dev, NULL) != 0) | ||
239 | return -EINVAL; | ||
240 | return count; | ||
241 | } | ||
202 | #endif | 242 | #endif |
203 | 243 | ||
204 | static struct device * next_device(struct klist_iter * i) | 244 | static struct device * next_device(struct klist_iter * i) |
@@ -418,21 +458,21 @@ out_put: | |||
418 | * - Add device to bus's list of devices. | 458 | * - Add device to bus's list of devices. |
419 | * - Try to attach to driver. | 459 | * - Try to attach to driver. |
420 | */ | 460 | */ |
421 | int bus_attach_device(struct device * dev) | 461 | void bus_attach_device(struct device * dev) |
422 | { | 462 | { |
423 | struct bus_type *bus = dev->bus; | 463 | struct bus_type *bus = dev->bus; |
424 | int ret = 0; | 464 | int ret = 0; |
425 | 465 | ||
426 | if (bus) { | 466 | if (bus) { |
427 | dev->is_registered = 1; | 467 | dev->is_registered = 1; |
428 | ret = device_attach(dev); | 468 | if (bus->drivers_autoprobe) |
429 | if (ret >= 0) { | 469 | ret = device_attach(dev); |
470 | WARN_ON(ret < 0); | ||
471 | if (ret >= 0) | ||
430 | klist_add_tail(&dev->knode_bus, &bus->klist_devices); | 472 | klist_add_tail(&dev->knode_bus, &bus->klist_devices); |
431 | ret = 0; | 473 | else |
432 | } else | ||
433 | dev->is_registered = 0; | 474 | dev->is_registered = 0; |
434 | } | 475 | } |
435 | return ret; | ||
436 | } | 476 | } |
437 | 477 | ||
438 | /** | 478 | /** |
@@ -515,9 +555,41 @@ static void remove_bind_files(struct device_driver *drv) | |||
515 | driver_remove_file(drv, &driver_attr_bind); | 555 | driver_remove_file(drv, &driver_attr_bind); |
516 | driver_remove_file(drv, &driver_attr_unbind); | 556 | driver_remove_file(drv, &driver_attr_unbind); |
517 | } | 557 | } |
558 | |||
559 | static int add_probe_files(struct bus_type *bus) | ||
560 | { | ||
561 | int retval; | ||
562 | |||
563 | bus->drivers_probe_attr.attr.name = "drivers_probe"; | ||
564 | bus->drivers_probe_attr.attr.mode = S_IWUSR; | ||
565 | bus->drivers_probe_attr.attr.owner = bus->owner; | ||
566 | bus->drivers_probe_attr.store = store_drivers_probe; | ||
567 | retval = bus_create_file(bus, &bus->drivers_probe_attr); | ||
568 | if (retval) | ||
569 | goto out; | ||
570 | |||
571 | bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe"; | ||
572 | bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO; | ||
573 | bus->drivers_autoprobe_attr.attr.owner = bus->owner; | ||
574 | bus->drivers_autoprobe_attr.show = show_drivers_autoprobe; | ||
575 | bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; | ||
576 | retval = bus_create_file(bus, &bus->drivers_autoprobe_attr); | ||
577 | if (retval) | ||
578 | bus_remove_file(bus, &bus->drivers_probe_attr); | ||
579 | out: | ||
580 | return retval; | ||
581 | } | ||
582 | |||
583 | static void remove_probe_files(struct bus_type *bus) | ||
584 | { | ||
585 | bus_remove_file(bus, &bus->drivers_autoprobe_attr); | ||
586 | bus_remove_file(bus, &bus->drivers_probe_attr); | ||
587 | } | ||
518 | #else | 588 | #else |
519 | static inline int add_bind_files(struct device_driver *drv) { return 0; } | 589 | static inline int add_bind_files(struct device_driver *drv) { return 0; } |
520 | static inline void remove_bind_files(struct device_driver *drv) {} | 590 | static inline void remove_bind_files(struct device_driver *drv) {} |
591 | static inline int add_probe_files(struct bus_type *bus) { return 0; } | ||
592 | static inline void remove_probe_files(struct bus_type *bus) {} | ||
521 | #endif | 593 | #endif |
522 | 594 | ||
523 | /** | 595 | /** |
@@ -531,7 +603,7 @@ int bus_add_driver(struct device_driver *drv) | |||
531 | int error = 0; | 603 | int error = 0; |
532 | 604 | ||
533 | if (!bus) | 605 | if (!bus) |
534 | return 0; | 606 | return -EINVAL; |
535 | 607 | ||
536 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); | 608 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); |
537 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | 609 | error = kobject_set_name(&drv->kobj, "%s", drv->name); |
@@ -541,9 +613,11 @@ int bus_add_driver(struct device_driver *drv) | |||
541 | if ((error = kobject_register(&drv->kobj))) | 613 | if ((error = kobject_register(&drv->kobj))) |
542 | goto out_put_bus; | 614 | goto out_put_bus; |
543 | 615 | ||
544 | error = driver_attach(drv); | 616 | if (drv->bus->drivers_autoprobe) { |
545 | if (error) | 617 | error = driver_attach(drv); |
546 | goto out_unregister; | 618 | if (error) |
619 | goto out_unregister; | ||
620 | } | ||
547 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | 621 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); |
548 | module_add_driver(drv->owner, drv); | 622 | module_add_driver(drv->owner, drv); |
549 | 623 | ||
@@ -605,8 +679,6 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, | |||
605 | ret = device_attach(dev); | 679 | ret = device_attach(dev); |
606 | if (dev->parent) | 680 | if (dev->parent) |
607 | up(&dev->parent->sem); | 681 | up(&dev->parent->sem); |
608 | if (ret > 0) | ||
609 | ret = 0; | ||
610 | } | 682 | } |
611 | return ret < 0 ? ret : 0; | 683 | return ret < 0 ? ret : 0; |
612 | } | 684 | } |
@@ -762,6 +834,12 @@ int bus_register(struct bus_type * bus) | |||
762 | 834 | ||
763 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); | 835 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); |
764 | klist_init(&bus->klist_drivers, NULL, NULL); | 836 | klist_init(&bus->klist_drivers, NULL, NULL); |
837 | |||
838 | bus->drivers_autoprobe = 1; | ||
839 | retval = add_probe_files(bus); | ||
840 | if (retval) | ||
841 | goto bus_probe_files_fail; | ||
842 | |||
765 | retval = bus_add_attrs(bus); | 843 | retval = bus_add_attrs(bus); |
766 | if (retval) | 844 | if (retval) |
767 | goto bus_attrs_fail; | 845 | goto bus_attrs_fail; |
@@ -770,6 +848,8 @@ int bus_register(struct bus_type * bus) | |||
770 | return 0; | 848 | return 0; |
771 | 849 | ||
772 | bus_attrs_fail: | 850 | bus_attrs_fail: |
851 | remove_probe_files(bus); | ||
852 | bus_probe_files_fail: | ||
773 | kset_unregister(&bus->drivers); | 853 | kset_unregister(&bus->drivers); |
774 | bus_drivers_fail: | 854 | bus_drivers_fail: |
775 | kset_unregister(&bus->devices); | 855 | kset_unregister(&bus->devices); |
@@ -779,7 +859,6 @@ out: | |||
779 | return retval; | 859 | return retval; |
780 | } | 860 | } |
781 | 861 | ||
782 | |||
783 | /** | 862 | /** |
784 | * bus_unregister - remove a bus from the system | 863 | * bus_unregister - remove a bus from the system |
785 | * @bus: bus. | 864 | * @bus: bus. |
@@ -791,6 +870,7 @@ void bus_unregister(struct bus_type * bus) | |||
791 | { | 870 | { |
792 | pr_debug("bus %s: unregistering\n", bus->name); | 871 | pr_debug("bus %s: unregistering\n", bus->name); |
793 | bus_remove_attrs(bus); | 872 | bus_remove_attrs(bus); |
873 | remove_probe_files(bus); | ||
794 | kset_unregister(&bus->drivers); | 874 | kset_unregister(&bus->drivers); |
795 | kset_unregister(&bus->devices); | 875 | kset_unregister(&bus->devices); |
796 | subsystem_unregister(&bus->subsys); | 876 | subsystem_unregister(&bus->subsys); |
diff --git a/drivers/base/class.c b/drivers/base/class.c index d5968128be2b..80bbb2074636 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -145,6 +145,7 @@ int class_register(struct class * cls) | |||
145 | INIT_LIST_HEAD(&cls->children); | 145 | INIT_LIST_HEAD(&cls->children); |
146 | INIT_LIST_HEAD(&cls->devices); | 146 | INIT_LIST_HEAD(&cls->devices); |
147 | INIT_LIST_HEAD(&cls->interfaces); | 147 | INIT_LIST_HEAD(&cls->interfaces); |
148 | kset_init(&cls->class_dirs); | ||
148 | init_MUTEX(&cls->sem); | 149 | init_MUTEX(&cls->sem); |
149 | error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); | 150 | error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); |
150 | if (error) | 151 | if (error) |
@@ -163,7 +164,6 @@ int class_register(struct class * cls) | |||
163 | void class_unregister(struct class * cls) | 164 | void class_unregister(struct class * cls) |
164 | { | 165 | { |
165 | pr_debug("device class '%s': unregistering\n", cls->name); | 166 | pr_debug("device class '%s': unregistering\n", cls->name); |
166 | kobject_unregister(cls->virtual_dir); | ||
167 | remove_class_attrs(cls); | 167 | remove_class_attrs(cls); |
168 | subsystem_unregister(&cls->subsys); | 168 | subsystem_unregister(&cls->subsys); |
169 | } | 169 | } |
diff --git a/drivers/base/core.c b/drivers/base/core.c index d7fcf823a42a..8aa090da1cd7 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -43,7 +43,8 @@ int (*platform_notify_remove)(struct device * dev) = NULL; | |||
43 | const char *dev_driver_string(struct device *dev) | 43 | const char *dev_driver_string(struct device *dev) |
44 | { | 44 | { |
45 | return dev->driver ? dev->driver->name : | 45 | return dev->driver ? dev->driver->name : |
46 | (dev->bus ? dev->bus->name : ""); | 46 | (dev->bus ? dev->bus->name : |
47 | (dev->class ? dev->class->name : "")); | ||
47 | } | 48 | } |
48 | EXPORT_SYMBOL(dev_driver_string); | 49 | EXPORT_SYMBOL(dev_driver_string); |
49 | 50 | ||
@@ -119,6 +120,8 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
119 | 120 | ||
120 | if (ktype == &ktype_device) { | 121 | if (ktype == &ktype_device) { |
121 | struct device *dev = to_dev(kobj); | 122 | struct device *dev = to_dev(kobj); |
123 | if (dev->uevent_suppress) | ||
124 | return 0; | ||
122 | if (dev->bus) | 125 | if (dev->bus) |
123 | return 1; | 126 | return 1; |
124 | if (dev->class) | 127 | if (dev->class) |
@@ -156,6 +159,11 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | |||
156 | "MINOR=%u", MINOR(dev->devt)); | 159 | "MINOR=%u", MINOR(dev->devt)); |
157 | } | 160 | } |
158 | 161 | ||
162 | if (dev->type && dev->type->name) | ||
163 | add_uevent_var(envp, num_envp, &i, | ||
164 | buffer, buffer_size, &length, | ||
165 | "DEVTYPE=%s", dev->type->name); | ||
166 | |||
159 | if (dev->driver) | 167 | if (dev->driver) |
160 | add_uevent_var(envp, num_envp, &i, | 168 | add_uevent_var(envp, num_envp, &i, |
161 | buffer, buffer_size, &length, | 169 | buffer, buffer_size, &length, |
@@ -238,71 +246,152 @@ static struct kset_uevent_ops device_uevent_ops = { | |||
238 | .uevent = dev_uevent, | 246 | .uevent = dev_uevent, |
239 | }; | 247 | }; |
240 | 248 | ||
249 | static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, | ||
250 | char *buf) | ||
251 | { | ||
252 | struct kobject *top_kobj; | ||
253 | struct kset *kset; | ||
254 | char *envp[32]; | ||
255 | char data[PAGE_SIZE]; | ||
256 | char *pos; | ||
257 | int i; | ||
258 | size_t count = 0; | ||
259 | int retval; | ||
260 | |||
261 | /* search the kset, the device belongs to */ | ||
262 | top_kobj = &dev->kobj; | ||
263 | if (!top_kobj->kset && top_kobj->parent) { | ||
264 | do { | ||
265 | top_kobj = top_kobj->parent; | ||
266 | } while (!top_kobj->kset && top_kobj->parent); | ||
267 | } | ||
268 | if (!top_kobj->kset) | ||
269 | goto out; | ||
270 | kset = top_kobj->kset; | ||
271 | if (!kset->uevent_ops || !kset->uevent_ops->uevent) | ||
272 | goto out; | ||
273 | |||
274 | /* respect filter */ | ||
275 | if (kset->uevent_ops && kset->uevent_ops->filter) | ||
276 | if (!kset->uevent_ops->filter(kset, &dev->kobj)) | ||
277 | goto out; | ||
278 | |||
279 | /* let the kset specific function add its keys */ | ||
280 | pos = data; | ||
281 | retval = kset->uevent_ops->uevent(kset, &dev->kobj, | ||
282 | envp, ARRAY_SIZE(envp), | ||
283 | pos, PAGE_SIZE); | ||
284 | if (retval) | ||
285 | goto out; | ||
286 | |||
287 | /* copy keys to file */ | ||
288 | for (i = 0; envp[i]; i++) { | ||
289 | pos = &buf[count]; | ||
290 | count += sprintf(pos, "%s\n", envp[i]); | ||
291 | } | ||
292 | out: | ||
293 | return count; | ||
294 | } | ||
295 | |||
241 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | 296 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, |
242 | const char *buf, size_t count) | 297 | const char *buf, size_t count) |
243 | { | 298 | { |
299 | if (memcmp(buf, "add", 3) != 0) | ||
300 | dev_err(dev, "uevent: unsupported action-string; this will " | ||
301 | "be ignored in a future kernel version"); | ||
244 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 302 | kobject_uevent(&dev->kobj, KOBJ_ADD); |
245 | return count; | 303 | return count; |
246 | } | 304 | } |
247 | 305 | ||
248 | static int device_add_groups(struct device *dev) | 306 | static int device_add_attributes(struct device *dev, |
307 | struct device_attribute *attrs) | ||
308 | { | ||
309 | int error = 0; | ||
310 | int i; | ||
311 | |||
312 | if (attrs) { | ||
313 | for (i = 0; attr_name(attrs[i]); i++) { | ||
314 | error = device_create_file(dev, &attrs[i]); | ||
315 | if (error) | ||
316 | break; | ||
317 | } | ||
318 | if (error) | ||
319 | while (--i >= 0) | ||
320 | device_remove_file(dev, &attrs[i]); | ||
321 | } | ||
322 | return error; | ||
323 | } | ||
324 | |||
325 | static void device_remove_attributes(struct device *dev, | ||
326 | struct device_attribute *attrs) | ||
249 | { | 327 | { |
250 | int i; | 328 | int i; |
329 | |||
330 | if (attrs) | ||
331 | for (i = 0; attr_name(attrs[i]); i++) | ||
332 | device_remove_file(dev, &attrs[i]); | ||
333 | } | ||
334 | |||
335 | static int device_add_groups(struct device *dev, | ||
336 | struct attribute_group **groups) | ||
337 | { | ||
251 | int error = 0; | 338 | int error = 0; |
339 | int i; | ||
252 | 340 | ||
253 | if (dev->groups) { | 341 | if (groups) { |
254 | for (i = 0; dev->groups[i]; i++) { | 342 | for (i = 0; groups[i]; i++) { |
255 | error = sysfs_create_group(&dev->kobj, dev->groups[i]); | 343 | error = sysfs_create_group(&dev->kobj, groups[i]); |
256 | if (error) { | 344 | if (error) { |
257 | while (--i >= 0) | 345 | while (--i >= 0) |
258 | sysfs_remove_group(&dev->kobj, dev->groups[i]); | 346 | sysfs_remove_group(&dev->kobj, groups[i]); |
259 | goto out; | 347 | break; |
260 | } | 348 | } |
261 | } | 349 | } |
262 | } | 350 | } |
263 | out: | ||
264 | return error; | 351 | return error; |
265 | } | 352 | } |
266 | 353 | ||
267 | static void device_remove_groups(struct device *dev) | 354 | static void device_remove_groups(struct device *dev, |
355 | struct attribute_group **groups) | ||
268 | { | 356 | { |
269 | int i; | 357 | int i; |
270 | if (dev->groups) { | 358 | |
271 | for (i = 0; dev->groups[i]; i++) { | 359 | if (groups) |
272 | sysfs_remove_group(&dev->kobj, dev->groups[i]); | 360 | for (i = 0; groups[i]; i++) |
273 | } | 361 | sysfs_remove_group(&dev->kobj, groups[i]); |
274 | } | ||
275 | } | 362 | } |
276 | 363 | ||
277 | static int device_add_attrs(struct device *dev) | 364 | static int device_add_attrs(struct device *dev) |
278 | { | 365 | { |
279 | struct class *class = dev->class; | 366 | struct class *class = dev->class; |
280 | struct device_type *type = dev->type; | 367 | struct device_type *type = dev->type; |
281 | int error = 0; | 368 | int error; |
282 | int i; | ||
283 | 369 | ||
284 | if (class && class->dev_attrs) { | 370 | if (class) { |
285 | for (i = 0; attr_name(class->dev_attrs[i]); i++) { | 371 | error = device_add_attributes(dev, class->dev_attrs); |
286 | error = device_create_file(dev, &class->dev_attrs[i]); | ||
287 | if (error) | ||
288 | break; | ||
289 | } | ||
290 | if (error) | 372 | if (error) |
291 | while (--i >= 0) | 373 | return error; |
292 | device_remove_file(dev, &class->dev_attrs[i]); | ||
293 | } | 374 | } |
294 | 375 | ||
295 | if (type && type->attrs) { | 376 | if (type) { |
296 | for (i = 0; attr_name(type->attrs[i]); i++) { | 377 | error = device_add_groups(dev, type->groups); |
297 | error = device_create_file(dev, &type->attrs[i]); | ||
298 | if (error) | ||
299 | break; | ||
300 | } | ||
301 | if (error) | 378 | if (error) |
302 | while (--i >= 0) | 379 | goto err_remove_class_attrs; |
303 | device_remove_file(dev, &type->attrs[i]); | ||
304 | } | 380 | } |
305 | 381 | ||
382 | error = device_add_groups(dev, dev->groups); | ||
383 | if (error) | ||
384 | goto err_remove_type_groups; | ||
385 | |||
386 | return 0; | ||
387 | |||
388 | err_remove_type_groups: | ||
389 | if (type) | ||
390 | device_remove_groups(dev, type->groups); | ||
391 | err_remove_class_attrs: | ||
392 | if (class) | ||
393 | device_remove_attributes(dev, class->dev_attrs); | ||
394 | |||
306 | return error; | 395 | return error; |
307 | } | 396 | } |
308 | 397 | ||
@@ -310,17 +399,14 @@ static void device_remove_attrs(struct device *dev) | |||
310 | { | 399 | { |
311 | struct class *class = dev->class; | 400 | struct class *class = dev->class; |
312 | struct device_type *type = dev->type; | 401 | struct device_type *type = dev->type; |
313 | int i; | ||
314 | 402 | ||
315 | if (class && class->dev_attrs) { | 403 | device_remove_groups(dev, dev->groups); |
316 | for (i = 0; attr_name(class->dev_attrs[i]); i++) | ||
317 | device_remove_file(dev, &class->dev_attrs[i]); | ||
318 | } | ||
319 | 404 | ||
320 | if (type && type->attrs) { | 405 | if (type) |
321 | for (i = 0; attr_name(type->attrs[i]); i++) | 406 | device_remove_groups(dev, type->groups); |
322 | device_remove_file(dev, &type->attrs[i]); | 407 | |
323 | } | 408 | if (class) |
409 | device_remove_attributes(dev, class->dev_attrs); | ||
324 | } | 410 | } |
325 | 411 | ||
326 | 412 | ||
@@ -394,9 +480,10 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr) | |||
394 | EXPORT_SYMBOL_GPL(device_remove_bin_file); | 480 | EXPORT_SYMBOL_GPL(device_remove_bin_file); |
395 | 481 | ||
396 | /** | 482 | /** |
397 | * device_schedule_callback - helper to schedule a callback for a device | 483 | * device_schedule_callback_owner - helper to schedule a callback for a device |
398 | * @dev: device. | 484 | * @dev: device. |
399 | * @func: callback function to invoke later. | 485 | * @func: callback function to invoke later. |
486 | * @owner: module owning the callback routine | ||
400 | * | 487 | * |
401 | * Attribute methods must not unregister themselves or their parent device | 488 | * Attribute methods must not unregister themselves or their parent device |
402 | * (which would amount to the same thing). Attempts to do so will deadlock, | 489 | * (which would amount to the same thing). Attempts to do so will deadlock, |
@@ -407,20 +494,23 @@ EXPORT_SYMBOL_GPL(device_remove_bin_file); | |||
407 | * argument in the workqueue's process context. @dev will be pinned until | 494 | * argument in the workqueue's process context. @dev will be pinned until |
408 | * @func returns. | 495 | * @func returns. |
409 | * | 496 | * |
497 | * This routine is usually called via the inline device_schedule_callback(), | ||
498 | * which automatically sets @owner to THIS_MODULE. | ||
499 | * | ||
410 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | 500 | * Returns 0 if the request was submitted, -ENOMEM if storage could not |
411 | * be allocated. | 501 | * be allocated, -ENODEV if a reference to @owner isn't available. |
412 | * | 502 | * |
413 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an | 503 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an |
414 | * underlying sysfs routine (since it is intended for use by attribute | 504 | * underlying sysfs routine (since it is intended for use by attribute |
415 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. | 505 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. |
416 | */ | 506 | */ |
417 | int device_schedule_callback(struct device *dev, | 507 | int device_schedule_callback_owner(struct device *dev, |
418 | void (*func)(struct device *)) | 508 | void (*func)(struct device *), struct module *owner) |
419 | { | 509 | { |
420 | return sysfs_schedule_callback(&dev->kobj, | 510 | return sysfs_schedule_callback(&dev->kobj, |
421 | (void (*)(void *)) func, dev); | 511 | (void (*)(void *)) func, dev, owner); |
422 | } | 512 | } |
423 | EXPORT_SYMBOL_GPL(device_schedule_callback); | 513 | EXPORT_SYMBOL_GPL(device_schedule_callback_owner); |
424 | 514 | ||
425 | static void klist_children_get(struct klist_node *n) | 515 | static void klist_children_get(struct klist_node *n) |
426 | { | 516 | { |
@@ -477,34 +567,58 @@ static struct kobject * get_device_parent(struct device *dev, | |||
477 | return NULL; | 567 | return NULL; |
478 | } | 568 | } |
479 | #else | 569 | #else |
480 | static struct kobject * virtual_device_parent(struct device *dev) | 570 | static struct kobject *virtual_device_parent(struct device *dev) |
481 | { | 571 | { |
482 | if (!dev->class) | 572 | static struct kobject *virtual_dir = NULL; |
483 | return ERR_PTR(-ENODEV); | ||
484 | 573 | ||
485 | if (!dev->class->virtual_dir) { | 574 | if (!virtual_dir) |
486 | static struct kobject *virtual_dir = NULL; | 575 | virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual"); |
487 | 576 | ||
488 | if (!virtual_dir) | 577 | return virtual_dir; |
489 | virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual"); | ||
490 | dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); | ||
491 | } | ||
492 | |||
493 | return dev->class->virtual_dir; | ||
494 | } | 578 | } |
495 | 579 | ||
496 | static struct kobject * get_device_parent(struct device *dev, | 580 | static struct kobject * get_device_parent(struct device *dev, |
497 | struct device *parent) | 581 | struct device *parent) |
498 | { | 582 | { |
499 | /* if this is a class device, and has no parent, create one */ | 583 | if (dev->class) { |
500 | if ((dev->class) && (parent == NULL)) { | 584 | struct kobject *kobj = NULL; |
501 | return virtual_device_parent(dev); | 585 | struct kobject *parent_kobj; |
502 | } else if (parent) | 586 | struct kobject *k; |
587 | |||
588 | /* | ||
589 | * If we have no parent, we live in "virtual". | ||
590 | * Class-devices with a bus-device as parent, live | ||
591 | * in a class-directory to prevent namespace collisions. | ||
592 | */ | ||
593 | if (parent == NULL) | ||
594 | parent_kobj = virtual_device_parent(dev); | ||
595 | else if (parent->class) | ||
596 | return &parent->kobj; | ||
597 | else | ||
598 | parent_kobj = &parent->kobj; | ||
599 | |||
600 | /* find our class-directory at the parent and reference it */ | ||
601 | spin_lock(&dev->class->class_dirs.list_lock); | ||
602 | list_for_each_entry(k, &dev->class->class_dirs.list, entry) | ||
603 | if (k->parent == parent_kobj) { | ||
604 | kobj = kobject_get(k); | ||
605 | break; | ||
606 | } | ||
607 | spin_unlock(&dev->class->class_dirs.list_lock); | ||
608 | if (kobj) | ||
609 | return kobj; | ||
610 | |||
611 | /* or create a new class-directory at the parent device */ | ||
612 | return kobject_kset_add_dir(&dev->class->class_dirs, | ||
613 | parent_kobj, dev->class->name); | ||
614 | } | ||
615 | |||
616 | if (parent) | ||
503 | return &parent->kobj; | 617 | return &parent->kobj; |
504 | return NULL; | 618 | return NULL; |
505 | } | 619 | } |
506 | |||
507 | #endif | 620 | #endif |
621 | |||
508 | static int setup_parent(struct device *dev, struct device *parent) | 622 | static int setup_parent(struct device *dev, struct device *parent) |
509 | { | 623 | { |
510 | struct kobject *kobj; | 624 | struct kobject *kobj; |
@@ -541,7 +655,6 @@ int device_add(struct device *dev) | |||
541 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); | 655 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); |
542 | 656 | ||
543 | parent = get_device(dev->parent); | 657 | parent = get_device(dev->parent); |
544 | |||
545 | error = setup_parent(dev, parent); | 658 | error = setup_parent(dev, parent); |
546 | if (error) | 659 | if (error) |
547 | goto Error; | 660 | goto Error; |
@@ -562,10 +675,11 @@ int device_add(struct device *dev) | |||
562 | BUS_NOTIFY_ADD_DEVICE, dev); | 675 | BUS_NOTIFY_ADD_DEVICE, dev); |
563 | 676 | ||
564 | dev->uevent_attr.attr.name = "uevent"; | 677 | dev->uevent_attr.attr.name = "uevent"; |
565 | dev->uevent_attr.attr.mode = S_IWUSR; | 678 | dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR; |
566 | if (dev->driver) | 679 | if (dev->driver) |
567 | dev->uevent_attr.attr.owner = dev->driver->owner; | 680 | dev->uevent_attr.attr.owner = dev->driver->owner; |
568 | dev->uevent_attr.store = store_uevent; | 681 | dev->uevent_attr.store = store_uevent; |
682 | dev->uevent_attr.show = show_uevent; | ||
569 | error = device_create_file(dev, &dev->uevent_attr); | 683 | error = device_create_file(dev, &dev->uevent_attr); |
570 | if (error) | 684 | if (error) |
571 | goto attrError; | 685 | goto attrError; |
@@ -614,16 +728,12 @@ int device_add(struct device *dev) | |||
614 | 728 | ||
615 | if ((error = device_add_attrs(dev))) | 729 | if ((error = device_add_attrs(dev))) |
616 | goto AttrsError; | 730 | goto AttrsError; |
617 | if ((error = device_add_groups(dev))) | ||
618 | goto GroupError; | ||
619 | if ((error = device_pm_add(dev))) | 731 | if ((error = device_pm_add(dev))) |
620 | goto PMError; | 732 | goto PMError; |
621 | if ((error = bus_add_device(dev))) | 733 | if ((error = bus_add_device(dev))) |
622 | goto BusError; | 734 | goto BusError; |
623 | if (!dev->uevent_suppress) | 735 | kobject_uevent(&dev->kobj, KOBJ_ADD); |
624 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 736 | bus_attach_device(dev); |
625 | if ((error = bus_attach_device(dev))) | ||
626 | goto AttachError; | ||
627 | if (parent) | 737 | if (parent) |
628 | klist_add_tail(&dev->knode_parent, &parent->klist_children); | 738 | klist_add_tail(&dev->knode_parent, &parent->klist_children); |
629 | 739 | ||
@@ -639,19 +749,15 @@ int device_add(struct device *dev) | |||
639 | up(&dev->class->sem); | 749 | up(&dev->class->sem); |
640 | } | 750 | } |
641 | Done: | 751 | Done: |
642 | kfree(class_name); | 752 | kfree(class_name); |
643 | put_device(dev); | 753 | put_device(dev); |
644 | return error; | 754 | return error; |
645 | AttachError: | ||
646 | bus_remove_device(dev); | ||
647 | BusError: | 755 | BusError: |
648 | device_pm_remove(dev); | 756 | device_pm_remove(dev); |
649 | PMError: | 757 | PMError: |
650 | if (dev->bus) | 758 | if (dev->bus) |
651 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | 759 | blocking_notifier_call_chain(&dev->bus->bus_notifier, |
652 | BUS_NOTIFY_DEL_DEVICE, dev); | 760 | BUS_NOTIFY_DEL_DEVICE, dev); |
653 | device_remove_groups(dev); | ||
654 | GroupError: | ||
655 | device_remove_attrs(dev); | 761 | device_remove_attrs(dev); |
656 | AttrsError: | 762 | AttrsError: |
657 | if (dev->devt_attr) { | 763 | if (dev->devt_attr) { |
@@ -677,15 +783,6 @@ int device_add(struct device *dev) | |||
677 | #endif | 783 | #endif |
678 | sysfs_remove_link(&dev->kobj, "device"); | 784 | sysfs_remove_link(&dev->kobj, "device"); |
679 | } | 785 | } |
680 | |||
681 | down(&dev->class->sem); | ||
682 | /* notify any interfaces that the device is now gone */ | ||
683 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | ||
684 | if (class_intf->remove_dev) | ||
685 | class_intf->remove_dev(dev, class_intf); | ||
686 | /* remove the device from the class list */ | ||
687 | list_del_init(&dev->node); | ||
688 | up(&dev->class->sem); | ||
689 | } | 786 | } |
690 | ueventattrError: | 787 | ueventattrError: |
691 | device_remove_file(dev, &dev->uevent_attr); | 788 | device_remove_file(dev, &dev->uevent_attr); |
@@ -796,9 +893,33 @@ void device_del(struct device * dev) | |||
796 | /* remove the device from the class list */ | 893 | /* remove the device from the class list */ |
797 | list_del_init(&dev->node); | 894 | list_del_init(&dev->node); |
798 | up(&dev->class->sem); | 895 | up(&dev->class->sem); |
896 | |||
897 | /* If we live in a parent class-directory, unreference it */ | ||
898 | if (dev->kobj.parent->kset == &dev->class->class_dirs) { | ||
899 | struct device *d; | ||
900 | int other = 0; | ||
901 | |||
902 | /* | ||
903 | * if we are the last child of our class, delete | ||
904 | * our class-directory at this parent | ||
905 | */ | ||
906 | down(&dev->class->sem); | ||
907 | list_for_each_entry(d, &dev->class->devices, node) { | ||
908 | if (d == dev) | ||
909 | continue; | ||
910 | if (d->kobj.parent == dev->kobj.parent) { | ||
911 | other = 1; | ||
912 | break; | ||
913 | } | ||
914 | } | ||
915 | if (!other) | ||
916 | kobject_del(dev->kobj.parent); | ||
917 | |||
918 | kobject_put(dev->kobj.parent); | ||
919 | up(&dev->class->sem); | ||
920 | } | ||
799 | } | 921 | } |
800 | device_remove_file(dev, &dev->uevent_attr); | 922 | device_remove_file(dev, &dev->uevent_attr); |
801 | device_remove_groups(dev); | ||
802 | device_remove_attrs(dev); | 923 | device_remove_attrs(dev); |
803 | bus_remove_device(dev); | 924 | bus_remove_device(dev); |
804 | 925 | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 6a48824e43ff..18dba8e78da7 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -94,19 +94,11 @@ int device_bind_driver(struct device *dev) | |||
94 | return ret; | 94 | return ret; |
95 | } | 95 | } |
96 | 96 | ||
97 | struct stupid_thread_structure { | ||
98 | struct device_driver *drv; | ||
99 | struct device *dev; | ||
100 | }; | ||
101 | |||
102 | static atomic_t probe_count = ATOMIC_INIT(0); | 97 | static atomic_t probe_count = ATOMIC_INIT(0); |
103 | static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); | 98 | static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); |
104 | 99 | ||
105 | static int really_probe(void *void_data) | 100 | static int really_probe(struct device *dev, struct device_driver *drv) |
106 | { | 101 | { |
107 | struct stupid_thread_structure *data = void_data; | ||
108 | struct device_driver *drv = data->drv; | ||
109 | struct device *dev = data->dev; | ||
110 | int ret = 0; | 102 | int ret = 0; |
111 | 103 | ||
112 | atomic_inc(&probe_count); | 104 | atomic_inc(&probe_count); |
@@ -154,7 +146,6 @@ probe_failed: | |||
154 | */ | 146 | */ |
155 | ret = 0; | 147 | ret = 0; |
156 | done: | 148 | done: |
157 | kfree(data); | ||
158 | atomic_dec(&probe_count); | 149 | atomic_dec(&probe_count); |
159 | wake_up(&probe_waitqueue); | 150 | wake_up(&probe_waitqueue); |
160 | return ret; | 151 | return ret; |
@@ -186,16 +177,14 @@ int driver_probe_done(void) | |||
186 | * format of the ID structures, nor what is to be considered a match and | 177 | * format of the ID structures, nor what is to be considered a match and |
187 | * what is not. | 178 | * what is not. |
188 | * | 179 | * |
189 | * This function returns 1 if a match is found, an error if one occurs | 180 | * This function returns 1 if a match is found, -ENODEV if the device is |
190 | * (that is not -ENODEV or -ENXIO), and 0 otherwise. | 181 | * not registered, and 0 otherwise. |
191 | * | 182 | * |
192 | * This function must be called with @dev->sem held. When called for a | 183 | * This function must be called with @dev->sem held. When called for a |
193 | * USB interface, @dev->parent->sem must be held as well. | 184 | * USB interface, @dev->parent->sem must be held as well. |
194 | */ | 185 | */ |
195 | int driver_probe_device(struct device_driver * drv, struct device * dev) | 186 | int driver_probe_device(struct device_driver * drv, struct device * dev) |
196 | { | 187 | { |
197 | struct stupid_thread_structure *data; | ||
198 | struct task_struct *probe_task; | ||
199 | int ret = 0; | 188 | int ret = 0; |
200 | 189 | ||
201 | if (!device_is_registered(dev)) | 190 | if (!device_is_registered(dev)) |
@@ -206,19 +195,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
206 | pr_debug("%s: Matched Device %s with Driver %s\n", | 195 | pr_debug("%s: Matched Device %s with Driver %s\n", |
207 | drv->bus->name, dev->bus_id, drv->name); | 196 | drv->bus->name, dev->bus_id, drv->name); |
208 | 197 | ||
209 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 198 | ret = really_probe(dev, drv); |
210 | if (!data) | ||
211 | return -ENOMEM; | ||
212 | data->drv = drv; | ||
213 | data->dev = dev; | ||
214 | |||
215 | if (drv->multithread_probe) { | ||
216 | probe_task = kthread_run(really_probe, data, | ||
217 | "probe-%s", dev->bus_id); | ||
218 | if (IS_ERR(probe_task)) | ||
219 | ret = really_probe(data); | ||
220 | } else | ||
221 | ret = really_probe(data); | ||
222 | 199 | ||
223 | done: | 200 | done: |
224 | return ret; | 201 | return ret; |
@@ -230,30 +207,57 @@ static int __device_attach(struct device_driver * drv, void * data) | |||
230 | return driver_probe_device(drv, dev); | 207 | return driver_probe_device(drv, dev); |
231 | } | 208 | } |
232 | 209 | ||
210 | static int device_probe_drivers(void *data) | ||
211 | { | ||
212 | struct device *dev = data; | ||
213 | int ret = 0; | ||
214 | |||
215 | if (dev->bus) { | ||
216 | down(&dev->sem); | ||
217 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); | ||
218 | up(&dev->sem); | ||
219 | } | ||
220 | return ret; | ||
221 | } | ||
222 | |||
233 | /** | 223 | /** |
234 | * device_attach - try to attach device to a driver. | 224 | * device_attach - try to attach device to a driver. |
235 | * @dev: device. | 225 | * @dev: device. |
236 | * | 226 | * |
237 | * Walk the list of drivers that the bus has and call | 227 | * Walk the list of drivers that the bus has and call |
238 | * driver_probe_device() for each pair. If a compatible | 228 | * driver_probe_device() for each pair. If a compatible |
239 | * pair is found, break out and return. | 229 | * pair is found, break out and return. If the bus specifies |
230 | * multithreaded probing, walking the list of drivers is done | ||
231 | * on a probing thread. | ||
240 | * | 232 | * |
241 | * Returns 1 if the device was bound to a driver; | 233 | * Returns 1 if the device was bound to a driver; |
242 | * 0 if no matching device was found; error code otherwise. | 234 | * 0 if no matching device was found or multithreaded probing is done; |
235 | * -ENODEV if the device is not registered. | ||
243 | * | 236 | * |
244 | * When called for a USB interface, @dev->parent->sem must be held. | 237 | * When called for a USB interface, @dev->parent->sem must be held. |
245 | */ | 238 | */ |
246 | int device_attach(struct device * dev) | 239 | int device_attach(struct device * dev) |
247 | { | 240 | { |
248 | int ret = 0; | 241 | int ret = 0; |
242 | struct task_struct *probe_task = ERR_PTR(-ENOMEM); | ||
249 | 243 | ||
250 | down(&dev->sem); | 244 | down(&dev->sem); |
251 | if (dev->driver) { | 245 | if (dev->driver) { |
252 | ret = device_bind_driver(dev); | 246 | ret = device_bind_driver(dev); |
253 | if (ret == 0) | 247 | if (ret == 0) |
254 | ret = 1; | 248 | ret = 1; |
255 | } else | 249 | else { |
256 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); | 250 | dev->driver = NULL; |
251 | ret = 0; | ||
252 | } | ||
253 | } else { | ||
254 | if (dev->bus->multithread_probe) | ||
255 | probe_task = kthread_run(device_probe_drivers, dev, | ||
256 | "probe-%s", dev->bus_id); | ||
257 | if(IS_ERR(probe_task)) | ||
258 | ret = bus_for_each_drv(dev->bus, NULL, dev, | ||
259 | __device_attach); | ||
260 | } | ||
257 | up(&dev->sem); | 261 | up(&dev->sem); |
258 | return ret; | 262 | return ret; |
259 | } | 263 | } |
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index cd467c9f33b3..9406259754ad 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c | |||
@@ -37,7 +37,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */ | |||
37 | 37 | ||
38 | #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) | 38 | #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) |
39 | 39 | ||
40 | static DECLARE_MUTEX (pools_lock); | 40 | static DEFINE_MUTEX (pools_lock); |
41 | 41 | ||
42 | static ssize_t | 42 | static ssize_t |
43 | show_pools (struct device *dev, struct device_attribute *attr, char *buf) | 43 | show_pools (struct device *dev, struct device_attribute *attr, char *buf) |
@@ -55,7 +55,7 @@ show_pools (struct device *dev, struct device_attribute *attr, char *buf) | |||
55 | size -= temp; | 55 | size -= temp; |
56 | next += temp; | 56 | next += temp; |
57 | 57 | ||
58 | down (&pools_lock); | 58 | mutex_lock(&pools_lock); |
59 | list_for_each_entry(pool, &dev->dma_pools, pools) { | 59 | list_for_each_entry(pool, &dev->dma_pools, pools) { |
60 | unsigned pages = 0; | 60 | unsigned pages = 0; |
61 | unsigned blocks = 0; | 61 | unsigned blocks = 0; |
@@ -73,7 +73,7 @@ show_pools (struct device *dev, struct device_attribute *attr, char *buf) | |||
73 | size -= temp; | 73 | size -= temp; |
74 | next += temp; | 74 | next += temp; |
75 | } | 75 | } |
76 | up (&pools_lock); | 76 | mutex_unlock(&pools_lock); |
77 | 77 | ||
78 | return PAGE_SIZE - size; | 78 | return PAGE_SIZE - size; |
79 | } | 79 | } |
@@ -143,7 +143,7 @@ dma_pool_create (const char *name, struct device *dev, | |||
143 | if (dev) { | 143 | if (dev) { |
144 | int ret; | 144 | int ret; |
145 | 145 | ||
146 | down (&pools_lock); | 146 | mutex_lock(&pools_lock); |
147 | if (list_empty (&dev->dma_pools)) | 147 | if (list_empty (&dev->dma_pools)) |
148 | ret = device_create_file (dev, &dev_attr_pools); | 148 | ret = device_create_file (dev, &dev_attr_pools); |
149 | else | 149 | else |
@@ -155,7 +155,7 @@ dma_pool_create (const char *name, struct device *dev, | |||
155 | kfree(retval); | 155 | kfree(retval); |
156 | retval = NULL; | 156 | retval = NULL; |
157 | } | 157 | } |
158 | up (&pools_lock); | 158 | mutex_unlock(&pools_lock); |
159 | } else | 159 | } else |
160 | INIT_LIST_HEAD (&retval->pools); | 160 | INIT_LIST_HEAD (&retval->pools); |
161 | 161 | ||
@@ -231,11 +231,11 @@ pool_free_page (struct dma_pool *pool, struct dma_page *page) | |||
231 | void | 231 | void |
232 | dma_pool_destroy (struct dma_pool *pool) | 232 | dma_pool_destroy (struct dma_pool *pool) |
233 | { | 233 | { |
234 | down (&pools_lock); | 234 | mutex_lock(&pools_lock); |
235 | list_del (&pool->pools); | 235 | list_del (&pool->pools); |
236 | if (pool->dev && list_empty (&pool->dev->dma_pools)) | 236 | if (pool->dev && list_empty (&pool->dev->dma_pools)) |
237 | device_remove_file (pool->dev, &dev_attr_pools); | 237 | device_remove_file (pool->dev, &dev_attr_pools); |
238 | up (&pools_lock); | 238 | mutex_unlock(&pools_lock); |
239 | 239 | ||
240 | while (!list_empty (&pool->page_list)) { | 240 | while (!list_empty (&pool->page_list)) { |
241 | struct dma_page *page; | 241 | struct dma_page *page; |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 082bfded3854..eb11475293ed 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -149,10 +149,6 @@ void put_driver(struct device_driver * drv) | |||
149 | * We pass off most of the work to the bus_add_driver() call, | 149 | * We pass off most of the work to the bus_add_driver() call, |
150 | * since most of the things we have to do deal with the bus | 150 | * since most of the things we have to do deal with the bus |
151 | * structures. | 151 | * structures. |
152 | * | ||
153 | * The one interesting aspect is that we setup @drv->unloaded | ||
154 | * as a completion that gets complete when the driver reference | ||
155 | * count reaches 0. | ||
156 | */ | 152 | */ |
157 | int driver_register(struct device_driver * drv) | 153 | int driver_register(struct device_driver * drv) |
158 | { | 154 | { |
@@ -162,35 +158,19 @@ int driver_register(struct device_driver * drv) | |||
162 | printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); | 158 | printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); |
163 | } | 159 | } |
164 | klist_init(&drv->klist_devices, NULL, NULL); | 160 | klist_init(&drv->klist_devices, NULL, NULL); |
165 | init_completion(&drv->unloaded); | ||
166 | return bus_add_driver(drv); | 161 | return bus_add_driver(drv); |
167 | } | 162 | } |
168 | 163 | ||
169 | |||
170 | /** | 164 | /** |
171 | * driver_unregister - remove driver from system. | 165 | * driver_unregister - remove driver from system. |
172 | * @drv: driver. | 166 | * @drv: driver. |
173 | * | 167 | * |
174 | * Again, we pass off most of the work to the bus-level call. | 168 | * Again, we pass off most of the work to the bus-level call. |
175 | * | ||
176 | * Though, once that is done, we wait until @drv->unloaded is completed. | ||
177 | * This will block until the driver refcount reaches 0, and it is | ||
178 | * released. Only modular drivers will call this function, and we | ||
179 | * have to guarantee that it won't complete, letting the driver | ||
180 | * unload until all references are gone. | ||
181 | */ | 169 | */ |
182 | 170 | ||
183 | void driver_unregister(struct device_driver * drv) | 171 | void driver_unregister(struct device_driver * drv) |
184 | { | 172 | { |
185 | bus_remove_driver(drv); | 173 | bus_remove_driver(drv); |
186 | /* | ||
187 | * If the driver is a module, we are probably in | ||
188 | * the module unload path, and we want to wait | ||
189 | * for everything to unload before we can actually | ||
190 | * finish the unload. | ||
191 | */ | ||
192 | if (drv->owner) | ||
193 | wait_for_completion(&drv->unloaded); | ||
194 | } | 174 | } |
195 | 175 | ||
196 | /** | 176 | /** |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c0a979a5074b..97ab5bd1c4d6 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -31,8 +31,6 @@ enum { | |||
31 | FW_STATUS_LOADING, | 31 | FW_STATUS_LOADING, |
32 | FW_STATUS_DONE, | 32 | FW_STATUS_DONE, |
33 | FW_STATUS_ABORT, | 33 | FW_STATUS_ABORT, |
34 | FW_STATUS_READY, | ||
35 | FW_STATUS_READY_NOHOTPLUG, | ||
36 | }; | 34 | }; |
37 | 35 | ||
38 | static int loading_timeout = 60; /* In seconds */ | 36 | static int loading_timeout = 60; /* In seconds */ |
@@ -96,9 +94,6 @@ static int firmware_uevent(struct device *dev, char **envp, int num_envp, | |||
96 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); | 94 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
97 | int i = 0, len = 0; | 95 | int i = 0, len = 0; |
98 | 96 | ||
99 | if (!test_bit(FW_STATUS_READY, &fw_priv->status)) | ||
100 | return -ENODEV; | ||
101 | |||
102 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 97 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, |
103 | "FIRMWARE=%s", fw_priv->fw_id)) | 98 | "FIRMWARE=%s", fw_priv->fw_id)) |
104 | return -ENOMEM; | 99 | return -ENOMEM; |
@@ -333,6 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, | |||
333 | f_dev->parent = device; | 328 | f_dev->parent = device; |
334 | f_dev->class = &firmware_class; | 329 | f_dev->class = &firmware_class; |
335 | dev_set_drvdata(f_dev, fw_priv); | 330 | dev_set_drvdata(f_dev, fw_priv); |
331 | f_dev->uevent_suppress = 1; | ||
336 | retval = device_register(f_dev); | 332 | retval = device_register(f_dev); |
337 | if (retval) { | 333 | if (retval) { |
338 | printk(KERN_ERR "%s: device_register failed\n", | 334 | printk(KERN_ERR "%s: device_register failed\n", |
@@ -382,9 +378,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, | |||
382 | } | 378 | } |
383 | 379 | ||
384 | if (uevent) | 380 | if (uevent) |
385 | set_bit(FW_STATUS_READY, &fw_priv->status); | 381 | f_dev->uevent_suppress = 0; |
386 | else | ||
387 | set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); | ||
388 | *dev_p = f_dev; | 382 | *dev_p = f_dev; |
389 | goto out; | 383 | goto out; |
390 | 384 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index bbbb973a9d3c..05dc8764e765 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -29,6 +29,9 @@ LIST_HEAD(dpm_off_irq); | |||
29 | DECLARE_MUTEX(dpm_sem); | 29 | DECLARE_MUTEX(dpm_sem); |
30 | DECLARE_MUTEX(dpm_list_sem); | 30 | DECLARE_MUTEX(dpm_list_sem); |
31 | 31 | ||
32 | int (*platform_enable_wakeup)(struct device *dev, int is_on); | ||
33 | |||
34 | |||
32 | /** | 35 | /** |
33 | * device_pm_set_parent - Specify power dependency. | 36 | * device_pm_set_parent - Specify power dependency. |
34 | * @dev: Device who needs power. | 37 | * @dev: Device who needs power. |
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 020be36705a6..a2c64188d713 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c | |||
@@ -26,7 +26,9 @@ int resume_device(struct device * dev) | |||
26 | 26 | ||
27 | TRACE_DEVICE(dev); | 27 | TRACE_DEVICE(dev); |
28 | TRACE_RESUME(0); | 28 | TRACE_RESUME(0); |
29 | |||
29 | down(&dev->sem); | 30 | down(&dev->sem); |
31 | |||
30 | if (dev->power.pm_parent | 32 | if (dev->power.pm_parent |
31 | && dev->power.pm_parent->power.power_state.event) { | 33 | && dev->power.pm_parent->power.power_state.event) { |
32 | dev_err(dev, "PM: resume from %d, parent %s still %d\n", | 34 | dev_err(dev, "PM: resume from %d, parent %s still %d\n", |
@@ -34,15 +36,24 @@ int resume_device(struct device * dev) | |||
34 | dev->power.pm_parent->bus_id, | 36 | dev->power.pm_parent->bus_id, |
35 | dev->power.pm_parent->power.power_state.event); | 37 | dev->power.pm_parent->power.power_state.event); |
36 | } | 38 | } |
39 | |||
37 | if (dev->bus && dev->bus->resume) { | 40 | if (dev->bus && dev->bus->resume) { |
38 | dev_dbg(dev,"resuming\n"); | 41 | dev_dbg(dev,"resuming\n"); |
39 | error = dev->bus->resume(dev); | 42 | error = dev->bus->resume(dev); |
40 | } | 43 | } |
41 | if (dev->class && dev->class->resume) { | 44 | |
45 | if (!error && dev->type && dev->type->resume) { | ||
46 | dev_dbg(dev,"resuming\n"); | ||
47 | error = dev->type->resume(dev); | ||
48 | } | ||
49 | |||
50 | if (!error && dev->class && dev->class->resume) { | ||
42 | dev_dbg(dev,"class resume\n"); | 51 | dev_dbg(dev,"class resume\n"); |
43 | error = dev->class->resume(dev); | 52 | error = dev->class->resume(dev); |
44 | } | 53 | } |
54 | |||
45 | up(&dev->sem); | 55 | up(&dev->sem); |
56 | |||
46 | TRACE_RESUME(error); | 57 | TRACE_RESUME(error); |
47 | return error; | 58 | return error; |
48 | } | 59 | } |
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index 3483ae4d57f5..58b6f77a1b34 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c | |||
@@ -36,7 +36,6 @@ void device_shutdown(void) | |||
36 | { | 36 | { |
37 | struct device * dev, *devn; | 37 | struct device * dev, *devn; |
38 | 38 | ||
39 | down_write(&devices_subsys.rwsem); | ||
40 | list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list, | 39 | list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list, |
41 | kobj.entry) { | 40 | kobj.entry) { |
42 | if (dev->bus && dev->bus->shutdown) { | 41 | if (dev->bus && dev->bus->shutdown) { |
@@ -47,7 +46,6 @@ void device_shutdown(void) | |||
47 | dev->driver->shutdown(dev); | 46 | dev->driver->shutdown(dev); |
48 | } | 47 | } |
49 | } | 48 | } |
50 | up_write(&devices_subsys.rwsem); | ||
51 | 49 | ||
52 | sysdev_shutdown(); | 50 | sysdev_shutdown(); |
53 | } | 51 | } |
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index ece136bf97e3..42d2b86ba765 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c | |||
@@ -78,6 +78,18 @@ int suspend_device(struct device * dev, pm_message_t state) | |||
78 | suspend_report_result(dev->class->suspend, error); | 78 | suspend_report_result(dev->class->suspend, error); |
79 | } | 79 | } |
80 | 80 | ||
81 | if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) { | ||
82 | dev_dbg(dev, "%s%s\n", | ||
83 | suspend_verb(state.event), | ||
84 | ((state.event == PM_EVENT_SUSPEND) | ||
85 | && device_may_wakeup(dev)) | ||
86 | ? ", may wakeup" | ||
87 | : "" | ||
88 | ); | ||
89 | error = dev->type->suspend(dev, state); | ||
90 | suspend_report_result(dev->type->suspend, error); | ||
91 | } | ||
92 | |||
81 | if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) { | 93 | if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) { |
82 | dev_dbg(dev, "%s%s\n", | 94 | dev_dbg(dev, "%s%s\n", |
83 | suspend_verb(state.event), | 95 | suspend_verb(state.event), |
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index afb71c66b6f3..a9e0b30fb1f2 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c | |||
@@ -310,14 +310,12 @@ static int proc_ide_read_driver | |||
310 | ide_driver_t *ide_drv; | 310 | ide_driver_t *ide_drv; |
311 | int len; | 311 | int len; |
312 | 312 | ||
313 | down_read(&dev->bus->subsys.rwsem); | ||
314 | if (dev->driver) { | 313 | if (dev->driver) { |
315 | ide_drv = container_of(dev->driver, ide_driver_t, gen_driver); | 314 | ide_drv = container_of(dev->driver, ide_driver_t, gen_driver); |
316 | len = sprintf(page, "%s version %s\n", | 315 | len = sprintf(page, "%s version %s\n", |
317 | dev->driver->name, ide_drv->version); | 316 | dev->driver->name, ide_drv->version); |
318 | } else | 317 | } else |
319 | len = sprintf(page, "ide-default version 0.9.newide\n"); | 318 | len = sprintf(page, "ide-default version 0.9.newide\n"); |
320 | up_read(&dev->bus->subsys.rwsem); | ||
321 | PROC_IDE_READ_RETURN(page,start,off,count,eof,len); | 319 | PROC_IDE_READ_RETURN(page,start,off,count,eof,len); |
322 | } | 320 | } |
323 | 321 | ||
@@ -327,7 +325,6 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) | |||
327 | int ret = 1; | 325 | int ret = 1; |
328 | int err; | 326 | int err; |
329 | 327 | ||
330 | down_write(&dev->bus->subsys.rwsem); | ||
331 | device_release_driver(dev); | 328 | device_release_driver(dev); |
332 | /* FIXME: device can still be in use by previous driver */ | 329 | /* FIXME: device can still be in use by previous driver */ |
333 | strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); | 330 | strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); |
@@ -345,7 +342,6 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) | |||
345 | } | 342 | } |
346 | if (dev->driver && !strcmp(dev->driver->name, driver)) | 343 | if (dev->driver && !strcmp(dev->driver->name, driver)) |
347 | ret = 0; | 344 | ret = 0; |
348 | up_write(&dev->bus->subsys.rwsem); | ||
349 | 345 | ||
350 | return ret; | 346 | return ret; |
351 | } | 347 | } |
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index c5ace190bfe6..dbeba45a031e 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -370,9 +370,7 @@ static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute | |||
370 | 370 | ||
371 | if (state == 1) { | 371 | if (state == 1) { |
372 | ud->ignore_driver = 1; | 372 | ud->ignore_driver = 1; |
373 | down_write(&ieee1394_bus_type.subsys.rwsem); | ||
374 | device_release_driver(dev); | 373 | device_release_driver(dev); |
375 | up_write(&ieee1394_bus_type.subsys.rwsem); | ||
376 | } else if (state == 0) | 374 | } else if (state == 0) |
377 | ud->ignore_driver = 0; | 375 | ud->ignore_driver = 0; |
378 | 376 | ||
@@ -1163,6 +1161,7 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, | |||
1163 | struct unit_directory *ud; | 1161 | struct unit_directory *ud; |
1164 | int i = 0; | 1162 | int i = 0; |
1165 | int length = 0; | 1163 | int length = 0; |
1164 | int retval = 0; | ||
1166 | /* ieee1394:venNmoNspNverN */ | 1165 | /* ieee1394:venNmoNspNverN */ |
1167 | char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; | 1166 | char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; |
1168 | 1167 | ||
@@ -1176,14 +1175,11 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, | |||
1176 | 1175 | ||
1177 | #define PUT_ENVP(fmt,val) \ | 1176 | #define PUT_ENVP(fmt,val) \ |
1178 | do { \ | 1177 | do { \ |
1179 | int printed; \ | 1178 | retval = add_uevent_var(envp, num_envp, &i, \ |
1180 | envp[i++] = buffer; \ | 1179 | buffer, buffer_size, &length, \ |
1181 | printed = snprintf(buffer, buffer_size - length, \ | 1180 | fmt, val); \ |
1182 | fmt, val); \ | 1181 | if (retval) \ |
1183 | if ((buffer_size - (length+printed) <= 0) || (i >= num_envp)) \ | 1182 | return retval; \ |
1184 | return -ENOMEM; \ | ||
1185 | length += printed+1; \ | ||
1186 | buffer += printed+1; \ | ||
1187 | } while (0) | 1183 | } while (0) |
1188 | 1184 | ||
1189 | PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id); | 1185 | PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id); |
@@ -1393,12 +1389,10 @@ static void nodemgr_suspend_ne(struct node_entry *ne) | |||
1393 | if (ud->ne != ne) | 1389 | if (ud->ne != ne) |
1394 | continue; | 1390 | continue; |
1395 | 1391 | ||
1396 | down_write(&ieee1394_bus_type.subsys.rwsem); | ||
1397 | if (ud->device.driver && | 1392 | if (ud->device.driver && |
1398 | (!ud->device.driver->suspend || | 1393 | (!ud->device.driver->suspend || |
1399 | ud->device.driver->suspend(&ud->device, PMSG_SUSPEND))) | 1394 | ud->device.driver->suspend(&ud->device, PMSG_SUSPEND))) |
1400 | device_release_driver(&ud->device); | 1395 | device_release_driver(&ud->device); |
1401 | up_write(&ieee1394_bus_type.subsys.rwsem); | ||
1402 | } | 1396 | } |
1403 | up(&nodemgr_ud_class.sem); | 1397 | up(&nodemgr_ud_class.sem); |
1404 | } | 1398 | } |
@@ -1418,10 +1412,8 @@ static void nodemgr_resume_ne(struct node_entry *ne) | |||
1418 | if (ud->ne != ne) | 1412 | if (ud->ne != ne) |
1419 | continue; | 1413 | continue; |
1420 | 1414 | ||
1421 | down_read(&ieee1394_bus_type.subsys.rwsem); | ||
1422 | if (ud->device.driver && ud->device.driver->resume) | 1415 | if (ud->device.driver && ud->device.driver->resume) |
1423 | ud->device.driver->resume(&ud->device); | 1416 | ud->device.driver->resume(&ud->device); |
1424 | up_read(&ieee1394_bus_type.subsys.rwsem); | ||
1425 | } | 1417 | } |
1426 | up(&nodemgr_ud_class.sem); | 1418 | up(&nodemgr_ud_class.sem); |
1427 | 1419 | ||
@@ -1442,7 +1434,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne) | |||
1442 | if (ud->ne != ne) | 1434 | if (ud->ne != ne) |
1443 | continue; | 1435 | continue; |
1444 | 1436 | ||
1445 | down_write(&ieee1394_bus_type.subsys.rwsem); | ||
1446 | if (ud->device.driver) { | 1437 | if (ud->device.driver) { |
1447 | pdrv = container_of(ud->device.driver, | 1438 | pdrv = container_of(ud->device.driver, |
1448 | struct hpsb_protocol_driver, | 1439 | struct hpsb_protocol_driver, |
@@ -1450,7 +1441,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne) | |||
1450 | if (pdrv->update && pdrv->update(ud)) | 1441 | if (pdrv->update && pdrv->update(ud)) |
1451 | device_release_driver(&ud->device); | 1442 | device_release_driver(&ud->device); |
1452 | } | 1443 | } |
1453 | up_write(&ieee1394_bus_type.subsys.rwsem); | ||
1454 | } | 1444 | } |
1455 | up(&nodemgr_ud_class.sem); | 1445 | up(&nodemgr_ud_class.sem); |
1456 | } | 1446 | } |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index a00fe470a829..bd686a2a517d 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -190,16 +190,14 @@ static void gameport_run_poll_handler(unsigned long d) | |||
190 | * Basic gameport -> driver core mappings | 190 | * Basic gameport -> driver core mappings |
191 | */ | 191 | */ |
192 | 192 | ||
193 | static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv) | 193 | static int gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv) |
194 | { | 194 | { |
195 | int error; | 195 | int error; |
196 | 196 | ||
197 | down_write(&gameport_bus.subsys.rwsem); | ||
198 | |||
199 | gameport->dev.driver = &drv->driver; | 197 | gameport->dev.driver = &drv->driver; |
200 | if (drv->connect(gameport, drv)) { | 198 | if (drv->connect(gameport, drv)) { |
201 | gameport->dev.driver = NULL; | 199 | gameport->dev.driver = NULL; |
202 | goto out; | 200 | return -ENODEV; |
203 | } | 201 | } |
204 | 202 | ||
205 | error = device_bind_driver(&gameport->dev); | 203 | error = device_bind_driver(&gameport->dev); |
@@ -211,31 +209,21 @@ static void gameport_bind_driver(struct gameport *gameport, struct gameport_driv | |||
211 | drv->description, error); | 209 | drv->description, error); |
212 | drv->disconnect(gameport); | 210 | drv->disconnect(gameport); |
213 | gameport->dev.driver = NULL; | 211 | gameport->dev.driver = NULL; |
214 | goto out; | 212 | return error; |
215 | } | 213 | } |
216 | 214 | ||
217 | out: | 215 | return 0; |
218 | up_write(&gameport_bus.subsys.rwsem); | ||
219 | } | ||
220 | |||
221 | static void gameport_release_driver(struct gameport *gameport) | ||
222 | { | ||
223 | down_write(&gameport_bus.subsys.rwsem); | ||
224 | device_release_driver(&gameport->dev); | ||
225 | up_write(&gameport_bus.subsys.rwsem); | ||
226 | } | 216 | } |
227 | 217 | ||
228 | static void gameport_find_driver(struct gameport *gameport) | 218 | static void gameport_find_driver(struct gameport *gameport) |
229 | { | 219 | { |
230 | int error; | 220 | int error; |
231 | 221 | ||
232 | down_write(&gameport_bus.subsys.rwsem); | ||
233 | error = device_attach(&gameport->dev); | 222 | error = device_attach(&gameport->dev); |
234 | if (error < 0) | 223 | if (error < 0) |
235 | printk(KERN_WARNING | 224 | printk(KERN_WARNING |
236 | "gameport: device_attach() failed for %s (%s), error: %d\n", | 225 | "gameport: device_attach() failed for %s (%s), error: %d\n", |
237 | gameport->phys, gameport->name, error); | 226 | gameport->phys, gameport->name, error); |
238 | up_write(&gameport_bus.subsys.rwsem); | ||
239 | } | 227 | } |
240 | 228 | ||
241 | 229 | ||
@@ -483,13 +471,12 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut | |||
483 | { | 471 | { |
484 | struct gameport *gameport = to_gameport_port(dev); | 472 | struct gameport *gameport = to_gameport_port(dev); |
485 | struct device_driver *drv; | 473 | struct device_driver *drv; |
486 | int retval; | 474 | int error; |
487 | 475 | ||
488 | retval = mutex_lock_interruptible(&gameport_mutex); | 476 | error = mutex_lock_interruptible(&gameport_mutex); |
489 | if (retval) | 477 | if (error) |
490 | return retval; | 478 | return error; |
491 | 479 | ||
492 | retval = count; | ||
493 | if (!strncmp(buf, "none", count)) { | 480 | if (!strncmp(buf, "none", count)) { |
494 | gameport_disconnect_port(gameport); | 481 | gameport_disconnect_port(gameport); |
495 | } else if (!strncmp(buf, "reconnect", count)) { | 482 | } else if (!strncmp(buf, "reconnect", count)) { |
@@ -499,15 +486,15 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut | |||
499 | gameport_find_driver(gameport); | 486 | gameport_find_driver(gameport); |
500 | } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { | 487 | } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { |
501 | gameport_disconnect_port(gameport); | 488 | gameport_disconnect_port(gameport); |
502 | gameport_bind_driver(gameport, to_gameport_driver(drv)); | 489 | error = gameport_bind_driver(gameport, to_gameport_driver(drv)); |
503 | put_driver(drv); | 490 | put_driver(drv); |
504 | } else { | 491 | } else { |
505 | retval = -EINVAL; | 492 | error = -EINVAL; |
506 | } | 493 | } |
507 | 494 | ||
508 | mutex_unlock(&gameport_mutex); | 495 | mutex_unlock(&gameport_mutex); |
509 | 496 | ||
510 | return retval; | 497 | return error ? error : count; |
511 | } | 498 | } |
512 | 499 | ||
513 | static struct device_attribute gameport_device_attrs[] = { | 500 | static struct device_attribute gameport_device_attrs[] = { |
@@ -655,7 +642,7 @@ static void gameport_disconnect_port(struct gameport *gameport) | |||
655 | do { | 642 | do { |
656 | parent = s->parent; | 643 | parent = s->parent; |
657 | 644 | ||
658 | gameport_release_driver(s); | 645 | device_release_driver(&s->dev); |
659 | gameport_destroy_port(s); | 646 | gameport_destroy_port(s); |
660 | } while ((s = parent) != gameport); | 647 | } while ((s = parent) != gameport); |
661 | } | 648 | } |
@@ -663,7 +650,7 @@ static void gameport_disconnect_port(struct gameport *gameport) | |||
663 | /* | 650 | /* |
664 | * Ok, no children left, now disconnect this port | 651 | * Ok, no children left, now disconnect this port |
665 | */ | 652 | */ |
666 | gameport_release_driver(gameport); | 653 | device_release_driver(&gameport->dev); |
667 | } | 654 | } |
668 | 655 | ||
669 | void gameport_rescan(struct gameport *gameport) | 656 | void gameport_rescan(struct gameport *gameport) |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index a15e531ec755..5895202b972c 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -115,18 +115,18 @@ static int serio_match_port(const struct serio_device_id *ids, struct serio *ser | |||
115 | * Basic serio -> driver core mappings | 115 | * Basic serio -> driver core mappings |
116 | */ | 116 | */ |
117 | 117 | ||
118 | static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) | 118 | static int serio_bind_driver(struct serio *serio, struct serio_driver *drv) |
119 | { | 119 | { |
120 | int error; | 120 | int error; |
121 | 121 | ||
122 | down_write(&serio_bus.subsys.rwsem); | ||
123 | |||
124 | if (serio_match_port(drv->id_table, serio)) { | 122 | if (serio_match_port(drv->id_table, serio)) { |
123 | |||
125 | serio->dev.driver = &drv->driver; | 124 | serio->dev.driver = &drv->driver; |
126 | if (serio_connect_driver(serio, drv)) { | 125 | if (serio_connect_driver(serio, drv)) { |
127 | serio->dev.driver = NULL; | 126 | serio->dev.driver = NULL; |
128 | goto out; | 127 | return -ENODEV; |
129 | } | 128 | } |
129 | |||
130 | error = device_bind_driver(&serio->dev); | 130 | error = device_bind_driver(&serio->dev); |
131 | if (error) { | 131 | if (error) { |
132 | printk(KERN_WARNING | 132 | printk(KERN_WARNING |
@@ -136,31 +136,21 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) | |||
136 | drv->description, error); | 136 | drv->description, error); |
137 | serio_disconnect_driver(serio); | 137 | serio_disconnect_driver(serio); |
138 | serio->dev.driver = NULL; | 138 | serio->dev.driver = NULL; |
139 | goto out; | 139 | return error; |
140 | } | 140 | } |
141 | } | 141 | } |
142 | out: | 142 | return 0; |
143 | up_write(&serio_bus.subsys.rwsem); | ||
144 | } | ||
145 | |||
146 | static void serio_release_driver(struct serio *serio) | ||
147 | { | ||
148 | down_write(&serio_bus.subsys.rwsem); | ||
149 | device_release_driver(&serio->dev); | ||
150 | up_write(&serio_bus.subsys.rwsem); | ||
151 | } | 143 | } |
152 | 144 | ||
153 | static void serio_find_driver(struct serio *serio) | 145 | static void serio_find_driver(struct serio *serio) |
154 | { | 146 | { |
155 | int error; | 147 | int error; |
156 | 148 | ||
157 | down_write(&serio_bus.subsys.rwsem); | ||
158 | error = device_attach(&serio->dev); | 149 | error = device_attach(&serio->dev); |
159 | if (error < 0) | 150 | if (error < 0) |
160 | printk(KERN_WARNING | 151 | printk(KERN_WARNING |
161 | "serio: device_attach() failed for %s (%s), error: %d\n", | 152 | "serio: device_attach() failed for %s (%s), error: %d\n", |
162 | serio->phys, serio->name, error); | 153 | serio->phys, serio->name, error); |
163 | up_write(&serio_bus.subsys.rwsem); | ||
164 | } | 154 | } |
165 | 155 | ||
166 | 156 | ||
@@ -470,13 +460,12 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
470 | { | 460 | { |
471 | struct serio *serio = to_serio_port(dev); | 461 | struct serio *serio = to_serio_port(dev); |
472 | struct device_driver *drv; | 462 | struct device_driver *drv; |
473 | int retval; | 463 | int error; |
474 | 464 | ||
475 | retval = mutex_lock_interruptible(&serio_mutex); | 465 | error = mutex_lock_interruptible(&serio_mutex); |
476 | if (retval) | 466 | if (error) |
477 | return retval; | 467 | return error; |
478 | 468 | ||
479 | retval = count; | ||
480 | if (!strncmp(buf, "none", count)) { | 469 | if (!strncmp(buf, "none", count)) { |
481 | serio_disconnect_port(serio); | 470 | serio_disconnect_port(serio); |
482 | } else if (!strncmp(buf, "reconnect", count)) { | 471 | } else if (!strncmp(buf, "reconnect", count)) { |
@@ -486,15 +475,15 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
486 | serio_find_driver(serio); | 475 | serio_find_driver(serio); |
487 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { | 476 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { |
488 | serio_disconnect_port(serio); | 477 | serio_disconnect_port(serio); |
489 | serio_bind_driver(serio, to_serio_driver(drv)); | 478 | error = serio_bind_driver(serio, to_serio_driver(drv)); |
490 | put_driver(drv); | 479 | put_driver(drv); |
491 | } else { | 480 | } else { |
492 | retval = -EINVAL; | 481 | error = -EINVAL; |
493 | } | 482 | } |
494 | 483 | ||
495 | mutex_unlock(&serio_mutex); | 484 | mutex_unlock(&serio_mutex); |
496 | 485 | ||
497 | return retval; | 486 | return error ? error : count; |
498 | } | 487 | } |
499 | 488 | ||
500 | static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf) | 489 | static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -665,7 +654,7 @@ static void serio_disconnect_port(struct serio *serio) | |||
665 | do { | 654 | do { |
666 | parent = s->parent; | 655 | parent = s->parent; |
667 | 656 | ||
668 | serio_release_driver(s); | 657 | device_release_driver(&s->dev); |
669 | serio_destroy_port(s); | 658 | serio_destroy_port(s); |
670 | } while ((s = parent) != serio); | 659 | } while ((s = parent) != serio); |
671 | } | 660 | } |
@@ -673,7 +662,7 @@ static void serio_disconnect_port(struct serio *serio) | |||
673 | /* | 662 | /* |
674 | * Ok, no children left, now disconnect this port | 663 | * Ok, no children left, now disconnect this port |
675 | */ | 664 | */ |
676 | serio_release_driver(serio); | 665 | device_release_driver(&serio->dev); |
677 | } | 666 | } |
678 | 667 | ||
679 | void serio_rescan(struct serio *serio) | 668 | void serio_rescan(struct serio *serio) |
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index d32698b02d7f..e0e82d849d5f 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c | |||
@@ -86,31 +86,26 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, | |||
86 | { | 86 | { |
87 | struct mmc_card *card = dev_to_mmc_card(dev); | 87 | struct mmc_card *card = dev_to_mmc_card(dev); |
88 | char ccc[13]; | 88 | char ccc[13]; |
89 | int i = 0; | 89 | int retval = 0, i = 0, length = 0; |
90 | 90 | ||
91 | #define add_env(fmt,val) \ | 91 | #define add_env(fmt,val) do { \ |
92 | ({ \ | 92 | retval = add_uevent_var(envp, num_envp, &i, \ |
93 | int len, ret = -ENOMEM; \ | 93 | buf, buf_size, &length, \ |
94 | if (i < num_envp) { \ | 94 | fmt, val); \ |
95 | envp[i++] = buf; \ | 95 | if (retval) \ |
96 | len = snprintf(buf, buf_size, fmt, val) + 1; \ | 96 | return retval; \ |
97 | buf_size -= len; \ | 97 | } while (0); |
98 | buf += len; \ | ||
99 | if (buf_size >= 0) \ | ||
100 | ret = 0; \ | ||
101 | } \ | ||
102 | ret; \ | ||
103 | }) | ||
104 | 98 | ||
105 | for (i = 0; i < 12; i++) | 99 | for (i = 0; i < 12; i++) |
106 | ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0'; | 100 | ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0'; |
107 | ccc[12] = '\0'; | 101 | ccc[12] = '\0'; |
108 | 102 | ||
109 | i = 0; | ||
110 | add_env("MMC_CCC=%s", ccc); | 103 | add_env("MMC_CCC=%s", ccc); |
111 | add_env("MMC_MANFID=%06x", card->cid.manfid); | 104 | add_env("MMC_MANFID=%06x", card->cid.manfid); |
112 | add_env("MMC_NAME=%s", mmc_card_name(card)); | 105 | add_env("MMC_NAME=%s", mmc_card_name(card)); |
113 | add_env("MMC_OEMID=%04x", card->cid.oemid); | 106 | add_env("MMC_OEMID=%04x", card->cid.oemid); |
107 | #undef add_env | ||
108 | envp[i] = NULL; | ||
114 | 109 | ||
115 | return 0; | 110 | return 0; |
116 | } | 111 | } |
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index 66da91bb1388..68c99b4c5255 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c | |||
@@ -276,21 +276,15 @@ static int fixed_mdio_register_device(int number, int speed, int duplex) | |||
276 | artificially, we are binding the driver here by hand; | 276 | artificially, we are binding the driver here by hand; |
277 | it will be the same for all the fixed phys anyway. | 277 | it will be the same for all the fixed phys anyway. |
278 | */ | 278 | */ |
279 | down_write(&phydev->dev.bus->subsys.rwsem); | ||
280 | |||
281 | phydev->dev.driver = &fixed_mdio_driver.driver; | 279 | phydev->dev.driver = &fixed_mdio_driver.driver; |
282 | 280 | ||
283 | err = phydev->dev.driver->probe(&phydev->dev); | 281 | err = phydev->dev.driver->probe(&phydev->dev); |
284 | if(err < 0) { | 282 | if(err < 0) { |
285 | printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id); | 283 | printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id); |
286 | up_write(&phydev->dev.bus->subsys.rwsem); | ||
287 | goto probe_fail; | 284 | goto probe_fail; |
288 | } | 285 | } |
289 | 286 | ||
290 | err = device_bind_driver(&phydev->dev); | 287 | err = device_bind_driver(&phydev->dev); |
291 | |||
292 | up_write(&phydev->dev.bus->subsys.rwsem); | ||
293 | |||
294 | if (err) | 288 | if (err) |
295 | goto probe_fail; | 289 | goto probe_fail; |
296 | 290 | ||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 7d5b6d1838c8..8f01952c4850 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -208,16 +208,12 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
208 | * exist, and we should use the genphy driver. */ | 208 | * exist, and we should use the genphy driver. */ |
209 | if (NULL == d->driver) { | 209 | if (NULL == d->driver) { |
210 | int err; | 210 | int err; |
211 | down_write(&d->bus->subsys.rwsem); | ||
212 | d->driver = &genphy_driver.driver; | 211 | d->driver = &genphy_driver.driver; |
213 | 212 | ||
214 | err = d->driver->probe(d); | 213 | err = d->driver->probe(d); |
215 | |||
216 | if (err >= 0) | 214 | if (err >= 0) |
217 | err = device_bind_driver(d); | 215 | err = device_bind_driver(d); |
218 | 216 | ||
219 | up_write(&d->bus->subsys.rwsem); | ||
220 | |||
221 | if (err) | 217 | if (err) |
222 | return ERR_PTR(err); | 218 | return ERR_PTR(err); |
223 | } | 219 | } |
@@ -258,11 +254,8 @@ void phy_detach(struct phy_device *phydev) | |||
258 | * was using the generic driver), we unbind the device | 254 | * was using the generic driver), we unbind the device |
259 | * from the generic driver so that there's a chance a | 255 | * from the generic driver so that there's a chance a |
260 | * real driver could be loaded */ | 256 | * real driver could be loaded */ |
261 | if (phydev->dev.driver == &genphy_driver.driver) { | 257 | if (phydev->dev.driver == &genphy_driver.driver) |
262 | down_write(&phydev->dev.bus->subsys.rwsem); | ||
263 | device_release_driver(&phydev->dev); | 258 | device_release_driver(&phydev->dev); |
264 | up_write(&phydev->dev.bus->subsys.rwsem); | ||
265 | } | ||
266 | } | 259 | } |
267 | EXPORT_SYMBOL(phy_detach); | 260 | EXPORT_SYMBOL(phy_detach); |
268 | 261 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index a3c1755b2f28..39e80fcef4b3 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -434,11 +434,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
434 | drv->driver.mod_name = mod_name; | 434 | drv->driver.mod_name = mod_name; |
435 | drv->driver.kobj.ktype = &pci_driver_kobj_type; | 435 | drv->driver.kobj.ktype = &pci_driver_kobj_type; |
436 | 436 | ||
437 | if (pci_multithread_probe) | ||
438 | drv->driver.multithread_probe = pci_multithread_probe; | ||
439 | else | ||
440 | drv->driver.multithread_probe = drv->multithread_probe; | ||
441 | |||
442 | spin_lock_init(&drv->dynids.lock); | 437 | spin_lock_init(&drv->dynids.lock); |
443 | INIT_LIST_HEAD(&drv->dynids.list); | 438 | INIT_LIST_HEAD(&drv->dynids.list); |
444 | 439 | ||
@@ -574,6 +569,7 @@ struct bus_type pci_bus_type = { | |||
574 | 569 | ||
575 | static int __init pci_driver_init(void) | 570 | static int __init pci_driver_init(void) |
576 | { | 571 | { |
572 | pci_bus_type.multithread_probe = pci_multithread_probe; | ||
577 | return bus_register(&pci_bus_type); | 573 | return bus_register(&pci_bus_type); |
578 | } | 574 | } |
579 | 575 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d3eab057b2d3..2a458279327a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
16 | #include <linux/pm.h> | ||
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
18 | #include <linux/string.h> | 19 | #include <linux/string.h> |
@@ -891,31 +892,48 @@ pci_disable_device(struct pci_dev *dev) | |||
891 | } | 892 | } |
892 | 893 | ||
893 | /** | 894 | /** |
894 | * pci_enable_wake - enable device to generate PME# when suspended | 895 | * pci_enable_wake - enable PCI device as wakeup event source |
895 | * @dev: - PCI device to operate on | 896 | * @dev: PCI device affected |
896 | * @state: - Current state of device. | 897 | * @state: PCI state from which device will issue wakeup events |
897 | * @enable: - Flag to enable or disable generation | 898 | * @enable: True to enable event generation; false to disable |
898 | * | ||
899 | * Set the bits in the device's PM Capabilities to generate PME# when | ||
900 | * the system is suspended. | ||
901 | * | 899 | * |
902 | * -EIO is returned if device doesn't have PM Capabilities. | 900 | * This enables the device as a wakeup event source, or disables it. |
903 | * -EINVAL is returned if device supports it, but can't generate wake events. | 901 | * When such events involves platform-specific hooks, those hooks are |
904 | * 0 if operation is successful. | 902 | * called automatically by this routine. |
905 | * | 903 | * |
904 | * Devices with legacy power management (no standard PCI PM capabilities) | ||
905 | * always require such platform hooks. Depending on the platform, devices | ||
906 | * supporting the standard PCI PME# signal may require such platform hooks; | ||
907 | * they always update bits in config space to allow PME# generation. | ||
908 | * | ||
909 | * -EIO is returned if the device can't ever be a wakeup event source. | ||
910 | * -EINVAL is returned if the device can't generate wakeup events from | ||
911 | * the specified PCI state. Returns zero if the operation is successful. | ||
906 | */ | 912 | */ |
907 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) | 913 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) |
908 | { | 914 | { |
909 | int pm; | 915 | int pm; |
916 | int status; | ||
910 | u16 value; | 917 | u16 value; |
911 | 918 | ||
919 | /* Note that drivers should verify device_may_wakeup(&dev->dev) | ||
920 | * before calling this function. Platform code should report | ||
921 | * errors when drivers try to enable wakeup on devices that | ||
922 | * can't issue wakeups, or on which wakeups were disabled by | ||
923 | * userspace updating the /sys/devices.../power/wakeup file. | ||
924 | */ | ||
925 | |||
926 | status = call_platform_enable_wakeup(&dev->dev, enable); | ||
927 | |||
912 | /* find PCI PM capability in list */ | 928 | /* find PCI PM capability in list */ |
913 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); | 929 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); |
914 | 930 | ||
915 | /* If device doesn't support PM Capabilities, but request is to disable | 931 | /* If device doesn't support PM Capabilities, but caller wants to |
916 | * wake events, it's a nop; otherwise fail */ | 932 | * disable wake events, it's a NOP. Otherwise fail unless the |
917 | if (!pm) | 933 | * platform hooks handled this legacy device already. |
918 | return enable ? -EIO : 0; | 934 | */ |
935 | if (!pm) | ||
936 | return enable ? status : 0; | ||
919 | 937 | ||
920 | /* Check device's ability to generate PME# */ | 938 | /* Check device's ability to generate PME# */ |
921 | pci_read_config_word(dev,pm+PCI_PM_PMC,&value); | 939 | pci_read_config_word(dev,pm+PCI_PM_PMC,&value); |
@@ -924,8 +942,14 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) | |||
924 | value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */ | 942 | value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */ |
925 | 943 | ||
926 | /* Check if it can generate PME# from requested state. */ | 944 | /* Check if it can generate PME# from requested state. */ |
927 | if (!value || !(value & (1 << state))) | 945 | if (!value || !(value & (1 << state))) { |
946 | /* if it can't, revert what the platform hook changed, | ||
947 | * always reporting the base "EINVAL, can't PME#" error | ||
948 | */ | ||
949 | if (enable) | ||
950 | call_platform_enable_wakeup(&dev->dev, 0); | ||
928 | return enable ? -EINVAL : 0; | 951 | return enable ? -EINVAL : 0; |
952 | } | ||
929 | 953 | ||
930 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); | 954 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); |
931 | 955 | ||
@@ -936,7 +960,7 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) | |||
936 | value &= ~PCI_PM_CTRL_PME_ENABLE; | 960 | value &= ~PCI_PM_CTRL_PME_ENABLE; |
937 | 961 | ||
938 | pci_write_config_word(dev, pm + PCI_PM_CTRL, value); | 962 | pci_write_config_word(dev, pm + PCI_PM_CTRL, value); |
939 | 963 | ||
940 | return 0; | 964 | return 0; |
941 | } | 965 | } |
942 | 966 | ||
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 91c047a7e635..dd6384b1efce 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c | |||
@@ -311,7 +311,6 @@ done: | |||
311 | return NULL; | 311 | return NULL; |
312 | 312 | ||
313 | found: | 313 | found: |
314 | down_write(&dev->dev.bus->subsys.rwsem); | ||
315 | dev->card_link = clink; | 314 | dev->card_link = clink; |
316 | dev->dev.driver = &drv->link.driver; | 315 | dev->dev.driver = &drv->link.driver; |
317 | if (pnp_bus_type.probe(&dev->dev)) | 316 | if (pnp_bus_type.probe(&dev->dev)) |
@@ -319,14 +318,11 @@ found: | |||
319 | if (device_bind_driver(&dev->dev)) | 318 | if (device_bind_driver(&dev->dev)) |
320 | goto err_out; | 319 | goto err_out; |
321 | 320 | ||
322 | up_write(&dev->dev.bus->subsys.rwsem); | ||
323 | |||
324 | return dev; | 321 | return dev; |
325 | 322 | ||
326 | err_out: | 323 | err_out: |
327 | dev->dev.driver = NULL; | 324 | dev->dev.driver = NULL; |
328 | dev->card_link = NULL; | 325 | dev->card_link = NULL; |
329 | up_write(&dev->dev.bus->subsys.rwsem); | ||
330 | return NULL; | 326 | return NULL; |
331 | } | 327 | } |
332 | 328 | ||
@@ -340,11 +336,9 @@ void pnp_release_card_device(struct pnp_dev * dev) | |||
340 | struct pnp_card_driver * drv = dev->card_link->driver; | 336 | struct pnp_card_driver * drv = dev->card_link->driver; |
341 | if (!drv) | 337 | if (!drv) |
342 | return; | 338 | return; |
343 | down_write(&dev->dev.bus->subsys.rwsem); | ||
344 | drv->link.remove = &card_remove; | 339 | drv->link.remove = &card_remove; |
345 | device_release_driver(&dev->dev); | 340 | device_release_driver(&dev->dev); |
346 | drv->link.remove = &card_remove_first; | 341 | drv->link.remove = &card_remove_first; |
347 | up_write(&dev->dev.bus->subsys.rwsem); | ||
348 | } | 342 | } |
349 | 343 | ||
350 | /* | 344 | /* |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 03355902c582..a23ff582db9d 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -871,6 +871,12 @@ io_subchannel_register(struct work_struct *work) | |||
871 | } | 871 | } |
872 | goto out; | 872 | goto out; |
873 | } | 873 | } |
874 | /* | ||
875 | * Now we know this subchannel will stay, we can throw | ||
876 | * our delayed uevent. | ||
877 | */ | ||
878 | sch->dev.uevent_suppress = 0; | ||
879 | kobject_uevent(&sch->dev.kobj, KOBJ_ADD); | ||
874 | /* make it known to the system */ | 880 | /* make it known to the system */ |
875 | ret = ccw_device_register(cdev); | 881 | ret = ccw_device_register(cdev); |
876 | if (ret) { | 882 | if (ret) { |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index bf37cdf43fae..5aac0ec36368 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -423,27 +423,25 @@ static int ap_uevent (struct device *dev, char **envp, int num_envp, | |||
423 | char *buffer, int buffer_size) | 423 | char *buffer, int buffer_size) |
424 | { | 424 | { |
425 | struct ap_device *ap_dev = to_ap_dev(dev); | 425 | struct ap_device *ap_dev = to_ap_dev(dev); |
426 | int length; | 426 | int retval = 0, length = 0, i = 0; |
427 | 427 | ||
428 | if (!ap_dev) | 428 | if (!ap_dev) |
429 | return -ENODEV; | 429 | return -ENODEV; |
430 | 430 | ||
431 | /* Set up DEV_TYPE environment variable. */ | 431 | /* Set up DEV_TYPE environment variable. */ |
432 | envp[0] = buffer; | 432 | retval = add_uevent_var(envp, num_envp, &i, |
433 | length = scnprintf(buffer, buffer_size, "DEV_TYPE=%04X", | 433 | buffer, buffer_size, &length, |
434 | ap_dev->device_type); | 434 | "DEV_TYPE=%04X", ap_dev->device_type); |
435 | if (buffer_size - length <= 0) | 435 | if (retval) |
436 | return -ENOMEM; | 436 | return retval; |
437 | buffer += length; | 437 | |
438 | buffer_size -= length; | ||
439 | /* Add MODALIAS= */ | 438 | /* Add MODALIAS= */ |
440 | envp[1] = buffer; | 439 | retval = add_uevent_var(envp, num_envp, &i, |
441 | length = scnprintf(buffer, buffer_size, "MODALIAS=ap:t%02X", | 440 | buffer, buffer_size, &length, |
442 | ap_dev->device_type); | 441 | "MODALIAS=ap:t%02X", ap_dev->device_type); |
443 | if (buffer_size - length <= 0) | 442 | |
444 | return -ENOMEM; | 443 | envp[i] = NULL; |
445 | envp[2] = NULL; | 444 | return retval; |
446 | return 0; | ||
447 | } | 445 | } |
448 | 446 | ||
449 | static struct bus_type ap_bus_type = { | 447 | static struct bus_type ap_bus_type = { |
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 81f805cc5ee7..89d56c8ecdd2 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c | |||
@@ -37,7 +37,6 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) | |||
37 | struct device *dev = NULL; | 37 | struct device *dev = NULL; |
38 | loff_t nr = 0; | 38 | loff_t nr = 0; |
39 | 39 | ||
40 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
41 | if (*offset == 0) | 40 | if (*offset == 0) |
42 | return SEQ_START_TOKEN; | 41 | return SEQ_START_TOKEN; |
43 | while (1) { | 42 | while (1) { |
@@ -53,7 +52,6 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) | |||
53 | static void | 52 | static void |
54 | qeth_procfile_seq_stop(struct seq_file *s, void* it) | 53 | qeth_procfile_seq_stop(struct seq_file *s, void* it) |
55 | { | 54 | { |
56 | up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
57 | } | 55 | } |
58 | 56 | ||
59 | static void * | 57 | static void * |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 38c3a291efac..bd8e7f323c69 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -435,7 +435,7 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) | |||
435 | struct class_device *cdev; | 435 | struct class_device *cdev; |
436 | struct Scsi_Host *shost = ERR_PTR(-ENXIO), *p; | 436 | struct Scsi_Host *shost = ERR_PTR(-ENXIO), *p; |
437 | 437 | ||
438 | down_read(&class->subsys.rwsem); | 438 | down(&class->sem); |
439 | list_for_each_entry(cdev, &class->children, node) { | 439 | list_for_each_entry(cdev, &class->children, node) { |
440 | p = class_to_shost(cdev); | 440 | p = class_to_shost(cdev); |
441 | if (p->host_no == hostnum) { | 441 | if (p->host_no == hostnum) { |
@@ -443,7 +443,7 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) | |||
443 | break; | 443 | break; |
444 | } | 444 | } |
445 | } | 445 | } |
446 | up_read(&class->subsys.rwsem); | 446 | up(&class->sem); |
447 | 447 | ||
448 | return shost; | 448 | return shost; |
449 | } | 449 | } |
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index aefc7987120d..6753ca059ee4 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
@@ -246,7 +246,6 @@ static char *usb_dump_interface_descriptor(char *start, char *end, | |||
246 | 246 | ||
247 | if (start > end) | 247 | if (start > end) |
248 | return start; | 248 | return start; |
249 | down_read(&usb_bus_type.subsys.rwsem); | ||
250 | if (iface) { | 249 | if (iface) { |
251 | driver_name = (iface->dev.driver | 250 | driver_name = (iface->dev.driver |
252 | ? iface->dev.driver->name | 251 | ? iface->dev.driver->name |
@@ -263,7 +262,6 @@ static char *usb_dump_interface_descriptor(char *start, char *end, | |||
263 | desc->bInterfaceSubClass, | 262 | desc->bInterfaceSubClass, |
264 | desc->bInterfaceProtocol, | 263 | desc->bInterfaceProtocol, |
265 | driver_name); | 264 | driver_name); |
266 | up_read(&usb_bus_type.subsys.rwsem); | ||
267 | return start; | 265 | return start; |
268 | } | 266 | } |
269 | 267 | ||
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 36e7a843bf91..fc3545ddb06e 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -421,14 +421,11 @@ static int claimintf(struct dev_state *ps, unsigned int ifnum) | |||
421 | if (test_bit(ifnum, &ps->ifclaimed)) | 421 | if (test_bit(ifnum, &ps->ifclaimed)) |
422 | return 0; | 422 | return 0; |
423 | 423 | ||
424 | /* lock against other changes to driver bindings */ | ||
425 | down_write(&usb_bus_type.subsys.rwsem); | ||
426 | intf = usb_ifnum_to_if(dev, ifnum); | 424 | intf = usb_ifnum_to_if(dev, ifnum); |
427 | if (!intf) | 425 | if (!intf) |
428 | err = -ENOENT; | 426 | err = -ENOENT; |
429 | else | 427 | else |
430 | err = usb_driver_claim_interface(&usbfs_driver, intf, ps); | 428 | err = usb_driver_claim_interface(&usbfs_driver, intf, ps); |
431 | up_write(&usb_bus_type.subsys.rwsem); | ||
432 | if (err == 0) | 429 | if (err == 0) |
433 | set_bit(ifnum, &ps->ifclaimed); | 430 | set_bit(ifnum, &ps->ifclaimed); |
434 | return err; | 431 | return err; |
@@ -444,8 +441,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum) | |||
444 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | 441 | if (ifnum >= 8*sizeof(ps->ifclaimed)) |
445 | return err; | 442 | return err; |
446 | dev = ps->dev; | 443 | dev = ps->dev; |
447 | /* lock against other changes to driver bindings */ | ||
448 | down_write(&usb_bus_type.subsys.rwsem); | ||
449 | intf = usb_ifnum_to_if(dev, ifnum); | 444 | intf = usb_ifnum_to_if(dev, ifnum); |
450 | if (!intf) | 445 | if (!intf) |
451 | err = -ENOENT; | 446 | err = -ENOENT; |
@@ -453,7 +448,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum) | |||
453 | usb_driver_release_interface(&usbfs_driver, intf); | 448 | usb_driver_release_interface(&usbfs_driver, intf); |
454 | err = 0; | 449 | err = 0; |
455 | } | 450 | } |
456 | up_write(&usb_bus_type.subsys.rwsem); | ||
457 | return err; | 451 | return err; |
458 | } | 452 | } |
459 | 453 | ||
@@ -813,7 +807,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) | |||
813 | 807 | ||
814 | if (copy_from_user(&gd, arg, sizeof(gd))) | 808 | if (copy_from_user(&gd, arg, sizeof(gd))) |
815 | return -EFAULT; | 809 | return -EFAULT; |
816 | down_read(&usb_bus_type.subsys.rwsem); | ||
817 | intf = usb_ifnum_to_if(ps->dev, gd.interface); | 810 | intf = usb_ifnum_to_if(ps->dev, gd.interface); |
818 | if (!intf || !intf->dev.driver) | 811 | if (!intf || !intf->dev.driver) |
819 | ret = -ENODATA; | 812 | ret = -ENODATA; |
@@ -822,7 +815,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) | |||
822 | sizeof(gd.driver)); | 815 | sizeof(gd.driver)); |
823 | ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0); | 816 | ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0); |
824 | } | 817 | } |
825 | up_read(&usb_bus_type.subsys.rwsem); | ||
826 | return ret; | 818 | return ret; |
827 | } | 819 | } |
828 | 820 | ||
@@ -1351,15 +1343,12 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1351 | 1343 | ||
1352 | /* disconnect kernel driver from interface */ | 1344 | /* disconnect kernel driver from interface */ |
1353 | case USBDEVFS_DISCONNECT: | 1345 | case USBDEVFS_DISCONNECT: |
1354 | |||
1355 | down_write(&usb_bus_type.subsys.rwsem); | ||
1356 | if (intf->dev.driver) { | 1346 | if (intf->dev.driver) { |
1357 | driver = to_usb_driver(intf->dev.driver); | 1347 | driver = to_usb_driver(intf->dev.driver); |
1358 | dev_dbg (&intf->dev, "disconnect by usbfs\n"); | 1348 | dev_dbg (&intf->dev, "disconnect by usbfs\n"); |
1359 | usb_driver_release_interface(driver, intf); | 1349 | usb_driver_release_interface(driver, intf); |
1360 | } else | 1350 | } else |
1361 | retval = -ENODATA; | 1351 | retval = -ENODATA; |
1362 | up_write(&usb_bus_type.subsys.rwsem); | ||
1363 | break; | 1352 | break; |
1364 | 1353 | ||
1365 | /* let kernel drivers try to (re)bind to the interface */ | 1354 | /* let kernel drivers try to (re)bind to the interface */ |
@@ -1371,7 +1360,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1371 | 1360 | ||
1372 | /* talk directly to the interface's driver */ | 1361 | /* talk directly to the interface's driver */ |
1373 | default: | 1362 | default: |
1374 | down_read(&usb_bus_type.subsys.rwsem); | ||
1375 | if (intf->dev.driver) | 1363 | if (intf->dev.driver) |
1376 | driver = to_usb_driver(intf->dev.driver); | 1364 | driver = to_usb_driver(intf->dev.driver); |
1377 | if (driver == NULL || driver->ioctl == NULL) { | 1365 | if (driver == NULL || driver->ioctl == NULL) { |
@@ -1381,7 +1369,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1381 | if (retval == -ENOIOCTLCMD) | 1369 | if (retval == -ENOIOCTLCMD) |
1382 | retval = -ENOTTY; | 1370 | retval = -ENOTTY; |
1383 | } | 1371 | } |
1384 | up_read(&usb_bus_type.subsys.rwsem); | ||
1385 | } | 1372 | } |
1386 | 1373 | ||
1387 | /* cleanup and return */ | 1374 | /* cleanup and return */ |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 9e3e943f313c..e6dd2b9210f6 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -287,9 +287,9 @@ static int usb_unbind_interface(struct device *dev) | |||
287 | * way to bind to an interface is to return the private data from | 287 | * way to bind to an interface is to return the private data from |
288 | * the driver's probe() method. | 288 | * the driver's probe() method. |
289 | * | 289 | * |
290 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | 290 | * Callers must own the device lock, so driver probe() entries don't need |
291 | * writelock. So driver probe() entries don't need extra locking, | 291 | * extra locking, but other call contexts may need to explicitly claim that |
292 | * but other call contexts may need to explicitly claim those locks. | 292 | * lock. |
293 | */ | 293 | */ |
294 | int usb_driver_claim_interface(struct usb_driver *driver, | 294 | int usb_driver_claim_interface(struct usb_driver *driver, |
295 | struct usb_interface *iface, void* priv) | 295 | struct usb_interface *iface, void* priv) |
@@ -330,9 +330,9 @@ EXPORT_SYMBOL(usb_driver_claim_interface); | |||
330 | * also causes the driver disconnect() method to be called. | 330 | * also causes the driver disconnect() method to be called. |
331 | * | 331 | * |
332 | * This call is synchronous, and may not be used in an interrupt context. | 332 | * This call is synchronous, and may not be used in an interrupt context. |
333 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | 333 | * Callers must own the device lock, so driver disconnect() entries don't |
334 | * writelock. So driver disconnect() entries don't need extra locking, | 334 | * need extra locking, but other call contexts may need to explicitly claim |
335 | * but other call contexts may need to explicitly claim those locks. | 335 | * that lock. |
336 | */ | 336 | */ |
337 | void usb_driver_release_interface(struct usb_driver *driver, | 337 | void usb_driver_release_interface(struct usb_driver *driver, |
338 | struct usb_interface *iface) | 338 | struct usb_interface *iface) |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b89a98e61323..7a6028599d62 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -119,8 +119,7 @@ MODULE_PARM_DESC(use_both_schemes, | |||
119 | "first one fails"); | 119 | "first one fails"); |
120 | 120 | ||
121 | 121 | ||
122 | #ifdef DEBUG | 122 | static inline char *portspeed(int portstatus) |
123 | static inline char *portspeed (int portstatus) | ||
124 | { | 123 | { |
125 | if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) | 124 | if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) |
126 | return "480 Mb/s"; | 125 | return "480 Mb/s"; |
@@ -129,7 +128,6 @@ static inline char *portspeed (int portstatus) | |||
129 | else | 128 | else |
130 | return "12 Mb/s"; | 129 | return "12 Mb/s"; |
131 | } | 130 | } |
132 | #endif | ||
133 | 131 | ||
134 | /* Note that hdev or one of its children must be locked! */ | 132 | /* Note that hdev or one of its children must be locked! */ |
135 | static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev) | 133 | static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev) |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 217a3d6d0a06..c359ccb32998 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -1349,7 +1349,7 @@ static void release_interface(struct device *dev) | |||
1349 | * | 1349 | * |
1350 | * This call is synchronous. The calling context must be able to sleep, | 1350 | * This call is synchronous. The calling context must be able to sleep, |
1351 | * must own the device lock, and must not hold the driver model's USB | 1351 | * must own the device lock, and must not hold the driver model's USB |
1352 | * bus rwsem; usb device driver probe() methods cannot use this routine. | 1352 | * bus mutex; usb device driver probe() methods cannot use this routine. |
1353 | * | 1353 | * |
1354 | * Returns zero on success, or else the status code returned by the | 1354 | * Returns zero on success, or else the status code returned by the |
1355 | * underlying call that failed. On successful completion, each interface | 1355 | * underlying call that failed. On successful completion, each interface |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index f0d29eda3c6d..e8bbe8bc2598 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -486,9 +486,6 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
486 | * or if bus glue did the same (e.g. for PCI add-in cards with | 486 | * or if bus glue did the same (e.g. for PCI add-in cards with |
487 | * PCI PM support). | 487 | * PCI PM support). |
488 | */ | 488 | */ |
489 | ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n", | ||
490 | hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), | ||
491 | ohci_readl (ohci, &ohci->regs->control)); | ||
492 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 | 489 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 |
493 | && !device_may_wakeup(hcd->self.controller)) | 490 | && !device_may_wakeup(hcd->self.controller)) |
494 | device_init_wakeup(hcd->self.controller, 1); | 491 | device_init_wakeup(hcd->self.controller, 1); |
@@ -744,9 +741,6 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
744 | { | 741 | { |
745 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 742 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
746 | 743 | ||
747 | ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n", | ||
748 | hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), | ||
749 | hcd->state); | ||
750 | ohci_dump (ohci, 1); | 744 | ohci_dump (ohci, 1); |
751 | 745 | ||
752 | flush_scheduled_work(); | 746 | flush_scheduled_work(); |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 682f928b7f4d..2e124e0075c5 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -179,6 +179,48 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode, | |||
179 | } | 179 | } |
180 | EXPORT_SYMBOL_GPL(debugfs_create_u32); | 180 | EXPORT_SYMBOL_GPL(debugfs_create_u32); |
181 | 181 | ||
182 | static void debugfs_u64_set(void *data, u64 val) | ||
183 | { | ||
184 | *(u64 *)data = val; | ||
185 | } | ||
186 | |||
187 | static u64 debugfs_u64_get(void *data) | ||
188 | { | ||
189 | return *(u64 *)data; | ||
190 | } | ||
191 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); | ||
192 | |||
193 | /** | ||
194 | * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value | ||
195 | * @name: a pointer to a string containing the name of the file to create. | ||
196 | * @mode: the permission that the file should have | ||
197 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
198 | * directory dentry if set. If this parameter is %NULL, then the | ||
199 | * file will be created in the root of the debugfs filesystem. | ||
200 | * @value: a pointer to the variable that the file should read to and write | ||
201 | * from. | ||
202 | * | ||
203 | * This function creates a file in debugfs with the given name that | ||
204 | * contains the value of the variable @value. If the @mode variable is so | ||
205 | * set, it can be read from, and written to. | ||
206 | * | ||
207 | * This function will return a pointer to a dentry if it succeeds. This | ||
208 | * pointer must be passed to the debugfs_remove() function when the file is | ||
209 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
210 | * you are responsible here.) If an error occurs, %NULL will be returned. | ||
211 | * | ||
212 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | ||
213 | * returned. It is not wise to check for this value, but rather, check for | ||
214 | * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling | ||
215 | * code. | ||
216 | */ | ||
217 | struct dentry *debugfs_create_u64(const char *name, mode_t mode, | ||
218 | struct dentry *parent, u64 *value) | ||
219 | { | ||
220 | return debugfs_create_file(name, mode, parent, value, &fops_u64); | ||
221 | } | ||
222 | EXPORT_SYMBOL_GPL(debugfs_create_u64); | ||
223 | |||
182 | static ssize_t read_file_bool(struct file *file, char __user *user_buf, | 224 | static ssize_t read_file_bool(struct file *file, char __user *user_buf, |
183 | size_t count, loff_t *ppos) | 225 | size_t count, loff_t *ppos) |
184 | { | 226 | { |
diff --git a/fs/namei.c b/fs/namei.c index ee60cc4d3453..880052cadbcd 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1243,22 +1243,13 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, | |||
1243 | return err; | 1243 | return err; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | /* | 1246 | static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd) |
1247 | * Restricted form of lookup. Doesn't follow links, single-component only, | ||
1248 | * needs parent already locked. Doesn't follow mounts. | ||
1249 | * SMP-safe. | ||
1250 | */ | ||
1251 | static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd) | ||
1252 | { | 1247 | { |
1253 | struct dentry * dentry; | 1248 | struct dentry *dentry; |
1254 | struct inode *inode; | 1249 | struct inode *inode; |
1255 | int err; | 1250 | int err; |
1256 | 1251 | ||
1257 | inode = base->d_inode; | 1252 | inode = base->d_inode; |
1258 | err = permission(inode, MAY_EXEC, nd); | ||
1259 | dentry = ERR_PTR(err); | ||
1260 | if (err) | ||
1261 | goto out; | ||
1262 | 1253 | ||
1263 | /* | 1254 | /* |
1264 | * See if the low-level filesystem might want | 1255 | * See if the low-level filesystem might want |
@@ -1287,35 +1278,76 @@ out: | |||
1287 | return dentry; | 1278 | return dentry; |
1288 | } | 1279 | } |
1289 | 1280 | ||
1281 | /* | ||
1282 | * Restricted form of lookup. Doesn't follow links, single-component only, | ||
1283 | * needs parent already locked. Doesn't follow mounts. | ||
1284 | * SMP-safe. | ||
1285 | */ | ||
1286 | static inline struct dentry * __lookup_hash(struct qstr *name, struct dentry *base, struct nameidata *nd) | ||
1287 | { | ||
1288 | struct dentry *dentry; | ||
1289 | struct inode *inode; | ||
1290 | int err; | ||
1291 | |||
1292 | inode = base->d_inode; | ||
1293 | |||
1294 | err = permission(inode, MAY_EXEC, nd); | ||
1295 | dentry = ERR_PTR(err); | ||
1296 | if (err) | ||
1297 | goto out; | ||
1298 | |||
1299 | dentry = __lookup_hash_kern(name, base, nd); | ||
1300 | out: | ||
1301 | return dentry; | ||
1302 | } | ||
1303 | |||
1290 | static struct dentry *lookup_hash(struct nameidata *nd) | 1304 | static struct dentry *lookup_hash(struct nameidata *nd) |
1291 | { | 1305 | { |
1292 | return __lookup_hash(&nd->last, nd->dentry, nd); | 1306 | return __lookup_hash(&nd->last, nd->dentry, nd); |
1293 | } | 1307 | } |
1294 | 1308 | ||
1295 | /* SMP-safe */ | 1309 | /* SMP-safe */ |
1296 | struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) | 1310 | static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len) |
1297 | { | 1311 | { |
1298 | unsigned long hash; | 1312 | unsigned long hash; |
1299 | struct qstr this; | ||
1300 | unsigned int c; | 1313 | unsigned int c; |
1301 | 1314 | ||
1302 | this.name = name; | 1315 | this->name = name; |
1303 | this.len = len; | 1316 | this->len = len; |
1304 | if (!len) | 1317 | if (!len) |
1305 | goto access; | 1318 | return -EACCES; |
1306 | 1319 | ||
1307 | hash = init_name_hash(); | 1320 | hash = init_name_hash(); |
1308 | while (len--) { | 1321 | while (len--) { |
1309 | c = *(const unsigned char *)name++; | 1322 | c = *(const unsigned char *)name++; |
1310 | if (c == '/' || c == '\0') | 1323 | if (c == '/' || c == '\0') |
1311 | goto access; | 1324 | return -EACCES; |
1312 | hash = partial_name_hash(c, hash); | 1325 | hash = partial_name_hash(c, hash); |
1313 | } | 1326 | } |
1314 | this.hash = end_name_hash(hash); | 1327 | this->hash = end_name_hash(hash); |
1328 | return 0; | ||
1329 | } | ||
1315 | 1330 | ||
1331 | struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | ||
1332 | { | ||
1333 | int err; | ||
1334 | struct qstr this; | ||
1335 | |||
1336 | err = __lookup_one_len(name, &this, base, len); | ||
1337 | if (err) | ||
1338 | return ERR_PTR(err); | ||
1316 | return __lookup_hash(&this, base, NULL); | 1339 | return __lookup_hash(&this, base, NULL); |
1317 | access: | 1340 | } |
1318 | return ERR_PTR(-EACCES); | 1341 | |
1342 | struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len) | ||
1343 | { | ||
1344 | int err; | ||
1345 | struct qstr this; | ||
1346 | |||
1347 | err = __lookup_one_len(name, &this, base, len); | ||
1348 | if (err) | ||
1349 | return ERR_PTR(err); | ||
1350 | return __lookup_hash_kern(&this, base, NULL); | ||
1319 | } | 1351 | } |
1320 | 1352 | ||
1321 | /* | 1353 | /* |
diff --git a/fs/super.c b/fs/super.c index 60b1e50cbf53..8341e4e1d738 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -725,16 +725,6 @@ static int test_bdev_super(struct super_block *s, void *data) | |||
725 | return (void *)s->s_bdev == data; | 725 | return (void *)s->s_bdev == data; |
726 | } | 726 | } |
727 | 727 | ||
728 | static void bdev_uevent(struct block_device *bdev, enum kobject_action action) | ||
729 | { | ||
730 | if (bdev->bd_disk) { | ||
731 | if (bdev->bd_part) | ||
732 | kobject_uevent(&bdev->bd_part->kobj, action); | ||
733 | else | ||
734 | kobject_uevent(&bdev->bd_disk->kobj, action); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | int get_sb_bdev(struct file_system_type *fs_type, | 728 | int get_sb_bdev(struct file_system_type *fs_type, |
739 | int flags, const char *dev_name, void *data, | 729 | int flags, const char *dev_name, void *data, |
740 | int (*fill_super)(struct super_block *, void *, int), | 730 | int (*fill_super)(struct super_block *, void *, int), |
@@ -782,7 +772,6 @@ int get_sb_bdev(struct file_system_type *fs_type, | |||
782 | } | 772 | } |
783 | 773 | ||
784 | s->s_flags |= MS_ACTIVE; | 774 | s->s_flags |= MS_ACTIVE; |
785 | bdev_uevent(bdev, KOBJ_MOUNT); | ||
786 | } | 775 | } |
787 | 776 | ||
788 | return simple_set_mnt(mnt, s); | 777 | return simple_set_mnt(mnt, s); |
@@ -801,7 +790,6 @@ void kill_block_super(struct super_block *sb) | |||
801 | { | 790 | { |
802 | struct block_device *bdev = sb->s_bdev; | 791 | struct block_device *bdev = sb->s_bdev; |
803 | 792 | ||
804 | bdev_uevent(bdev, KOBJ_UMOUNT); | ||
805 | generic_shutdown_super(sb); | 793 | generic_shutdown_super(sb); |
806 | sync_blockdev(bdev); | 794 | sync_blockdev(bdev); |
807 | close_bdev_excl(bdev); | 795 | close_bdev_excl(bdev); |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index d3b9f5f07db1..8ea2a51ce883 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -59,7 +59,7 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off) | |||
59 | if (copy_to_user(userbuf, buffer, count)) | 59 | if (copy_to_user(userbuf, buffer, count)) |
60 | return -EFAULT; | 60 | return -EFAULT; |
61 | 61 | ||
62 | pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count); | 62 | pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count); |
63 | 63 | ||
64 | *off = offs + count; | 64 | *off = offs + count; |
65 | 65 | ||
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index fc4633378dc0..db0413a411d6 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -633,6 +633,7 @@ struct sysfs_schedule_callback_struct { | |||
633 | struct kobject *kobj; | 633 | struct kobject *kobj; |
634 | void (*func)(void *); | 634 | void (*func)(void *); |
635 | void *data; | 635 | void *data; |
636 | struct module *owner; | ||
636 | struct work_struct work; | 637 | struct work_struct work; |
637 | }; | 638 | }; |
638 | 639 | ||
@@ -643,6 +644,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work) | |||
643 | 644 | ||
644 | (ss->func)(ss->data); | 645 | (ss->func)(ss->data); |
645 | kobject_put(ss->kobj); | 646 | kobject_put(ss->kobj); |
647 | module_put(ss->owner); | ||
646 | kfree(ss); | 648 | kfree(ss); |
647 | } | 649 | } |
648 | 650 | ||
@@ -651,6 +653,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work) | |||
651 | * @kobj: object we're acting for. | 653 | * @kobj: object we're acting for. |
652 | * @func: callback function to invoke later. | 654 | * @func: callback function to invoke later. |
653 | * @data: argument to pass to @func. | 655 | * @data: argument to pass to @func. |
656 | * @owner: module owning the callback code | ||
654 | * | 657 | * |
655 | * sysfs attribute methods must not unregister themselves or their parent | 658 | * sysfs attribute methods must not unregister themselves or their parent |
656 | * kobject (which would amount to the same thing). Attempts to do so will | 659 | * kobject (which would amount to the same thing). Attempts to do so will |
@@ -663,20 +666,25 @@ static void sysfs_schedule_callback_work(struct work_struct *work) | |||
663 | * until @func returns. | 666 | * until @func returns. |
664 | * | 667 | * |
665 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | 668 | * Returns 0 if the request was submitted, -ENOMEM if storage could not |
666 | * be allocated. | 669 | * be allocated, -ENODEV if a reference to @owner isn't available. |
667 | */ | 670 | */ |
668 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | 671 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), |
669 | void *data) | 672 | void *data, struct module *owner) |
670 | { | 673 | { |
671 | struct sysfs_schedule_callback_struct *ss; | 674 | struct sysfs_schedule_callback_struct *ss; |
672 | 675 | ||
676 | if (!try_module_get(owner)) | ||
677 | return -ENODEV; | ||
673 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); | 678 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); |
674 | if (!ss) | 679 | if (!ss) { |
680 | module_put(owner); | ||
675 | return -ENOMEM; | 681 | return -ENOMEM; |
682 | } | ||
676 | kobject_get(kobj); | 683 | kobject_get(kobj); |
677 | ss->kobj = kobj; | 684 | ss->kobj = kobj; |
678 | ss->func = func; | 685 | ss->func = func; |
679 | ss->data = data; | 686 | ss->data = data; |
687 | ss->owner = owner; | ||
680 | INIT_WORK(&ss->work, sysfs_schedule_callback_work); | 688 | INIT_WORK(&ss->work, sysfs_schedule_callback_work); |
681 | schedule_work(&ss->work); | 689 | schedule_work(&ss->work); |
682 | return 0; | 690 | return 0; |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index b20951c93761..52eed2a7a5ef 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
@@ -70,9 +70,11 @@ void sysfs_remove_group(struct kobject * kobj, | |||
70 | { | 70 | { |
71 | struct dentry * dir; | 71 | struct dentry * dir; |
72 | 72 | ||
73 | if (grp->name) | 73 | if (grp->name) { |
74 | dir = lookup_one_len(grp->name, kobj->dentry, | 74 | dir = lookup_one_len_kern(grp->name, kobj->dentry, |
75 | strlen(grp->name)); | 75 | strlen(grp->name)); |
76 | BUG_ON(IS_ERR(dir)); | ||
77 | } | ||
76 | else | 78 | else |
77 | dir = dget(kobj->dentry); | 79 | dir = dget(kobj->dentry); |
78 | 80 | ||
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 9fa0983d1aa8..5a9c49534d08 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
@@ -44,6 +44,8 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode, | |||
44 | struct dentry *parent, u16 *value); | 44 | struct dentry *parent, u16 *value); |
45 | struct dentry *debugfs_create_u32(const char *name, mode_t mode, | 45 | struct dentry *debugfs_create_u32(const char *name, mode_t mode, |
46 | struct dentry *parent, u32 *value); | 46 | struct dentry *parent, u32 *value); |
47 | struct dentry *debugfs_create_u64(const char *name, mode_t mode, | ||
48 | struct dentry *parent, u64 *value); | ||
47 | struct dentry *debugfs_create_bool(const char *name, mode_t mode, | 49 | struct dentry *debugfs_create_bool(const char *name, mode_t mode, |
48 | struct dentry *parent, u32 *value); | 50 | struct dentry *parent, u32 *value); |
49 | 51 | ||
@@ -104,6 +106,13 @@ static inline struct dentry *debugfs_create_u32(const char *name, mode_t mode, | |||
104 | return ERR_PTR(-ENODEV); | 106 | return ERR_PTR(-ENODEV); |
105 | } | 107 | } |
106 | 108 | ||
109 | static inline struct dentry *debugfs_create_u64(const char *name, mode_t mode, | ||
110 | struct dentry *parent, | ||
111 | u64 *value) | ||
112 | { | ||
113 | return ERR_PTR(-ENODEV); | ||
114 | } | ||
115 | |||
107 | static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, | 116 | static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, |
108 | struct dentry *parent, | 117 | struct dentry *parent, |
109 | u32 *value) | 118 | u32 *value) |
diff --git a/include/linux/device.h b/include/linux/device.h index 5cf30e95c8b6..a0cd2ced31a9 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -34,9 +34,24 @@ struct device; | |||
34 | struct device_driver; | 34 | struct device_driver; |
35 | struct class; | 35 | struct class; |
36 | struct class_device; | 36 | struct class_device; |
37 | struct bus_type; | ||
38 | |||
39 | struct bus_attribute { | ||
40 | struct attribute attr; | ||
41 | ssize_t (*show)(struct bus_type *, char * buf); | ||
42 | ssize_t (*store)(struct bus_type *, const char * buf, size_t count); | ||
43 | }; | ||
44 | |||
45 | #define BUS_ATTR(_name,_mode,_show,_store) \ | ||
46 | struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store) | ||
47 | |||
48 | extern int __must_check bus_create_file(struct bus_type *, | ||
49 | struct bus_attribute *); | ||
50 | extern void bus_remove_file(struct bus_type *, struct bus_attribute *); | ||
37 | 51 | ||
38 | struct bus_type { | 52 | struct bus_type { |
39 | const char * name; | 53 | const char * name; |
54 | struct module * owner; | ||
40 | 55 | ||
41 | struct subsystem subsys; | 56 | struct subsystem subsys; |
42 | struct kset drivers; | 57 | struct kset drivers; |
@@ -49,6 +64,8 @@ struct bus_type { | |||
49 | struct bus_attribute * bus_attrs; | 64 | struct bus_attribute * bus_attrs; |
50 | struct device_attribute * dev_attrs; | 65 | struct device_attribute * dev_attrs; |
51 | struct driver_attribute * drv_attrs; | 66 | struct driver_attribute * drv_attrs; |
67 | struct bus_attribute drivers_autoprobe_attr; | ||
68 | struct bus_attribute drivers_probe_attr; | ||
52 | 69 | ||
53 | int (*match)(struct device * dev, struct device_driver * drv); | 70 | int (*match)(struct device * dev, struct device_driver * drv); |
54 | int (*uevent)(struct device *dev, char **envp, | 71 | int (*uevent)(struct device *dev, char **envp, |
@@ -61,6 +78,9 @@ struct bus_type { | |||
61 | int (*suspend_late)(struct device * dev, pm_message_t state); | 78 | int (*suspend_late)(struct device * dev, pm_message_t state); |
62 | int (*resume_early)(struct device * dev); | 79 | int (*resume_early)(struct device * dev); |
63 | int (*resume)(struct device * dev); | 80 | int (*resume)(struct device * dev); |
81 | |||
82 | unsigned int drivers_autoprobe:1; | ||
83 | unsigned int multithread_probe:1; | ||
64 | }; | 84 | }; |
65 | 85 | ||
66 | extern int __must_check bus_register(struct bus_type * bus); | 86 | extern int __must_check bus_register(struct bus_type * bus); |
@@ -102,26 +122,10 @@ extern int bus_unregister_notifier(struct bus_type *bus, | |||
102 | #define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be | 122 | #define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be |
103 | unbound */ | 123 | unbound */ |
104 | 124 | ||
105 | /* sysfs interface for exporting bus attributes */ | ||
106 | |||
107 | struct bus_attribute { | ||
108 | struct attribute attr; | ||
109 | ssize_t (*show)(struct bus_type *, char * buf); | ||
110 | ssize_t (*store)(struct bus_type *, const char * buf, size_t count); | ||
111 | }; | ||
112 | |||
113 | #define BUS_ATTR(_name,_mode,_show,_store) \ | ||
114 | struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store) | ||
115 | |||
116 | extern int __must_check bus_create_file(struct bus_type *, | ||
117 | struct bus_attribute *); | ||
118 | extern void bus_remove_file(struct bus_type *, struct bus_attribute *); | ||
119 | |||
120 | struct device_driver { | 125 | struct device_driver { |
121 | const char * name; | 126 | const char * name; |
122 | struct bus_type * bus; | 127 | struct bus_type * bus; |
123 | 128 | ||
124 | struct completion unloaded; | ||
125 | struct kobject kobj; | 129 | struct kobject kobj; |
126 | struct klist klist_devices; | 130 | struct klist klist_devices; |
127 | struct klist_node knode_bus; | 131 | struct klist_node knode_bus; |
@@ -135,8 +139,6 @@ struct device_driver { | |||
135 | void (*shutdown) (struct device * dev); | 139 | void (*shutdown) (struct device * dev); |
136 | int (*suspend) (struct device * dev, pm_message_t state); | 140 | int (*suspend) (struct device * dev, pm_message_t state); |
137 | int (*resume) (struct device * dev); | 141 | int (*resume) (struct device * dev); |
138 | |||
139 | unsigned int multithread_probe:1; | ||
140 | }; | 142 | }; |
141 | 143 | ||
142 | 144 | ||
@@ -181,10 +183,9 @@ struct class { | |||
181 | struct list_head children; | 183 | struct list_head children; |
182 | struct list_head devices; | 184 | struct list_head devices; |
183 | struct list_head interfaces; | 185 | struct list_head interfaces; |
186 | struct kset class_dirs; | ||
184 | struct semaphore sem; /* locks both the children and interfaces lists */ | 187 | struct semaphore sem; /* locks both the children and interfaces lists */ |
185 | 188 | ||
186 | struct kobject *virtual_dir; | ||
187 | |||
188 | struct class_attribute * class_attrs; | 189 | struct class_attribute * class_attrs; |
189 | struct class_device_attribute * class_dev_attrs; | 190 | struct class_device_attribute * class_dev_attrs; |
190 | struct device_attribute * dev_attrs; | 191 | struct device_attribute * dev_attrs; |
@@ -328,11 +329,23 @@ extern struct class_device *class_device_create(struct class *cls, | |||
328 | __attribute__((format(printf,5,6))); | 329 | __attribute__((format(printf,5,6))); |
329 | extern void class_device_destroy(struct class *cls, dev_t devt); | 330 | extern void class_device_destroy(struct class *cls, dev_t devt); |
330 | 331 | ||
332 | /* | ||
333 | * The type of device, "struct device" is embedded in. A class | ||
334 | * or bus can contain devices of different types | ||
335 | * like "partitions" and "disks", "mouse" and "event". | ||
336 | * This identifies the device type and carries type-specific | ||
337 | * information, equivalent to the kobj_type of a kobject. | ||
338 | * If "name" is specified, the uevent will contain it in | ||
339 | * the DEVTYPE variable. | ||
340 | */ | ||
331 | struct device_type { | 341 | struct device_type { |
332 | struct device_attribute *attrs; | 342 | const char *name; |
343 | struct attribute_group **groups; | ||
333 | int (*uevent)(struct device *dev, char **envp, int num_envp, | 344 | int (*uevent)(struct device *dev, char **envp, int num_envp, |
334 | char *buffer, int buffer_size); | 345 | char *buffer, int buffer_size); |
335 | void (*release)(struct device *dev); | 346 | void (*release)(struct device *dev); |
347 | int (*suspend)(struct device * dev, pm_message_t state); | ||
348 | int (*resume)(struct device * dev); | ||
336 | }; | 349 | }; |
337 | 350 | ||
338 | /* interface for exporting device attributes */ | 351 | /* interface for exporting device attributes */ |
@@ -354,8 +367,12 @@ extern int __must_check device_create_bin_file(struct device *dev, | |||
354 | struct bin_attribute *attr); | 367 | struct bin_attribute *attr); |
355 | extern void device_remove_bin_file(struct device *dev, | 368 | extern void device_remove_bin_file(struct device *dev, |
356 | struct bin_attribute *attr); | 369 | struct bin_attribute *attr); |
357 | extern int device_schedule_callback(struct device *dev, | 370 | extern int device_schedule_callback_owner(struct device *dev, |
358 | void (*func)(struct device *)); | 371 | void (*func)(struct device *), struct module *owner); |
372 | |||
373 | /* This is a macro to avoid include problems with THIS_MODULE */ | ||
374 | #define device_schedule_callback(dev, func) \ | ||
375 | device_schedule_callback_owner(dev, func, THIS_MODULE) | ||
359 | 376 | ||
360 | /* device resource management */ | 377 | /* device resource management */ |
361 | typedef void (*dr_release_t)(struct device *dev, void *res); | 378 | typedef void (*dr_release_t)(struct device *dev, void *res); |
@@ -554,7 +571,11 @@ extern const char *dev_driver_string(struct device *dev); | |||
554 | #define dev_dbg(dev, format, arg...) \ | 571 | #define dev_dbg(dev, format, arg...) \ |
555 | dev_printk(KERN_DEBUG , dev , format , ## arg) | 572 | dev_printk(KERN_DEBUG , dev , format , ## arg) |
556 | #else | 573 | #else |
557 | #define dev_dbg(dev, format, arg...) do { (void)(dev); } while (0) | 574 | static inline int __attribute__ ((format (printf, 2, 3))) |
575 | dev_dbg(struct device * dev, const char * fmt, ...) | ||
576 | { | ||
577 | return 0; | ||
578 | } | ||
558 | #endif | 579 | #endif |
559 | 580 | ||
560 | #define dev_err(dev, format, arg...) \ | 581 | #define dev_err(dev, format, arg...) \ |
diff --git a/include/linux/kobject.h b/include/linux/kobject.h index b850e0310538..eb0e63ef297f 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/sysfs.h> | 22 | #include <linux/sysfs.h> |
23 | #include <linux/compiler.h> | 23 | #include <linux/compiler.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/rwsem.h> | ||
26 | #include <linux/kref.h> | 25 | #include <linux/kref.h> |
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/wait.h> | 27 | #include <linux/wait.h> |
@@ -43,11 +42,9 @@ enum kobject_action { | |||
43 | KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */ | 42 | KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */ |
44 | KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */ | 43 | KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */ |
45 | KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */ | 44 | KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */ |
46 | KOBJ_MOUNT = (__force kobject_action_t) 0x04, /* mount event for block devices (broken) */ | 45 | KOBJ_OFFLINE = (__force kobject_action_t) 0x04, /* device offline */ |
47 | KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */ | 46 | KOBJ_ONLINE = (__force kobject_action_t) 0x05, /* device online */ |
48 | KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */ | 47 | KOBJ_MOVE = (__force kobject_action_t) 0x06, /* device move */ |
49 | KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */ | ||
50 | KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */ | ||
51 | }; | 48 | }; |
52 | 49 | ||
53 | struct kobject { | 50 | struct kobject { |
@@ -89,6 +86,8 @@ extern void kobject_unregister(struct kobject *); | |||
89 | extern struct kobject * kobject_get(struct kobject *); | 86 | extern struct kobject * kobject_get(struct kobject *); |
90 | extern void kobject_put(struct kobject *); | 87 | extern void kobject_put(struct kobject *); |
91 | 88 | ||
89 | extern struct kobject *kobject_kset_add_dir(struct kset *kset, | ||
90 | struct kobject *, const char *); | ||
92 | extern struct kobject *kobject_add_dir(struct kobject *, const char *); | 91 | extern struct kobject *kobject_add_dir(struct kobject *, const char *); |
93 | 92 | ||
94 | extern char * kobject_get_path(struct kobject *, gfp_t); | 93 | extern char * kobject_get_path(struct kobject *, gfp_t); |
@@ -175,7 +174,6 @@ extern struct kobject * kset_find_obj(struct kset *, const char *); | |||
175 | 174 | ||
176 | struct subsystem { | 175 | struct subsystem { |
177 | struct kset kset; | 176 | struct kset kset; |
178 | struct rw_semaphore rwsem; | ||
179 | }; | 177 | }; |
180 | 178 | ||
181 | #define decl_subsys(_name,_type,_uevent_ops) \ | 179 | #define decl_subsys(_name,_type,_uevent_ops) \ |
diff --git a/include/linux/namei.h b/include/linux/namei.h index d39a5a67e979..b7dd24917f0d 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -82,6 +82,7 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); | |||
82 | extern void release_open_intent(struct nameidata *); | 82 | extern void release_open_intent(struct nameidata *); |
83 | 83 | ||
84 | extern struct dentry * lookup_one_len(const char *, struct dentry *, int); | 84 | extern struct dentry * lookup_one_len(const char *, struct dentry *, int); |
85 | extern struct dentry *lookup_one_len_kern(const char *, struct dentry *, int); | ||
85 | 86 | ||
86 | extern int follow_down(struct vfsmount **, struct dentry **); | 87 | extern int follow_down(struct vfsmount **, struct dentry **); |
87 | extern int follow_up(struct vfsmount **, struct dentry **); | 88 | extern int follow_up(struct vfsmount **, struct dentry **); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 481ea0663f19..a3ad76221c6f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -361,8 +361,6 @@ struct pci_driver { | |||
361 | struct pci_error_handlers *err_handler; | 361 | struct pci_error_handlers *err_handler; |
362 | struct device_driver driver; | 362 | struct device_driver driver; |
363 | struct pci_dynids dynids; | 363 | struct pci_dynids dynids; |
364 | |||
365 | int multithread_probe; | ||
366 | }; | 364 | }; |
367 | 365 | ||
368 | #define to_pci_driver(drv) container_of(drv,struct pci_driver, driver) | 366 | #define to_pci_driver(drv) container_of(drv,struct pci_driver, driver) |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 21db05ac7c0b..9bd86db4d395 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -166,6 +166,24 @@ extern struct pm_ops *pm_ops; | |||
166 | extern int pm_suspend(suspend_state_t state); | 166 | extern int pm_suspend(suspend_state_t state); |
167 | 167 | ||
168 | 168 | ||
169 | /** | ||
170 | * arch_suspend_disable_irqs - disable IRQs for suspend | ||
171 | * | ||
172 | * Disables IRQs (in the default case). This is a weak symbol in the common | ||
173 | * code and thus allows architectures to override it if more needs to be | ||
174 | * done. Not called for suspend to disk. | ||
175 | */ | ||
176 | extern void arch_suspend_disable_irqs(void); | ||
177 | |||
178 | /** | ||
179 | * arch_suspend_enable_irqs - enable IRQs after suspend | ||
180 | * | ||
181 | * Enables IRQs (in the default case). This is a weak symbol in the common | ||
182 | * code and thus allows architectures to override it if more needs to be | ||
183 | * done. Not called for suspend to disk. | ||
184 | */ | ||
185 | extern void arch_suspend_enable_irqs(void); | ||
186 | |||
169 | /* | 187 | /* |
170 | * Device power management | 188 | * Device power management |
171 | */ | 189 | */ |
@@ -273,6 +291,20 @@ extern void __suspend_report_result(const char *function, void *fn, int ret); | |||
273 | __suspend_report_result(__FUNCTION__, fn, ret); \ | 291 | __suspend_report_result(__FUNCTION__, fn, ret); \ |
274 | } while (0) | 292 | } while (0) |
275 | 293 | ||
294 | /* | ||
295 | * Platform hook to activate device wakeup capability, if that's not already | ||
296 | * handled by enable_irq_wake() etc. | ||
297 | * Returns zero on success, else negative errno | ||
298 | */ | ||
299 | extern int (*platform_enable_wakeup)(struct device *dev, int is_on); | ||
300 | |||
301 | static inline int call_platform_enable_wakeup(struct device *dev, int is_on) | ||
302 | { | ||
303 | if (platform_enable_wakeup) | ||
304 | return (*platform_enable_wakeup)(dev, is_on); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
276 | #else /* !CONFIG_PM */ | 308 | #else /* !CONFIG_PM */ |
277 | 309 | ||
278 | static inline int device_suspend(pm_message_t state) | 310 | static inline int device_suspend(pm_message_t state) |
@@ -294,6 +326,11 @@ static inline void dpm_runtime_resume(struct device * dev) | |||
294 | 326 | ||
295 | #define suspend_report_result(fn, ret) do { } while (0) | 327 | #define suspend_report_result(fn, ret) do { } while (0) |
296 | 328 | ||
329 | static inline int call_platform_enable_wakeup(struct device *dev, int is_on) | ||
330 | { | ||
331 | return -EIO; | ||
332 | } | ||
333 | |||
297 | #endif | 334 | #endif |
298 | 335 | ||
299 | /* changes to device_may_wakeup take effect on the next pm state change. | 336 | /* changes to device_may_wakeup take effect on the next pm state change. |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index fea9a6b3fb7b..7d5d1ec95c2e 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -80,7 +80,7 @@ struct sysfs_ops { | |||
80 | #ifdef CONFIG_SYSFS | 80 | #ifdef CONFIG_SYSFS |
81 | 81 | ||
82 | extern int sysfs_schedule_callback(struct kobject *kobj, | 82 | extern int sysfs_schedule_callback(struct kobject *kobj, |
83 | void (*func)(void *), void *data); | 83 | void (*func)(void *), void *data, struct module *owner); |
84 | 84 | ||
85 | extern int __must_check | 85 | extern int __must_check |
86 | sysfs_create_dir(struct kobject *, struct dentry *); | 86 | sysfs_create_dir(struct kobject *, struct dentry *); |
@@ -137,7 +137,7 @@ extern int __must_check sysfs_init(void); | |||
137 | #else /* CONFIG_SYSFS */ | 137 | #else /* CONFIG_SYSFS */ |
138 | 138 | ||
139 | static inline int sysfs_schedule_callback(struct kobject *kobj, | 139 | static inline int sysfs_schedule_callback(struct kobject *kobj, |
140 | void (*func)(void *), void *data) | 140 | void (*func)(void *), void *data, struct module *owner) |
141 | { | 141 | { |
142 | return -ENOSYS; | 142 | return -ENOSYS; |
143 | } | 143 | } |
diff --git a/kernel/module.c b/kernel/module.c index dcdb32b8b13c..9da5af668a20 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1148,8 +1148,10 @@ int mod_sysfs_setup(struct module *mod, | |||
1148 | goto out; | 1148 | goto out; |
1149 | 1149 | ||
1150 | mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders"); | 1150 | mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders"); |
1151 | if (!mod->holders_dir) | 1151 | if (!mod->holders_dir) { |
1152 | err = -ENOMEM; | ||
1152 | goto out_unreg; | 1153 | goto out_unreg; |
1154 | } | ||
1153 | 1155 | ||
1154 | err = module_param_sysfs_setup(mod, kparam, num_params); | 1156 | err = module_param_sysfs_setup(mod, kparam, num_params); |
1155 | if (err) | 1157 | if (err) |
diff --git a/kernel/power/main.c b/kernel/power/main.c index a064dfd8877a..3062e940d1fa 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -111,13 +111,24 @@ static int suspend_prepare(suspend_state_t state) | |||
111 | return error; | 111 | return error; |
112 | } | 112 | } |
113 | 113 | ||
114 | /* default implementation */ | ||
115 | void __attribute__ ((weak)) arch_suspend_disable_irqs(void) | ||
116 | { | ||
117 | local_irq_disable(); | ||
118 | } | ||
119 | |||
120 | /* default implementation */ | ||
121 | void __attribute__ ((weak)) arch_suspend_enable_irqs(void) | ||
122 | { | ||
123 | local_irq_enable(); | ||
124 | } | ||
114 | 125 | ||
115 | int suspend_enter(suspend_state_t state) | 126 | int suspend_enter(suspend_state_t state) |
116 | { | 127 | { |
117 | int error = 0; | 128 | int error = 0; |
118 | unsigned long flags; | ||
119 | 129 | ||
120 | local_irq_save(flags); | 130 | arch_suspend_disable_irqs(); |
131 | BUG_ON(!irqs_disabled()); | ||
121 | 132 | ||
122 | if ((error = device_power_down(PMSG_SUSPEND))) { | 133 | if ((error = device_power_down(PMSG_SUSPEND))) { |
123 | printk(KERN_ERR "Some devices failed to power down\n"); | 134 | printk(KERN_ERR "Some devices failed to power down\n"); |
@@ -126,7 +137,8 @@ int suspend_enter(suspend_state_t state) | |||
126 | error = pm_ops->enter(state); | 137 | error = pm_ops->enter(state); |
127 | device_power_up(); | 138 | device_power_up(); |
128 | Done: | 139 | Done: |
129 | local_irq_restore(flags); | 140 | arch_suspend_enable_irqs(); |
141 | BUG_ON(irqs_disabled()); | ||
130 | return error; | 142 | return error; |
131 | } | 143 | } |
132 | 144 | ||
diff --git a/lib/kobject.c b/lib/kobject.c index 057921c5945a..cecf2fbede3e 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -157,7 +157,7 @@ static void unlink(struct kobject * kobj) | |||
157 | } | 157 | } |
158 | 158 | ||
159 | /** | 159 | /** |
160 | * kobject_add - add an object to the hierarchy. | 160 | * kobject_shadow_add - add an object to the hierarchy. |
161 | * @kobj: object. | 161 | * @kobj: object. |
162 | * @shadow_parent: sysfs directory to add to. | 162 | * @shadow_parent: sysfs directory to add to. |
163 | */ | 163 | */ |
@@ -174,6 +174,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) | |||
174 | if (!*kobj->k_name) { | 174 | if (!*kobj->k_name) { |
175 | pr_debug("kobject attempted to be registered with no name!\n"); | 175 | pr_debug("kobject attempted to be registered with no name!\n"); |
176 | WARN_ON(1); | 176 | WARN_ON(1); |
177 | kobject_put(kobj); | ||
177 | return -EINVAL; | 178 | return -EINVAL; |
178 | } | 179 | } |
179 | parent = kobject_get(kobj->parent); | 180 | parent = kobject_get(kobj->parent); |
@@ -190,8 +191,8 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) | |||
190 | 191 | ||
191 | list_add_tail(&kobj->entry,&kobj->kset->list); | 192 | list_add_tail(&kobj->entry,&kobj->kset->list); |
192 | spin_unlock(&kobj->kset->list_lock); | 193 | spin_unlock(&kobj->kset->list_lock); |
194 | kobj->parent = parent; | ||
193 | } | 195 | } |
194 | kobj->parent = parent; | ||
195 | 196 | ||
196 | error = create_dir(kobj, shadow_parent); | 197 | error = create_dir(kobj, shadow_parent); |
197 | if (error) { | 198 | if (error) { |
@@ -311,13 +312,43 @@ EXPORT_SYMBOL(kobject_set_name); | |||
311 | int kobject_rename(struct kobject * kobj, const char *new_name) | 312 | int kobject_rename(struct kobject * kobj, const char *new_name) |
312 | { | 313 | { |
313 | int error = 0; | 314 | int error = 0; |
315 | const char *devpath = NULL; | ||
316 | char *devpath_string = NULL; | ||
317 | char *envp[2]; | ||
314 | 318 | ||
315 | kobj = kobject_get(kobj); | 319 | kobj = kobject_get(kobj); |
316 | if (!kobj) | 320 | if (!kobj) |
317 | return -EINVAL; | 321 | return -EINVAL; |
318 | if (!kobj->parent) | 322 | if (!kobj->parent) |
319 | return -EINVAL; | 323 | return -EINVAL; |
324 | |||
325 | devpath = kobject_get_path(kobj, GFP_KERNEL); | ||
326 | if (!devpath) { | ||
327 | error = -ENOMEM; | ||
328 | goto out; | ||
329 | } | ||
330 | devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL); | ||
331 | if (!devpath_string) { | ||
332 | error = -ENOMEM; | ||
333 | goto out; | ||
334 | } | ||
335 | sprintf(devpath_string, "DEVPATH_OLD=%s", devpath); | ||
336 | envp[0] = devpath_string; | ||
337 | envp[1] = NULL; | ||
338 | /* Note : if we want to send the new name alone, not the full path, | ||
339 | * we could probably use kobject_name(kobj); */ | ||
340 | |||
320 | error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name); | 341 | error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name); |
342 | |||
343 | /* This function is mostly/only used for network interface. | ||
344 | * Some hotplug package track interfaces by their name and | ||
345 | * therefore want to know when the name is changed by the user. */ | ||
346 | if (!error) | ||
347 | kobject_uevent_env(kobj, KOBJ_MOVE, envp); | ||
348 | |||
349 | out: | ||
350 | kfree(devpath_string); | ||
351 | kfree(devpath); | ||
321 | kobject_put(kobj); | 352 | kobject_put(kobj); |
322 | 353 | ||
323 | return error; | 354 | return error; |
@@ -488,13 +519,15 @@ static struct kobj_type dir_ktype = { | |||
488 | }; | 519 | }; |
489 | 520 | ||
490 | /** | 521 | /** |
491 | * kobject_add_dir - add sub directory of object. | 522 | * kobject_kset_add_dir - add sub directory of object. |
523 | * @kset: kset the directory is belongs to. | ||
492 | * @parent: object in which a directory is created. | 524 | * @parent: object in which a directory is created. |
493 | * @name: directory name. | 525 | * @name: directory name. |
494 | * | 526 | * |
495 | * Add a plain directory object as child of given object. | 527 | * Add a plain directory object as child of given object. |
496 | */ | 528 | */ |
497 | struct kobject *kobject_add_dir(struct kobject *parent, const char *name) | 529 | struct kobject *kobject_kset_add_dir(struct kset *kset, |
530 | struct kobject *parent, const char *name) | ||
498 | { | 531 | { |
499 | struct kobject *k; | 532 | struct kobject *k; |
500 | int ret; | 533 | int ret; |
@@ -506,13 +539,14 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name) | |||
506 | if (!k) | 539 | if (!k) |
507 | return NULL; | 540 | return NULL; |
508 | 541 | ||
542 | k->kset = kset; | ||
509 | k->parent = parent; | 543 | k->parent = parent; |
510 | k->ktype = &dir_ktype; | 544 | k->ktype = &dir_ktype; |
511 | kobject_set_name(k, name); | 545 | kobject_set_name(k, name); |
512 | ret = kobject_register(k); | 546 | ret = kobject_register(k); |
513 | if (ret < 0) { | 547 | if (ret < 0) { |
514 | printk(KERN_WARNING "kobject_add_dir: " | 548 | printk(KERN_WARNING "%s: kobject_register error: %d\n", |
515 | "kobject_register error: %d\n", ret); | 549 | __func__, ret); |
516 | kobject_del(k); | 550 | kobject_del(k); |
517 | return NULL; | 551 | return NULL; |
518 | } | 552 | } |
@@ -521,6 +555,18 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name) | |||
521 | } | 555 | } |
522 | 556 | ||
523 | /** | 557 | /** |
558 | * kobject_add_dir - add sub directory of object. | ||
559 | * @parent: object in which a directory is created. | ||
560 | * @name: directory name. | ||
561 | * | ||
562 | * Add a plain directory object as child of given object. | ||
563 | */ | ||
564 | struct kobject *kobject_add_dir(struct kobject *parent, const char *name) | ||
565 | { | ||
566 | return kobject_kset_add_dir(NULL, parent, name); | ||
567 | } | ||
568 | |||
569 | /** | ||
524 | * kset_init - initialize a kset for use | 570 | * kset_init - initialize a kset for use |
525 | * @k: kset | 571 | * @k: kset |
526 | */ | 572 | */ |
@@ -613,7 +659,6 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name) | |||
613 | 659 | ||
614 | void subsystem_init(struct subsystem * s) | 660 | void subsystem_init(struct subsystem * s) |
615 | { | 661 | { |
616 | init_rwsem(&s->rwsem); | ||
617 | kset_init(&s->kset); | 662 | kset_init(&s->kset); |
618 | } | 663 | } |
619 | 664 | ||
@@ -622,8 +667,7 @@ void subsystem_init(struct subsystem * s) | |||
622 | * @s: the subsystem we're registering. | 667 | * @s: the subsystem we're registering. |
623 | * | 668 | * |
624 | * Once we register the subsystem, we want to make sure that | 669 | * Once we register the subsystem, we want to make sure that |
625 | * the kset points back to this subsystem for correct usage of | 670 | * the kset points back to this subsystem. |
626 | * the rwsem. | ||
627 | */ | 671 | */ |
628 | 672 | ||
629 | int subsystem_register(struct subsystem * s) | 673 | int subsystem_register(struct subsystem * s) |
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 82fc1794b691..12e311dc664c 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c | |||
@@ -42,10 +42,6 @@ static char *action_to_string(enum kobject_action action) | |||
42 | return "remove"; | 42 | return "remove"; |
43 | case KOBJ_CHANGE: | 43 | case KOBJ_CHANGE: |
44 | return "change"; | 44 | return "change"; |
45 | case KOBJ_MOUNT: | ||
46 | return "mount"; | ||
47 | case KOBJ_UMOUNT: | ||
48 | return "umount"; | ||
49 | case KOBJ_OFFLINE: | 45 | case KOBJ_OFFLINE: |
50 | return "offline"; | 46 | return "offline"; |
51 | case KOBJ_ONLINE: | 47 | case KOBJ_ONLINE: |
@@ -95,10 +91,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
95 | 91 | ||
96 | /* search the kset we belong to */ | 92 | /* search the kset we belong to */ |
97 | top_kobj = kobj; | 93 | top_kobj = kobj; |
98 | if (!top_kobj->kset && top_kobj->parent) { | 94 | while (!top_kobj->kset && top_kobj->parent) { |
99 | do { | 95 | top_kobj = top_kobj->parent; |
100 | top_kobj = top_kobj->parent; | ||
101 | } while (!top_kobj->kset && top_kobj->parent); | ||
102 | } | 96 | } |
103 | if (!top_kobj->kset) { | 97 | if (!top_kobj->kset) { |
104 | pr_debug("kobject attempted to send uevent without kset!\n"); | 98 | pr_debug("kobject attempted to send uevent without kset!\n"); |
@@ -115,6 +109,16 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
115 | return 0; | 109 | return 0; |
116 | } | 110 | } |
117 | 111 | ||
112 | /* originating subsystem */ | ||
113 | if (uevent_ops && uevent_ops->name) | ||
114 | subsystem = uevent_ops->name(kset, kobj); | ||
115 | else | ||
116 | subsystem = kobject_name(&kset->kobj); | ||
117 | if (!subsystem) { | ||
118 | pr_debug("unset subsytem caused the event to drop!\n"); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
118 | /* environment index */ | 122 | /* environment index */ |
119 | envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); | 123 | envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); |
120 | if (!envp) | 124 | if (!envp) |
@@ -134,12 +138,6 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
134 | goto exit; | 138 | goto exit; |
135 | } | 139 | } |
136 | 140 | ||
137 | /* originating subsystem */ | ||
138 | if (uevent_ops && uevent_ops->name) | ||
139 | subsystem = uevent_ops->name(kset, kobj); | ||
140 | else | ||
141 | subsystem = kobject_name(&kset->kobj); | ||
142 | |||
143 | /* event environemnt for helper process only */ | 141 | /* event environemnt for helper process only */ |
144 | envp[i++] = "HOME=/"; | 142 | envp[i++] = "HOME=/"; |
145 | envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; | 143 | envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; |
diff --git a/lib/kref.c b/lib/kref.c index 0d07cc31c818..a6dc3ec328e0 100644 --- a/lib/kref.c +++ b/lib/kref.c | |||
@@ -21,6 +21,7 @@ | |||
21 | void kref_init(struct kref *kref) | 21 | void kref_init(struct kref *kref) |
22 | { | 22 | { |
23 | atomic_set(&kref->refcount,1); | 23 | atomic_set(&kref->refcount,1); |
24 | smp_mb(); | ||
24 | } | 25 | } |
25 | 26 | ||
26 | /** | 27 | /** |
@@ -31,6 +32,7 @@ void kref_get(struct kref *kref) | |||
31 | { | 32 | { |
32 | WARN_ON(!atomic_read(&kref->refcount)); | 33 | WARN_ON(!atomic_read(&kref->refcount)); |
33 | atomic_inc(&kref->refcount); | 34 | atomic_inc(&kref->refcount); |
35 | smp_mb__after_atomic_inc(); | ||
34 | } | 36 | } |
35 | 37 | ||
36 | /** | 38 | /** |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 221a64ab64f7..b21307b15b82 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -412,20 +412,25 @@ static int netdev_uevent(struct device *d, char **envp, | |||
412 | int num_envp, char *buf, int size) | 412 | int num_envp, char *buf, int size) |
413 | { | 413 | { |
414 | struct net_device *dev = to_net_dev(d); | 414 | struct net_device *dev = to_net_dev(d); |
415 | int i = 0; | 415 | int retval, len = 0, i = 0; |
416 | int n; | ||
417 | 416 | ||
418 | /* pass interface to uevent. */ | 417 | /* pass interface to uevent. */ |
419 | envp[i++] = buf; | 418 | retval = add_uevent_var(envp, num_envp, &i, |
420 | n = snprintf(buf, size, "INTERFACE=%s", dev->name) + 1; | 419 | buf, size, &len, |
421 | buf += n; | 420 | "INTERFACE=%s", dev->name); |
422 | size -= n; | 421 | if (retval) |
423 | 422 | goto exit; | |
424 | if ((size <= 0) || (i >= num_envp)) | 423 | |
425 | return -ENOMEM; | 424 | /* pass ifindex to uevent. |
426 | 425 | * ifindex is useful as it won't change (interface name may change) | |
426 | * and is what RtNetlink uses natively. */ | ||
427 | retval = add_uevent_var(envp, num_envp, &i, | ||
428 | buf, size, &len, | ||
429 | "IFINDEX=%d", dev->ifindex); | ||
430 | |||
431 | exit: | ||
427 | envp[i] = NULL; | 432 | envp[i] = NULL; |
428 | return 0; | 433 | return retval; |
429 | } | 434 | } |
430 | #endif | 435 | #endif |
431 | 436 | ||
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 47b3e3768df0..418a98a10c73 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c | |||
@@ -61,9 +61,9 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, | |||
61 | { | 61 | { |
62 | struct soundbus_dev * soundbus_dev; | 62 | struct soundbus_dev * soundbus_dev; |
63 | struct of_device * of; | 63 | struct of_device * of; |
64 | char *scratch, *compat, *compat2; | 64 | char *compat; |
65 | int i = 0; | 65 | int retval = 0, i = 0, length = 0; |
66 | int length, cplen, cplen2, seen = 0; | 66 | int cplen, seen = 0; |
67 | 67 | ||
68 | if (!dev) | 68 | if (!dev) |
69 | return -ENODEV; | 69 | return -ENODEV; |
@@ -75,63 +75,47 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, | |||
75 | of = &soundbus_dev->ofdev; | 75 | of = &soundbus_dev->ofdev; |
76 | 76 | ||
77 | /* stuff we want to pass to /sbin/hotplug */ | 77 | /* stuff we want to pass to /sbin/hotplug */ |
78 | envp[i++] = scratch = buffer; | 78 | retval = add_uevent_var(envp, num_envp, &i, |
79 | length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name); | 79 | buffer, buffer_size, &length, |
80 | ++length; | 80 | "OF_NAME=%s", of->node->name); |
81 | buffer_size -= length; | 81 | if (retval) |
82 | if ((buffer_size <= 0) || (i >= num_envp)) | 82 | return retval; |
83 | return -ENOMEM; | 83 | |
84 | scratch += length; | 84 | retval = add_uevent_var(envp, num_envp, &i, |
85 | 85 | buffer, buffer_size, &length, | |
86 | envp[i++] = scratch; | 86 | "OF_TYPE=%s", of->node->type); |
87 | length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type); | 87 | if (retval) |
88 | ++length; | 88 | return retval; |
89 | buffer_size -= length; | ||
90 | if ((buffer_size <= 0) || (i >= num_envp)) | ||
91 | return -ENOMEM; | ||
92 | scratch += length; | ||
93 | 89 | ||
94 | /* Since the compatible field can contain pretty much anything | 90 | /* Since the compatible field can contain pretty much anything |
95 | * it's not really legal to split it out with commas. We split it | 91 | * it's not really legal to split it out with commas. We split it |
96 | * up using a number of environment variables instead. */ | 92 | * up using a number of environment variables instead. */ |
97 | 93 | ||
98 | compat = (char *) get_property(of->node, "compatible", &cplen); | 94 | compat = (char *) get_property(of->node, "compatible", &cplen); |
99 | compat2 = compat; | ||
100 | cplen2= cplen; | ||
101 | while (compat && cplen > 0) { | 95 | while (compat && cplen > 0) { |
102 | envp[i++] = scratch; | 96 | int tmp = length; |
103 | length = scnprintf (scratch, buffer_size, | 97 | retval = add_uevent_var(envp, num_envp, &i, |
104 | "OF_COMPATIBLE_%d=%s", seen, compat); | 98 | buffer, buffer_size, &length, |
105 | ++length; | 99 | "OF_COMPATIBLE_%d=%s", seen, compat); |
106 | buffer_size -= length; | 100 | if (retval) |
107 | if ((buffer_size <= 0) || (i >= num_envp)) | 101 | return retval; |
108 | return -ENOMEM; | 102 | compat += length - tmp; |
109 | scratch += length; | 103 | cplen -= length - tmp; |
110 | length = strlen (compat) + 1; | 104 | seen += 1; |
111 | compat += length; | ||
112 | cplen -= length; | ||
113 | seen++; | ||
114 | } | 105 | } |
115 | 106 | ||
116 | envp[i++] = scratch; | 107 | retval = add_uevent_var(envp, num_envp, &i, |
117 | length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen); | 108 | buffer, buffer_size, &length, |
118 | ++length; | 109 | "OF_COMPATIBLE_N=%d", seen); |
119 | buffer_size -= length; | 110 | if (retval) |
120 | if ((buffer_size <= 0) || (i >= num_envp)) | 111 | return retval; |
121 | return -ENOMEM; | 112 | retval = add_uevent_var(envp, num_envp, &i, |
122 | scratch += length; | 113 | buffer, buffer_size, &length, |
123 | 114 | "MODALIAS=%s", soundbus_dev->modalias); | |
124 | envp[i++] = scratch; | ||
125 | length = scnprintf (scratch, buffer_size, "MODALIAS=%s", | ||
126 | soundbus_dev->modalias); | ||
127 | |||
128 | buffer_size -= length; | ||
129 | if ((buffer_size <= 0) || (i >= num_envp)) | ||
130 | return -ENOMEM; | ||
131 | 115 | ||
132 | envp[i] = NULL; | 116 | envp[i] = NULL; |
133 | 117 | ||
134 | return 0; | 118 | return retval; |
135 | } | 119 | } |
136 | 120 | ||
137 | static int soundbus_device_remove(struct device *dev) | 121 | static int soundbus_device_remove(struct device *dev) |