]> git.ipfire.org Git - people/ms/linux.git/commitdiff
x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems
authorAndreas Herrmann <andreas.herrmann3@amd.com>
Thu, 24 Feb 2011 14:53:46 +0000 (15:53 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 7 Mar 2011 23:05:12 +0000 (15:05 -0800)
commit 7f74f8f28a2bd9db9404f7d364e2097a0c42cc12 upstream.

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

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>
Cc: Borislav Petkov <borislav.petkov@amd.com>
LKML-Reference: <20110224145346.GD3658@alberich.amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/x86/include/asm/acpi.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/early-quirks.c

index 55d106b5e31b2ff68f4738cf458a4c9c09eafc7e..f90c73215626086731e32afe39b0cc75c6a17154 100644 (file)
@@ -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;
index 71232b941b6c9c6409fd14e9479f3d1625eeaeb0..80cc938fa64c54755a98e213f8391d9ef17df212 100644 (file)
@@ -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;
@@ -410,10 +411,15 @@ 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,
index 76b8cd953deed9f8a50d572cdc52b5edb68bc3b7..9efbdcc56425b18ce38224cf7b866c1bf66c5d5a 100644 (file)
@@ -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)))