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 | |
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')
-rw-r--r-- | arch/x86/kernel/apic_32.c | 21 | ||||
-rw-r--r-- | arch/x86/kernel/apic_64.c | 51 |
2 files changed, 62 insertions, 10 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index df6ed603e547..f8c1251984e2 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c | |||
@@ -1033,9 +1033,10 @@ static void __cpuinit lapic_setup_esr(void) | |||
1033 | */ | 1033 | */ |
1034 | void __cpuinit setup_local_APIC(void) | 1034 | void __cpuinit setup_local_APIC(void) |
1035 | { | 1035 | { |
1036 | unsigned long value, integrated; | 1036 | unsigned int value; |
1037 | int i, j; | 1037 | int i, j; |
1038 | 1038 | ||
1039 | #ifdef CONFIG_X86_32 | ||
1039 | /* Pound the ESR really hard over the head with a big hammer - mbligh */ | 1040 | /* Pound the ESR really hard over the head with a big hammer - mbligh */ |
1040 | if (esr_disable) { | 1041 | if (esr_disable) { |
1041 | apic_write(APIC_ESR, 0); | 1042 | apic_write(APIC_ESR, 0); |
@@ -1043,14 +1044,16 @@ void __cpuinit setup_local_APIC(void) | |||
1043 | apic_write(APIC_ESR, 0); | 1044 | apic_write(APIC_ESR, 0); |
1044 | apic_write(APIC_ESR, 0); | 1045 | apic_write(APIC_ESR, 0); |
1045 | } | 1046 | } |
1047 | #endif | ||
1046 | 1048 | ||
1047 | integrated = lapic_is_integrated(); | 1049 | preempt_disable(); |
1048 | 1050 | ||
1049 | /* | 1051 | /* |
1050 | * Double-check whether this APIC is really registered. | 1052 | * Double-check whether this APIC is really registered. |
1053 | * This is meaningless in clustered apic mode, so we skip it. | ||
1051 | */ | 1054 | */ |
1052 | if (!apic_id_registered()) | 1055 | if (!apic_id_registered()) |
1053 | WARN_ON_ONCE(1); | 1056 | BUG(); |
1054 | 1057 | ||
1055 | /* | 1058 | /* |
1056 | * Intel recommends to set DFR, LDR and TPR before enabling | 1059 | * Intel recommends to set DFR, LDR and TPR before enabling |
@@ -1096,6 +1099,7 @@ void __cpuinit setup_local_APIC(void) | |||
1096 | */ | 1099 | */ |
1097 | value |= APIC_SPIV_APIC_ENABLED; | 1100 | value |= APIC_SPIV_APIC_ENABLED; |
1098 | 1101 | ||
1102 | #ifdef CONFIG_X86_32 | ||
1099 | /* | 1103 | /* |
1100 | * Some unknown Intel IO/APIC (or APIC) errata is biting us with | 1104 | * Some unknown Intel IO/APIC (or APIC) errata is biting us with |
1101 | * certain networking cards. If high frequency interrupts are | 1105 | * certain networking cards. If high frequency interrupts are |
@@ -1116,8 +1120,13 @@ void __cpuinit setup_local_APIC(void) | |||
1116 | * See also the comment in end_level_ioapic_irq(). --macro | 1120 | * See also the comment in end_level_ioapic_irq(). --macro |
1117 | */ | 1121 | */ |
1118 | 1122 | ||
1119 | /* Enable focus processor (bit==0) */ | 1123 | /* |
1124 | * - enable focus processor (bit==0) | ||
1125 | * - 64bit mode always use processor focus | ||
1126 | * so no need to set it | ||
1127 | */ | ||
1120 | value &= ~APIC_SPIV_FOCUS_DISABLED; | 1128 | value &= ~APIC_SPIV_FOCUS_DISABLED; |
1129 | #endif | ||
1121 | 1130 | ||
1122 | /* | 1131 | /* |
1123 | * Set spurious IRQ vector | 1132 | * Set spurious IRQ vector |
@@ -1154,9 +1163,11 @@ void __cpuinit setup_local_APIC(void) | |||
1154 | value = APIC_DM_NMI; | 1163 | value = APIC_DM_NMI; |
1155 | else | 1164 | else |
1156 | value = APIC_DM_NMI | APIC_LVT_MASKED; | 1165 | value = APIC_DM_NMI | APIC_LVT_MASKED; |
1157 | if (!integrated) /* 82489DX */ | 1166 | if (!lapic_is_integrated()) /* 82489DX */ |
1158 | value |= APIC_LVT_LEVEL_TRIGGER; | 1167 | value |= APIC_LVT_LEVEL_TRIGGER; |
1159 | apic_write(APIC_LVT1, value); | 1168 | apic_write(APIC_LVT1, value); |
1169 | |||
1170 | preempt_enable(); | ||
1160 | } | 1171 | } |
1161 | 1172 | ||
1162 | void __cpuinit end_local_APIC_setup(void) | 1173 | void __cpuinit end_local_APIC_setup(void) |
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 | ||