Loading arch/x86/kernel/acpi/boot.c +304 −0 Original line number Diff line number Diff line Loading @@ -846,6 +846,310 @@ static int __init acpi_parse_madt_lapic_entries(void) #endif /* CONFIG_X86_LOCAL_APIC */ #ifdef CONFIG_X86_IO_APIC #define MP_ISA_BUS 0 #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) extern int es7000_plat; #endif static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; static int mp_find_ioapic(int gsi) { int i = 0; /* Find the IOAPIC that manages this GSI. */ for (i = 0; i < nr_ioapics; i++) { if ((gsi >= mp_ioapic_routing[i].gsi_base) && (gsi <= mp_ioapic_routing[i].gsi_end)) return i; } printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); return -1; } static u8 __init uniq_ioapic_id(u8 id) { #ifdef CONFIG_X86_32 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) return io_apic_get_unique_id(nr_ioapics, id); else return id; #else int i; DECLARE_BITMAP(used, 256); bitmap_zero(used, 256); for (i = 0; i < nr_ioapics; i++) { struct mpc_config_ioapic *ia = &mp_ioapics[i]; __set_bit(ia->mpc_apicid, used); } if (!test_bit(id, used)) return id; return find_first_zero_bit(used, 256); #endif } static int bad_ioapic(unsigned long address) { if (nr_ioapics >= MAX_IO_APICS) { printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " "(found %d)\n", MAX_IO_APICS, nr_ioapics); panic("Recompile kernel with bigger MAX_IO_APICS!\n"); } if (!address) { printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" " found in table, skipping!\n"); return 1; } return 0; } void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) { int idx = 0; if (bad_ioapic(address)) return; idx = nr_ioapics; mp_ioapics[idx].mpc_type = MP_IOAPIC; mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; mp_ioapics[idx].mpc_apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id); #ifdef CONFIG_X86_32 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); #else mp_ioapics[idx].mpc_apicver = 0; #endif /* * Build basic GSI lookup table to facilitate gsi->io_apic lookups * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; mp_ioapic_routing[idx].gsi_base = gsi_base; mp_ioapic_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx); printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); nr_ioapics++; } void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { int ioapic = -1; int pin = -1; /* * Convert 'gsi' to 'ioapic.pin'. */ ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; pin = gsi - mp_ioapic_routing[ioapic].gsi_base; /* * TBD: This check is for faulty timer entries, where the override * erroneously sets the trigger to level, resulting in a HUGE * increase of timer interrupts! */ if ((bus_irq == 0) && (trigger == 3)) trigger = 1; mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC; mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT; mp_irqs[mp_irq_entries].mpc_irqflag = (trigger << 2) | polarity; mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS; mp_irqs[mp_irq_entries].mpc_srcbusirq = bus_irq; /* IRQ */ mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ mp_irqs[mp_irq_entries].mpc_dstirq = pin; /* INTIN# */ if (++mp_irq_entries == MAX_IRQ_SOURCES) panic("Max # of irq sources exceeded!!\n"); } void __init mp_config_acpi_legacy_irqs(void) { int i = 0; int ioapic = -1; #if defined (CONFIG_MCA) || defined (CONFIG_EISA) /* * Fabricate the legacy ISA bus (bus #31). */ mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; #endif set_bit(MP_ISA_BUS, mp_bus_not_pci); Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) /* * Older generations of ES7000 have no legacy identity mappings */ if (es7000_plat == 1) return; #endif /* * Locate the IOAPIC that manages the ISA IRQs (0-15). */ ioapic = mp_find_ioapic(0); if (ioapic < 0) return; mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC; mp_irqs[mp_irq_entries].mpc_irqflag = 0; /* Conforming */ mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS; #ifdef CONFIG_X86_IO_APIC mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; #endif /* * Use the default configuration for the IRQs 0-15. Unless * overridden by (MADT) interrupt source override entries. */ for (i = 0; i < 16; i++) { int idx; for (idx = 0; idx < mp_irq_entries; idx++) { struct mpc_config_intsrc *irq = mp_irqs + idx; /* Do we already have a mapping for this ISA IRQ? */ if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) break; /* Do we already have a mapping for this IOAPIC pin */ if ((irq->mpc_dstapic == mp_irqs[mp_irq_entries].mpc_dstapic) && (irq->mpc_dstirq == i)) break; } if (idx != mp_irq_entries) { printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); continue; /* IRQ already used */ } mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT; mp_irqs[mp_irq_entries].mpc_srcbusirq = i; /* Identity mapped */ mp_irqs[mp_irq_entries].mpc_dstirq = i; if (++mp_irq_entries == MAX_IRQ_SOURCES) panic("Max # of irq sources exceeded!!\n"); } } int mp_register_gsi(u32 gsi, int triggering, int polarity) { int ioapic; int ioapic_pin; #ifdef CONFIG_X86_32 #define MAX_GSI_NUM 4096 #define IRQ_COMPRESSION_START 64 static int pci_irq = IRQ_COMPRESSION_START; /* * Mapping between Global System Interrupts, which * represent all possible interrupts, and IRQs * assigned to actual devices. */ static int gsi_to_irq[MAX_GSI_NUM]; #else if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) return gsi; #endif /* Don't set up the ACPI SCI because it's already set up */ if (acpi_gbl_FADT.sci_interrupt == gsi) return gsi; ioapic = mp_find_ioapic(gsi); if (ioapic < 0) { printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); return gsi; } ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; #ifdef CONFIG_X86_32 if (ioapic_renumber_irq) gsi = ioapic_renumber_irq(ioapic, gsi); #endif /* * Avoid pin reprogramming. PRTs typically include entries * with redundant pin->gsi mappings (but unique PCI devices); * we only program the IOAPIC on the first. */ if (ioapic_pin > MP_MAX_IOAPIC_PIN) { printk(KERN_ERR "Invalid reference to IOAPIC pin " "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); return gsi; } if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); #ifdef CONFIG_X86_32 return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); #else return gsi; #endif } set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); #ifdef CONFIG_X86_32 /* * For GSI >= 64, use IRQ compression */ if ((gsi >= IRQ_COMPRESSION_START) && (triggering == ACPI_LEVEL_SENSITIVE)) { /* * For PCI devices assign IRQs in order, avoiding gaps * due to unused I/O APIC pins. */ int irq = gsi; if (gsi < MAX_GSI_NUM) { /* * Retain the VIA chipset work-around (gsi > 15), but * avoid a problem where the 8254 timer (IRQ0) is setup * via an override (so it's not on pin 0 of the ioapic), * and at the same time, the pin 0 interrupt is a PCI * type. The gsi > 15 test could cause these two pins * to be shared as IRQ0, and they are not shareable. * So test for this condition, and if necessary, avoid * the pin collision. */ gsi = pci_irq++; /* * Don't assign IRQ used by ACPI SCI */ if (gsi == acpi_gbl_FADT.sci_interrupt) gsi = pci_irq++; gsi_to_irq[irq] = gsi; } else { printk(KERN_ERR "GSI %u is too high\n", gsi); return gsi; } } #endif io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, polarity == ACPI_ACTIVE_HIGH ? 0 : 1); return gsi; } /* * Parse IOAPIC related entries in MADT * returns 0 on success, < 0 on error Loading arch/x86/kernel/mpparse.c +1 −298 Original line number Diff line number Diff line /* 2 * Intel Multiprocessor Specification 1.1 and 1.4 * Intel Multiprocessor Specification 1.1 and 1.4 * compliant MP-table parsing routines. * * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> Loading Loading @@ -788,300 +788,3 @@ void __init find_smp_config(void) { __find_smp_config(1); } /* -------------------------------------------------------------------------- ACPI-based MP Configuration -------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI #ifdef CONFIG_X86_IO_APIC #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) extern int es7000_plat; #endif #define MP_ISA_BUS 0 static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; static int mp_find_ioapic(int gsi) { int i = 0; /* Find the IOAPIC that manages this GSI. */ for (i = 0; i < nr_ioapics; i++) { if ((gsi >= mp_ioapic_routing[i].gsi_base) && (gsi <= mp_ioapic_routing[i].gsi_end)) return i; } printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); return -1; } static u8 __init uniq_ioapic_id(u8 id) { #ifdef CONFIG_X86_32 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) return io_apic_get_unique_id(nr_ioapics, id); else return id; #else int i; DECLARE_BITMAP(used, 256); bitmap_zero(used, 256); for (i = 0; i < nr_ioapics; i++) { struct mpc_config_ioapic *ia = &mp_ioapics[i]; __set_bit(ia->mpc_apicid, used); } if (!test_bit(id, used)) return id; return find_first_zero_bit(used, 256); #endif } void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) { int idx = 0; if (bad_ioapic(address)) return; idx = nr_ioapics; mp_ioapics[idx].mpc_type = MP_IOAPIC; mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; mp_ioapics[idx].mpc_apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id); #ifdef CONFIG_X86_32 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); #else mp_ioapics[idx].mpc_apicver = 0; #endif /* * Build basic GSI lookup table to facilitate gsi->io_apic lookups * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; mp_ioapic_routing[idx].gsi_base = gsi_base; mp_ioapic_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx); printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); nr_ioapics++; } void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { struct mpc_config_intsrc intsrc; int ioapic = -1; int pin = -1; /* * Convert 'gsi' to 'ioapic.pin'. */ ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; pin = gsi - mp_ioapic_routing[ioapic].gsi_base; /* * TBD: This check is for faulty timer entries, where the override * erroneously sets the trigger to level, resulting in a HUGE * increase of timer interrupts! */ if ((bus_irq == 0) && (trigger == 3)) trigger = 1; intsrc.mpc_type = MP_INTSRC; intsrc.mpc_irqtype = mp_INT; intsrc.mpc_irqflag = (trigger << 2) | polarity; intsrc.mpc_srcbus = MP_ISA_BUS; intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ intsrc.mpc_dstirq = pin; /* INTIN# */ MP_intsrc_info(&intsrc); } void __init mp_config_acpi_legacy_irqs(void) { struct mpc_config_intsrc intsrc; int i = 0; int ioapic = -1; #if defined (CONFIG_MCA) || defined (CONFIG_EISA) /* * Fabricate the legacy ISA bus (bus #31). */ mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; #endif set_bit(MP_ISA_BUS, mp_bus_not_pci); Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) /* * Older generations of ES7000 have no legacy identity mappings */ if (es7000_plat == 1) return; #endif /* * Locate the IOAPIC that manages the ISA IRQs (0-15). */ ioapic = mp_find_ioapic(0); if (ioapic < 0) return; intsrc.mpc_type = MP_INTSRC; intsrc.mpc_irqflag = 0; /* Conforming */ intsrc.mpc_srcbus = MP_ISA_BUS; #ifdef CONFIG_X86_IO_APIC intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; #endif /* * Use the default configuration for the IRQs 0-15. Unless * overridden by (MADT) interrupt source override entries. */ for (i = 0; i < 16; i++) { int idx; for (idx = 0; idx < mp_irq_entries; idx++) { struct mpc_config_intsrc *irq = mp_irqs + idx; /* Do we already have a mapping for this ISA IRQ? */ if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) break; /* Do we already have a mapping for this IOAPIC pin */ if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && (irq->mpc_dstirq == i)) break; } if (idx != mp_irq_entries) { printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); continue; /* IRQ already used */ } intsrc.mpc_irqtype = mp_INT; intsrc.mpc_srcbusirq = i; /* Identity mapped */ intsrc.mpc_dstirq = i; MP_intsrc_info(&intsrc); } } int mp_register_gsi(u32 gsi, int triggering, int polarity) { int ioapic; int ioapic_pin; #ifdef CONFIG_X86_32 #define MAX_GSI_NUM 4096 #define IRQ_COMPRESSION_START 64 static int pci_irq = IRQ_COMPRESSION_START; /* * Mapping between Global System Interrupts, which * represent all possible interrupts, and IRQs * assigned to actual devices. */ static int gsi_to_irq[MAX_GSI_NUM]; #else if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) return gsi; #endif /* Don't set up the ACPI SCI because it's already set up */ if (acpi_gbl_FADT.sci_interrupt == gsi) return gsi; ioapic = mp_find_ioapic(gsi); if (ioapic < 0) { printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); return gsi; } ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; #ifdef CONFIG_X86_32 if (ioapic_renumber_irq) gsi = ioapic_renumber_irq(ioapic, gsi); #endif /* * Avoid pin reprogramming. PRTs typically include entries * with redundant pin->gsi mappings (but unique PCI devices); * we only program the IOAPIC on the first. */ if (ioapic_pin > MP_MAX_IOAPIC_PIN) { printk(KERN_ERR "Invalid reference to IOAPIC pin " "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); return gsi; } if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); #ifdef CONFIG_X86_32 return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); #else return gsi; #endif } set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); #ifdef CONFIG_X86_32 /* * For GSI >= 64, use IRQ compression */ if ((gsi >= IRQ_COMPRESSION_START) && (triggering == ACPI_LEVEL_SENSITIVE)) { /* * For PCI devices assign IRQs in order, avoiding gaps * due to unused I/O APIC pins. */ int irq = gsi; if (gsi < MAX_GSI_NUM) { /* * Retain the VIA chipset work-around (gsi > 15), but * avoid a problem where the 8254 timer (IRQ0) is setup * via an override (so it's not on pin 0 of the ioapic), * and at the same time, the pin 0 interrupt is a PCI * type. The gsi > 15 test could cause these two pins * to be shared as IRQ0, and they are not shareable. * So test for this condition, and if necessary, avoid * the pin collision. */ gsi = pci_irq++; /* * Don't assign IRQ used by ACPI SCI */ if (gsi == acpi_gbl_FADT.sci_interrupt) gsi = pci_irq++; gsi_to_irq[irq] = gsi; } else { printk(KERN_ERR "GSI %u is too high\n", gsi); return gsi; } } #endif io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, polarity == ACPI_ACTIVE_HIGH ? 0 : 1); return gsi; } #endif /* CONFIG_X86_IO_APIC */ #endif /* CONFIG_ACPI */ Loading
arch/x86/kernel/acpi/boot.c +304 −0 Original line number Diff line number Diff line Loading @@ -846,6 +846,310 @@ static int __init acpi_parse_madt_lapic_entries(void) #endif /* CONFIG_X86_LOCAL_APIC */ #ifdef CONFIG_X86_IO_APIC #define MP_ISA_BUS 0 #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) extern int es7000_plat; #endif static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; static int mp_find_ioapic(int gsi) { int i = 0; /* Find the IOAPIC that manages this GSI. */ for (i = 0; i < nr_ioapics; i++) { if ((gsi >= mp_ioapic_routing[i].gsi_base) && (gsi <= mp_ioapic_routing[i].gsi_end)) return i; } printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); return -1; } static u8 __init uniq_ioapic_id(u8 id) { #ifdef CONFIG_X86_32 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) return io_apic_get_unique_id(nr_ioapics, id); else return id; #else int i; DECLARE_BITMAP(used, 256); bitmap_zero(used, 256); for (i = 0; i < nr_ioapics; i++) { struct mpc_config_ioapic *ia = &mp_ioapics[i]; __set_bit(ia->mpc_apicid, used); } if (!test_bit(id, used)) return id; return find_first_zero_bit(used, 256); #endif } static int bad_ioapic(unsigned long address) { if (nr_ioapics >= MAX_IO_APICS) { printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " "(found %d)\n", MAX_IO_APICS, nr_ioapics); panic("Recompile kernel with bigger MAX_IO_APICS!\n"); } if (!address) { printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" " found in table, skipping!\n"); return 1; } return 0; } void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) { int idx = 0; if (bad_ioapic(address)) return; idx = nr_ioapics; mp_ioapics[idx].mpc_type = MP_IOAPIC; mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; mp_ioapics[idx].mpc_apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id); #ifdef CONFIG_X86_32 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); #else mp_ioapics[idx].mpc_apicver = 0; #endif /* * Build basic GSI lookup table to facilitate gsi->io_apic lookups * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; mp_ioapic_routing[idx].gsi_base = gsi_base; mp_ioapic_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx); printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); nr_ioapics++; } void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { int ioapic = -1; int pin = -1; /* * Convert 'gsi' to 'ioapic.pin'. */ ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; pin = gsi - mp_ioapic_routing[ioapic].gsi_base; /* * TBD: This check is for faulty timer entries, where the override * erroneously sets the trigger to level, resulting in a HUGE * increase of timer interrupts! */ if ((bus_irq == 0) && (trigger == 3)) trigger = 1; mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC; mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT; mp_irqs[mp_irq_entries].mpc_irqflag = (trigger << 2) | polarity; mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS; mp_irqs[mp_irq_entries].mpc_srcbusirq = bus_irq; /* IRQ */ mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ mp_irqs[mp_irq_entries].mpc_dstirq = pin; /* INTIN# */ if (++mp_irq_entries == MAX_IRQ_SOURCES) panic("Max # of irq sources exceeded!!\n"); } void __init mp_config_acpi_legacy_irqs(void) { int i = 0; int ioapic = -1; #if defined (CONFIG_MCA) || defined (CONFIG_EISA) /* * Fabricate the legacy ISA bus (bus #31). */ mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; #endif set_bit(MP_ISA_BUS, mp_bus_not_pci); Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) /* * Older generations of ES7000 have no legacy identity mappings */ if (es7000_plat == 1) return; #endif /* * Locate the IOAPIC that manages the ISA IRQs (0-15). */ ioapic = mp_find_ioapic(0); if (ioapic < 0) return; mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC; mp_irqs[mp_irq_entries].mpc_irqflag = 0; /* Conforming */ mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS; #ifdef CONFIG_X86_IO_APIC mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; #endif /* * Use the default configuration for the IRQs 0-15. Unless * overridden by (MADT) interrupt source override entries. */ for (i = 0; i < 16; i++) { int idx; for (idx = 0; idx < mp_irq_entries; idx++) { struct mpc_config_intsrc *irq = mp_irqs + idx; /* Do we already have a mapping for this ISA IRQ? */ if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) break; /* Do we already have a mapping for this IOAPIC pin */ if ((irq->mpc_dstapic == mp_irqs[mp_irq_entries].mpc_dstapic) && (irq->mpc_dstirq == i)) break; } if (idx != mp_irq_entries) { printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); continue; /* IRQ already used */ } mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT; mp_irqs[mp_irq_entries].mpc_srcbusirq = i; /* Identity mapped */ mp_irqs[mp_irq_entries].mpc_dstirq = i; if (++mp_irq_entries == MAX_IRQ_SOURCES) panic("Max # of irq sources exceeded!!\n"); } } int mp_register_gsi(u32 gsi, int triggering, int polarity) { int ioapic; int ioapic_pin; #ifdef CONFIG_X86_32 #define MAX_GSI_NUM 4096 #define IRQ_COMPRESSION_START 64 static int pci_irq = IRQ_COMPRESSION_START; /* * Mapping between Global System Interrupts, which * represent all possible interrupts, and IRQs * assigned to actual devices. */ static int gsi_to_irq[MAX_GSI_NUM]; #else if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) return gsi; #endif /* Don't set up the ACPI SCI because it's already set up */ if (acpi_gbl_FADT.sci_interrupt == gsi) return gsi; ioapic = mp_find_ioapic(gsi); if (ioapic < 0) { printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); return gsi; } ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; #ifdef CONFIG_X86_32 if (ioapic_renumber_irq) gsi = ioapic_renumber_irq(ioapic, gsi); #endif /* * Avoid pin reprogramming. PRTs typically include entries * with redundant pin->gsi mappings (but unique PCI devices); * we only program the IOAPIC on the first. */ if (ioapic_pin > MP_MAX_IOAPIC_PIN) { printk(KERN_ERR "Invalid reference to IOAPIC pin " "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); return gsi; } if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); #ifdef CONFIG_X86_32 return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); #else return gsi; #endif } set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); #ifdef CONFIG_X86_32 /* * For GSI >= 64, use IRQ compression */ if ((gsi >= IRQ_COMPRESSION_START) && (triggering == ACPI_LEVEL_SENSITIVE)) { /* * For PCI devices assign IRQs in order, avoiding gaps * due to unused I/O APIC pins. */ int irq = gsi; if (gsi < MAX_GSI_NUM) { /* * Retain the VIA chipset work-around (gsi > 15), but * avoid a problem where the 8254 timer (IRQ0) is setup * via an override (so it's not on pin 0 of the ioapic), * and at the same time, the pin 0 interrupt is a PCI * type. The gsi > 15 test could cause these two pins * to be shared as IRQ0, and they are not shareable. * So test for this condition, and if necessary, avoid * the pin collision. */ gsi = pci_irq++; /* * Don't assign IRQ used by ACPI SCI */ if (gsi == acpi_gbl_FADT.sci_interrupt) gsi = pci_irq++; gsi_to_irq[irq] = gsi; } else { printk(KERN_ERR "GSI %u is too high\n", gsi); return gsi; } } #endif io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, polarity == ACPI_ACTIVE_HIGH ? 0 : 1); return gsi; } /* * Parse IOAPIC related entries in MADT * returns 0 on success, < 0 on error Loading
arch/x86/kernel/mpparse.c +1 −298 Original line number Diff line number Diff line /* 2 * Intel Multiprocessor Specification 1.1 and 1.4 * Intel Multiprocessor Specification 1.1 and 1.4 * compliant MP-table parsing routines. * * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> Loading Loading @@ -788,300 +788,3 @@ void __init find_smp_config(void) { __find_smp_config(1); } /* -------------------------------------------------------------------------- ACPI-based MP Configuration -------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI #ifdef CONFIG_X86_IO_APIC #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) extern int es7000_plat; #endif #define MP_ISA_BUS 0 static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; static int mp_find_ioapic(int gsi) { int i = 0; /* Find the IOAPIC that manages this GSI. */ for (i = 0; i < nr_ioapics; i++) { if ((gsi >= mp_ioapic_routing[i].gsi_base) && (gsi <= mp_ioapic_routing[i].gsi_end)) return i; } printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); return -1; } static u8 __init uniq_ioapic_id(u8 id) { #ifdef CONFIG_X86_32 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) return io_apic_get_unique_id(nr_ioapics, id); else return id; #else int i; DECLARE_BITMAP(used, 256); bitmap_zero(used, 256); for (i = 0; i < nr_ioapics; i++) { struct mpc_config_ioapic *ia = &mp_ioapics[i]; __set_bit(ia->mpc_apicid, used); } if (!test_bit(id, used)) return id; return find_first_zero_bit(used, 256); #endif } void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) { int idx = 0; if (bad_ioapic(address)) return; idx = nr_ioapics; mp_ioapics[idx].mpc_type = MP_IOAPIC; mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; mp_ioapics[idx].mpc_apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id); #ifdef CONFIG_X86_32 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); #else mp_ioapics[idx].mpc_apicver = 0; #endif /* * Build basic GSI lookup table to facilitate gsi->io_apic lookups * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; mp_ioapic_routing[idx].gsi_base = gsi_base; mp_ioapic_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx); printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); nr_ioapics++; } void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { struct mpc_config_intsrc intsrc; int ioapic = -1; int pin = -1; /* * Convert 'gsi' to 'ioapic.pin'. */ ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; pin = gsi - mp_ioapic_routing[ioapic].gsi_base; /* * TBD: This check is for faulty timer entries, where the override * erroneously sets the trigger to level, resulting in a HUGE * increase of timer interrupts! */ if ((bus_irq == 0) && (trigger == 3)) trigger = 1; intsrc.mpc_type = MP_INTSRC; intsrc.mpc_irqtype = mp_INT; intsrc.mpc_irqflag = (trigger << 2) | polarity; intsrc.mpc_srcbus = MP_ISA_BUS; intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ intsrc.mpc_dstirq = pin; /* INTIN# */ MP_intsrc_info(&intsrc); } void __init mp_config_acpi_legacy_irqs(void) { struct mpc_config_intsrc intsrc; int i = 0; int ioapic = -1; #if defined (CONFIG_MCA) || defined (CONFIG_EISA) /* * Fabricate the legacy ISA bus (bus #31). */ mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; #endif set_bit(MP_ISA_BUS, mp_bus_not_pci); Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) /* * Older generations of ES7000 have no legacy identity mappings */ if (es7000_plat == 1) return; #endif /* * Locate the IOAPIC that manages the ISA IRQs (0-15). */ ioapic = mp_find_ioapic(0); if (ioapic < 0) return; intsrc.mpc_type = MP_INTSRC; intsrc.mpc_irqflag = 0; /* Conforming */ intsrc.mpc_srcbus = MP_ISA_BUS; #ifdef CONFIG_X86_IO_APIC intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; #endif /* * Use the default configuration for the IRQs 0-15. Unless * overridden by (MADT) interrupt source override entries. */ for (i = 0; i < 16; i++) { int idx; for (idx = 0; idx < mp_irq_entries; idx++) { struct mpc_config_intsrc *irq = mp_irqs + idx; /* Do we already have a mapping for this ISA IRQ? */ if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) break; /* Do we already have a mapping for this IOAPIC pin */ if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && (irq->mpc_dstirq == i)) break; } if (idx != mp_irq_entries) { printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); continue; /* IRQ already used */ } intsrc.mpc_irqtype = mp_INT; intsrc.mpc_srcbusirq = i; /* Identity mapped */ intsrc.mpc_dstirq = i; MP_intsrc_info(&intsrc); } } int mp_register_gsi(u32 gsi, int triggering, int polarity) { int ioapic; int ioapic_pin; #ifdef CONFIG_X86_32 #define MAX_GSI_NUM 4096 #define IRQ_COMPRESSION_START 64 static int pci_irq = IRQ_COMPRESSION_START; /* * Mapping between Global System Interrupts, which * represent all possible interrupts, and IRQs * assigned to actual devices. */ static int gsi_to_irq[MAX_GSI_NUM]; #else if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) return gsi; #endif /* Don't set up the ACPI SCI because it's already set up */ if (acpi_gbl_FADT.sci_interrupt == gsi) return gsi; ioapic = mp_find_ioapic(gsi); if (ioapic < 0) { printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); return gsi; } ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; #ifdef CONFIG_X86_32 if (ioapic_renumber_irq) gsi = ioapic_renumber_irq(ioapic, gsi); #endif /* * Avoid pin reprogramming. PRTs typically include entries * with redundant pin->gsi mappings (but unique PCI devices); * we only program the IOAPIC on the first. */ if (ioapic_pin > MP_MAX_IOAPIC_PIN) { printk(KERN_ERR "Invalid reference to IOAPIC pin " "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); return gsi; } if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); #ifdef CONFIG_X86_32 return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); #else return gsi; #endif } set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); #ifdef CONFIG_X86_32 /* * For GSI >= 64, use IRQ compression */ if ((gsi >= IRQ_COMPRESSION_START) && (triggering == ACPI_LEVEL_SENSITIVE)) { /* * For PCI devices assign IRQs in order, avoiding gaps * due to unused I/O APIC pins. */ int irq = gsi; if (gsi < MAX_GSI_NUM) { /* * Retain the VIA chipset work-around (gsi > 15), but * avoid a problem where the 8254 timer (IRQ0) is setup * via an override (so it's not on pin 0 of the ioapic), * and at the same time, the pin 0 interrupt is a PCI * type. The gsi > 15 test could cause these two pins * to be shared as IRQ0, and they are not shareable. * So test for this condition, and if necessary, avoid * the pin collision. */ gsi = pci_irq++; /* * Don't assign IRQ used by ACPI SCI */ if (gsi == acpi_gbl_FADT.sci_interrupt) gsi = pci_irq++; gsi_to_irq[irq] = gsi; } else { printk(KERN_ERR "GSI %u is too high\n", gsi); return gsi; } } #endif io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, polarity == ACPI_ACTIVE_HIGH ? 0 : 1); return gsi; } #endif /* CONFIG_X86_IO_APIC */ #endif /* CONFIG_ACPI */