x86: Move es7000_plat out of mpparse.c
PATCH 1/2 x86: Move es7000_plat out of mpparse.c
---
arch/x86/kernel/mpparse.c | 11 ++++++----- arch/x86/mach-es7000/es7000plat.c | 2 ++ include/asm-x86/system.h | 1 - 3 files changed, 8 insertions(+), 6 deletions(-)
arch/x86/kernel/mpparse.c +6 -5
@@ -793,15 +793,14 @@ void __init find_smp_config(void)ACPI-based MP Configuration -------------------------------------------------------------------------- */ -/* -* Keep this outside and initialized to 0, for !CONFIG_ACPI builds: -*/ -int es7000_plat; -#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 0static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS ];
@@ -928,11 +927,13 @@ void __init mp_config_acpi_legacy_irqs(void)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).
arch/x86/mach-es7000/es7000plat.c +2 -0
@@ -75,6 +75,8 @@ es7000_rename_gsi(int ioapic, int gsi)return gsi; } +int es7000_plat; +void __init setup_unisys (void ) {
include/asm-x86/system.h +0 -1
@@ -318,7 +318,6 @@ static inline void clflush(volatile void *__p)void disable_hlt (void );void enable_hlt (void ); -extern int es7000_plat;void cpu_idle_wait (void );extern unsigned long arch_align_stack (unsigned long sp);
PATCH 2/2 x86: complete move ACPI from mpparse.c
---
arch/x86/kernel/acpi/boot.c | 286 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/mpparse.c | 299 ------------------------------------------- 2 files changed, 287 insertions(+), 298 deletions(-)
arch/x86/kernel/acpi/boot.c +286 -0
@@ -844,6 +844,292 @@ 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 +} + +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; +} +/* * Parse IOAPIC related entries in MADT * returns 0 on success, < 0 on error
arch/x86/kernel/mpparse.c +1 -298
306 lines not on this page · raw message
Ingo Molnar
AppliedRe: [PATCH 2/2] x86: complete move ACPI from mpparse.c
Quoted 4 lines · Alexey Starikovskiy
arch/x86/kernel/mpparse.c +0
-1-#ifdef CONFIG_ACPI
[ ...]
Quoted 1 line
-#endif /*
CONFIG_ACPI*/
applied, thanks Alexey. Nice cleanup.
Ingo
Quoted 4 lines · Alexey Starikovskiy
arch/x86/kernel/mpparse.c | 11 ++++++----- arch/x86/mach-es7000/es7000plat.c | 2 ++ include/asm-x86/system.h | 1 - 3 files changed, 8 insertions(+), 6 deletions(-)
thanks Alexey, applied.
Ingo
x86.git testing found that this broke the build:
arch/x86/kernel/acpi/boot.c: In function 'mp_register_ioapic':arch/x86/kernel/acpi/boot.c:896: error: implicit declaration of function 'bad_ioapic' arch/x86/kernel/acpi/boot.c: In function 'mp_override_legacy_irq':arch/x86/kernel/acpi/boot.c:959: error: implicit declaration of function 'MP_intsrc_info'
with this config:
http://redhat.com/~mingo/misc/config-Tue_May_13_11_52_24_CEST_2008.bad
Ingo
Ingo, please drop second patch, I'll rework it.
Quoted 12 lines · Ingo Molnar
x86.git testing found that this broke the build:
arch/x86/kernel/acpi/boot.c: In function 'mp_register_ioapic':arch/x86/kernel/acpi/boot.c:896: error: implicit declaration of function 'bad_ioapic'arch/x86/kernel/acpi/boot.c: In function 'mp_override_legacy_irq':arch/x86/kernel/acpi/boot.c:959: error: implicit declaration of function 'MP_intsrc_info'with this config:
http://redhat.com/~mingo/misc/config-Tue_May_13_11_52_24_CEST_2008.bad
Ingo
Quoted 1 line · Alexey Starikovskiy
Ingo, please drop second patch, I'll rework it.
still fails with:
arch/x86/mach-generic/../../x86/mach-es7000/es7000plat.c: In function 'es7000_rename_gsi':arch/x86/mach-generic/../../x86/mach-es7000/es7000plat.c:64: error:
'es7000_plat' undeclared (first use in this function) arch/x86/mach-generic/../../x86/mach-es7000/es7000plat.c:64: error:
(Each undeclared identifier is reported only once arch/x86/mach-generic/../../x86/mach-es7000/es7000plat.c:64: error: for each function it appears in.)
with:
http://redhat.com/~mingo/misc/config-Tue_May_13_16_16_10_CEST_2008.bad
Ingo
PATCH 1/1 x86: Move es7000_plat out of mpparse.c
---
arch/x86/kernel/mpparse.c | 11 ++++++----- arch/x86/mach-es7000/es7000plat.c | 2 ++ include/asm-x86/system.h | 1 - 3 files changed, 8 insertions(+), 6 deletions(-)
arch/x86/kernel/mpparse.c +6 -5
@@ -793,15 +793,14 @@ void __init find_smp_config(void)ACPI-based MP Configuration -------------------------------------------------------------------------- */ -/* -* Keep this outside and initialized to 0, for !CONFIG_ACPI builds: -*/ -int es7000_plat; -#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 0static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS ];
@@ -928,11 +927,13 @@ void __init mp_config_acpi_legacy_irqs(void)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).
arch/x86/mach-es7000/es7000plat.c +2 -0
@@ -52,6 +52,8 @@ static struct mip_reg *host_reg;static int mip_port;static unsigned long mip_addr, host_addr; +int es7000_plat; +/* * GSI override for ES7000 platforms. */
include/asm-x86/system.h +0 -1
@@ -318,7 +318,6 @@ static inline void clflush(volatile void *__p)void disable_hlt (void );void enable_hlt (void ); -extern int es7000_plat;void cpu_idle_wait (void );extern unsigned long arch_align_stack (unsigned long sp);
PATCH 1/1 x86: complete move ACPI from mpparse.c
In reply to Ingo Molnar---
arch/x86/kernel/acpi/boot.c | 304 +++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/mpparse.c | 299 ------------------------------------------ 2 files changed, 305 insertions(+), 298 deletions(-)
arch/x86/kernel/acpi/boot.c +304 -0
@@ -844,6 +844,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
arch/x86/kernel/mpparse.c +1 -298
306 lines not on this page · raw message