--- /dev/null
+From 8c3ba8d049247dc06b6dcee1711a11b26647aa44 Mon Sep 17 00:00:00 2001
+From: Kerstin Jonsson <kerstin.jonsson@ericsson.com>
+Date: Mon, 24 May 2010 12:13:15 -0700
+Subject: x86, apic: ack all pending irqs when crashed/on kexec
+
+From: Kerstin Jonsson <kerstin.jonsson@ericsson.com>
+
+commit 8c3ba8d049247dc06b6dcee1711a11b26647aa44 upstream.
+
+When the SMP kernel decides to crash_kexec() the local APICs may have
+pending interrupts in their vector tables.
+
+The setup routine for the local APIC has a deficient mechanism for
+clearing these interrupts, it only handles interrupts that has already
+been dispatched to the local core for servicing (the ISR register) safely,
+it doesn't consider lower prioritized queued interrupts stored in the IRR
+register.
+
+If you have more than one pending interrupt within the same 32 bit word in
+the LAPIC vector table registers you may find yourself entering the IO
+APIC setup with pending interrupts left in the LAPIC. This is a situation
+for wich the IO APIC setup is not prepared. Depending of what/which
+interrupt vector/vectors are stuck in the APIC tables your system may show
+various degrees of malfunctioning. That was the reason why the
+check_timer() failed in our system, the timer interrupts was blocked by
+pending interrupts from the old kernel when routed trough the IO APIC.
+
+Additional comment from Jiri Bohac:
+==============
+If this should go into stable release,
+I'd add some kind of limit on the number of iterations, just to be safe from
+hard to debug lock-ups:
+
++if (loops++ > MAX_LOOPS) {
++ printk("LAPIC pending clean-up")
++ break;
++}
+ while (queued);
+
+with MAX_LOOPS something like 1E9 this would leave plenty of time for the
+pending IRQs to be cleared and would and still cause at most a second of delay
+if the loop were to lock-up for whatever reason.
+
+[trenn@suse.de:
+
+V2: Use tsc if avail to bail out after 1 sec due to possible virtual
+ apic_read calls which may take rather long (suggested by: Avi Kivity
+ <avi@redhat.com>) If no tsc is available bail out quickly after
+ cpu_khz, if we broke out too early and still have irqs pending (which
+ should never happen?) we still get a WARN_ON...
+
+V3: - Fixed indentation -> checkpatch clean
+ - max_loops must be signed
+
+V4: - Fix typo, mixed up tsc and ntsc in first rdtscll() call
+
+V5: Adjust WARN_ON() condition to also catch error in cpu_has_tsc case]
+
+Cc: <jbohac@novell.com>
+Cc: Yinghai Lu <yinghai@kernel.org>
+Cc: Kerstin Jonsson <kerstin.jonsson@ericsson.com>
+Cc: Avi Kivity <avi@redhat.com>
+Cc: Suresh Siddha <suresh.b.siddha@intel.com>
+Tested-by: Eric W. Biederman <ebiederm@xmission.com>
+Signed-off-by: Thomas Renninger <trenn@suse.de>
+LKML-Reference: <201005241913.o4OJDGWM010865@imap1.linux-foundation.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
+Cc: Thomas Renninger <trenn@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/apic/apic.c | 41 +++++++++++++++++++++++++++++++++--------
+ 1 file changed, 33 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/kernel/apic/apic.c
++++ b/arch/x86/kernel/apic/apic.c
+@@ -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(vo
+ */
+ 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