From: Len Brown Hi Linus, please do a bk pull http://linux-acpi.bkbits.net/linux-acpi-release-2.6.0 The world will not stop revolving if these wait till 2.6.1, but it will make 2.6.0 easier to support if they're included. 3 bug fixes -- all are in 2.4: 1390: adds cmdline to allow manual over-ride if out policy of forcing the ACPI SCI to level triggered is wrong. If we don't apply, some folks with no ACPI events will need to patch. 1177: makes print_IO_APIC() output useful instead of garbage. If we don't apply, then we need to send this patch to anybody who has an IO-APIC mode interrupt issue in ACPI mode. 1434: 1-line panic fix BIOS with correct ACPI table check-sums but garbled data can cause panic immediately after loading with no kernel output unless this is fixed. thanks, -Len ps. a plain patch is also available here: ftp://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/patches/release/2.6.0-test9/acpi-20031002-2.6.0-test9.diff.gz This will update the following files: arch/i386/kernel/dmi_scan.c | 1 arch/x86_64/kernel/mpparse.c | 2 through these ChangeSets: (03/11/18 1.1453) [ACPI] "acpi_pic_sci=edge" in case platform requires Edge Triggered SCI http://bugzilla.kernel.org/show_bug.cgi?id=1390 (03/11/18 1.1452) [ACPI] print_IO_APIC() only after it is programmed http://bugzilla.kernel.org/show_bug.cgi?id=1177 (03/11/07 1.1414.1.7) [ACPI] In ACPI mode, delay print_IO_APIC() to make its output valid. http://bugzilla.kernel.org/show_bug.cgi?id=1177 (03/11/07 1.1414.1.6) [ACPI] If ACPI is disabled by DMI BIOS date, then turn it off completely, including table parsing for HT. This avoids a crash due to ancient garbled tables. acpi=force is available to over-ride this default. http://bugzilla.kernel.org/show_bug.cgi?id=1434 Documentation/kernel-parameters.txt | 5 +++ arch/i386/kernel/acpi/boot.c | 53 ++++++++++++++++++++++++++++++------ arch/i386/kernel/dmi_scan.c | 1 arch/i386/kernel/io_apic.c | 10 ++---- arch/i386/kernel/mpparse.c | 4 ++ arch/x86_64/kernel/acpi/boot.c | 53 ++++++++++++++++++++++++++++++------ arch/x86_64/kernel/io_apic.c | 8 ++--- arch/x86_64/kernel/mpparse.c | 2 + drivers/acpi/bus.c | 4 +- 9 files changed, 112 insertions(+), 28 deletions(-) diff -puN arch/i386/kernel/acpi/boot.c~acpi-update arch/i386/kernel/acpi/boot.c --- 25/arch/i386/kernel/acpi/boot.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/arch/i386/kernel/acpi/boot.c 2003-11-19 21:30:27.000000000 -0800 @@ -250,29 +250,66 @@ acpi_parse_nmi_src ( #ifdef CONFIG_ACPI_BUS /* - * Set specified PIC IRQ to level triggered mode. + * "acpi_pic_sci=level" (current default) + * programs the PIC-mode SCI to Level Trigger. + * (NO-OP if the BIOS set Level Trigger already) + * + * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's + * it may require Edge Trigger -- use "acpi_pic_sci=edge" + * (NO-OP if the BIOS set Edge Trigger already) * * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) - * - * As the BIOS should have done this for us, - * print a warning if the IRQ wasn't already set to level. */ -void acpi_pic_set_level_irq(unsigned int irq) +static __initdata acpi_pic_sci_trigger; /* 0: level, 1: edge */ + +void __init +acpi_pic_sci_set_trigger(unsigned int irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); unsigned char val = inb(port); + + printk(PREFIX "IRQ%d SCI:", irq); if (!(val & mask)) { - printk(KERN_WARNING PREFIX "IRQ %d was Edge Triggered, " - "setting to Level Triggerd\n", irq); - outb(val | mask, port); + printk(" Edge"); + + if (!acpi_pic_sci_trigger) { + printk(" set to Level"); + outb(val | mask, port); + } + } else { + printk(" Level"); + + if (acpi_pic_sci_trigger) { + printk(" set to Edge"); + outb(val | mask, port); + } } + printk(" Trigger.\n"); } + +int __init +acpi_pic_sci_setup(char *str) +{ + while (str && *str) { + if (strncmp(str, "level", 5) == 0) + acpi_pic_sci_trigger = 0; /* force level trigger */ + if (strncmp(str, "edge", 4) == 0) + acpi_pic_sci_trigger = 1; /* force edge trigger */ + str = strchr(str, ','); + if (str) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("acpi_pic_sci=", acpi_pic_sci_setup); + #endif /* CONFIG_ACPI_BUS */ diff -puN arch/i386/kernel/dmi_scan.c~acpi-update arch/i386/kernel/dmi_scan.c --- 25/arch/i386/kernel/dmi_scan.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/arch/i386/kernel/dmi_scan.c 2003-11-19 21:30:27.000000000 -0800 @@ -1011,6 +1011,7 @@ static __init void dmi_check_blacklist(v printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s); printk(KERN_NOTICE "You can enable it with acpi=force\n"); acpi_disabled = 1; + acpi_ht = 0; } } } diff -puN arch/i386/kernel/io_apic.c~acpi-update arch/i386/kernel/io_apic.c --- 25/arch/i386/kernel/io_apic.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/arch/i386/kernel/io_apic.c 2003-11-19 21:30:27.000000000 -0800 @@ -1650,10 +1650,6 @@ static void __init setup_ioapic_ids_from unsigned char old_id; unsigned long flags; - if (acpi_ioapic) - /* This gets done during IOAPIC enumeration for ACPI. */ - return; - /* * This is broken; anything with a real cpu count has to * circumvent this idiocy regardless. @@ -2286,12 +2282,14 @@ void __init setup_IO_APIC(void) /* * Set up IO-APIC IRQ routing. */ - setup_ioapic_ids_from_mpc(); + if (!acpi_ioapic) + setup_ioapic_ids_from_mpc(); sync_Arb_IDs(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - print_IO_APIC(); + if (!acpi_ioapic) + print_IO_APIC(); } /* diff -puN arch/i386/kernel/mpparse.c~acpi-update arch/i386/kernel/mpparse.c --- 25/arch/i386/kernel/mpparse.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/arch/i386/kernel/mpparse.c 2003-11-19 21:30:27.000000000 -0800 @@ -1166,6 +1166,10 @@ void __init mp_parse_prt (void) mp_ioapic_routing[ioapic].apic_id, ioapic_pin, entry->irq); } + + print_IO_APIC(); + + return; } #endif /*CONFIG_ACPI_PCI*/ diff -puN arch/x86_64/kernel/acpi/boot.c~acpi-update arch/x86_64/kernel/acpi/boot.c --- 25/arch/x86_64/kernel/acpi/boot.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/acpi/boot.c 2003-11-19 21:30:27.000000000 -0800 @@ -253,29 +253,66 @@ acpi_parse_hpet ( #ifdef CONFIG_ACPI_BUS /* - * Set specified PIC IRQ to level triggered mode. + * "acpi_pic_sci=level" (current default) + * programs the PIC-mode SCI to Level Trigger. + * (NO-OP if the BIOS set Level Trigger already) + * + * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's + * it may require Edge Trigger -- use "acpi_pic_sci=edge" + * (NO-OP if the BIOS set Edge Trigger already) * * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) - * - * As the BIOS should have done this for us, - * print a warning if the IRQ wasn't already set to level. */ -void acpi_pic_set_level_irq(unsigned int irq) +static __initdata acpi_pic_sci_trigger; /* 0: level, 1: edge */ + +void __init +acpi_pic_sci_set_trigger(unsigned int irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); unsigned char val = inb(port); + + printk(PREFIX "IRQ%d SCI:", irq); if (!(val & mask)) { - printk(KERN_WARNING PREFIX "IRQ %d was Edge Triggered, " - "setting to Level Triggerd\n", irq); - outb(val | mask, port); + printk(" Edge"); + + if (!acpi_pic_sci_trigger) { + printk(" set to Level"); + outb(val | mask, port); + } + } else { + printk(" Level"); + + if (acpi_pic_sci_trigger) { + printk(" set to Edge"); + outb(val | mask, port); + } + } + printk(" Trigger.\n"); +} + +int __init +acpi_pic_sci_setup(char *str) +{ + while (str && *str) { + if (strncmp(str, "level", 5) == 0) + acpi_pic_sci_trigger = 0; /* force level trigger */ + if (strncmp(str, "edge", 4) == 0) + acpi_pic_sci_trigger = 1; /* force edge trigger */ + str = strchr(str, ','); + if (str) + str += strspn(str, ", \t"); } + return 1; } + +__setup("acpi_pic_sci=", acpi_pic_sci_setup); + #endif /* CONFIG_ACPI_BUS */ static unsigned long __init diff -puN arch/x86_64/kernel/io_apic.c~acpi-update arch/x86_64/kernel/io_apic.c --- 25/arch/x86_64/kernel/io_apic.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/io_apic.c 2003-11-19 21:30:27.000000000 -0800 @@ -1087,8 +1087,6 @@ static void __init setup_ioapic_ids_from unsigned char old_id; unsigned long flags; - if (acpi_ioapic) return; /* ACPI does that already */ - /* * Set the IOAPIC ID to the value stored in the MPC table. */ @@ -1673,12 +1671,14 @@ void __init setup_IO_APIC(void) /* * Set up the IO-APIC IRQ routing table. */ - setup_ioapic_ids_from_mpc(); + if (!acpi_ioapic) + setup_ioapic_ids_from_mpc(); sync_Arb_IDs(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - print_IO_APIC(); + if (!acpi_ioapic) + print_IO_APIC(); } /* Ensure the ACPI SCI interrupt level is active low, edge-triggered */ diff -puN arch/x86_64/kernel/mpparse.c~acpi-update arch/x86_64/kernel/mpparse.c --- 25/arch/x86_64/kernel/mpparse.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/mpparse.c 2003-11-19 21:30:27.000000000 -0800 @@ -950,6 +950,8 @@ void __init mp_parse_prt (void) entry->irq); } + print_IO_APIC(); + return; } diff -puN Documentation/kernel-parameters.txt~acpi-update Documentation/kernel-parameters.txt --- 25/Documentation/kernel-parameters.txt~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/Documentation/kernel-parameters.txt 2003-11-19 21:30:27.000000000 -0800 @@ -92,6 +92,11 @@ running once the system is up. ht -- run only enough ACPI to enable Hyper Threading See also Documentation/pm.txt. + acpi_pic_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode + Format: { level | edge } + level Force PIC-mode SCI to Level Trigger (default) + edge Force PIC-mode SCI to Edge Trigge + ad1816= [HW,OSS] Format: ,,, See also Documentation/sound/oss/AD1816. diff -puN drivers/acpi/bus.c~acpi-update drivers/acpi/bus.c --- 25/drivers/acpi/bus.c~acpi-update 2003-11-19 21:30:27.000000000 -0800 +++ 25-akpm/drivers/acpi/bus.c 2003-11-19 21:30:27.000000000 -0800 @@ -39,7 +39,7 @@ #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME ("acpi_bus") -extern void acpi_pic_set_level_irq(unsigned int irq); +extern void __init acpi_pic_sci_set_trigger(unsigned int irq); FADT_DESCRIPTOR acpi_fadt; struct acpi_device *acpi_root; @@ -615,7 +615,7 @@ acpi_bus_init (void) if (acpi_ioapic) mp_config_ioapic_for_sci(acpi_fadt.sci_int); else - acpi_pic_set_level_irq(acpi_fadt.sci_int); + acpi_pic_sci_set_trigger(acpi_fadt.sci_int); #endif status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); _