summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Goby <benoit@android.com>2011-01-26 18:28:33 -0800
committerBenoit Goby <benoit@android.com>2011-01-27 22:57:54 -0800
commit6f0193721acf50368b585e3fad8c206049e2e07a (patch)
tree3a3257257d34e5d7f582aff144366ddf883a629e
parenteac4ccd16357ad77f34c28813d8fcf35ba81fa33 (diff)
PM: Change dpm watchdog to support async suspend
Exclude from the watchdog the time spent waiting for children that are resumed asynchronously and time every devices, whether or not they resumed synchronously. Change-Id: I84209dfd5df72842e045096c906fd61e20e6d183 Signed-off-by: Benoit Goby <benoit@android.com>
-rw-r--r--drivers/base/power/main.c50
1 files changed, 20 insertions, 30 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 33f9aafb47fb..4ff491f49ee4 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -47,11 +47,10 @@ static DEFINE_MUTEX(dpm_list_mtx);
static pm_message_t pm_transition;
static void dpm_drv_timeout(unsigned long data);
-static DEFINE_TIMER(dpm_drv_wd, dpm_drv_timeout, 0, 0);
-static struct {
+struct dpm_drv_wd_data {
struct device *dev;
struct task_struct *tsk;
-} dpm_drv_wd_data;
+};
/*
* Set once the preparation of devices for a PM transition has started, reset
@@ -605,8 +604,9 @@ static bool is_async(struct device *dev)
*/
static void dpm_drv_timeout(unsigned long data)
{
- struct device *dev = dpm_drv_wd_data.dev;
- struct task_struct *tsk = dpm_drv_wd_data.tsk;
+ struct dpm_drv_wd_data *wd_data = (void *)data;
+ struct device *dev = wd_data->dev;
+ struct task_struct *tsk = wd_data->tsk;
printk(KERN_EMERG "**** DPM device timeout: %s (%s)\n", dev_name(dev),
(dev->driver ? dev->driver->name : "no driver"));
@@ -618,29 +618,6 @@ static void dpm_drv_timeout(unsigned long data)
}
/**
- * dpm_drv_wdset - Sets up driver suspend/resume watchdog timer.
- * @dev: struct device which we're guarding.
- *
- */
-static void dpm_drv_wdset(struct device *dev)
-{
- dpm_drv_wd_data.dev = dev;
- dpm_drv_wd_data.tsk = get_current();
- dpm_drv_wd.data = (unsigned long) &dpm_drv_wd_data;
- mod_timer(&dpm_drv_wd, jiffies + (HZ * 3));
-}
-
-/**
- * dpm_drv_wdclr - clears driver suspend/resume watchdog timer.
- * @dev: struct device which we're no longer guarding.
- *
- */
-static void dpm_drv_wdclr(struct device *dev)
-{
- del_timer_sync(&dpm_drv_wd);
-}
-
-/**
* dpm_resume - Execute "resume" callbacks for non-sysdev devices.
* @state: PM transition of the system being carried out.
*
@@ -896,8 +873,19 @@ static int async_error;
static int __device_suspend(struct device *dev, pm_message_t state, bool async)
{
int error = 0;
+ struct timer_list timer;
+ struct dpm_drv_wd_data data;
dpm_wait_for_children(dev, async);
+
+ data.dev = dev;
+ data.tsk = get_current();
+ init_timer_on_stack(&timer);
+ timer.expires = jiffies + HZ * 3;
+ timer.function = dpm_drv_timeout;
+ timer.data = (unsigned long)&data;
+ add_timer(&timer);
+
device_lock(dev);
if (async_error)
@@ -939,6 +927,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
End:
device_unlock(dev);
+
+ del_timer_sync(&timer);
+ destroy_timer_on_stack(&timer);
+
complete_all(&dev->power.completion);
return error;
@@ -991,9 +983,7 @@ static int dpm_suspend(pm_message_t state)
get_device(dev);
mutex_unlock(&dpm_list_mtx);
- dpm_drv_wdset(dev);
error = device_suspend(dev);
- dpm_drv_wdclr(dev);
mutex_lock(&dpm_list_mtx);
if (error) {