aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/spurious.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/spurious.c')
-rw-r--r--kernel/irq/spurious.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 0af9e59c82eb..bd0e42d3e0ba 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -25,30 +25,42 @@ static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0);
25/* 25/*
26 * Recovery handler for misrouted interrupts. 26 * Recovery handler for misrouted interrupts.
27 */ 27 */
28static int try_one_irq(int irq, struct irq_desc *desc) 28static int try_one_irq(int irq, struct irq_desc *desc, bool force)
29{ 29{
30 struct irqaction *action; 30 struct irqaction *action;
31 int ok = 0, work = 0; 31 int ok = 0, work = 0;
32 32
33 raw_spin_lock(&desc->lock); 33 raw_spin_lock(&desc->lock);
34
35 /* PER_CPU and nested thread interrupts are never polled */
36 if (desc->status & (IRQ_PER_CPU | IRQ_NESTED_THREAD))
37 goto out;
38
39 /*
40 * Do not poll disabled interrupts unless the spurious
41 * disabled poller asks explicitely.
42 */
43 if ((desc->status & IRQ_DISABLED) && !force)
44 goto out;
45
46 /*
47 * All handlers must agree on IRQF_SHARED, so we test just the
48 * first. Check for action->next as well.
49 */
50 action = desc->action;
51 if (!action || !(action->flags & IRQF_SHARED) ||
52 (action->flags & __IRQF_TIMER) || !action->next)
53 goto out;
54
34 /* Already running on another processor */ 55 /* Already running on another processor */
35 if (desc->status & IRQ_INPROGRESS) { 56 if (desc->status & IRQ_INPROGRESS) {
36 /* 57 /*
37 * Already running: If it is shared get the other 58 * Already running: If it is shared get the other
38 * CPU to go looking for our mystery interrupt too 59 * CPU to go looking for our mystery interrupt too
39 */ 60 */
40 if (desc->action && (desc->action->flags & IRQF_SHARED)) 61 desc->status |= IRQ_PENDING;
41 desc->status |= IRQ_PENDING;
42 raw_spin_unlock(&desc->lock);
43 return ok;
44 }
45 /*
46 * All handlers must agree on IRQF_SHARED, so we test just the
47 * first. Check for action->next as well.
48 */
49 action = desc->action;
50 if (!action || !(action->flags & IRQF_SHARED) || !action->next)
51 goto out; 62 goto out;
63 }
52 64
53 /* Honour the normal IRQ locking */ 65 /* Honour the normal IRQ locking */
54 desc->status |= IRQ_INPROGRESS; 66 desc->status |= IRQ_INPROGRESS;
@@ -87,7 +99,7 @@ static int misrouted_irq(int irq)
87 if (i == irq) /* Already tried */ 99 if (i == irq) /* Already tried */
88 continue; 100 continue;
89 101
90 if (try_one_irq(i, desc)) 102 if (try_one_irq(i, desc, false))
91 ok = 1; 103 ok = 1;
92 } 104 }
93 /* So the caller can adjust the irq error counts */ 105 /* So the caller can adjust the irq error counts */
@@ -112,7 +124,7 @@ static void poll_spurious_irqs(unsigned long dummy)
112 continue; 124 continue;
113 125
114 local_irq_disable(); 126 local_irq_disable();
115 try_one_irq(i, desc); 127 try_one_irq(i, desc, true);
116 local_irq_enable(); 128 local_irq_enable();
117 } 129 }
118 130