Hi everyone,

There I am again. The patch I wrote seems to get popular. So here we go.
Everyone having trouble with things that can be related to interrupts
should give this a try.

The patch give the ability to use
LILO boot: linux ioapic_level=3,4 xtpic=10,11
to treat the irqs 3 & 4 as level triggered interrupts and the irqs 10 and 11 as
XT-PIC interrupts (delivered only to CPU0).

Of course, use it to change interrupts that may be causing the trouble. FIRST
try ioapic_level=irq (as this will distribute irqs over the processors as
well), NEXT if the first did not solve anything try xtpic=irq to see if that
solve it.  DON'T FORGET to let me know what happened. I have a serious lack of
data at the moment. Please send me /proc/interrupts too!

The interrupts that should be changed are the high trafic irqs.  That is: the
mouse & the network card.  The problem will mostly occur in the non-PCI cards
and the standard ports (mouse serial & ps/2).

This patch should apply cleanly to 2.2.10, ie no warnings during patch nor
during compile. (Not tested with other kernels, but it should be easy to modify
if nescessary).

This is NOT specifically a kernel bug, it's more like a BIOS bug. But it's
too early to say what exactly is causing this trouble.

Greetings,
Jos van de Ven
diff -u -r linux-2.2.10/arch/i386/kernel/io_apic.c 
linux-2.2.10-ioapic/arch/i386/kernel/io_apic.c
--- linux-2.2.10/arch/i386/kernel/io_apic.c     Fri May  7 01:07:03 1999
+++ linux-2.2.10-ioapic/arch/i386/kernel/io_apic.c      Mon Jul  5 18:48:27 1999
@@ -100,6 +100,28 @@
 int mpc_default_type = 0;                      /* non-0 if default (table-less)
                                                   MP configuration */
 
+/*
+ *
+ * IRQ's that are handled by the old PIC in all cases:
+ * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
+ *   Linux doesn't really care, as it's not actually used
+ *   for any interrupt handling anyway.
+ * - IRQ13 is the FPU error IRQ, and may be connected
+ *   directly from the FPU to the old PIC. Linux doesn't
+ *   really care, because Linux doesn't want to use IRQ13
+ *   anyway (exception 16 is the proper FPU error signal)
+ *
+ * Additionally, something is definitely wrong with irq9
+ * on PIIX4 boards.
+ */
+int pic_irqs = ((1<<2)|(1<<13));
+
+/*
+ * For buggy BIOS we want to be able to overrule Edge
+ * interrupts trigger type. Normally this should not
+ * be nescessary.
+ */
+int ioapic_level_mask = 0;
 
 /*
  * This is performance-critical, we want to do it O(1)
@@ -268,6 +290,49 @@
 }
 
 /*
+ * If we want a IRQ to be Level triggered when the BIOS (incorrectly)
+ * reports edge, we can use kernel parameter ioapic_level=n,n,n,...
+ */
+void __init ioapic_level_setup(char *str, int *ints)
+{
+       int i, max;
+
+       if (ints) {
+               printk("IO-APIC-level enabling for\n");
+               max = MAX_PIRQS;
+               max = ints[0];
+
+               for (i = 0; i < max; i++) {
+                       printk("IRQ%d\n", ints[i+1]);
+                       ioapic_level_mask |= (1<<ints[i+1]);
+               }
+       }
+}
+
+/*
+ * We can use the kernel parameter xtpic=n,n,n,... to force
+ * the use of the xtpic on certain interrupts.
+ */
+void __init ioapic_xtpic_setup(char *str, int *ints)
+{
+       int i, max;
+
+       if (ints) {
+               printk("XT-PIC setting for\n");
+               max = MAX_PIRQS;
+               if (ints[0] < MAX_PIRQS)
+                       max = ints[0];
+
+               for (i = 0; i < max; i++) {
+                       if (ints[i+1] <= 15) {
+                               printk("IRQ%d\n", ints[i+1]);
+                               pic_irqs |= (1<<ints[i+1]);
+                       }
+               }
+       }
+}
+
+/*
  * Find the IRQ entry number of a certain pin.
  */
 static int __init find_irq_entry(int pin, int type)
@@ -478,6 +543,14 @@
                        break;
                }
        }
+       /*
+        * If we want a IRQ to be Level triggered when the BIOS (incorrectly)
+        * reports edge, we give a extra warning. (kernel parameter 
+ioapic_level=n,n,n,...)
+        */
+       if (ioapic_level_mask & (1<<mp_irqs[idx].mpc_dstirq)) {
+               printk("WARNING: Forcing IRQ%d to level\n", mp_irqs[idx].mpc_dstirq);
+               trigger=1;
+       }
        return trigger;
 }
 
@@ -1253,21 +1326,6 @@
        }
 }
 
-/*
- *
- * IRQ's that are handled by the old PIC in all cases:
- * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
- *   Linux doesn't really care, as it's not actually used
- *   for any interrupt handling anyway.
- * - IRQ13 is the FPU error IRQ, and may be connected
- *   directly from the FPU to the old PIC. Linux doesn't
- *   really care, because Linux doesn't want to use IRQ13
- *   anyway (exception 16 is the proper FPU error signal)
- *
- * Additionally, something is definitely wrong with irq9
- * on PIIX4 boards.
- */
-#define PIC_IRQS       ((1<<2)|(1<<13))
 
 void __init setup_IO_APIC(void)
 {
@@ -1286,7 +1344,7 @@
                pirqs_enabled)
        {
                printk("ENABLING IO-APIC IRQs\n");
-               io_apic_irqs = ~PIC_IRQS;
+               io_apic_irqs = ~pic_irqs;
        } else {
                if (ioapic_blacklisted())
                        printk(" blacklisted board, DISABLING IO-APIC IRQs\n");
diff -u -r linux-2.2.10/init/main.c linux-2.2.10-ioapic/init/main.c
--- linux-2.2.10/init/main.c    Tue May 11 18:57:14 1999
+++ linux-2.2.10-ioapic/init/main.c     Mon Jul  5 18:43:26 1999
@@ -95,6 +95,8 @@
 extern void smp_setup(char *str, int *ints);
 #ifdef __i386__
 extern void ioapic_pirq_setup(char *str, int *ints);
+extern void ioapic_level_setup(char *str, int *ints);
+extern void ioapic_xtpic_setup(char *str, int *ints);
 extern void ioapic_setup(char *str, int *ints);
 #endif
 extern void no_scroll(char *str, int *ints);
@@ -550,8 +552,10 @@
        { "nosmp", smp_setup },
        { "maxcpus=", smp_setup },
 #ifdef CONFIG_X86_IO_APIC
-       { "noapic", ioapic_setup },
-       { "pirq=", ioapic_pirq_setup },
+        { "xtpic=", ioapic_xtpic_setup },
+        { "ioapic_level=", ioapic_level_setup },
+        { "noapic", ioapic_setup },
+        { "pirq=", ioapic_pirq_setup },
 #endif
 #endif
 #ifdef CONFIG_BLK_DEV_RAM

Reply via email to