xref: /openbmc/linux/kernel/irq/spurious.c (revision 87c2ce3b)
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 
14 static int irqfixup;
15 
16 /*
17  * Recovery handler for misrouted interrupts.
18  */
19 
20 static int misrouted_irq(int irq, struct pt_regs *regs)
21 {
22 	int i;
23 	irq_desc_t *desc;
24 	int ok = 0;
25 	int work = 0;	/* Did we do work for a real IRQ */
26 
27 	for(i = 1; i < NR_IRQS; i++) {
28 		struct irqaction *action;
29 
30 		if (i == irq)	/* Already tried */
31 			continue;
32 		desc = &irq_desc[i];
33 		spin_lock(&desc->lock);
34 		action = desc->action;
35 		/* Already running on another processor */
36 		if (desc->status & IRQ_INPROGRESS) {
37 			/*
38 			 * Already running: If it is shared get the other
39 			 * CPU to go looking for our mystery interrupt too
40 			 */
41 			if (desc->action && (desc->action->flags & SA_SHIRQ))
42 				desc->status |= IRQ_PENDING;
43 			spin_unlock(&desc->lock);
44 			continue;
45 		}
46 		/* Honour the normal IRQ locking */
47 		desc->status |= IRQ_INPROGRESS;
48 		spin_unlock(&desc->lock);
49 		while (action) {
50 			/* Only shared IRQ handlers are safe to call */
51 			if (action->flags & SA_SHIRQ) {
52 				if (action->handler(i, action->dev_id, regs) ==
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 
68 		while ((desc->status & IRQ_PENDING) && action) {
69 			/*
70 			 * Perform real IRQ processing for the IRQ we deferred
71 			 */
72 			work = 1;
73 			spin_unlock(&desc->lock);
74 			handle_IRQ_event(i, regs, action);
75 			spin_lock(&desc->lock);
76 			desc->status &= ~IRQ_PENDING;
77 		}
78 		desc->status &= ~IRQ_INPROGRESS;
79 		/*
80 		 * If we did actual work for the real IRQ line we must let the
81 		 * IRQ controller clean up too
82 		 */
83 		if(work)
84 			desc->handler->end(i);
85 		spin_unlock(&desc->lock);
86 	}
87 	/* So the caller can adjust the irq error counts */
88 	return ok;
89 }
90 
91 /*
92  * If 99,900 of the previous 100,000 interrupts have not been handled
93  * then assume that the IRQ is stuck in some manner. Drop a diagnostic
94  * and try to turn the IRQ off.
95  *
96  * (The other 100-of-100,000 interrupts may have been a correctly
97  *  functioning device sharing an IRQ with the failing one)
98  *
99  * Called under desc->lock
100  */
101 
102 static void
103 __report_bad_irq(unsigned int irq, irq_desc_t *desc, 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 	action = desc->action;
117 	while (action) {
118 		printk(KERN_ERR "[<%p>]", action->handler);
119 		print_symbol(" (%s)",
120 			(unsigned long)action->handler);
121 		printk("\n");
122 		action = action->next;
123 	}
124 }
125 
126 static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
127 {
128 	static int count = 100;
129 
130 	if (count > 0) {
131 		count--;
132 		__report_bad_irq(irq, desc, action_ret);
133 	}
134 }
135 
136 void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret,
137 			struct pt_regs *regs)
138 {
139 	if (action_ret != IRQ_HANDLED) {
140 		desc->irqs_unhandled++;
141 		if (action_ret != IRQ_NONE)
142 			report_bad_irq(irq, desc, action_ret);
143 	}
144 
145 	if (unlikely(irqfixup)) {
146 		/* Don't punish working computers */
147 		if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
148 			int ok = misrouted_irq(irq, regs);
149 			if (action_ret == IRQ_NONE)
150 				desc->irqs_unhandled -= ok;
151 		}
152 	}
153 
154 	desc->irq_count++;
155 	if (desc->irq_count < 100000)
156 		return;
157 
158 	desc->irq_count = 0;
159 	if (desc->irqs_unhandled > 99900) {
160 		/*
161 		 * The interrupt is stuck
162 		 */
163 		__report_bad_irq(irq, desc, action_ret);
164 		/*
165 		 * Now kill the IRQ
166 		 */
167 		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
168 		desc->status |= IRQ_DISABLED;
169 		desc->handler->disable(irq);
170 	}
171 	desc->irqs_unhandled = 0;
172 }
173 
174 int noirqdebug;
175 
176 int __init noirqdebug_setup(char *str)
177 {
178 	noirqdebug = 1;
179 	printk(KERN_INFO "IRQ lockup detection disabled\n");
180 	return 1;
181 }
182 
183 __setup("noirqdebug", noirqdebug_setup);
184 
185 static int __init irqfixup_setup(char *str)
186 {
187 	irqfixup = 1;
188 	printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
189 	printk(KERN_WARNING "This may impact system performance.\n");
190 	return 1;
191 }
192 
193 __setup("irqfixup", irqfixup_setup);
194 
195 static int __init irqpoll_setup(char *str)
196 {
197 	irqfixup = 2;
198 	printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
199 				"enabled\n");
200 	printk(KERN_WARNING "This may significantly impact system "
201 				"performance\n");
202 	return 1;
203 }
204 
205 __setup("irqpoll", irqpoll_setup);
206