diff mbox

Quirk to fix suspend/resume on another Lenovo ThinkPad Edge, model 030246G.

Message ID 20110224145657.GE3658@alberich.amd.com
State Accepted
Delegated to: Andy Whitcroft
Headers show

Commit Message

Andreas Herrmann Feb. 24, 2011, 2:56 p.m. UTC
On Wed, Feb 23, 2011 at 03:58:40PM +0100, Andreas Herrmann wrote:
> On Wed, Feb 16, 2011 at 04:17:02AM -0500, Stefan Bader wrote:
> > Hi Andreas,
> > 
> > I know there probably are already enough people poking you about when there
> > might be a generic fix. Just wanted to point out that Thomas reported a SB880
> > (in case that makes a difference to SB800 that seemed to be reported before).
> 
> Hi Stefan,
> 
> patch is prepared.
> Just want to have verified it on one known buggy system here.
> I'll send it out by end of today or tomorrow.

I've just submitted below patch to LKML
(http://marc.info/?i=20110224145346.GD3658@alberich.amd.com)


Andreas

---
On some SB800 systems polarity for IOAPIC pin2 is wrongly specified as
low active by BIOS. This caused system hangs after resume from S3 when
HPET was used in one-shot mode on such systems because a timer
interrupt was missed (HPET signal is high active).

For more details see http://marc.info/?l=linux-kernel&m=129623757413868

Cc: stable@kernel.org # 37.x, 32.x
Tested-by: Manoj Iyer <manoj.iyer@canonical.com>
Tested-by: Andre Przywara <andre.przywara@amd.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
---
 arch/x86/include/asm/acpi.h    |    1 +
 arch/x86/kernel/acpi/boot.c    |   16 ++++++++++++----
 arch/x86/kernel/early-quirks.c |   16 +++++++---------
 3 files changed, 20 insertions(+), 13 deletions(-)
diff mbox

Patch

diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 211ca3f..4ea15ca 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -88,6 +88,7 @@  extern int acpi_disabled;
 extern int acpi_pci_disabled;
 extern int acpi_skip_timer_override;
 extern int acpi_use_timer_override;
+extern int acpi_fix_pin2_polarity;
 
 extern u8 acpi_sci_flags;
 extern int acpi_sci_override_gsi;
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b3a7113..ff25db6 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -72,6 +72,7 @@  u8 acpi_sci_flags __initdata;
 int acpi_sci_override_gsi __initdata;
 int acpi_skip_timer_override __initdata;
 int acpi_use_timer_override __initdata;
+int acpi_fix_pin2_polarity __initdata;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
@@ -415,10 +416,17 @@  acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
 		return 0;
 	}
 
-	if (acpi_skip_timer_override &&
-	    intsrc->source_irq == 0 && intsrc->global_irq == 2) {
-		printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
-		return 0;
+	if (intsrc->source_irq == 0 && intsrc->global_irq == 2) {
+		if (acpi_skip_timer_override) {
+			printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
+			return 0;
+		}
+		if (acpi_fix_pin2_polarity &&
+		    (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
+			intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
+			printk(PREFIX "BIOS IRQ0 pin2 override: "
+			       "forcing polarity to high active.\n");
+		}
 	}
 
 	mp_override_legacy_irq(intsrc->source_irq,
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 76b8cd9..9efbdcc 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -143,15 +143,10 @@  static void __init ati_bugs(int num, int slot, int func)
 
 static u32 __init ati_sbx00_rev(int num, int slot, int func)
 {
-	u32 old, d;
+	u32 d;
 
-	d = read_pci_config(num, slot, func, 0x70);
-	old = d;
-	d &= ~(1<<8);
-	write_pci_config(num, slot, func, 0x70, d);
 	d = read_pci_config(num, slot, func, 0x8);
 	d &= 0xff;
-	write_pci_config(num, slot, func, 0x70, old);
 
 	return d;
 }
@@ -160,13 +155,16 @@  static void __init ati_bugs_contd(int num, int slot, int func)
 {
 	u32 d, rev;
 
-	if (acpi_use_timer_override)
-		return;
-
 	rev = ati_sbx00_rev(num, slot, func);
+	if (rev >= 0x40)
+		acpi_fix_pin2_polarity = 1;
+
 	if (rev > 0x13)
 		return;
 
+	if (acpi_use_timer_override)
+		return;
+
 	/* check for IRQ0 interrupt swap */
 	d = read_pci_config(num, slot, func, 0x64);
 	if (!(d & (1<<14)))