aboutsummaryrefslogtreecommitdiff
path: root/drivers/base/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power')
-rw-r--r--drivers/base/power/Makefile4
-rw-r--r--drivers/base/power/main.c44
-rw-r--r--drivers/base/power/power.h9
-rw-r--r--drivers/base/power/resume.c23
-rw-r--r--drivers/base/power/runtime.c85
-rw-r--r--drivers/base/power/suspend.c72
-rw-r--r--drivers/base/power/sysfs.c66
-rw-r--r--drivers/base/power/trace.c5
8 files changed, 50 insertions, 258 deletions
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index 91f230939c1..966a5e28741 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,10 +1,10 @@
obj-y := shutdown.o
-obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o
+obj-$(CONFIG_PM) += main.o suspend.o resume.o sysfs.o
obj-$(CONFIG_PM_TRACE) += trace.o
ifeq ($(CONFIG_DEBUG_DRIVER),y)
EXTRA_CFLAGS += -DDEBUG
endif
-ifeq ($(CONFIG_PM_DEBUG),y)
+ifeq ($(CONFIG_PM_VERBOSE),y)
EXTRA_CFLAGS += -DDEBUG
endif
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 05dc8764e76..eb9f38d0aa5 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -20,64 +20,44 @@
*/
#include <linux/device.h>
+#include <linux/mutex.h>
+
#include "power.h"
LIST_HEAD(dpm_active);
LIST_HEAD(dpm_off);
LIST_HEAD(dpm_off_irq);
-DECLARE_MUTEX(dpm_sem);
-DECLARE_MUTEX(dpm_list_sem);
+DEFINE_MUTEX(dpm_mtx);
+DEFINE_MUTEX(dpm_list_mtx);
int (*platform_enable_wakeup)(struct device *dev, int is_on);
-
-/**
- * device_pm_set_parent - Specify power dependency.
- * @dev: Device who needs power.
- * @parent: Device that supplies power.
- *
- * This function is used to manually describe a power-dependency
- * relationship. It may be used to specify a transversal relationship
- * (where the power supplier is not the physical (or electrical)
- * ancestor of a specific device.
- * The effect of this is that the supplier will not be powered down
- * before the power dependent.
- */
-
-void device_pm_set_parent(struct device * dev, struct device * parent)
-{
- put_device(dev->power.pm_parent);
- dev->power.pm_parent = get_device(parent);
-}
-EXPORT_SYMBOL_GPL(device_pm_set_parent);
-
-int device_pm_add(struct device * dev)
+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",
kobject_name(&dev->kobj));
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
list_add_tail(&dev->power.entry, &dpm_active);
- device_pm_set_parent(dev, dev->parent);
- if ((error = dpm_sysfs_add(dev)))
+ error = dpm_sysfs_add(dev);
+ if (error)
list_del(&dev->power.entry);
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
return error;
}
-void device_pm_remove(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",
kobject_name(&dev->kobj));
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
dpm_sysfs_remove(dev);
- put_device(dev->power.pm_parent);
list_del_init(&dev->power.entry);
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index fb3d35a9e10..591a0dd5dee 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -14,12 +14,12 @@ extern void device_shutdown(void);
/*
* Used to synchronize global power management operations.
*/
-extern struct semaphore dpm_sem;
+extern struct mutex dpm_mtx;
/*
* Used to serialize changes to the dpm_* lists.
*/
-extern struct semaphore dpm_list_sem;
+extern struct mutex dpm_list_mtx;
/*
* The PM lists.
@@ -62,11 +62,6 @@ extern int resume_device(struct device *);
*/
extern int suspend_device(struct device *, pm_message_t);
-
-/*
- * runtime.c
- */
-
#else /* CONFIG_PM */
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index a2c64188d71..00fd84ae6e6 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -29,14 +29,6 @@ int resume_device(struct device * dev)
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",
- dev->power.power_state.event,
- 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);
@@ -80,7 +72,7 @@ static int resume_device_early(struct device * dev)
*/
void dpm_resume(void)
{
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
while(!list_empty(&dpm_off)) {
struct list_head * entry = dpm_off.next;
struct device * dev = to_device(entry);
@@ -88,13 +80,12 @@ void dpm_resume(void)
get_device(dev);
list_move_tail(entry, &dpm_active);
- up(&dpm_list_sem);
- if (!dev->power.prev_state.event)
- resume_device(dev);
- down(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
+ resume_device(dev);
+ mutex_lock(&dpm_list_mtx);
put_device(dev);
}
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
}
@@ -108,9 +99,9 @@ void dpm_resume(void)
void device_resume(void)
{
might_sleep();
- down(&dpm_sem);
+ mutex_lock(&dpm_mtx);
dpm_resume();
- up(&dpm_sem);
+ mutex_unlock(&dpm_mtx);
}
EXPORT_SYMBOL_GPL(device_resume);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
deleted file mode 100644
index 96370ec1d67..00000000000
--- a/drivers/base/power/runtime.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * drivers/base/power/runtime.c - Handling dynamic device power management.
- *
- * Copyright (c) 2003 Patrick Mochel
- * Copyright (c) 2003 Open Source Development Lab
- *
- */
-
-#include <linux/device.h>
-#include "power.h"
-
-
-static void runtime_resume(struct device * dev)
-{
- dev_dbg(dev, "resuming\n");
- if (!dev->power.power_state.event)
- return;
- if (!resume_device(dev))
- dev->power.power_state = PMSG_ON;
-}
-
-
-/**
- * dpm_runtime_resume - Power one device back on.
- * @dev: Device.
- *
- * Bring one device back to the on state by first powering it
- * on, then restoring state. We only operate on devices that aren't
- * already on.
- * FIXME: We need to handle devices that are in an unknown state.
- */
-
-void dpm_runtime_resume(struct device * dev)
-{
- down(&dpm_sem);
- runtime_resume(dev);
- up(&dpm_sem);
-}
-EXPORT_SYMBOL(dpm_runtime_resume);
-
-
-/**
- * dpm_runtime_suspend - Put one device in low-power state.
- * @dev: Device.
- * @state: State to enter.
- */
-
-int dpm_runtime_suspend(struct device * dev, pm_message_t state)
-{
- int error = 0;
-
- down(&dpm_sem);
- if (dev->power.power_state.event == state.event)
- goto Done;
-
- if (dev->power.power_state.event)
- runtime_resume(dev);
-
- if (!(error = suspend_device(dev, state)))
- dev->power.power_state = state;
- Done:
- up(&dpm_sem);
- return error;
-}
-EXPORT_SYMBOL(dpm_runtime_suspend);
-
-
-#if 0
-/**
- * dpm_set_power_state - Update power_state field.
- * @dev: Device.
- * @state: Power state device is in.
- *
- * This is an update mechanism for drivers to notify the core
- * what power state a device is in. Device probing code may not
- * always be able to tell, but we need accurate information to
- * work reliably.
- */
-void dpm_set_power_state(struct device * dev, pm_message_t state)
-{
- down(&dpm_sem);
- dev->power.power_state = state;
- up(&dpm_sem);
-}
-#endif /* 0 */
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 42d2b86ba76..26df9b23173 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -40,6 +40,14 @@ static inline char *suspend_verb(u32 event)
}
+static void
+suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
+{
+ dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
+ ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
+ ", may wakeup" : "");
+}
+
/**
* suspend_device - Save state of one device.
* @dev: Device.
@@ -55,49 +63,21 @@ int suspend_device(struct device * dev, pm_message_t state)
dev_dbg(dev, "PM: suspend %d-->%d\n",
dev->power.power_state.event, state.event);
}
- if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state.event) {
- dev_err(dev,
- "PM: suspend %d->%d, parent %s already %d\n",
- dev->power.power_state.event, state.event,
- dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state.event);
- }
-
- dev->power.prev_state = dev->power.power_state;
- if (dev->class && dev->class->suspend && !dev->power.power_state.event) {
- dev_dbg(dev, "class %s%s\n",
- suspend_verb(state.event),
- ((state.event == PM_EVENT_SUSPEND)
- && device_may_wakeup(dev))
- ? ", may wakeup"
- : ""
- );
+ if (dev->class && dev->class->suspend) {
+ suspend_device_dbg(dev, state, "class ");
error = dev->class->suspend(dev, 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"
- : ""
- );
+ if (!error && dev->type && dev->type->suspend) {
+ suspend_device_dbg(dev, state, "type ");
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),
- ((state.event == PM_EVENT_SUSPEND)
- && device_may_wakeup(dev))
- ? ", may wakeup"
- : ""
- );
+ if (!error && dev->bus && dev->bus->suspend) {
+ suspend_device_dbg(dev, state, "");
error = dev->bus->suspend(dev, state);
suspend_report_result(dev->bus->suspend, error);
}
@@ -108,21 +88,15 @@ int suspend_device(struct device * dev, pm_message_t state)
/*
* This is called with interrupts off, only a single CPU
- * running. We can't do down() on a semaphore (and we don't
+ * running. We can't acquire a mutex or semaphore (and we don't
* need the protection)
*/
static int suspend_device_late(struct device *dev, pm_message_t state)
{
int error = 0;
- if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) {
- dev_dbg(dev, "LATE %s%s\n",
- suspend_verb(state.event),
- ((state.event == PM_EVENT_SUSPEND)
- && device_may_wakeup(dev))
- ? ", may wakeup"
- : ""
- );
+ if (dev->bus && dev->bus->suspend_late) {
+ suspend_device_dbg(dev, state, "LATE ");
error = dev->bus->suspend_late(dev, state);
suspend_report_result(dev->bus->suspend_late, error);
}
@@ -153,18 +127,18 @@ int device_suspend(pm_message_t state)
int error = 0;
might_sleep();
- down(&dpm_sem);
- down(&dpm_list_sem);
+ mutex_lock(&dpm_mtx);
+ mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_active) && error == 0) {
struct list_head * entry = dpm_active.prev;
struct device * dev = to_device(entry);
get_device(dev);
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
error = suspend_device(dev, state);
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
/* Check if the device got removed */
if (!list_empty(&dev->power.entry)) {
@@ -179,11 +153,11 @@ int device_suspend(pm_message_t state)
error == -EAGAIN ? " (please convert to suspend_late)" : "");
put_device(dev);
}
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
if (error)
dpm_resume();
- up(&dpm_sem);
+ mutex_unlock(&dpm_mtx);
return error;
}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 2d47517dbe3..f2ed179cd69 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -7,69 +7,6 @@
#include "power.h"
-#ifdef CONFIG_PM_SYSFS_DEPRECATED
-
-/**
- * state - Control current power state of device
- *
- * show() returns the current power state of the device. '0' indicates
- * the device is on. Other values (2) indicate the device is in some low
- * power state.
- *
- * store() sets the current power state, which is an integer valued
- * 0, 2, or 3. Devices with bus.suspend_late(), or bus.resume_early()
- * methods fail this operation; those methods couldn't be called.
- * Otherwise,
- *
- * - If the recorded dev->power.power_state.event matches the
- * target value, nothing is done.
- * - If the recorded event code is nonzero, the device is reactivated
- * by calling bus.resume() and/or class.resume().
- * - If the target value is nonzero, the device is suspended by
- * calling class.suspend() and/or bus.suspend() with event code
- * PM_EVENT_SUSPEND.
- *
- * This mechanism is DEPRECATED and should only be used for testing.
- */
-
-static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
-{
- if (dev->power.power_state.event)
- return sprintf(buf, "2\n");
- else
- return sprintf(buf, "0\n");
-}
-
-static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
-{
- pm_message_t state;
- int error = -EINVAL;
-
- /* disallow incomplete suspend sequences */
- if (dev->bus && (dev->bus->suspend_late || dev->bus->resume_early))
- return error;
-
- state.event = PM_EVENT_SUSPEND;
- /* Older apps expected to write "3" here - confused with PCI D3 */
- if ((n == 1) && !strcmp(buf, "3"))
- error = dpm_runtime_suspend(dev, state);
-
- if ((n == 1) && !strcmp(buf, "2"))
- error = dpm_runtime_suspend(dev, state);
-
- if ((n == 1) && !strcmp(buf, "0")) {
- dpm_runtime_resume(dev);
- error = 0;
- }
-
- return error ? error : n;
-}
-
-static DEVICE_ATTR(state, 0644, state_show, state_store);
-
-
-#endif /* CONFIG_PM_SYSFS_DEPRECATED */
-
/*
* wakeup - Report/change current wakeup option for device
*
@@ -143,9 +80,6 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
static struct attribute * power_attrs[] = {
-#ifdef CONFIG_PM_SYSFS_DEPRECATED
- &dev_attr_state.attr,
-#endif
&dev_attr_wakeup.attr,
NULL,
};
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index a9ab30fefff..2b0c601e422 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -142,6 +142,7 @@ void set_trace_device(struct device *dev)
{
dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH);
}
+EXPORT_SYMBOL(set_trace_device);
/*
* We could just take the "tracedata" index into the .tracedata
@@ -162,6 +163,7 @@ void generate_resume_trace(void *tracedata, unsigned int user)
file_hash_value = hash_string(lineno, file, FILEHASH);
set_magic_time(user_hash_value, file_hash_value, dev_hash_value);
}
+EXPORT_SYMBOL(generate_resume_trace);
extern char __tracedata_start, __tracedata_end;
static int show_file_hash(unsigned int value)
@@ -170,7 +172,8 @@ static int show_file_hash(unsigned int value)
char *tracedata;
match = 0;
- for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) {
+ for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ;
+ tracedata += 2 + sizeof(unsigned long)) {
unsigned short lineno = *(unsigned short *)tracedata;
const char *file = *(const char **)(tracedata + 2);
unsigned int hash = hash_string(lineno, file, FILEHASH);