diff options
Diffstat (limited to 'arch/x86_64/kernel/apic.c')
-rw-r--r-- | arch/x86_64/kernel/apic.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index e5b14c57ea..100a30c400 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c | |||
@@ -342,6 +342,7 @@ void __init init_bsp_APIC(void) | |||
342 | void __cpuinit setup_local_APIC (void) | 342 | void __cpuinit setup_local_APIC (void) |
343 | { | 343 | { |
344 | unsigned int value, maxlvt; | 344 | unsigned int value, maxlvt; |
345 | int i, j; | ||
345 | 346 | ||
346 | value = apic_read(APIC_LVR); | 347 | value = apic_read(APIC_LVR); |
347 | 348 | ||
@@ -371,6 +372,25 @@ void __cpuinit setup_local_APIC (void) | |||
371 | apic_write(APIC_TASKPRI, value); | 372 | apic_write(APIC_TASKPRI, value); |
372 | 373 | ||
373 | /* | 374 | /* |
375 | * After a crash, we no longer service the interrupts and a pending | ||
376 | * interrupt from previous kernel might still have ISR bit set. | ||
377 | * | ||
378 | * Most probably by now CPU has serviced that pending interrupt and | ||
379 | * it might not have done the ack_APIC_irq() because it thought, | ||
380 | * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it | ||
381 | * does not clear the ISR bit and cpu thinks it has already serivced | ||
382 | * the interrupt. Hence a vector might get locked. It was noticed | ||
383 | * for timer irq (vector 0x31). Issue an extra EOI to clear ISR. | ||
384 | */ | ||
385 | for (i = APIC_ISR_NR - 1; i >= 0; i--) { | ||
386 | value = apic_read(APIC_ISR + i*0x10); | ||
387 | for (j = 31; j >= 0; j--) { | ||
388 | if (value & (1<<j)) | ||
389 | ack_APIC_irq(); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | /* | ||
374 | * Now that we are all set up, enable the APIC | 394 | * Now that we are all set up, enable the APIC |
375 | */ | 395 | */ |
376 | value = apic_read(APIC_SPIV); | 396 | value = apic_read(APIC_SPIV); |
@@ -595,7 +615,7 @@ static int __init apic_set_verbosity(char *str) | |||
595 | printk(KERN_WARNING "APIC Verbosity level %s not recognised" | 615 | printk(KERN_WARNING "APIC Verbosity level %s not recognised" |
596 | " use apic=verbose or apic=debug", str); | 616 | " use apic=verbose or apic=debug", str); |
597 | 617 | ||
598 | return 0; | 618 | return 1; |
599 | } | 619 | } |
600 | 620 | ||
601 | __setup("apic=", apic_set_verbosity); | 621 | __setup("apic=", apic_set_verbosity); |
@@ -1117,35 +1137,35 @@ int __init APIC_init_uniprocessor (void) | |||
1117 | static __init int setup_disableapic(char *str) | 1137 | static __init int setup_disableapic(char *str) |
1118 | { | 1138 | { |
1119 | disable_apic = 1; | 1139 | disable_apic = 1; |
1120 | return 0; | 1140 | return 1; |
1121 | } | 1141 | } |
1122 | 1142 | ||
1123 | static __init int setup_nolapic(char *str) | 1143 | static __init int setup_nolapic(char *str) |
1124 | { | 1144 | { |
1125 | disable_apic = 1; | 1145 | disable_apic = 1; |
1126 | return 0; | 1146 | return 1; |
1127 | } | 1147 | } |
1128 | 1148 | ||
1129 | static __init int setup_noapictimer(char *str) | 1149 | static __init int setup_noapictimer(char *str) |
1130 | { | 1150 | { |
1131 | if (str[0] != ' ' && str[0] != 0) | 1151 | if (str[0] != ' ' && str[0] != 0) |
1132 | return -1; | 1152 | return 0; |
1133 | disable_apic_timer = 1; | 1153 | disable_apic_timer = 1; |
1134 | return 0; | 1154 | return 1; |
1135 | } | 1155 | } |
1136 | 1156 | ||
1137 | static __init int setup_apicmaintimer(char *str) | 1157 | static __init int setup_apicmaintimer(char *str) |
1138 | { | 1158 | { |
1139 | apic_runs_main_timer = 1; | 1159 | apic_runs_main_timer = 1; |
1140 | nohpet = 1; | 1160 | nohpet = 1; |
1141 | return 0; | 1161 | return 1; |
1142 | } | 1162 | } |
1143 | __setup("apicmaintimer", setup_apicmaintimer); | 1163 | __setup("apicmaintimer", setup_apicmaintimer); |
1144 | 1164 | ||
1145 | static __init int setup_noapicmaintimer(char *str) | 1165 | static __init int setup_noapicmaintimer(char *str) |
1146 | { | 1166 | { |
1147 | apic_runs_main_timer = -1; | 1167 | apic_runs_main_timer = -1; |
1148 | return 0; | 1168 | return 1; |
1149 | } | 1169 | } |
1150 | __setup("noapicmaintimer", setup_noapicmaintimer); | 1170 | __setup("noapicmaintimer", setup_noapicmaintimer); |
1151 | 1171 | ||