1/*
2 * linux/kernel/irq/spurious.c
3 *
4 * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
5 *
6 * This file contains spurious interrupt handling.
7 */
8
9#include <linux/irq.h>
10#include <linux/module.h>
11#include <linux/kallsyms.h>
12#include <linux/interrupt.h>
13
14static int irqfixup __read_mostly;
15
16/*
17 * Recovery handler for misrouted interrupts.
18 */
19static int misrouted_irq(int irq)
20{
21	int i;
22	int ok = 0;
23	int work = 0;	/* Did we do work for a real IRQ */
24
25	for (i = 1; i < NR_IRQS; i++) {
26		struct irq_desc *desc = irq_desc + i;
27		struct irqaction *action;
28
29		if (i == irq)	/* Already tried */
30			continue;
31
32		spin_lock(&desc->lock);
33		/* Already running on another processor */
34		if (desc->status & IRQ_INPROGRESS) {
35			/*
36			 * Already running: If it is shared get the other
37			 * CPU to go looking for our mystery interrupt too
38			 */
39			if (desc->action && (desc->action->flags & IRQF_SHARED))
40				desc->status |= IRQ_PENDING;
41			spin_unlock(&desc->lock);
42			continue;
43		}
44		/* Honour the normal IRQ locking */
45		desc->status |= IRQ_INPROGRESS;
46		action = desc->action;
47		spin_unlock(&desc->lock);
48
49		while (action) {
50			/* Only shared IRQ handlers are safe to call */
51			if (action->flags & IRQF_SHARED) {
52				if (action->handler(i, action->dev_id) ==
53						IRQ_HANDLED)
54					ok = 1;
55			}
56			action = action->next;
57		}
58		local_irq_disable();
59		/* Now clean up the flags */
60		spin_lock(&desc->lock);
61		action = desc->action;
62
63		/*
64		 * While we were looking for a fixup someone queued a real
65		 * IRQ clashing with our walk:
66		 */
67		while ((desc->status & IRQ_PENDING) && action) {
68			/*
69			 * Perform real IRQ processing for the IRQ we deferred
70			 */
71			work = 1;
72			spin_unlock(&desc->lock);
73			handle_IRQ_event(i, action);
74			spin_lock(&desc->lock);
75			desc->status &= ~IRQ_PENDING;
76		}
77		desc->status &= ~IRQ_INPROGRESS;
78		/*
79		 * If we did actual work for the real IRQ line we must let the
80		 * IRQ controller clean up too
81		 */
82		if (work && desc->chip && desc->chip->end)
83			desc->chip->end(i);
84		spin_unlock(&desc->lock);
85	}
86	/* So the caller can adjust the irq error counts */
87	return ok;
88}
89
90/*
91 * If 99,900 of the previous 100,000 interrupts have not been handled
92 * then assume that the IRQ is stuck in some manner. Drop a diagnostic
93 * and try to turn the IRQ off.
94 *
95 * (The other 100-of-100,000 interrupts may have been a correctly
96 *  functioning device sharing an IRQ with the failing one)
97 *
98 * Called under desc->lock
99 */
100
101static void
102__report_bad_irq(unsigned int irq, struct irq_desc *desc,
103		 irqreturn_t action_ret)
104{
105	struct irqaction *action;
106
107	if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
108		printk(KERN_ERR "irq event %d: bogus return value %x\n",
109				irq, action_ret);
110	} else {
111		printk(KERN_ERR "irq %d: nobody cared (try booting with "
112				"the \"irqpoll\" option)\n", irq);
113	}
114	dump_stack();
115	printk(KERN_ERR "handlers:\n");
116
117	action = desc->action;
118	while (action) {
119		printk(KERN_ERR "[<%p>]", action->handler);
120		print_symbol(" (%s)",
121			(unsigned long)action->handler);
122		printk("\n");
123		action = action->next;
124	}
125}
126
127static void
128report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
129{
130	static int count = 100;
131
132	if (count > 0) {
133		count--;
134		__report_bad_irq(irq, desc, action_ret);
135	}
136}
137
138static inline int try_misrouted_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
139{
140	struct irqaction *action;
141
142	if (!irqfixup)
143		return 0;
144
145	/* We didn't actually handle the IRQ - see if it was misrouted? */
146	if (action_ret == IRQ_NONE)
147		return 1;
148
149	/*
150	 * But for 'irqfixup == 2' we also do it for handled interrupts if
151	 * they are marked as IRQF_IRQPOLL (or for irq zero, which is the
152	 * traditional PC timer interrupt.. Legacy)
153	 */
154	if (irqfixup < 2)
155		return 0;
156
157	if (!irq)
158		return 1;
159
160	/*
161	 * Since we don't get the descriptor lock, "action" can
162	 * change under us.  We don't really care, but we don't
163	 * want to follow a NULL pointer. So tell the compiler to
164	 * just load it once by using a barrier.
165	 */
166	action = desc->action;
167	barrier();
168	return action && (action->flags & IRQF_IRQPOLL);
169}
170
171void note_interrupt(unsigned int irq, struct irq_desc *desc,
172		    irqreturn_t action_ret)
173{
174	if (unlikely(action_ret != IRQ_HANDLED)) {
175		desc->irqs_unhandled++;
176		if (unlikely(action_ret != IRQ_NONE))
177			report_bad_irq(irq, desc, action_ret);
178	}
179
180	if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
181		int ok = misrouted_irq(irq);
182		if (action_ret == IRQ_NONE)
183			desc->irqs_unhandled -= ok;
184	}
185
186	desc->irq_count++;
187	if (likely(desc->irq_count < 100000))
188		return;
189
190	desc->irq_count = 0;
191	if (unlikely(desc->irqs_unhandled > 99900)) {
192		/*
193		 * The interrupt is stuck
194		 */
195		__report_bad_irq(irq, desc, action_ret);
196		/*
197		 * Now kill the IRQ
198		 */
199		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
200		desc->status |= IRQ_DISABLED;
201		desc->depth = 1;
202		desc->chip->disable(irq);
203	}
204	desc->irqs_unhandled = 0;
205}
206
207int noirqdebug = 1;
208
209int noirqdebug_setup(char *str)
210{
211	noirqdebug = 1;
212	printk(KERN_INFO "IRQ lockup detection disabled\n");
213
214	return 1;
215}
216
217__setup("noirqdebug", noirqdebug_setup);
218
219static int __init irqfixup_setup(char *str)
220{
221	irqfixup = 1;
222	printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
223	printk(KERN_WARNING "This may impact system performance.\n");
224
225	return 1;
226}
227
228__setup("irqfixup", irqfixup_setup);
229
230static int __init irqpoll_setup(char *str)
231{
232	irqfixup = 2;
233	printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
234				"enabled\n");
235	printk(KERN_WARNING "This may significantly impact system "
236				"performance\n");
237	return 1;
238}
239
240__setup("irqpoll", irqpoll_setup);
241