Merge tag 'kvm-arm-for-3.18-take-2' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / kernel / irq / chip.c
index 6223fab9a9d22b7bedd5e6b1f23ccd8a0347d6d1..e5202f00cabcdb892b3f4ad39c53f7fe943a0751 100644 (file)
@@ -342,6 +342,31 @@ static bool irq_check_poll(struct irq_desc *desc)
        return irq_wait_for_poll(desc);
 }
 
+static bool irq_may_run(struct irq_desc *desc)
+{
+       unsigned int mask = IRQD_IRQ_INPROGRESS | IRQD_WAKEUP_ARMED;
+
+       /*
+        * If the interrupt is not in progress and is not an armed
+        * wakeup interrupt, proceed.
+        */
+       if (!irqd_has_set(&desc->irq_data, mask))
+               return true;
+
+       /*
+        * If the interrupt is an armed wakeup source, mark it pending
+        * and suspended, disable it and notify the pm core about the
+        * event.
+        */
+       if (irq_pm_check_wakeup(desc))
+               return false;
+
+       /*
+        * Handle a potential concurrent poll on a different core.
+        */
+       return irq_check_poll(desc);
+}
+
 /**
  *     handle_simple_irq - Simple and software-decoded IRQs.
  *     @irq:   the interrupt number
@@ -359,9 +384,8 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
 {
        raw_spin_lock(&desc->lock);
 
-       if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
-               if (!irq_check_poll(desc))
-                       goto out_unlock;
+       if (!irq_may_run(desc))
+               goto out_unlock;
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
        kstat_incr_irqs_this_cpu(irq, desc);
@@ -412,9 +436,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
        raw_spin_lock(&desc->lock);
        mask_ack_irq(desc);
 
-       if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
-               if (!irq_check_poll(desc))
-                       goto out_unlock;
+       if (!irq_may_run(desc))
+               goto out_unlock;
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
        kstat_incr_irqs_this_cpu(irq, desc);
@@ -485,9 +508,8 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
 
        raw_spin_lock(&desc->lock);
 
-       if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
-               if (!irq_check_poll(desc))
-                       goto out;
+       if (!irq_may_run(desc))
+               goto out;
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
        kstat_incr_irqs_this_cpu(irq, desc);
@@ -541,19 +563,23 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
        raw_spin_lock(&desc->lock);
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+
+       if (!irq_may_run(desc)) {
+               desc->istate |= IRQS_PENDING;
+               mask_ack_irq(desc);
+               goto out_unlock;
+       }
+
        /*
-        * If we're currently running this IRQ, or its disabled,
-        * we shouldn't process the IRQ. Mark it pending, handle
-        * the necessary masking and go out
+        * If its disabled or no action available then mask it and get
+        * out of here.
         */
-       if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
-                    irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
-               if (!irq_check_poll(desc)) {
-                       desc->istate |= IRQS_PENDING;
-                       mask_ack_irq(desc);
-                       goto out_unlock;
-               }
+       if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
+               desc->istate |= IRQS_PENDING;
+               mask_ack_irq(desc);
+               goto out_unlock;
        }
+
        kstat_incr_irqs_this_cpu(irq, desc);
 
        /* Start handling the irq */
@@ -602,18 +628,21 @@ void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
        raw_spin_lock(&desc->lock);
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+
+       if (!irq_may_run(desc)) {
+               desc->istate |= IRQS_PENDING;
+               goto out_eoi;
+       }
+
        /*
-        * If we're currently running this IRQ, or its disabled,
-        * we shouldn't process the IRQ. Mark it pending, handle
-        * the necessary masking and go out
+        * If its disabled or no action available then mask it and get
+        * out of here.
         */
-       if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
-                    irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
-               if (!irq_check_poll(desc)) {
-                       desc->istate |= IRQS_PENDING;
-                       goto out_eoi;
-               }
+       if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
+               desc->istate |= IRQS_PENDING;
+               goto out_eoi;
        }
+
        kstat_incr_irqs_this_cpu(irq, desc);
 
        do {
@@ -670,7 +699,7 @@ void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct irqaction *action = desc->action;
-       void *dev_id = __this_cpu_ptr(action->percpu_dev_id);
+       void *dev_id = raw_cpu_ptr(action->percpu_dev_id);
        irqreturn_t res;
 
        kstat_incr_irqs_this_cpu(irq, desc);