summaryrefslogtreecommitdiffstats
path: root/drivers/base/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power')
-rw-r--r--drivers/base/power/main.c9
-rw-r--r--drivers/base/power/resume.c13
-rw-r--r--drivers/base/power/shutdown.c2
-rw-r--r--drivers/base/power/suspend.c12
4 files changed, 31 insertions, 5 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index fdfa3d0cf6a..05dc8764e76 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -29,6 +29,9 @@ LIST_HEAD(dpm_off_irq);
DECLARE_MUTEX(dpm_sem);
DECLARE_MUTEX(dpm_list_sem);
+int (*platform_enable_wakeup)(struct device *dev, int is_on);
+
+
/**
* device_pm_set_parent - Specify power dependency.
* @dev: Device who needs power.
@@ -54,7 +57,8 @@ int device_pm_add(struct device * dev)
int error;
pr_debug("PM: Adding info for %s:%s\n",
- dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
+ dev->bus ? dev->bus->name : "No Bus",
+ kobject_name(&dev->kobj));
down(&dpm_list_sem);
list_add_tail(&dev->power.entry, &dpm_active);
device_pm_set_parent(dev, dev->parent);
@@ -67,7 +71,8 @@ int device_pm_add(struct device * dev)
void device_pm_remove(struct device * dev)
{
pr_debug("PM: Removing info for %s:%s\n",
- dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
+ dev->bus ? dev->bus->name : "No Bus",
+ kobject_name(&dev->kobj));
down(&dpm_list_sem);
dpm_sysfs_remove(dev);
put_device(dev->power.pm_parent);
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 020be36705a..a2c64188d71 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -26,7 +26,9 @@ int resume_device(struct device * dev)
TRACE_DEVICE(dev);
TRACE_RESUME(0);
+
down(&dev->sem);
+
if (dev->power.pm_parent
&& dev->power.pm_parent->power.power_state.event) {
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
@@ -34,15 +36,24 @@ int resume_device(struct device * dev)
dev->power.pm_parent->bus_id,
dev->power.pm_parent->power.power_state.event);
}
+
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
error = dev->bus->resume(dev);
}
- if (dev->class && dev->class->resume) {
+
+ if (!error && dev->type && dev->type->resume) {
+ dev_dbg(dev,"resuming\n");
+ error = dev->type->resume(dev);
+ }
+
+ if (!error && dev->class && dev->class->resume) {
dev_dbg(dev,"class resume\n");
error = dev->class->resume(dev);
}
+
up(&dev->sem);
+
TRACE_RESUME(error);
return error;
}
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index 3483ae4d57f..58b6f77a1b3 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -36,7 +36,6 @@ void device_shutdown(void)
{
struct device * dev, *devn;
- down_write(&devices_subsys.rwsem);
list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list,
kobj.entry) {
if (dev->bus && dev->bus->shutdown) {
@@ -47,7 +46,6 @@ void device_shutdown(void)
dev->driver->shutdown(dev);
}
}
- up_write(&devices_subsys.rwsem);
sysdev_shutdown();
}
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index ece136bf97e..42d2b86ba76 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)
suspend_report_result(dev->class->suspend, error);
}
+ if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) {
+ dev_dbg(dev, "%s%s\n",
+ suspend_verb(state.event),
+ ((state.event == PM_EVENT_SUSPEND)
+ && device_may_wakeup(dev))
+ ? ", may wakeup"
+ : ""
+ );
+ error = dev->type->suspend(dev, state);
+ suspend_report_result(dev->type->suspend, error);
+ }
+
if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "%s%s\n",
suspend_verb(state.event),