/[linux-patches]/genpatches-2.6/tags/2.6.12-10/2700_irqpoll.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.12-10/2700_irqpoll.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 101 - (show annotations) (download)
Sat Jul 16 11:24:53 2005 UTC (12 years, 10 months ago) by dsd
File size: 8159 byte(s)
2.6.12-10 release
1 From: Alan Cox <alan@lxorguk.ukuu.org.uk>
2 Date: Wed, 29 Jun 2005 03:45:18 +0000 (-0700)
3 Subject: [PATCH] irqpoll
4 X-Git-Tag: v2.6.13-rc1
5 X-Git-Url: http://www.kernel.org/git/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=200803dfe4ff772740d63db725ab2f1b185ccf92
6
7 [PATCH] irqpoll
8
9 Anyone reporting a stuck IRQ should try these options. Its effectiveness
10 varies we've found in the Fedora case. Quite a few systems with misdescribed
11 IRQ routing just work when you use irqpoll. It also fixes up the VIA systems
12 although thats now fixed with the VIA quirk (which we could just make default
13 as its what Redmond OS does but Linus didn't like it historically).
14
15 A small number of systems have jammed IRQ sources or misdescribes that cause
16 an IRQ that we have no handler registered anywhere for. In those cases it
17 doesn't help.
18
19 Signed-off-by: Alan Cox <number6@the-village.bc.nu>
20 Signed-off-by: Andrew Morton <akpm@osdl.org>
21 Signed-off-by: Linus Torvalds <torvalds@osdl.org>
22 ---
23
24 diff -urNpX dontdiff linux-2.6.12/arch/ppc64/kernel/irq.c linux-dsd/arch/ppc64/kernel/irq.c
25 --- linux-2.6.12/arch/ppc64/kernel/irq.c 2005-06-17 20:48:29.000000000 +0100
26 +++ linux-dsd/arch/ppc64/kernel/irq.c 2005-07-13 13:47:38.000000000 +0100
27 @@ -245,7 +245,7 @@ void ppc_irq_dispatch_handler(struct pt_
28
29 spin_lock(&desc->lock);
30 if (!noirqdebug)
31 - note_interrupt(irq, desc, action_ret);
32 + note_interrupt(irq, desc, action_ret, regs);
33 if (likely(!(desc->status & IRQ_PENDING)))
34 break;
35 desc->status &= ~IRQ_PENDING;
36 diff -urNpX dontdiff linux-2.6.12/Documentation/kernel-parameters.txt linux-dsd/Documentation/kernel-parameters.txt
37 --- linux-2.6.12/Documentation/kernel-parameters.txt 2005-06-17 20:48:29.000000000 +0100
38 +++ linux-dsd/Documentation/kernel-parameters.txt 2005-07-13 13:47:38.000000000 +0100
39 @@ -433,6 +433,10 @@ running once the system is up.
40 Format: {"of[f]" | "sk[ipmbr]"}
41 See comment in arch/i386/boot/edd.S
42
43 + edd [EDD]
44 + Format: {"of[f]" | "sk[ipmbr]"}
45 + See comment in arch/i386/boot/edd.S
46 +
47 eicon= [HW,ISDN]
48 Format: <id>,<membase>,<irq>
49
50 @@ -611,6 +615,17 @@ running once the system is up.
51 ips= [HW,SCSI] Adaptec / IBM ServeRAID controller
52 See header of drivers/scsi/ips.c.
53
54 + irqfixup [HW]
55 + When an interrupt is not handled search all handlers
56 + for it. Intended to get systems with badly broken
57 + firmware running.
58 +
59 + irqpoll [HW]
60 + When an interrupt is not handled search all handlers
61 + for it. Also check all handlers each timer
62 + interrupt. Intended to get systems with badly broken
63 + firmware running.
64 +
65 isapnp= [ISAPNP]
66 Format: <RDP>, <reset>, <pci_scan>, <verbosity>
67
68 diff -urNpX dontdiff linux-2.6.12/include/linux/irq.h linux-dsd/include/linux/irq.h
69 --- linux-2.6.12/include/linux/irq.h 2005-06-17 20:48:29.000000000 +0100
70 +++ linux-dsd/include/linux/irq.h 2005-07-13 13:48:42.000000000 +0100
71 @@ -83,7 +83,8 @@ extern int noirqdebug_setup(char *str);
72 extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
73 struct irqaction *action);
74 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
75 -extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret);
76 +extern void note_interrupt(unsigned int irq, irq_desc_t *desc,
77 + int action_ret, struct pt_regs *regs);
78 extern void report_bad_irq(unsigned int irq, irq_desc_t *desc, int action_ret);
79 extern int can_request_irq(unsigned int irq, unsigned long irqflags);
80
81 diff -urNpX dontdiff linux-2.6.12/kernel/irq/handle.c linux-dsd/kernel/irq/handle.c
82 --- linux-2.6.12/kernel/irq/handle.c 2005-06-17 20:48:29.000000000 +0100
83 +++ linux-dsd/kernel/irq/handle.c 2005-07-13 13:47:38.000000000 +0100
84 @@ -172,7 +172,7 @@ fastcall unsigned int __do_IRQ(unsigned
85
86 spin_lock(&desc->lock);
87 if (!noirqdebug)
88 - note_interrupt(irq, desc, action_ret);
89 + note_interrupt(irq, desc, action_ret, regs);
90 if (likely(!(desc->status & IRQ_PENDING)))
91 break;
92 desc->status &= ~IRQ_PENDING;
93 diff -urNpX dontdiff linux-2.6.12/kernel/irq/spurious.c linux-dsd/kernel/irq/spurious.c
94 --- linux-2.6.12/kernel/irq/spurious.c 2005-06-17 20:48:29.000000000 +0100
95 +++ linux-dsd/kernel/irq/spurious.c 2005-07-13 13:47:38.000000000 +0100
96 @@ -11,6 +11,83 @@
97 #include <linux/kallsyms.h>
98 #include <linux/interrupt.h>
99
100 +static int irqfixup;
101 +
102 +/*
103 + * Recovery handler for misrouted interrupts.
104 + */
105 +
106 +static int misrouted_irq(int irq, struct pt_regs *regs)
107 +{
108 + int i;
109 + irq_desc_t *desc;
110 + int ok = 0;
111 + int work = 0; /* Did we do work for a real IRQ */
112 +
113 + for(i = 1; i < NR_IRQS; i++) {
114 + struct irqaction *action;
115 +
116 + if (i == irq) /* Already tried */
117 + continue;
118 + desc = &irq_desc[i];
119 + spin_lock(&desc->lock);
120 + action = desc->action;
121 + /* Already running on another processor */
122 + if (desc->status & IRQ_INPROGRESS) {
123 + /*
124 + * Already running: If it is shared get the other
125 + * CPU to go looking for our mystery interrupt too
126 + */
127 + if (desc->action && (desc->action->flags & SA_SHIRQ))
128 + desc->status |= IRQ_PENDING;
129 + spin_unlock(&desc->lock);
130 + continue;
131 + }
132 + /* Honour the normal IRQ locking */
133 + desc->status |= IRQ_INPROGRESS;
134 + spin_unlock(&desc->lock);
135 + while (action) {
136 + /* Only shared IRQ handlers are safe to call */
137 + if (action->flags & SA_SHIRQ) {
138 + if (action->handler(i, action->dev_id, regs) ==
139 + IRQ_HANDLED)
140 + ok = 1;
141 + }
142 + action = action->next;
143 + }
144 + local_irq_disable();
145 + /* Now clean up the flags */
146 + spin_lock(&desc->lock);
147 + action = desc->action;
148 +
149 + /*
150 + * While we were looking for a fixup someone queued a real
151 + * IRQ clashing with our walk
152 + */
153 +
154 + while ((desc->status & IRQ_PENDING) && action) {
155 + /*
156 + * Perform real IRQ processing for the IRQ we deferred
157 + */
158 + work = 1;
159 + spin_unlock(&desc->lock);
160 + handle_IRQ_event(i, regs, action);
161 + spin_lock(&desc->lock);
162 + desc->status &= ~IRQ_PENDING;
163 + }
164 + desc->status &= ~IRQ_INPROGRESS;
165 + /*
166 + * If we did actual work for the real IRQ line we must let the
167 + * IRQ controller clean up too
168 + */
169 + if(work)
170 + desc->handler->end(i);
171 + spin_unlock(&desc->lock);
172 + }
173 + /* So the caller can adjust the irq error counts */
174 + return ok;
175 +}
176 +
177 /*
178 * If 99,900 of the previous 100,000 interrupts have not been handled
179 * then assume that the IRQ is stuck in some manner. Drop a diagnostic
180 @@ -31,7 +108,8 @@ __report_bad_irq(unsigned int irq, irq_d
181 printk(KERN_ERR "irq event %d: bogus return value %x\n",
182 irq, action_ret);
183 } else {
184 - printk(KERN_ERR "irq %d: nobody cared!\n", irq);
185 + printk(KERN_ERR "irq %d: nobody cared (try booting with "
186 + "the \"irqpoll\" option)\n", irq);
187 }
188 dump_stack();
189 printk(KERN_ERR "handlers:\n");
190 @@ -55,7 +133,8 @@ void report_bad_irq(unsigned int irq, ir
191 }
192 }
193
194 -void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
195 +void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret,
196 + struct pt_regs *regs)
197 {
198 if (action_ret != IRQ_HANDLED) {
199 desc->irqs_unhandled++;
200 @@ -63,6 +142,15 @@ void note_interrupt(unsigned int irq, ir
201 report_bad_irq(irq, desc, action_ret);
202 }
203
204 + if (unlikely(irqfixup)) {
205 + /* Don't punish working computers */
206 + if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
207 + int ok = misrouted_irq(irq, regs);
208 + if (action_ret == IRQ_NONE)
209 + desc->irqs_unhandled -= ok;
210 + }
211 + }
212 +
213 desc->irq_count++;
214 if (desc->irq_count < 100000)
215 return;
216 @@ -94,3 +182,24 @@ int __init noirqdebug_setup(char *str)
217
218 __setup("noirqdebug", noirqdebug_setup);
219
220 +static int __init irqfixup_setup(char *str)
221 +{
222 + irqfixup = 1;
223 + printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
224 + printk(KERN_WARNING "This may impact system performance.\n");
225 + return 1;
226 +}
227 +
228 +__setup("irqfixup", irqfixup_setup);
229 +
230 +static 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);

  ViewVC Help
Powered by ViewVC 1.1.20