diff options
Diffstat (limited to 'drivers/base/power')
-rw-r--r-- | drivers/base/power/main.c | 44 | ||||
-rw-r--r-- | drivers/base/power/power.h | 4 | ||||
-rw-r--r-- | drivers/base/power/resume.c | 23 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 12 | ||||
-rw-r--r-- | drivers/base/power/suspend.c | 72 |
5 files changed, 50 insertions, 105 deletions
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..2760f25b3ac 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. 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 index 96370ec1d67..df6174d8586 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -32,9 +32,9 @@ static void runtime_resume(struct device * dev) void dpm_runtime_resume(struct device * dev) { - down(&dpm_sem); + mutex_lock(&dpm_mtx); runtime_resume(dev); - up(&dpm_sem); + mutex_unlock(&dpm_mtx); } EXPORT_SYMBOL(dpm_runtime_resume); @@ -49,7 +49,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state) { int error = 0; - down(&dpm_sem); + mutex_lock(&dpm_mtx); if (dev->power.power_state.event == state.event) goto Done; @@ -59,7 +59,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state) if (!(error = suspend_device(dev, state))) dev->power.power_state = state; Done: - up(&dpm_sem); + mutex_unlock(&dpm_mtx); return error; } EXPORT_SYMBOL(dpm_runtime_suspend); @@ -78,8 +78,8 @@ EXPORT_SYMBOL(dpm_runtime_suspend); */ void dpm_set_power_state(struct device * dev, pm_message_t state) { - down(&dpm_sem); + mutex_lock(&dpm_mtx); dev->power.power_state = state; - up(&dpm_sem); + mutex_unlock(&dpm_mtx); } #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; } |