|
@@ -51,6 +51,7 @@
|
|
|
#include <asm/smp.h>
|
|
|
#include <asm/mce.h>
|
|
|
#include <asm/kvm_para.h>
|
|
|
+#include <asm/tsc.h>
|
|
|
|
|
|
unsigned int num_processors;
|
|
|
|
|
@@ -1151,8 +1152,13 @@ static void __cpuinit lapic_setup_esr(void)
|
|
|
*/
|
|
|
void __cpuinit setup_local_APIC(void)
|
|
|
{
|
|
|
- unsigned int value;
|
|
|
- int i, j;
|
|
|
+ unsigned int value, queued;
|
|
|
+ int i, j, acked = 0;
|
|
|
+ unsigned long long tsc = 0, ntsc;
|
|
|
+ long long max_loops = cpu_khz;
|
|
|
+
|
|
|
+ if (cpu_has_tsc)
|
|
|
+ rdtscll(tsc);
|
|
|
|
|
|
if (disable_apic) {
|
|
|
arch_disable_smp_support();
|
|
@@ -1204,13 +1210,32 @@ void __cpuinit setup_local_APIC(void)
|
|
|
* the interrupt. Hence a vector might get locked. It was noticed
|
|
|
* for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
|
|
|
*/
|
|
|
- for (i = APIC_ISR_NR - 1; i >= 0; i--) {
|
|
|
- value = apic_read(APIC_ISR + i*0x10);
|
|
|
- for (j = 31; j >= 0; j--) {
|
|
|
- if (value & (1<<j))
|
|
|
- ack_APIC_irq();
|
|
|
+ do {
|
|
|
+ queued = 0;
|
|
|
+ for (i = APIC_ISR_NR - 1; i >= 0; i--)
|
|
|
+ queued |= apic_read(APIC_IRR + i*0x10);
|
|
|
+
|
|
|
+ for (i = APIC_ISR_NR - 1; i >= 0; i--) {
|
|
|
+ value = apic_read(APIC_ISR + i*0x10);
|
|
|
+ for (j = 31; j >= 0; j--) {
|
|
|
+ if (value & (1<<j)) {
|
|
|
+ ack_APIC_irq();
|
|
|
+ acked++;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
+ if (acked > 256) {
|
|
|
+ printk(KERN_ERR "LAPIC pending interrupts after %d EOI\n",
|
|
|
+ acked);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (cpu_has_tsc) {
|
|
|
+ rdtscll(ntsc);
|
|
|
+ max_loops = (cpu_khz << 10) - (ntsc - tsc);
|
|
|
+ } else
|
|
|
+ max_loops--;
|
|
|
+ } while (queued && max_loops > 0);
|
|
|
+ WARN_ON(max_loops <= 0);
|
|
|
|
|
|
/*
|
|
|
* Now that we are all set up, enable the APIC
|