# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/03/22 16:02:16-05:00 len.brown@intel.com # [ACPI] ACPI SCI shall be level/low unless explicit over-ride # http://bugzilla.kernel.org/show_bug.cgi?id=1622 # add "acpi_sci=edge" and "acpi_sci=high" manual over-ride # # include/asm-i386/mpspec.h # 2004/03/22 16:00:03-05:00 len.brown@intel.com +0 -7 # delete mp_config_ioapic_for_sci() # # drivers/acpi/bus.c # 2004/03/22 16:00:03-05:00 len.brown@intel.com +18 -2 # delete mp_config_ioapic_for_sci() # add param to acpi_pic_sci_set_trigger. # # arch/i386/kernel/setup.c # 2004/03/22 16:00:03-05:00 len.brown@intel.com +13 -0 # add acpi_sci= -- they need to be early to preceed MADT table parsing # # arch/i386/kernel/mpparse.c # 2004/03/22 16:00:03-05:00 len.brown@intel.com +0 -63 # delete mp_config_ioapic_for_sci() -- it had several problems. # walking the MADT was redundant # not setting flags for no-override case to level/low was incorrect # calling io_apic_set_pci_routing() on a legacy IRQ was incorrect # # arch/i386/kernel/acpi/boot.c # 2004/03/22 16:00:03-05:00 len.brown@intel.com +67 -33 # add acpi_parse_sci_int_src_ovr() for handling SCI interrupt flags # grab the SCI from the early FADT parse # fix typo in acpi_pic_sci_set_triger() that allowed it only to set for level trigger # # Documentation/kernel-parameters.txt # 2004/03/22 16:00:03-05:00 len.brown@intel.com +2 -4 # replace acpi_pic_sci= with acpi_sci= # diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Mon Mar 22 16:02:31 2004 +++ b/Documentation/kernel-parameters.txt Mon Mar 22 16:02:31 2004 @@ -99,10 +99,8 @@ 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 + acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode + Format: { level | edge | high | low } acpi_irq_balance [HW,ACPI] ACPI will balance active IRQs default in APIC mode diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c --- a/arch/i386/kernel/acpi/boot.c Mon Mar 22 16:02:31 2004 +++ b/arch/i386/kernel/acpi/boot.c Mon Mar 22 16:02:31 2004 @@ -50,6 +50,9 @@ int acpi_ioapic; int acpi_strict; +acpi_interrupt_flags acpi_sci_flags __initdata; +int acpi_sci_override_gsi __initdata; + #ifdef CONFIG_X86_LOCAL_APIC static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; #endif @@ -244,6 +247,34 @@ return 0; } +/* + * Parse Interrupt Source Override for the ACPI SCI + */ +static void +acpi_parse_sci_int_src_ovr(u8 bus_irq, u16 polarity, u16 trigger, u32 global_irq) +{ + if (trigger == 0) /* compatible SCI trigger is level */ + trigger = 3; + + if (polarity == 0) /* compatible SCI polarity is low */ + polarity = 3; + + /* Command-line over-ride via acpi_sci= */ + if (acpi_sci_flags.trigger) + trigger = acpi_sci_flags.trigger; + + if (acpi_sci_flags.polarity) + polarity = acpi_sci_flags.polarity; + + mp_override_legacy_irq(bus_irq, polarity, trigger, global_irq); + + /* + * stash over-ride to indicate we've been here + * and for later update of acpi_fadt + */ + acpi_sci_override_gsi = global_irq; + return; +} static int __init acpi_parse_int_src_ovr ( @@ -257,6 +288,13 @@ acpi_table_print_madt_entry(header); + if (intsrc->bus_irq == acpi_fadt.sci_int) { + acpi_parse_sci_int_src_ovr(intsrc->bus_irq, + intsrc->flags.polarity, intsrc->flags.trigger, + intsrc->global_irq); + return 0; + } + mp_override_legacy_irq ( intsrc->bus_irq, intsrc->flags.polarity, @@ -287,14 +325,14 @@ #endif /* CONFIG_X86_IO_APIC */ #ifdef CONFIG_ACPI_BUS + /* - * "acpi_pic_sci=level" (current default) - * programs the PIC-mode SCI to Level Trigger. - * (NO-OP if the BIOS set Level Trigger already) + * acpi_pic_sci_set_trigger() + * + * use ELCR to set PIC-mode trigger type for SCI * * If a PIC-mode SCI is not recognized or gives spurious IRQ7's - * it may require Edge Trigger -- use "acpi_pic_sci=edge" - * (NO-OP if the BIOS set Edge Trigger already) + * it may require Edge Trigger -- use "acpi_sci=edge" * * 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. @@ -302,10 +340,8 @@ * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) */ -static int __initdata acpi_pic_sci_trigger; /* 0: level, 1: edge */ - void __init -acpi_pic_sci_set_trigger(unsigned int irq) +acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); @@ -316,37 +352,21 @@ if (!(val & mask)) { printk(" Edge"); - if (!acpi_pic_sci_trigger) { + if (trigger == 3) { printk(" set to Level"); outb(val | mask, port); } } else { printk(" Level"); - if (acpi_pic_sci_trigger) { + if (trigger == 1) { printk(" set to Edge"); - outb(val | mask, port); + 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 */ @@ -442,8 +462,6 @@ #define acpi_parse_hpet NULL #endif -/* detect the location of the ACPI PM Timer */ -#ifdef CONFIG_X86_PM_TIMER extern u32 pmtmr_ioport; static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) @@ -456,6 +474,13 @@ return 0; } +#ifdef CONFIG_ACPI_INTERPRETER + /* initialize sci_int early for INT_SRC_OVR MADT parsing */ + acpi_fadt.sci_int = fadt->sci_int; +#endif + +#ifdef CONFIG_X86_PM_TIMER + /* detect the location of the ACPI PM Timer */ if (fadt->revision >= FADT2_REVISION_ID) { /* FADT rev. 2 */ if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO) @@ -468,11 +493,9 @@ } if (pmtmr_ioport) printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport); +#endif return 0; } -#else -#define acpi_parse_fadt NULL -#endif unsigned long __init @@ -592,6 +615,13 @@ return count; } + /* + * If BIOS did not supply an INT_SRC_OVR for the SCI + * pretend we got one so we can set the SCI flags. + */ + if (!acpi_sci_override_gsi) + acpi_parse_sci_int_src_ovr(acpi_fadt.sci_int, 0, 0, acpi_fadt.sci_int); + count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS); if (count < 0) { printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); @@ -697,11 +727,15 @@ } /* + * set sci_int and PM timer address + */ + acpi_table_parse(ACPI_FADT, acpi_parse_fadt); + + /* * Process the Multiple APIC Description Table (MADT), if present */ acpi_process_madt(); - acpi_table_parse(ACPI_FADT, acpi_parse_fadt); acpi_table_parse(ACPI_HPET, acpi_parse_hpet); acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Mon Mar 22 16:02:31 2004 +++ b/arch/i386/kernel/mpparse.c Mon Mar 22 16:02:31 2004 @@ -1036,69 +1036,6 @@ extern FADT_DESCRIPTOR acpi_fadt; -void __init mp_config_ioapic_for_sci(u32 gsi) -{ - int ioapic; - int ioapic_pin; - struct acpi_table_madt *madt; - struct acpi_table_int_src_ovr *entry = NULL; - acpi_interrupt_flags flags; - void *madt_end; - acpi_status status; - - /* - * Ensure that if there is an interrupt source override entry - * for the ACPI SCI, we leave it as is. Unfortunately this involves - * walking the MADT again. - */ - status = acpi_get_firmware_table("APIC", 1, ACPI_LOGICAL_ADDRESSING, - (struct acpi_table_header **) &madt); - if (ACPI_SUCCESS(status)) { - madt_end = (void *) (unsigned long)madt + madt->header.length; - - entry = (struct acpi_table_int_src_ovr *) - ((unsigned long) madt + sizeof(struct acpi_table_madt)); - - while ((void *) entry < madt_end) { - if (entry->header.type == ACPI_MADT_INT_SRC_OVR && - acpi_fadt.sci_int == entry->bus_irq) - goto found; - - entry = (struct acpi_table_int_src_ovr *) - ((unsigned long) entry + entry->header.length); - } - } - /* - * Although the ACPI spec says that the SCI should be level/low - * don't reprogram it unless there is an explicit MADT OVR entry - * instructing us to do so -- otherwise we break Tyan boards which - * have the SCI wired edge/high but no MADT OVR. - */ - return; - -found: - /* - * See the note at the end of ACPI 2.0b section - * 5.2.10.8 for what this is about. - */ - flags = entry->flags; - acpi_fadt.sci_int = entry->global_irq; - gsi = entry->global_irq; - - ioapic = mp_find_ioapic(gsi); - - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; - - /* - * MPS INTI flags: - * trigger: 0=default, 1=edge, 3=level - * polarity: 0=default, 1=high, 3=low - * Per ACPI spec, default for SCI means level/low. - */ - io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, - (flags.trigger == 1 ? 0 : 1), (flags.polarity == 1 ? 0 : 1)); -} - #ifdef CONFIG_ACPI_PCI void __init mp_parse_prt (void) diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Mon Mar 22 16:02:31 2004 +++ b/arch/i386/kernel/setup.c Mon Mar 22 16:02:31 2004 @@ -79,6 +79,7 @@ #ifdef CONFIG_ACPI_BOOT int __initdata acpi_force = 0; +extern acpi_interrupt_flags acpi_sci_flags; #endif int MCA_bus; @@ -595,6 +596,18 @@ else if (!memcmp(from, "pci=noacpi", 10)) { acpi_noirq_set(); } + + else if (!memcmp(from, "acpi_sci=edge", 13)) + acpi_sci_flags.trigger = 1; + + else if (!memcmp(from, "acpi_sci=level", 14)) + acpi_sci_flags.trigger = 3; + + else if (!memcmp(from, "acpi_sci=high", 13)) + acpi_sci_flags.polarity = 1; + + else if (!memcmp(from, "acpi_sci=low", 12)) + acpi_sci_flags.polarity = 3; #ifdef CONFIG_X86_LOCAL_APIC /* disable IO-APIC */ diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c --- a/drivers/acpi/bus.c Mon Mar 22 16:02:31 2004 +++ b/drivers/acpi/bus.c Mon Mar 22 16:02:31 2004 @@ -39,7 +39,11 @@ #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME ("acpi_bus") +#ifdef CONFIG_X86_64 extern void __init acpi_pic_sci_set_trigger(unsigned int irq); +#elif defined(CONFIG_X86) +extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); +#endif FADT_DESCRIPTOR acpi_fadt; struct acpi_device *acpi_root; @@ -609,13 +613,25 @@ printk(KERN_ERR PREFIX "Unable to get the FADT\n"); goto error1; } - -#ifdef CONFIG_X86 +#ifdef CONFIG_X86_64 /* Ensure the SCI is set to level-triggered, active-low */ if (acpi_ioapic) mp_config_ioapic_for_sci(acpi_fadt.sci_int); else acpi_pic_sci_set_trigger(acpi_fadt.sci_int); +#elif defined(CONFIG_X86) + if (!acpi_ioapic) { + extern acpi_interrupt_flags acpi_sci_flags; + /* Set PIC-mode SCI trigger type */ + acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger); + } else { + extern int acpi_sci_override_gsi; + /* + * now that acpi_fadt is initialized, + * update it with result from INT_SRC_OVR parsing + */ + acpi_fadt.sci_int = acpi_sci_override_gsi; + } #endif status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); diff -Nru a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h --- a/include/asm-i386/mpspec.h Mon Mar 22 16:02:31 2004 +++ b/include/asm-i386/mpspec.h Mon Mar 22 16:02:31 2004 @@ -34,13 +34,6 @@ extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi); extern void mp_config_acpi_legacy_irqs (void); extern void mp_parse_prt (void); - -#ifdef CONFIG_X86_IO_APIC -extern void mp_config_ioapic_for_sci(u32 gsi); -#else -static inline void mp_config_ioapic_for_sci(u32 gsi) -{ } -#endif #endif /*CONFIG_ACPI_BOOT*/ #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)