summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRebecca Schultz Zavin <rebecca@android.com>2011-01-28 21:58:22 -0800
committerRebecca Schultz Zavin <rebecca@android.com>2011-01-28 21:58:22 -0800
commitbfb8b878f3e4b004eae71ad55ad3f3baca57452a (patch)
tree6c3192a7486e53b138d2620c99ef62103e46ea57
parent8f47f22d81d514a3c947d161b2fcd4a51351a5da (diff)
parent6f0193721acf50368b585e3fad8c206049e2e07a (diff)
Merge remote branch 'common/android-2.6.36' into android-tegra-2.6.36
-rw-r--r--drivers/base/power/main.c50
-rw-r--r--kernel/irq/pm.c6
2 files changed, 25 insertions, 31 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) {
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index 0d4005d85b03..1df62ef4713b 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -72,8 +72,12 @@ int check_wakeup_irqs(void)
int irq;
for_each_irq_desc(irq, desc)
- if ((desc->status & IRQ_WAKEUP) && (desc->status & IRQ_PENDING))
+ if ((desc->status & IRQ_WAKEUP) &&
+ (desc->status & IRQ_PENDING)) {
+ pr_info("Wakeup IRQ %d %s pending, suspend aborted\n",
+ irq, desc->name ? desc->name : "");
return -EBUSY;
+ }
return 0;
}