|
@@ -76,6 +76,8 @@ char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};
|
|
|
*/
|
|
|
unsigned int apic_verbosity;
|
|
|
|
|
|
+int pic_mode;
|
|
|
+
|
|
|
/* Have we found an MP table */
|
|
|
int smp_found_config;
|
|
|
|
|
@@ -943,8 +945,17 @@ void __cpuinit setup_local_APIC(void)
|
|
|
unsigned int value;
|
|
|
int i, j;
|
|
|
|
|
|
+#ifdef CONFIG_X86_32
|
|
|
+ /* Pound the ESR really hard over the head with a big hammer - mbligh */
|
|
|
+ if (esr_disable) {
|
|
|
+ apic_write(APIC_ESR, 0);
|
|
|
+ apic_write(APIC_ESR, 0);
|
|
|
+ apic_write(APIC_ESR, 0);
|
|
|
+ apic_write(APIC_ESR, 0);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
preempt_disable();
|
|
|
- value = apic_read(APIC_LVR);
|
|
|
|
|
|
/*
|
|
|
* Double-check whether this APIC is really registered.
|
|
@@ -997,7 +1008,34 @@ void __cpuinit setup_local_APIC(void)
|
|
|
*/
|
|
|
value |= APIC_SPIV_APIC_ENABLED;
|
|
|
|
|
|
- /* We always use processor focus */
|
|
|
+#ifdef CONFIG_X86_32
|
|
|
+ /*
|
|
|
+ * Some unknown Intel IO/APIC (or APIC) errata is biting us with
|
|
|
+ * certain networking cards. If high frequency interrupts are
|
|
|
+ * happening on a particular IOAPIC pin, plus the IOAPIC routing
|
|
|
+ * entry is masked/unmasked at a high rate as well then sooner or
|
|
|
+ * later IOAPIC line gets 'stuck', no more interrupts are received
|
|
|
+ * from the device. If focus CPU is disabled then the hang goes
|
|
|
+ * away, oh well :-(
|
|
|
+ *
|
|
|
+ * [ This bug can be reproduced easily with a level-triggered
|
|
|
+ * PCI Ne2000 networking cards and PII/PIII processors, dual
|
|
|
+ * BX chipset. ]
|
|
|
+ */
|
|
|
+ /*
|
|
|
+ * Actually disabling the focus CPU check just makes the hang less
|
|
|
+ * frequent as it makes the interrupt distributon model be more
|
|
|
+ * like LRU than MRU (the short-term load is more even across CPUs).
|
|
|
+ * See also the comment in end_level_ioapic_irq(). --macro
|
|
|
+ */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * - enable focus processor (bit==0)
|
|
|
+ * - 64bit mode always use processor focus
|
|
|
+ * so no need to set it
|
|
|
+ */
|
|
|
+ value &= ~APIC_SPIV_FOCUS_DISABLED;
|
|
|
+#endif
|
|
|
|
|
|
/*
|
|
|
* Set spurious IRQ vector
|
|
@@ -1016,14 +1054,14 @@ void __cpuinit setup_local_APIC(void)
|
|
|
* TODO: set up through-local-APIC from through-I/O-APIC? --macro
|
|
|
*/
|
|
|
value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
|
|
|
- if (!smp_processor_id() && !value) {
|
|
|
+ if (!smp_processor_id() && (pic_mode || !value)) {
|
|
|
value = APIC_DM_EXTINT;
|
|
|
apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
|
|
|
- smp_processor_id());
|
|
|
+ smp_processor_id());
|
|
|
} else {
|
|
|
value = APIC_DM_EXTINT | APIC_LVT_MASKED;
|
|
|
apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
|
|
|
- smp_processor_id());
|
|
|
+ smp_processor_id());
|
|
|
}
|
|
|
apic_write(APIC_LVT0, value);
|
|
|
|
|
@@ -1034,7 +1072,10 @@ void __cpuinit setup_local_APIC(void)
|
|
|
value = APIC_DM_NMI;
|
|
|
else
|
|
|
value = APIC_DM_NMI | APIC_LVT_MASKED;
|
|
|
+ if (!lapic_is_integrated()) /* 82489DX */
|
|
|
+ value |= APIC_LVT_LEVEL_TRIGGER;
|
|
|
apic_write(APIC_LVT1, value);
|
|
|
+
|
|
|
preempt_enable();
|
|
|
}
|
|
|
|