diff options
author | Cyrill Gorcunov <gorcunov@gmail.com> | 2008-08-24 05:01:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:53:01 -0400 |
commit | 89c38c2867ebe37c4c5aee23e7fa1bffb025b171 (patch) | |
tree | c0f9fbc1b4cf58e3431b0fb5ab26f3cb9b5c7330 /arch/x86/kernel/apic_64.c | |
parent | 80e5609cabd7e4321769701a70297f819a15b08d (diff) |
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: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic_64.c')
-rw-r--r-- | arch/x86/kernel/apic_64.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 4587e16f73ec..283968d4e024 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
@@ -76,6 +76,8 @@ char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE}; | |||
76 | */ | 76 | */ |
77 | unsigned int apic_verbosity; | 77 | unsigned int apic_verbosity; |
78 | 78 | ||
79 | int pic_mode; | ||
80 | |||
79 | /* Have we found an MP table */ | 81 | /* Have we found an MP table */ |
80 | int smp_found_config; | 82 | int smp_found_config; |
81 | 83 | ||
@@ -943,8 +945,17 @@ void __cpuinit setup_local_APIC(void) | |||
943 | unsigned int value; | 945 | unsigned int value; |
944 | int i, j; | 946 | int i, j; |
945 | 947 | ||
948 | #ifdef CONFIG_X86_32 | ||
949 | /* Pound the ESR really hard over the head with a big hammer - mbligh */ | ||
950 | if (esr_disable) { | ||
951 | apic_write(APIC_ESR, 0); | ||
952 | apic_write(APIC_ESR, 0); | ||
953 | apic_write(APIC_ESR, 0); | ||
954 | apic_write(APIC_ESR, 0); | ||
955 | } | ||
956 | #endif | ||
957 | |||
946 | preempt_disable(); | 958 | preempt_disable(); |
947 | value = apic_read(APIC_LVR); | ||
948 | 959 | ||
949 | /* | 960 | /* |
950 | * Double-check whether this APIC is really registered. | 961 | * Double-check whether this APIC is really registered. |
@@ -997,7 +1008,34 @@ void __cpuinit setup_local_APIC(void) | |||
997 | */ | 1008 | */ |
998 | value |= APIC_SPIV_APIC_ENABLED; | 1009 | value |= APIC_SPIV_APIC_ENABLED; |
999 | 1010 | ||
1000 | /* We always use processor focus */ | 1011 | #ifdef CONFIG_X86_32 |
1012 | /* | ||
1013 | * Some unknown Intel IO/APIC (or APIC) errata is biting us with | ||
1014 | * certain networking cards. If high frequency interrupts are | ||
1015 | * happening on a particular IOAPIC pin, plus the IOAPIC routing | ||
1016 | * entry is masked/unmasked at a high rate as well then sooner or | ||
1017 | * later IOAPIC line gets 'stuck', no more interrupts are received | ||
1018 | * from the device. If focus CPU is disabled then the hang goes | ||
1019 | * away, oh well :-( | ||
1020 | * | ||
1021 | * [ This bug can be reproduced easily with a level-triggered | ||
1022 | * PCI Ne2000 networking cards and PII/PIII processors, dual | ||
1023 | * BX chipset. ] | ||
1024 | */ | ||
1025 | /* | ||
1026 | * Actually disabling the focus CPU check just makes the hang less | ||
1027 | * frequent as it makes the interrupt distributon model be more | ||
1028 | * like LRU than MRU (the short-term load is more even across CPUs). | ||
1029 | * See also the comment in end_level_ioapic_irq(). --macro | ||
1030 | */ | ||
1031 | |||
1032 | /* | ||
1033 | * - enable focus processor (bit==0) | ||
1034 | * - 64bit mode always use processor focus | ||
1035 | * so no need to set it | ||
1036 | */ | ||
1037 | value &= ~APIC_SPIV_FOCUS_DISABLED; | ||
1038 | #endif | ||
1001 | 1039 | ||
1002 | /* | 1040 | /* |
1003 | * Set spurious IRQ vector | 1041 | * Set spurious IRQ vector |
@@ -1016,14 +1054,14 @@ void __cpuinit setup_local_APIC(void) | |||
1016 | * TODO: set up through-local-APIC from through-I/O-APIC? --macro | 1054 | * TODO: set up through-local-APIC from through-I/O-APIC? --macro |
1017 | */ | 1055 | */ |
1018 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; | 1056 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; |
1019 | if (!smp_processor_id() && !value) { | 1057 | if (!smp_processor_id() && (pic_mode || !value)) { |
1020 | value = APIC_DM_EXTINT; | 1058 | value = APIC_DM_EXTINT; |
1021 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", | 1059 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", |
1022 | smp_processor_id()); | 1060 | smp_processor_id()); |
1023 | } else { | 1061 | } else { |
1024 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; | 1062 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; |
1025 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", | 1063 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", |
1026 | smp_processor_id()); | 1064 | smp_processor_id()); |
1027 | } | 1065 | } |
1028 | apic_write(APIC_LVT0, value); | 1066 | apic_write(APIC_LVT0, value); |
1029 | 1067 | ||
@@ -1034,7 +1072,10 @@ void __cpuinit setup_local_APIC(void) | |||
1034 | value = APIC_DM_NMI; | 1072 | value = APIC_DM_NMI; |
1035 | else | 1073 | else |
1036 | value = APIC_DM_NMI | APIC_LVT_MASKED; | 1074 | value = APIC_DM_NMI | APIC_LVT_MASKED; |
1075 | if (!lapic_is_integrated()) /* 82489DX */ | ||
1076 | value |= APIC_LVT_LEVEL_TRIGGER; | ||
1037 | apic_write(APIC_LVT1, value); | 1077 | apic_write(APIC_LVT1, value); |
1078 | |||
1038 | preempt_enable(); | 1079 | preempt_enable(); |
1039 | } | 1080 | } |
1040 | 1081 | ||