]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/base/power/wakeirq.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / base / power / wakeirq.c
index 404d94c6c8bc6a4531b0666a77c5b86daab207a6..ae0429827f31052fff58362131e171f33ff27a17 100644 (file)
@@ -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);
+       }
 }