aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/attribute_container.c1
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/bus.c24
-rw-r--r--drivers/base/class.c46
-rw-r--r--drivers/base/core.c58
-rw-r--r--drivers/base/dd.c21
-rw-r--r--drivers/base/devres.c2
-rw-r--r--drivers/base/firmware_class.c6
-rw-r--r--drivers/base/power/main.c44
-rw-r--r--drivers/base/power/power.h4
-rw-r--r--drivers/base/power/resume.c23
-rw-r--r--drivers/base/power/runtime.c12
-rw-r--r--drivers/base/power/suspend.c72
-rw-r--r--drivers/base/sys.c24
14 files changed, 134 insertions, 205 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 1ec0654665cf..7370d7cf5988 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/mutex.h>
21 22
22#include "base.h" 23#include "base.h"
23 24
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 5512d84452f2..47eb02d9f1af 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -44,6 +44,6 @@ struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
44 44
45extern char *make_class_name(const char *name, struct kobject *kobj); 45extern char *make_class_name(const char *name, struct kobject *kobj);
46 46
47extern void devres_release_all(struct device *dev); 47extern int devres_release_all(struct device *dev);
48 48
49extern struct kset devices_subsys; 49extern struct kset devices_subsys;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index dca734819e50..61c67526a656 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -138,12 +138,24 @@ void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
138 } 138 }
139} 139}
140 140
141static struct kobj_type ktype_bus = { 141static struct kobj_type bus_ktype = {
142 .sysfs_ops = &bus_sysfs_ops, 142 .sysfs_ops = &bus_sysfs_ops,
143};
144
145static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
146{
147 struct kobj_type *ktype = get_ktype(kobj);
143 148
149 if (ktype == &bus_ktype)
150 return 1;
151 return 0;
152}
153
154static struct kset_uevent_ops bus_uevent_ops = {
155 .filter = bus_uevent_filter,
144}; 156};
145 157
146static decl_subsys(bus, &ktype_bus, NULL); 158static decl_subsys(bus, &bus_ktype, &bus_uevent_ops);
147 159
148 160
149#ifdef CONFIG_HOTPLUG 161#ifdef CONFIG_HOTPLUG
@@ -562,7 +574,6 @@ static int add_probe_files(struct bus_type *bus)
562 574
563 bus->drivers_probe_attr.attr.name = "drivers_probe"; 575 bus->drivers_probe_attr.attr.name = "drivers_probe";
564 bus->drivers_probe_attr.attr.mode = S_IWUSR; 576 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; 577 bus->drivers_probe_attr.store = store_drivers_probe;
567 retval = bus_create_file(bus, &bus->drivers_probe_attr); 578 retval = bus_create_file(bus, &bus->drivers_probe_attr);
568 if (retval) 579 if (retval)
@@ -570,7 +581,6 @@ static int add_probe_files(struct bus_type *bus)
570 581
571 bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe"; 582 bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
572 bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO; 583 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; 584 bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
575 bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; 585 bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
576 retval = bus_create_file(bus, &bus->drivers_autoprobe_attr); 586 retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
@@ -610,7 +620,8 @@ int bus_add_driver(struct device_driver *drv)
610 if (error) 620 if (error)
611 goto out_put_bus; 621 goto out_put_bus;
612 drv->kobj.kset = &bus->drivers; 622 drv->kobj.kset = &bus->drivers;
613 if ((error = kobject_register(&drv->kobj))) 623 error = kobject_register(&drv->kobj);
624 if (error)
614 goto out_put_bus; 625 goto out_put_bus;
615 626
616 if (drv->bus->drivers_autoprobe) { 627 if (drv->bus->drivers_autoprobe) {
@@ -760,7 +771,8 @@ static int bus_add_attrs(struct bus_type * bus)
760 771
761 if (bus->bus_attrs) { 772 if (bus->bus_attrs) {
762 for (i = 0; attr_name(bus->bus_attrs[i]); i++) { 773 for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
763 if ((error = bus_create_file(bus,&bus->bus_attrs[i]))) 774 error = bus_create_file(bus,&bus->bus_attrs[i]);
775 if (error)
764 goto Err; 776 goto Err;
765 } 777 }
766 } 778 }
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 8c506dbe3913..4d2222618b78 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -312,9 +312,6 @@ static void class_dev_release(struct kobject * kobj)
312 312
313 pr_debug("device class '%s': release.\n", cd->class_id); 313 pr_debug("device class '%s': release.\n", cd->class_id);
314 314
315 kfree(cd->devt_attr);
316 cd->devt_attr = NULL;
317
318 if (cd->release) 315 if (cd->release)
319 cd->release(cd); 316 cd->release(cd);
320 else if (cls->release) 317 else if (cls->release)
@@ -547,6 +544,9 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
547 return print_dev_t(buf, class_dev->devt); 544 return print_dev_t(buf, class_dev->devt);
548} 545}
549 546
547static struct class_device_attribute class_devt_attr =
548 __ATTR(dev, S_IRUGO, show_dev, NULL);
549
550static ssize_t store_uevent(struct class_device *class_dev, 550static ssize_t store_uevent(struct class_device *class_dev,
551 const char *buf, size_t count) 551 const char *buf, size_t count)
552{ 552{
@@ -554,6 +554,9 @@ static ssize_t store_uevent(struct class_device *class_dev,
554 return count; 554 return count;
555} 555}
556 556
557static struct class_device_attribute class_uevent_attr =
558 __ATTR(uevent, S_IWUSR, NULL, store_uevent);
559
557void class_device_initialize(struct class_device *class_dev) 560void class_device_initialize(struct class_device *class_dev)
558{ 561{
559 kobj_set_kset_s(class_dev, class_obj_subsys); 562 kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -603,32 +606,15 @@ int class_device_add(struct class_device *class_dev)
603 &parent_class->subsys.kobj, "subsystem"); 606 &parent_class->subsys.kobj, "subsystem");
604 if (error) 607 if (error)
605 goto out3; 608 goto out3;
606 class_dev->uevent_attr.attr.name = "uevent"; 609
607 class_dev->uevent_attr.attr.mode = S_IWUSR; 610 error = class_device_create_file(class_dev, &class_uevent_attr);
608 class_dev->uevent_attr.attr.owner = parent_class->owner;
609 class_dev->uevent_attr.store = store_uevent;
610 error = class_device_create_file(class_dev, &class_dev->uevent_attr);
611 if (error) 611 if (error)
612 goto out3; 612 goto out3;
613 613
614 if (MAJOR(class_dev->devt)) { 614 if (MAJOR(class_dev->devt)) {
615 struct class_device_attribute *attr; 615 error = class_device_create_file(class_dev, &class_devt_attr);
616 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 616 if (error)
617 if (!attr) {
618 error = -ENOMEM;
619 goto out4;
620 }
621 attr->attr.name = "dev";
622 attr->attr.mode = S_IRUGO;
623 attr->attr.owner = parent_class->owner;
624 attr->show = show_dev;
625 error = class_device_create_file(class_dev, attr);
626 if (error) {
627 kfree(attr);
628 goto out4; 617 goto out4;
629 }
630
631 class_dev->devt_attr = attr;
632 } 618 }
633 619
634 error = class_device_add_attrs(class_dev); 620 error = class_device_add_attrs(class_dev);
@@ -671,10 +657,10 @@ int class_device_add(struct class_device *class_dev)
671 out6: 657 out6:
672 class_device_remove_attrs(class_dev); 658 class_device_remove_attrs(class_dev);
673 out5: 659 out5:
674 if (class_dev->devt_attr) 660 if (MAJOR(class_dev->devt))
675 class_device_remove_file(class_dev, class_dev->devt_attr); 661 class_device_remove_file(class_dev, &class_devt_attr);
676 out4: 662 out4:
677 class_device_remove_file(class_dev, &class_dev->uevent_attr); 663 class_device_remove_file(class_dev, &class_uevent_attr);
678 out3: 664 out3:
679 kobject_del(&class_dev->kobj); 665 kobject_del(&class_dev->kobj);
680 out2: 666 out2:
@@ -774,9 +760,9 @@ void class_device_del(struct class_device *class_dev)
774 sysfs_remove_link(&class_dev->kobj, "device"); 760 sysfs_remove_link(&class_dev->kobj, "device");
775 } 761 }
776 sysfs_remove_link(&class_dev->kobj, "subsystem"); 762 sysfs_remove_link(&class_dev->kobj, "subsystem");
777 class_device_remove_file(class_dev, &class_dev->uevent_attr); 763 class_device_remove_file(class_dev, &class_uevent_attr);
778 if (class_dev->devt_attr) 764 if (MAJOR(class_dev->devt))
779 class_device_remove_file(class_dev, class_dev->devt_attr); 765 class_device_remove_file(class_dev, &class_devt_attr);
780 class_device_remove_attrs(class_dev); 766 class_device_remove_attrs(class_dev);
781 class_device_remove_groups(class_dev); 767 class_device_remove_groups(class_dev);
782 768
diff --git a/drivers/base/core.c b/drivers/base/core.c
index dd40d78a023d..0455aa78fa13 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -310,6 +310,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
310 return count; 310 return count;
311} 311}
312 312
313static struct device_attribute uevent_attr =
314 __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
315
313static int device_add_attributes(struct device *dev, 316static int device_add_attributes(struct device *dev,
314 struct device_attribute *attrs) 317 struct device_attribute *attrs)
315{ 318{
@@ -423,6 +426,9 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
423 return print_dev_t(buf, dev->devt); 426 return print_dev_t(buf, dev->devt);
424} 427}
425 428
429static struct device_attribute devt_attr =
430 __ATTR(dev, S_IRUGO, show_dev, NULL);
431
426/* 432/*
427 * devices_subsys - structure to be registered with kobject core. 433 * devices_subsys - structure to be registered with kobject core.
428 */ 434 */
@@ -681,35 +687,14 @@ int device_add(struct device *dev)
681 blocking_notifier_call_chain(&dev->bus->bus_notifier, 687 blocking_notifier_call_chain(&dev->bus->bus_notifier,
682 BUS_NOTIFY_ADD_DEVICE, dev); 688 BUS_NOTIFY_ADD_DEVICE, dev);
683 689
684 dev->uevent_attr.attr.name = "uevent"; 690 error = device_create_file(dev, &uevent_attr);
685 dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
686 if (dev->driver)
687 dev->uevent_attr.attr.owner = dev->driver->owner;
688 dev->uevent_attr.store = store_uevent;
689 dev->uevent_attr.show = show_uevent;
690 error = device_create_file(dev, &dev->uevent_attr);
691 if (error) 691 if (error)
692 goto attrError; 692 goto attrError;
693 693
694 if (MAJOR(dev->devt)) { 694 if (MAJOR(dev->devt)) {
695 struct device_attribute *attr; 695 error = device_create_file(dev, &devt_attr);
696 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 696 if (error)
697 if (!attr) {
698 error = -ENOMEM;
699 goto ueventattrError;
700 }
701 attr->attr.name = "dev";
702 attr->attr.mode = S_IRUGO;
703 if (dev->driver)
704 attr->attr.owner = dev->driver->owner;
705 attr->show = show_dev;
706 error = device_create_file(dev, attr);
707 if (error) {
708 kfree(attr);
709 goto ueventattrError; 697 goto ueventattrError;
710 }
711
712 dev->devt_attr = attr;
713 } 698 }
714 699
715 if (dev->class) { 700 if (dev->class) {
@@ -733,11 +718,14 @@ int device_add(struct device *dev)
733 } 718 }
734 } 719 }
735 720
736 if ((error = device_add_attrs(dev))) 721 error = device_add_attrs(dev);
722 if (error)
737 goto AttrsError; 723 goto AttrsError;
738 if ((error = device_pm_add(dev))) 724 error = device_pm_add(dev);
725 if (error)
739 goto PMError; 726 goto PMError;
740 if ((error = bus_add_device(dev))) 727 error = bus_add_device(dev);
728 if (error)
741 goto BusError; 729 goto BusError;
742 kobject_uevent(&dev->kobj, KOBJ_ADD); 730 kobject_uevent(&dev->kobj, KOBJ_ADD);
743 bus_attach_device(dev); 731 bus_attach_device(dev);
@@ -767,10 +755,8 @@ int device_add(struct device *dev)
767 BUS_NOTIFY_DEL_DEVICE, dev); 755 BUS_NOTIFY_DEL_DEVICE, dev);
768 device_remove_attrs(dev); 756 device_remove_attrs(dev);
769 AttrsError: 757 AttrsError:
770 if (dev->devt_attr) { 758 if (MAJOR(dev->devt))
771 device_remove_file(dev, dev->devt_attr); 759 device_remove_file(dev, &devt_attr);
772 kfree(dev->devt_attr);
773 }
774 760
775 if (dev->class) { 761 if (dev->class) {
776 sysfs_remove_link(&dev->kobj, "subsystem"); 762 sysfs_remove_link(&dev->kobj, "subsystem");
@@ -792,7 +778,7 @@ int device_add(struct device *dev)
792 } 778 }
793 } 779 }
794 ueventattrError: 780 ueventattrError:
795 device_remove_file(dev, &dev->uevent_attr); 781 device_remove_file(dev, &uevent_attr);
796 attrError: 782 attrError:
797 kobject_uevent(&dev->kobj, KOBJ_REMOVE); 783 kobject_uevent(&dev->kobj, KOBJ_REMOVE);
798 kobject_del(&dev->kobj); 784 kobject_del(&dev->kobj);
@@ -869,10 +855,8 @@ void device_del(struct device * dev)
869 855
870 if (parent) 856 if (parent)
871 klist_del(&dev->knode_parent); 857 klist_del(&dev->knode_parent);
872 if (dev->devt_attr) { 858 if (MAJOR(dev->devt))
873 device_remove_file(dev, dev->devt_attr); 859 device_remove_file(dev, &devt_attr);
874 kfree(dev->devt_attr);
875 }
876 if (dev->class) { 860 if (dev->class) {
877 sysfs_remove_link(&dev->kobj, "subsystem"); 861 sysfs_remove_link(&dev->kobj, "subsystem");
878 /* If this is not a "fake" compatible device, remove the 862 /* If this is not a "fake" compatible device, remove the
@@ -926,7 +910,7 @@ void device_del(struct device * dev)
926 up(&dev->class->sem); 910 up(&dev->class->sem);
927 } 911 }
928 } 912 }
929 device_remove_file(dev, &dev->uevent_attr); 913 device_remove_file(dev, &uevent_attr);
930 device_remove_attrs(dev); 914 device_remove_attrs(dev);
931 bus_remove_device(dev); 915 bus_remove_device(dev);
932 916
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index b0088b0efecd..7ac474db88c5 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -281,24 +281,16 @@ int driver_attach(struct device_driver * drv)
281 return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); 281 return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
282} 282}
283 283
284/** 284/*
285 * device_release_driver - manually detach device from driver.
286 * @dev: device.
287 *
288 * Manually detach device from driver.
289 *
290 * __device_release_driver() must be called with @dev->sem held. 285 * __device_release_driver() must be called with @dev->sem held.
291 * When called for a USB interface, @dev->parent->sem must be held 286 * When called for a USB interface, @dev->parent->sem must be held as well.
292 * as well.
293 */ 287 */
294
295static void __device_release_driver(struct device * dev) 288static void __device_release_driver(struct device * dev)
296{ 289{
297 struct device_driver * drv; 290 struct device_driver * drv;
298 291
299 drv = dev->driver; 292 drv = get_driver(dev->driver);
300 if (drv) { 293 if (drv) {
301 get_driver(drv);
302 driver_sysfs_remove(dev); 294 driver_sysfs_remove(dev);
303 sysfs_remove_link(&dev->kobj, "driver"); 295 sysfs_remove_link(&dev->kobj, "driver");
304 klist_remove(&dev->knode_driver); 296 klist_remove(&dev->knode_driver);
@@ -318,6 +310,13 @@ static void __device_release_driver(struct device * dev)
318 } 310 }
319} 311}
320 312
313/**
314 * device_release_driver - manually detach device from driver.
315 * @dev: device.
316 *
317 * Manually detach device from driver.
318 * When called for a USB interface, @dev->parent->sem must be held.
319 */
321void device_release_driver(struct device * dev) 320void device_release_driver(struct device * dev)
322{ 321{
323 /* 322 /*
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index e1c0730a3b99..e8beb8e5b626 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -10,6 +10,8 @@
10#include <linux/device.h> 10#include <linux/device.h>
11#include <linux/module.h> 11#include <linux/module.h>
12 12
13#include "base.h"
14
13struct devres_node { 15struct devres_node {
14 struct list_head entry; 16 struct list_head entry;
15 dr_release_t release; 17 dr_release_t release;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 89a5f4a54913..53f0ee6f3016 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -175,7 +175,7 @@ static ssize_t firmware_loading_store(struct device *dev,
175static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); 175static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
176 176
177static ssize_t 177static ssize_t
178firmware_data_read(struct kobject *kobj, 178firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
179 char *buffer, loff_t offset, size_t count) 179 char *buffer, loff_t offset, size_t count)
180{ 180{
181 struct device *dev = to_dev(kobj); 181 struct device *dev = to_dev(kobj);
@@ -240,7 +240,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
240 * the driver as a firmware image. 240 * the driver as a firmware image.
241 **/ 241 **/
242static ssize_t 242static ssize_t
243firmware_data_write(struct kobject *kobj, 243firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
244 char *buffer, loff_t offset, size_t count) 244 char *buffer, loff_t offset, size_t count)
245{ 245{
246 struct device *dev = to_dev(kobj); 246 struct device *dev = to_dev(kobj);
@@ -271,7 +271,7 @@ out:
271} 271}
272 272
273static struct bin_attribute firmware_attr_data_tmpl = { 273static struct bin_attribute firmware_attr_data_tmpl = {
274 .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE}, 274 .attr = {.name = "data", .mode = 0644},
275 .size = 0, 275 .size = 0,
276 .read = firmware_data_read, 276 .read = firmware_data_read,
277 .write = firmware_data_write, 277 .write = firmware_data_write,
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 05dc8764e765..eb9f38d0aa58 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -20,64 +20,44 @@
20 */ 20 */
21 21
22#include <linux/device.h> 22#include <linux/device.h>
23#include <linux/mutex.h>
24
23#include "power.h" 25#include "power.h"
24 26
25LIST_HEAD(dpm_active); 27LIST_HEAD(dpm_active);
26LIST_HEAD(dpm_off); 28LIST_HEAD(dpm_off);
27LIST_HEAD(dpm_off_irq); 29LIST_HEAD(dpm_off_irq);
28 30
29DECLARE_MUTEX(dpm_sem); 31DEFINE_MUTEX(dpm_mtx);
30DECLARE_MUTEX(dpm_list_sem); 32DEFINE_MUTEX(dpm_list_mtx);
31 33
32int (*platform_enable_wakeup)(struct device *dev, int is_on); 34int (*platform_enable_wakeup)(struct device *dev, int is_on);
33 35
34 36int device_pm_add(struct device *dev)
35/**
36 * device_pm_set_parent - Specify power dependency.
37 * @dev: Device who needs power.
38 * @parent: Device that supplies power.
39 *
40 * This function is used to manually describe a power-dependency
41 * relationship. It may be used to specify a transversal relationship
42 * (where the power supplier is not the physical (or electrical)
43 * ancestor of a specific device.
44 * The effect of this is that the supplier will not be powered down
45 * before the power dependent.
46 */
47
48void device_pm_set_parent(struct device * dev, struct device * parent)
49{
50 put_device(dev->power.pm_parent);
51 dev->power.pm_parent = get_device(parent);
52}
53EXPORT_SYMBOL_GPL(device_pm_set_parent);
54
55int device_pm_add(struct device * dev)
56{ 37{
57 int error; 38 int error;
58 39
59 pr_debug("PM: Adding info for %s:%s\n", 40 pr_debug("PM: Adding info for %s:%s\n",
60 dev->bus ? dev->bus->name : "No Bus", 41 dev->bus ? dev->bus->name : "No Bus",
61 kobject_name(&dev->kobj)); 42 kobject_name(&dev->kobj));
62 down(&dpm_list_sem); 43 mutex_lock(&dpm_list_mtx);
63 list_add_tail(&dev->power.entry, &dpm_active); 44 list_add_tail(&dev->power.entry, &dpm_active);
64 device_pm_set_parent(dev, dev->parent); 45 error = dpm_sysfs_add(dev);
65 if ((error = dpm_sysfs_add(dev))) 46 if (error)
66 list_del(&dev->power.entry); 47 list_del(&dev->power.entry);
67 up(&dpm_list_sem); 48 mutex_unlock(&dpm_list_mtx);
68 return error; 49 return error;
69} 50}
70 51
71void device_pm_remove(struct device * dev) 52void device_pm_remove(struct device *dev)
72{ 53{
73 pr_debug("PM: Removing info for %s:%s\n", 54 pr_debug("PM: Removing info for %s:%s\n",
74 dev->bus ? dev->bus->name : "No Bus", 55 dev->bus ? dev->bus->name : "No Bus",
75 kobject_name(&dev->kobj)); 56 kobject_name(&dev->kobj));
76 down(&dpm_list_sem); 57 mutex_lock(&dpm_list_mtx);
77 dpm_sysfs_remove(dev); 58 dpm_sysfs_remove(dev);
78 put_device(dev->power.pm_parent);
79 list_del_init(&dev->power.entry); 59 list_del_init(&dev->power.entry);
80 up(&dpm_list_sem); 60 mutex_unlock(&dpm_list_mtx);
81} 61}
82 62
83 63
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index fb3d35a9e101..2760f25b3ac5 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -14,12 +14,12 @@ extern void device_shutdown(void);
14/* 14/*
15 * Used to synchronize global power management operations. 15 * Used to synchronize global power management operations.
16 */ 16 */
17extern struct semaphore dpm_sem; 17extern struct mutex dpm_mtx;
18 18
19/* 19/*
20 * Used to serialize changes to the dpm_* lists. 20 * Used to serialize changes to the dpm_* lists.
21 */ 21 */
22extern struct semaphore dpm_list_sem; 22extern struct mutex dpm_list_mtx;
23 23
24/* 24/*
25 * The PM lists. 25 * The PM lists.
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index a2c64188d713..00fd84ae6e66 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -29,14 +29,6 @@ int resume_device(struct device * dev)
29 29
30 down(&dev->sem); 30 down(&dev->sem);
31 31
32 if (dev->power.pm_parent
33 && dev->power.pm_parent->power.power_state.event) {
34 dev_err(dev, "PM: resume from %d, parent %s still %d\n",
35 dev->power.power_state.event,
36 dev->power.pm_parent->bus_id,
37 dev->power.pm_parent->power.power_state.event);
38 }
39
40 if (dev->bus && dev->bus->resume) { 32 if (dev->bus && dev->bus->resume) {
41 dev_dbg(dev,"resuming\n"); 33 dev_dbg(dev,"resuming\n");
42 error = dev->bus->resume(dev); 34 error = dev->bus->resume(dev);
@@ -80,7 +72,7 @@ static int resume_device_early(struct device * dev)
80 */ 72 */
81void dpm_resume(void) 73void dpm_resume(void)
82{ 74{
83 down(&dpm_list_sem); 75 mutex_lock(&dpm_list_mtx);
84 while(!list_empty(&dpm_off)) { 76 while(!list_empty(&dpm_off)) {
85 struct list_head * entry = dpm_off.next; 77 struct list_head * entry = dpm_off.next;
86 struct device * dev = to_device(entry); 78 struct device * dev = to_device(entry);
@@ -88,13 +80,12 @@ void dpm_resume(void)
88 get_device(dev); 80 get_device(dev);
89 list_move_tail(entry, &dpm_active); 81 list_move_tail(entry, &dpm_active);
90 82
91 up(&dpm_list_sem); 83 mutex_unlock(&dpm_list_mtx);
92 if (!dev->power.prev_state.event) 84 resume_device(dev);
93 resume_device(dev); 85 mutex_lock(&dpm_list_mtx);
94 down(&dpm_list_sem);
95 put_device(dev); 86 put_device(dev);
96 } 87 }
97 up(&dpm_list_sem); 88 mutex_unlock(&dpm_list_mtx);
98} 89}
99 90
100 91
@@ -108,9 +99,9 @@ void dpm_resume(void)
108void device_resume(void) 99void device_resume(void)
109{ 100{
110 might_sleep(); 101 might_sleep();
111 down(&dpm_sem); 102 mutex_lock(&dpm_mtx);
112 dpm_resume(); 103 dpm_resume();
113 up(&dpm_sem); 104 mutex_unlock(&dpm_mtx);
114} 105}
115 106
116EXPORT_SYMBOL_GPL(device_resume); 107EXPORT_SYMBOL_GPL(device_resume);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 96370ec1d673..df6174d85866 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -32,9 +32,9 @@ static void runtime_resume(struct device * dev)
32 32
33void dpm_runtime_resume(struct device * dev) 33void dpm_runtime_resume(struct device * dev)
34{ 34{
35 down(&dpm_sem); 35 mutex_lock(&dpm_mtx);
36 runtime_resume(dev); 36 runtime_resume(dev);
37 up(&dpm_sem); 37 mutex_unlock(&dpm_mtx);
38} 38}
39EXPORT_SYMBOL(dpm_runtime_resume); 39EXPORT_SYMBOL(dpm_runtime_resume);
40 40
@@ -49,7 +49,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
49{ 49{
50 int error = 0; 50 int error = 0;
51 51
52 down(&dpm_sem); 52 mutex_lock(&dpm_mtx);
53 if (dev->power.power_state.event == state.event) 53 if (dev->power.power_state.event == state.event)
54 goto Done; 54 goto Done;
55 55
@@ -59,7 +59,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
59 if (!(error = suspend_device(dev, state))) 59 if (!(error = suspend_device(dev, state)))
60 dev->power.power_state = state; 60 dev->power.power_state = state;
61 Done: 61 Done:
62 up(&dpm_sem); 62 mutex_unlock(&dpm_mtx);
63 return error; 63 return error;
64} 64}
65EXPORT_SYMBOL(dpm_runtime_suspend); 65EXPORT_SYMBOL(dpm_runtime_suspend);
@@ -78,8 +78,8 @@ EXPORT_SYMBOL(dpm_runtime_suspend);
78 */ 78 */
79void dpm_set_power_state(struct device * dev, pm_message_t state) 79void dpm_set_power_state(struct device * dev, pm_message_t state)
80{ 80{
81 down(&dpm_sem); 81 mutex_lock(&dpm_mtx);
82 dev->power.power_state = state; 82 dev->power.power_state = state;
83 up(&dpm_sem); 83 mutex_unlock(&dpm_mtx);
84} 84}
85#endif /* 0 */ 85#endif /* 0 */
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 42d2b86ba765..26df9b231737 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -40,6 +40,14 @@ static inline char *suspend_verb(u32 event)
40} 40}
41 41
42 42
43static void
44suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
45{
46 dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
47 ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
48 ", may wakeup" : "");
49}
50
43/** 51/**
44 * suspend_device - Save state of one device. 52 * suspend_device - Save state of one device.
45 * @dev: Device. 53 * @dev: Device.
@@ -55,49 +63,21 @@ int suspend_device(struct device * dev, pm_message_t state)
55 dev_dbg(dev, "PM: suspend %d-->%d\n", 63 dev_dbg(dev, "PM: suspend %d-->%d\n",
56 dev->power.power_state.event, state.event); 64 dev->power.power_state.event, state.event);
57 } 65 }
58 if (dev->power.pm_parent
59 && dev->power.pm_parent->power.power_state.event) {
60 dev_err(dev,
61 "PM: suspend %d->%d, parent %s already %d\n",
62 dev->power.power_state.event, state.event,
63 dev->power.pm_parent->bus_id,
64 dev->power.pm_parent->power.power_state.event);
65 }
66
67 dev->power.prev_state = dev->power.power_state;
68 66
69 if (dev->class && dev->class->suspend && !dev->power.power_state.event) { 67 if (dev->class && dev->class->suspend) {
70 dev_dbg(dev, "class %s%s\n", 68 suspend_device_dbg(dev, state, "class ");
71 suspend_verb(state.event),
72 ((state.event == PM_EVENT_SUSPEND)
73 && device_may_wakeup(dev))
74 ? ", may wakeup"
75 : ""
76 );
77 error = dev->class->suspend(dev, state); 69 error = dev->class->suspend(dev, state);
78 suspend_report_result(dev->class->suspend, error); 70 suspend_report_result(dev->class->suspend, error);
79 } 71 }
80 72
81 if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) { 73 if (!error && dev->type && dev->type->suspend) {
82 dev_dbg(dev, "%s%s\n", 74 suspend_device_dbg(dev, state, "type ");
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); 75 error = dev->type->suspend(dev, state);
90 suspend_report_result(dev->type->suspend, error); 76 suspend_report_result(dev->type->suspend, error);
91 } 77 }
92 78
93 if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) { 79 if (!error && dev->bus && dev->bus->suspend) {
94 dev_dbg(dev, "%s%s\n", 80 suspend_device_dbg(dev, state, "");
95 suspend_verb(state.event),
96 ((state.event == PM_EVENT_SUSPEND)
97 && device_may_wakeup(dev))
98 ? ", may wakeup"
99 : ""
100 );
101 error = dev->bus->suspend(dev, state); 81 error = dev->bus->suspend(dev, state);
102 suspend_report_result(dev->bus->suspend, error); 82 suspend_report_result(dev->bus->suspend, error);
103 } 83 }
@@ -108,21 +88,15 @@ int suspend_device(struct device * dev, pm_message_t state)
108 88
109/* 89/*
110 * This is called with interrupts off, only a single CPU 90 * This is called with interrupts off, only a single CPU
111 * running. We can't do down() on a semaphore (and we don't 91 * running. We can't acquire a mutex or semaphore (and we don't
112 * need the protection) 92 * need the protection)
113 */ 93 */
114static int suspend_device_late(struct device *dev, pm_message_t state) 94static int suspend_device_late(struct device *dev, pm_message_t state)
115{ 95{
116 int error = 0; 96 int error = 0;
117 97
118 if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) { 98 if (dev->bus && dev->bus->suspend_late) {
119 dev_dbg(dev, "LATE %s%s\n", 99 suspend_device_dbg(dev, state, "LATE ");
120 suspend_verb(state.event),
121 ((state.event == PM_EVENT_SUSPEND)
122 && device_may_wakeup(dev))
123 ? ", may wakeup"
124 : ""
125 );
126 error = dev->bus->suspend_late(dev, state); 100 error = dev->bus->suspend_late(dev, state);
127 suspend_report_result(dev->bus->suspend_late, error); 101 suspend_report_result(dev->bus->suspend_late, error);
128 } 102 }
@@ -153,18 +127,18 @@ int device_suspend(pm_message_t state)
153 int error = 0; 127 int error = 0;
154 128
155 might_sleep(); 129 might_sleep();
156 down(&dpm_sem); 130 mutex_lock(&dpm_mtx);
157 down(&dpm_list_sem); 131 mutex_lock(&dpm_list_mtx);
158 while (!list_empty(&dpm_active) && error == 0) { 132 while (!list_empty(&dpm_active) && error == 0) {
159 struct list_head * entry = dpm_active.prev; 133 struct list_head * entry = dpm_active.prev;
160 struct device * dev = to_device(entry); 134 struct device * dev = to_device(entry);
161 135
162 get_device(dev); 136 get_device(dev);
163 up(&dpm_list_sem); 137 mutex_unlock(&dpm_list_mtx);
164 138
165 error = suspend_device(dev, state); 139 error = suspend_device(dev, state);
166 140
167 down(&dpm_list_sem); 141 mutex_lock(&dpm_list_mtx);
168 142
169 /* Check if the device got removed */ 143 /* Check if the device got removed */
170 if (!list_empty(&dev->power.entry)) { 144 if (!list_empty(&dev->power.entry)) {
@@ -179,11 +153,11 @@ int device_suspend(pm_message_t state)
179 error == -EAGAIN ? " (please convert to suspend_late)" : ""); 153 error == -EAGAIN ? " (please convert to suspend_late)" : "");
180 put_device(dev); 154 put_device(dev);
181 } 155 }
182 up(&dpm_list_sem); 156 mutex_unlock(&dpm_list_mtx);
183 if (error) 157 if (error)
184 dpm_resume(); 158 dpm_resume();
185 159
186 up(&dpm_sem); 160 mutex_unlock(&dpm_mtx);
187 return error; 161 return error;
188} 162}
189 163
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 29f1291966c1..18febe26caa1 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,7 +21,7 @@
21#include <linux/string.h> 21#include <linux/string.h>
22#include <linux/pm.h> 22#include <linux/pm.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include <asm/semaphore.h> 24#include <linux/mutex.h>
25 25
26#include "base.h" 26#include "base.h"
27 27
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister);
155 155
156 156
157static LIST_HEAD(sysdev_drivers); 157static LIST_HEAD(sysdev_drivers);
158static DECLARE_MUTEX(sysdev_drivers_lock); 158static DEFINE_MUTEX(sysdev_drivers_lock);
159 159
160/** 160/**
161 * sysdev_driver_register - Register auxillary driver 161 * sysdev_driver_register - Register auxillary driver
@@ -172,7 +172,7 @@ static DECLARE_MUTEX(sysdev_drivers_lock);
172int sysdev_driver_register(struct sysdev_class * cls, 172int sysdev_driver_register(struct sysdev_class * cls,
173 struct sysdev_driver * drv) 173 struct sysdev_driver * drv)
174{ 174{
175 down(&sysdev_drivers_lock); 175 mutex_lock(&sysdev_drivers_lock);
176 if (cls && kset_get(&cls->kset)) { 176 if (cls && kset_get(&cls->kset)) {
177 list_add_tail(&drv->entry, &cls->drivers); 177 list_add_tail(&drv->entry, &cls->drivers);
178 178
@@ -184,7 +184,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
184 } 184 }
185 } else 185 } else
186 list_add_tail(&drv->entry, &sysdev_drivers); 186 list_add_tail(&drv->entry, &sysdev_drivers);
187 up(&sysdev_drivers_lock); 187 mutex_unlock(&sysdev_drivers_lock);
188 return 0; 188 return 0;
189} 189}
190 190
@@ -197,7 +197,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
197void sysdev_driver_unregister(struct sysdev_class * cls, 197void sysdev_driver_unregister(struct sysdev_class * cls,
198 struct sysdev_driver * drv) 198 struct sysdev_driver * drv)
199{ 199{
200 down(&sysdev_drivers_lock); 200 mutex_lock(&sysdev_drivers_lock);
201 list_del_init(&drv->entry); 201 list_del_init(&drv->entry);
202 if (cls) { 202 if (cls) {
203 if (drv->remove) { 203 if (drv->remove) {
@@ -207,7 +207,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
207 } 207 }
208 kset_put(&cls->kset); 208 kset_put(&cls->kset);
209 } 209 }
210 up(&sysdev_drivers_lock); 210 mutex_unlock(&sysdev_drivers_lock);
211} 211}
212 212
213EXPORT_SYMBOL_GPL(sysdev_driver_register); 213EXPORT_SYMBOL_GPL(sysdev_driver_register);
@@ -246,7 +246,7 @@ int sysdev_register(struct sys_device * sysdev)
246 if (!error) { 246 if (!error) {
247 struct sysdev_driver * drv; 247 struct sysdev_driver * drv;
248 248
249 down(&sysdev_drivers_lock); 249 mutex_lock(&sysdev_drivers_lock);
250 /* Generic notification is implicit, because it's that 250 /* Generic notification is implicit, because it's that
251 * code that should have called us. 251 * code that should have called us.
252 */ 252 */
@@ -262,7 +262,7 @@ int sysdev_register(struct sys_device * sysdev)
262 if (drv->add) 262 if (drv->add)
263 drv->add(sysdev); 263 drv->add(sysdev);
264 } 264 }
265 up(&sysdev_drivers_lock); 265 mutex_unlock(&sysdev_drivers_lock);
266 } 266 }
267 return error; 267 return error;
268} 268}
@@ -271,7 +271,7 @@ void sysdev_unregister(struct sys_device * sysdev)
271{ 271{
272 struct sysdev_driver * drv; 272 struct sysdev_driver * drv;
273 273
274 down(&sysdev_drivers_lock); 274 mutex_lock(&sysdev_drivers_lock);
275 list_for_each_entry(drv, &sysdev_drivers, entry) { 275 list_for_each_entry(drv, &sysdev_drivers, entry) {
276 if (drv->remove) 276 if (drv->remove)
277 drv->remove(sysdev); 277 drv->remove(sysdev);
@@ -281,7 +281,7 @@ void sysdev_unregister(struct sys_device * sysdev)
281 if (drv->remove) 281 if (drv->remove)
282 drv->remove(sysdev); 282 drv->remove(sysdev);
283 } 283 }
284 up(&sysdev_drivers_lock); 284 mutex_unlock(&sysdev_drivers_lock);
285 285
286 kobject_unregister(&sysdev->kobj); 286 kobject_unregister(&sysdev->kobj);
287} 287}
@@ -308,7 +308,7 @@ void sysdev_shutdown(void)
308 308
309 pr_debug("Shutting Down System Devices\n"); 309 pr_debug("Shutting Down System Devices\n");
310 310
311 down(&sysdev_drivers_lock); 311 mutex_lock(&sysdev_drivers_lock);
312 list_for_each_entry_reverse(cls, &system_subsys.list, 312 list_for_each_entry_reverse(cls, &system_subsys.list,
313 kset.kobj.entry) { 313 kset.kobj.entry) {
314 struct sys_device * sysdev; 314 struct sys_device * sysdev;
@@ -337,7 +337,7 @@ void sysdev_shutdown(void)
337 cls->shutdown(sysdev); 337 cls->shutdown(sysdev);
338 } 338 }
339 } 339 }
340 up(&sysdev_drivers_lock); 340 mutex_unlock(&sysdev_drivers_lock);
341} 341}
342 342
343static void __sysdev_resume(struct sys_device *dev) 343static void __sysdev_resume(struct sys_device *dev)