Commit 89c38c28 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Ingo Molnar

x86: apic - unify setup_local_APIC

- remove useless read of APIC_LVR
- wrap with preempt_disable/enable
- check for integrated APIC just in place

v2: fix by Yinghai Lu.
	fix lapic_is_integrated using
	let 64-bit too have pic_mode
Signed-off-by: default avatarCyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: default avatarYinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 80e5609c
...@@ -1033,9 +1033,10 @@ static void __cpuinit lapic_setup_esr(void) ...@@ -1033,9 +1033,10 @@ static void __cpuinit lapic_setup_esr(void)
*/ */
void __cpuinit setup_local_APIC(void) void __cpuinit setup_local_APIC(void)
{ {
unsigned long value, integrated; unsigned int value;
int i, j; int i, j;
#ifdef CONFIG_X86_32
/* Pound the ESR really hard over the head with a big hammer - mbligh */ /* Pound the ESR really hard over the head with a big hammer - mbligh */
if (esr_disable) { if (esr_disable) {
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
...@@ -1043,14 +1044,16 @@ void __cpuinit setup_local_APIC(void) ...@@ -1043,14 +1044,16 @@ void __cpuinit setup_local_APIC(void)
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
} }
#endif
integrated = lapic_is_integrated(); preempt_disable();
/* /*
* Double-check whether this APIC is really registered. * Double-check whether this APIC is really registered.
* This is meaningless in clustered apic mode, so we skip it.
*/ */
if (!apic_id_registered()) if (!apic_id_registered())
WARN_ON_ONCE(1); BUG();
/* /*
* Intel recommends to set DFR, LDR and TPR before enabling * Intel recommends to set DFR, LDR and TPR before enabling
...@@ -1096,6 +1099,7 @@ void __cpuinit setup_local_APIC(void) ...@@ -1096,6 +1099,7 @@ void __cpuinit setup_local_APIC(void)
*/ */
value |= APIC_SPIV_APIC_ENABLED; value |= APIC_SPIV_APIC_ENABLED;
#ifdef CONFIG_X86_32
/* /*
* Some unknown Intel IO/APIC (or APIC) errata is biting us with * Some unknown Intel IO/APIC (or APIC) errata is biting us with
* certain networking cards. If high frequency interrupts are * certain networking cards. If high frequency interrupts are
...@@ -1116,8 +1120,13 @@ void __cpuinit setup_local_APIC(void) ...@@ -1116,8 +1120,13 @@ void __cpuinit setup_local_APIC(void)
* See also the comment in end_level_ioapic_irq(). --macro * See also the comment in end_level_ioapic_irq(). --macro
*/ */
/* Enable focus processor (bit==0) */ /*
* - enable focus processor (bit==0)
* - 64bit mode always use processor focus
* so no need to set it
*/
value &= ~APIC_SPIV_FOCUS_DISABLED; value &= ~APIC_SPIV_FOCUS_DISABLED;
#endif
/* /*
* Set spurious IRQ vector * Set spurious IRQ vector
...@@ -1154,9 +1163,11 @@ void __cpuinit setup_local_APIC(void) ...@@ -1154,9 +1163,11 @@ void __cpuinit setup_local_APIC(void)
value = APIC_DM_NMI; value = APIC_DM_NMI;
else else
value = APIC_DM_NMI | APIC_LVT_MASKED; value = APIC_DM_NMI | APIC_LVT_MASKED;
if (!integrated) /* 82489DX */ if (!lapic_is_integrated()) /* 82489DX */
value |= APIC_LVT_LEVEL_TRIGGER; value |= APIC_LVT_LEVEL_TRIGGER;
apic_write(APIC_LVT1, value); apic_write(APIC_LVT1, value);
preempt_enable();
} }
void __cpuinit end_local_APIC_setup(void) void __cpuinit end_local_APIC_setup(void)
......
...@@ -76,6 +76,8 @@ char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE}; ...@@ -76,6 +76,8 @@ char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};
*/ */
unsigned int apic_verbosity; unsigned int apic_verbosity;
int pic_mode;
/* Have we found an MP table */ /* Have we found an MP table */
int smp_found_config; int smp_found_config;
...@@ -943,8 +945,17 @@ void __cpuinit setup_local_APIC(void) ...@@ -943,8 +945,17 @@ void __cpuinit setup_local_APIC(void)
unsigned int value; unsigned int value;
int i, j; 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(); preempt_disable();
value = apic_read(APIC_LVR);
/* /*
* Double-check whether this APIC is really registered. * Double-check whether this APIC is really registered.
...@@ -997,7 +1008,34 @@ void __cpuinit setup_local_APIC(void) ...@@ -997,7 +1008,34 @@ void __cpuinit setup_local_APIC(void)
*/ */
value |= APIC_SPIV_APIC_ENABLED; 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 * Set spurious IRQ vector
...@@ -1016,14 +1054,14 @@ void __cpuinit setup_local_APIC(void) ...@@ -1016,14 +1054,14 @@ void __cpuinit setup_local_APIC(void)
* TODO: set up through-local-APIC from through-I/O-APIC? --macro * TODO: set up through-local-APIC from through-I/O-APIC? --macro
*/ */
value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
if (!smp_processor_id() && !value) { if (!smp_processor_id() && (pic_mode || !value)) {
value = APIC_DM_EXTINT; value = APIC_DM_EXTINT;
apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
smp_processor_id()); smp_processor_id());
} else { } else {
value = APIC_DM_EXTINT | APIC_LVT_MASKED; value = APIC_DM_EXTINT | APIC_LVT_MASKED;
apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
smp_processor_id()); smp_processor_id());
} }
apic_write(APIC_LVT0, value); apic_write(APIC_LVT0, value);
...@@ -1034,7 +1072,10 @@ void __cpuinit setup_local_APIC(void) ...@@ -1034,7 +1072,10 @@ void __cpuinit setup_local_APIC(void)
value = APIC_DM_NMI; value = APIC_DM_NMI;
else else
value = APIC_DM_NMI | APIC_LVT_MASKED; value = APIC_DM_NMI | APIC_LVT_MASKED;
if (!lapic_is_integrated()) /* 82489DX */
value |= APIC_LVT_LEVEL_TRIGGER;
apic_write(APIC_LVT1, value); apic_write(APIC_LVT1, value);
preempt_enable(); preempt_enable();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment