Avoid wasting IRQs for PCI devices (i386)
PATCH 1/1 Avoid wasting IRQs for PCI devices (i386)
I have submitted the patch for x86_64, this is submission for i386.
<--snip-->
The patch changes the way IRQs are handed out to PCI devices. Currently, each I/O APIC pin gets associated with an IRQ, no matter if the pin is used or not. This imposes severe limitation on systems that have designs that employ many I/O APICs, only utilizing couple lines of each, such as P64H2 chipset. It is used in ES7000, and currently, there is no way to boot the system with more that 9 I/O APICs. The simple change below allows to boot a system with say 64 (or more) I/O APICs, each providing 1 slot, which otherwise impossible because of the IRQ gaps created for unused lines on each I/O APIC. It does not resolve the problem with number of devices that exceeds number of possible IRQs, but eases up a tension for IRQs on any large system with potentually large number of devices.
---
arch/i386/kernel/mpparse.c renamed from arch/i386/kernel/mpparse.c~irq-pack-i386 +25 -1
@@ -1056,11 +1056,20 @@ void __init mp_config_acpi_legacy_irqs ( } } +#define MAX_GSI_NUM 4096 +int mp_register_gsi (u32 gsi,int edge_level,int active_high_low) {int ioapic =-1 ;int ioapic_pin =0 ;int idx, bit =0 ; +static int pci_irq =16 ; +/* +* Mapping between Global System Interrups, which +* represent all possible interrupts, and IRQs +* assigned to actual devices. +*/ +static int gsi_to_irq[MAX_GSI_NUM ];#ifdef CONFIG_ACPI_BUS /* Don't set up the ACPI SCI because it's already set up */
@@ -1095,11 +1104,26 @@ int mp_register_gsi (u32 gsi, int edge_lif ((1 <<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {Dprintk (KERN_DEBUG "Pin %d-%d already programmed\n" , mp_ioapic_routing[ioapic].apic_id, ioapic_pin); -return gsi; +return gsi_to_irq[gsi]; } mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 <<bit); +if (edge_level) { +/* +* For PCI devices assign IRQs in order, avoiding gaps +* due to unused I/O APIC pins. +*/ +int irq = gsi; +if (gsi <MAX_GSI_NUM ) { + gsi = pci_irq++; + gsi_to_irq[irq] = gsi; + }else { +printk (KERN_ERR "GSI %u is too high\n" , gsi); +return gsi; + } + } +io_apic_set_pci_routing (ioapic, ioapic_pin, gsi, edge_level ==ACPI_EDGE_SENSITIVE ?0 :1 , active_high_low ==ACPI_ACTIVE_HIGH ?0 :1 );
_