aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/wakeirq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power/wakeirq.c')
-rw-r--r--drivers/base/power/wakeirq.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index 404d94c6c8bc..ae0429827f31 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -141,6 +141,13 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
struct wake_irq *wirq = _wirq;
int res;
+ /* Maybe abort suspend? */
+ if (irqd_is_wakeup_set(irq_get_irq_data(irq))) {
+ pm_wakeup_event(wirq->dev, 0);
+
+ return IRQ_HANDLED;
+ }
+
/* We don't want RPM_ASYNC or RPM_NOWAIT here */
res = pm_runtime_resume(wirq->dev);
if (res < 0)
@@ -183,6 +190,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
wirq->irq = irq;
irq_set_status_flags(irq, IRQ_NOAUTOEN);
+ /* Prevent deferred spurious wakeirqs with disable_irq_nosync() */
+ irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
+
/*
* Consumer device may need to power up and restore state
* so we use a threaded irq.
@@ -312,8 +322,12 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq)
if (!wirq)
return;
- if (device_may_wakeup(wirq->dev))
+ if (device_may_wakeup(wirq->dev)) {
+ if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED)
+ enable_irq(wirq->irq);
+
enable_irq_wake(wirq->irq);
+ }
}
/**
@@ -328,6 +342,10 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq)
if (!wirq)
return;
- if (device_may_wakeup(wirq->dev))
+ if (device_may_wakeup(wirq->dev)) {
disable_irq_wake(wirq->irq);
+
+ if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED)
+ disable_irq_nosync(wirq->irq);
+ }
}