]> git.pld-linux.org Git - packages/kernel.git/blame - 2.2.21-ppc_openpic_fix.patch
- obsolete
[packages/kernel.git] / 2.2.21-ppc_openpic_fix.patch
CommitLineData
40a4a0a9
KT
1diff -urN linux.orig/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
2--- linux.orig/arch/ppc/kernel/chrp_setup.c Sun Mar 25 18:31:49 2001
30fe9923 3+++ linux/arch/ppc/kernel/chrp_setup.c Tue Aug 27 15:46:50 2002
40a4a0a9
KT
4@@ -4,6 +4,7 @@
5 * Copyright (C) 1995 Linus Torvalds
6 * Adapted from 'alpha' version by Gary Thomas
7 * Modified by Cort Dougan (cort@cs.nmt.edu)
8+ * Fixed IRQ time out problem by Krzysztof Taraszka (dzimi@pld.org.pl)
9 */
10
11 /*
12@@ -359,6 +360,81 @@
13 }
14 }
15
16+void
17+chrp_do_IRQ(struct pt_regs *regs,
18+ int cpu,
19+ int isfake)
20+{
21+ int irq;
22+ unsigned long bits = 0;
23+ int openpic_eoi_done = 0;
24+
25+#ifdef __SMP__
26+ {
27+ unsigned int loops = 1000000;
28+ while (test_bit(0, &global_irq_lock)) {
29+ if (smp_processor_id() == global_irq_holder) {
30+ printk("uh oh, interrupt while we hold global irq lock!\n");
31+#ifdef CONFIG_XMON
32+ xmon(0);
33+#endif
34+ break;
35+ }
36+ if (loops-- == 0) {
37+ printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
38+#ifdef CONFIG_XMON
39+ xmon(0);
40+#endif
41+ }
42+ }
43+ }
44+#endif /* __SMP__ */
45+
46+ irq = openpic_irq(smp_processor_id());
47+ if (irq == IRQ_8259_CASCADE)
48+ {
49+ /*
50+ * This magic address generates a PCI IACK cycle.
51+ *
52+ * This should go in the above mask/ack code soon. -- Cort
53+ */
54+ if ( chrp_int_ack_special )
55+ irq = *chrp_int_ack_special;
56+ else
57+ irq = i8259_irq(0);
58+ /*
59+ * Acknowledge as soon as possible to allow i8259
60+ * interrupt nesting */
61+ openpic_eoi(smp_processor_id());
62+ openpic_eoi_done = 1;
63+ }
64+ if (irq == OPENPIC_VEC_SPURIOUS)
65+ {
66+ /*
67+ * Spurious interrupts should never be
68+ * acknowledged
69+ */
70+ ppc_spurious_interrupts++;
71+ openpic_eoi_done = 1;
72+ goto out;
73+ }
74+ bits = 1UL << irq;
75+
76+ if (irq < 0)
77+ {
78+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
79+ irq, regs->nip);
80+ ppc_spurious_interrupts++;
81+ }
82+ else
83+ {
84+ ppc_irq_dispatch_handler( regs, irq );
85+ }
86+out:
87+ if (!openpic_eoi_done)
88+ openpic_eoi(smp_processor_id());
89+}
90+
91 __initfunc(void
92 chrp_init_IRQ(void))
93 {
94@@ -570,7 +646,7 @@
95 ppc_md.get_cpuinfo = chrp_get_cpuinfo;
96 ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
97 ppc_md.init_IRQ = chrp_init_IRQ;
98- ppc_md.do_IRQ = open_pic_do_IRQ;
99+ ppc_md.do_IRQ = chrp_do_IRQ;
100
101 ppc_md.init = chrp_init2;
102
103diff -urN linux.orig/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
104--- linux.orig/arch/ppc/kernel/open_pic.c Sun Mar 25 18:31:49 2001
30fe9923 105+++ linux/arch/ppc/kernel/open_pic.c Tue Aug 27 15:46:50 2002
40a4a0a9
KT
106@@ -11,116 +11,45 @@
107 #include <linux/signal.h>
108 #include <linux/openpic.h>
109 #include <asm/irq.h>
110-#include <asm/processor.h>
111 #include "open_pic.h"
112 #include "i8259.h"
113
114-extern volatile unsigned char *chrp_int_ack_special;
115-
116-void open_pic_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
117-{
118- int irq;
119- int openpic_eoi_done = 0;
120-
121 #ifdef __SMP__
122- {
123- unsigned int loops = 1000000;
124- while (test_bit(0, &global_irq_lock)) {
125- if (smp_processor_id() == global_irq_holder) {
126- printk("uh oh, interrupt while we hold global irq lock!\n");
127-#ifdef CONFIG_XMON
128- xmon(0);
129-#endif
130- break;
131- }
132- if (loops-- == 0) {
133- printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
134-#ifdef CONFIG_XMON
135- xmon(0);
136-#endif
137- }
138- }
139- }
140+void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
141+{
142+ smp_message_recv(cpl-OPENPIC_VEC_IPI);
143+}
144 #endif /* __SMP__ */
145-
146- irq = openpic_irq(smp_processor_id());
147- /* make sure open_pic.irq_offset is set to something!
148- * do we really need the _MACH_Pmac test??
149- */
150- if (!(_machine == _MACH_Pmac) && (irq == open_pic.irq_offset))
151- {
152- /*
153- * This magic address generates a PCI IACK cycle.
154- *
155- * This should go in the above mask/ack code soon. -- Cort
156- */
157- if ( chrp_int_ack_special )
158- irq = *chrp_int_ack_special;
159-#ifndef CONFIG_PMAC
160- else
161- irq = i8259_irq(0);
162-#endif
163- /*
164- * Acknowledge as soon as possible to allow i8259
165- * interrupt nesting */
166- openpic_eoi(smp_processor_id());
167- openpic_eoi_done = 1;
168- }
169- if (irq == OPENPIC_VEC_SPURIOUS)
170- {
171- /*
172- * Spurious interrupts should never be
173- * acknowledged
174- */
175- ppc_spurious_interrupts++;
176- openpic_eoi_done = 1;
177- goto out;
178- }
179
180- if (irq < 0)
181- {
182- printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
183- irq, regs->nip);
184- ppc_spurious_interrupts++;
185- }
186- else
187- {
188- ppc_irq_dispatch_handler( regs, irq );
189- }
190-out:
191- if (!openpic_eoi_done)
192- openpic_eoi(smp_processor_id());
193+void chrp_mask_and_ack_irq(unsigned int irq_nr)
194+{
195+ if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
196+ i8259_pic.mask_and_ack(irq_nr);
197 }
198
199-#ifdef __SMP__
200-void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
201+static void chrp_mask_irq(unsigned int irq_nr)
202 {
203- smp_message_recv(cpl-OPENPIC_VEC_IPI);
204+ if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
205+ i8259_pic.disable(irq_nr);
206+ else
207+ openpic_disable_irq(irq_nr-open_pic.irq_offset);
208 }
209-#endif /* __SMP__ */
210
211+static void chrp_unmask_irq(unsigned int irq_nr)
212+{
213+ if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
214+ i8259_pic.enable(irq_nr);
215+ else
216+ openpic_enable_irq(irq_nr-open_pic.irq_offset);
217+}
218
219 struct hw_interrupt_type open_pic = {
220 " OpenPIC ",
221 NULL,
222 NULL,
223 NULL,
224- openpic_enable_irq,
225- openpic_disable_irq,
226- /* Theorically, the mask&ack should be NULL for OpenPIC. However, doing
227- * so shows tons of bogus interrupts coming in.
228- * This problem is apparently due to the common code always calling
229- * unmask(). I apparently (need more test) fixed it in the 2.4 new IRQ
230- * management by cleanly implementing the handler's end() function, so
231- * neither mask nor unmask are needed. In the meantime, the fix below will
232- * work for 2.2 -Benh
233- *
234- * Hopefully this will fix my bogus interrups on MTX
235- * I merged everthing together so we don't have the same code in three
236- * places. This might cause stability problems, but I'd rather
237- * get it right once than three different times because someone forgot
238- * to make the same change to PReP or something --Troy
239- */
240- openpic_disable_irq,
241+ chrp_unmask_irq,
242+ chrp_mask_irq,
243+ chrp_mask_and_ack_irq,
244 0
245 };
246diff -urN linux.orig/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h
247--- linux.orig/arch/ppc/kernel/open_pic.h Sun Mar 25 18:31:49 2001
30fe9923 248+++ linux/arch/ppc/kernel/open_pic.h Tue Aug 27 15:46:50 2002
40a4a0a9
KT
249@@ -6,7 +6,6 @@
250
251 extern struct hw_interrupt_type open_pic;
252
253-void open_pic_do_IRQ(struct pt_regs *regs, int cpu, int isfake);
254 void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
255 void openpic_enable_IPI(u_int ipi);
256 void do_openpic_setup_cpu(void);
257diff -urN linux.orig/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c
258--- linux.orig/arch/ppc/kernel/openpic.c Fri Nov 2 17:39:05 2001
30fe9923 259+++ linux/arch/ppc/kernel/openpic.c Tue Aug 27 15:46:50 2002
40a4a0a9
KT
260@@ -10,6 +10,9 @@
261 * to avoid bogus interrupts and to make sure the disable function exits with
262 * the interrupt actually masked. --BenH
263 * Todo: map interrupts to all available CPUs after the ack round
264+ *
265+ * Fixed IRQ time out problem by
266+ * Krzysztof Taraszka (dzimi@pld.org.pl)
267 *
268 * This file is subject to the terms and conditions of the GNU General Public
269 * License. See the file COPYING in the main directory of this archive
270@@ -33,6 +36,8 @@
271 #define REGISTER_DEBUG
272 #undef REGISTER_DEBUG
273
274+#define OPENPIC_SENSE_POLARITY 0x00800000 /* Undoc'd */
275+
276 #ifdef __powerpc__
277 extern int use_of_interrupt_tree;
278 #endif
279@@ -173,7 +178,6 @@
280 * other ones are just masked out.
281 * Note: We might want to adjust priorities too.
282 */
283-
284 /* Not an init func, called on pbook wakeup --BenH */
285 void
286 __init
287@@ -229,7 +233,7 @@
288
289 /* Initialize IPI interrupts */
290 for (i = 0; i < OPENPIC_NUM_IPI; i++) {
291- openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i);
292+ openpic_initipi(i, 0/*10*/, OPENPIC_VEC_IPI+i);
293 }
294
295 if (_machine != _MACH_Pmac) {
296@@ -266,7 +270,7 @@
297 openpic_initirq( np->intrs[j].line,
298 pri,
299 np->intrs[j].line,
300- 0,
301+ np->intrs[j].sense,
302 np->intrs[j].sense);
303 irq_desc[np->intrs[j].line].level = np->intrs[j].sense;
304 }
305@@ -276,8 +280,8 @@
306 /* Fixme: read level value from controller */
307 printk("openpic: WARNING, openpic running without interrupt tree\n");
308 }
309- }
310-
311+ }
312+
313 /* Initialize the spurious interrupt */
314 openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
315
316@@ -311,10 +315,6 @@
317 {
318 openpic_setfield(&OpenPIC->Global.Global_Configuration0,
319 OPENPIC_CONFIG_RESET);
320- /* Wait for reset to complete */
321- while(openpic_readfield(&OpenPIC->Global.Global_Configuration0,
322- OPENPIC_CONFIG_RESET))
323- ;
324 }
325
326
327@@ -465,12 +465,12 @@
328
329 for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
330 openpic_enable_IPI(i);
331-
332+#if 0
333 /* let the openpic know we want intrs */
334 for ( i = 0; i < NumSources ; i++ )
335 openpic_mapirq(i, openpic_read(&OpenPIC->Source[i].Destination)
336 | (1<<smp_processor_id()) );
337-
338+#endif
339 openpic_set_priority(smp_processor_id(), 0);
340 }
341
342@@ -506,11 +506,7 @@
343 */
344 void openpic_enable_irq(u_int irq)
345 {
346- /* on SMP, we get IPI vector numbers here, we should handle them
347- * or at least ignore them.
348- */
349- if (irq < 0 || irq >= NumSources)
350- return;
351+ check_arg_irq(irq);
352 openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
353 /* make sure mask gets to controller before we return to user */
354 do {
355@@ -519,30 +515,15 @@
356 OPENPIC_MASK));
357 }
358
359-u_int openpic_get_enable(u_int irq)
360-{
361- if (irq < 0 || irq >= NumSources)
362- return 0;
363- return !openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
364- OPENPIC_MASK);
365-}
366-
367 void openpic_disable_irq(u_int irq)
368 {
369- u32 vp;
370-
371- /* on SMP, we get IPI vector numbers here, we should handle them
372- * or at least ignore them.
373- */
374- if (irq < 0 || irq >= NumSources)
375- return;
376+ check_arg_irq(irq);
377 openpic_setfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
378 /* make sure mask gets to controller before we return to user */
379 do {
380- mb(); /* sync is probably useless here */
381- vp = openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
382- OPENPIC_MASK | OPENPIC_ACTIVITY);
383- } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
384+ mb();
385+ } while(!openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
386+ OPENPIC_MASK));
387 }
388
389 /*
390@@ -561,11 +542,10 @@
391 check_arg_vec(vec);
392 openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
393 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
394- OPENPIC_POLARITY_MASK | OPENPIC_SENSE_MASK,
395+ OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
396 (pri << OPENPIC_PRIORITY_SHIFT) | vec |
397- (pol ? OPENPIC_POLARITY_POSITIVE :
398- OPENPIC_POLARITY_NEGATIVE) |
399- (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
400+ (pol ? OPENPIC_SENSE_POLARITY : 0) |
401+ (sense ? OPENPIC_SENSE_LEVEL : 0));
402 }
403
404 /*
405@@ -608,7 +588,7 @@
406 save_irq_src_vp[i] = openpic_read(&OpenPIC->Source[i].Vector_Priority);
407 save_irq_src_dest[i] = openpic_read(&OpenPIC->Source[i].Destination);
408 }
409- for (i=0; i<NumProcessors; i++) {
410+for (i=0; i<NumProcessors; i++) {
411 save_cpu_task_pri[i] = openpic_read(&OpenPIC->Processor[i].Current_Task_Priority);
412 openpic_set_priority(i, 0xf);
413 }
414@@ -626,7 +606,7 @@
415 }
416 for (i=0; i<OPENPIC_NUM_IPI; i++)
417 openpic_write(&OpenPIC->Global.IPI_Vector_Priority(i), save_ipi_vp[i]);
418- for (i=0; i<NumSources; i++) {
419+for (i=0; i<NumSources; i++) {
420 openpic_write(&OpenPIC->Source[i].Vector_Priority, save_irq_src_vp[i]);
421 openpic_write(&OpenPIC->Source[i].Destination, save_irq_src_dest[i]);
422 }
423diff -urN linux.orig/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
424--- linux.orig/arch/ppc/kernel/pmac_pic.c Sun Mar 25 18:31:49 2001
30fe9923
KT
425+++ linux/arch/ppc/kernel/pmac_pic.c Tue Aug 27 15:47:42 2002
426@@ -32,6 +32,8 @@
427
428 extern u_int openpic_read(volatile u_int *addr);
429
430+extern void chrp_do_IRQ(struct pt_regs *,int , int);
431+
432 #define MAXCOUNT 10000000
433
434 #define GATWICK_IRQ_POOL_SIZE 10
435@@ -385,7 +387,7 @@
40a4a0a9
KT
436 irq_desc[i].ctl = &open_pic;
437 irq_desc[i].level = 0;
438 }
439- ppc_md.do_IRQ = open_pic_do_IRQ;
440+ ppc_md.do_IRQ = chrp_do_IRQ;
441 open_pic.irq_offset = 0;
442 openpic_init(1);
443 #ifdef CONFIG_XMON
444diff -urN linux.orig/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
445--- linux.orig/arch/ppc/kernel/prep_pci.c Sun Mar 25 18:31:49 2001
30fe9923 446+++ linux/arch/ppc/kernel/prep_pci.c Tue Aug 27 15:46:50 2002
40a4a0a9
KT
447@@ -5,6 +5,9 @@
448 * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
449 *
450 * The motherboard routes/maps will disappear shortly. -- Cort
451+ *
452+ * Add chrp_do_IRQ into ppc_md.do_IRQ -- Krzysztof Taraszka (dzimi@pld.org.pl)
453+ *
454 */
455
456 #include <linux/types.h>
457@@ -43,6 +46,8 @@
458 /* Used for Motorola to store system config register */
459 static unsigned long *ProcInfo;
460
461+extern void chrp_do_IRQ(struct pt_regs *,int , int);
462+
463 /* Tables for known hardware */
464
465 /* Motorola PowerStackII - Utah */
466@@ -783,7 +788,7 @@
467 OpenPIC_InitSenses = mvme2600_openpic_initsenses;
468 OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
469
470- ppc_md.do_IRQ = open_pic_do_IRQ;
471+ ppc_md.do_IRQ = chrp_do_IRQ;
472
473 /* If raven is present on Motorola store the system config register
474 * for later use.
This page took 0.522871 seconds and 4 git commands to generate.