]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.34 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 24 Aug 2010 21:37:49 +0000 (14:37 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 24 Aug 2010 21:37:49 +0000 (14:37 -0700)
queue-2.6.34/series
queue-2.6.34/x86-apic-ack-all-pending-irqs-when-crashed-on-kexec.patch [new file with mode: 0644]

index 5c771bfdeae7599f10199f4b21c80d1e43853db3..304ba9acbfcc98abd5ccf63e8f63f6af86944ded 100644 (file)
@@ -88,3 +88,4 @@ usb-xhci-remove-buggy-assignment-in-next_trb.patch
 usb-ftdi_sio-add-id-for-ionics-plugcomputer.patch
 usb-ftdi_sio-add-product-id-for-lenz-li-usb.patch
 tracing-fix-timer-tracing.patch
+x86-apic-ack-all-pending-irqs-when-crashed-on-kexec.patch
diff --git a/queue-2.6.34/x86-apic-ack-all-pending-irqs-when-crashed-on-kexec.patch b/queue-2.6.34/x86-apic-ack-all-pending-irqs-when-crashed-on-kexec.patch
new file mode 100644 (file)
index 0000000..f4dd31b
--- /dev/null
@@ -0,0 +1,140 @@
+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