x86: unify mp_register_gsi
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
committed by
Ingo Molnar
parent
c769bfee57
commit
cfa08d6cc3
@@ -994,14 +994,15 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_GSI_NUM 4096
|
|
||||||
#define IRQ_COMPRESSION_START 64
|
|
||||||
|
|
||||||
int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
||||||
{
|
{
|
||||||
int ioapic = -1;
|
int ioapic = -1;
|
||||||
int ioapic_pin = 0;
|
int ioapic_pin = 0;
|
||||||
int idx, bit = 0;
|
int idx, bit = 0;
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
#define MAX_GSI_NUM 4096
|
||||||
|
#define IRQ_COMPRESSION_START 64
|
||||||
|
|
||||||
static int pci_irq = IRQ_COMPRESSION_START;
|
static int pci_irq = IRQ_COMPRESSION_START;
|
||||||
/*
|
/*
|
||||||
* Mapping between Global System Interrupts, which
|
* Mapping between Global System Interrupts, which
|
||||||
@@ -1009,6 +1010,11 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|||||||
* assigned to actual devices.
|
* assigned to actual devices.
|
||||||
*/
|
*/
|
||||||
static int gsi_to_irq[MAX_GSI_NUM];
|
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 */
|
/* Don't set up the ACPI SCI because it's already set up */
|
||||||
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
||||||
@@ -1022,8 +1028,10 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|||||||
|
|
||||||
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
|
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
if (ioapic_renumber_irq)
|
if (ioapic_renumber_irq)
|
||||||
gsi = ioapic_renumber_irq(ioapic, gsi);
|
gsi = ioapic_renumber_irq(ioapic, gsi);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Avoid pin reprogramming. PRTs typically include entries
|
* Avoid pin reprogramming. PRTs typically include entries
|
||||||
@@ -1041,11 +1049,15 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|||||||
if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
|
if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
|
||||||
Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
|
Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
|
||||||
mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
|
mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
|
return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
|
||||||
|
#else
|
||||||
|
return gsi;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
|
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
/*
|
/*
|
||||||
* For GSI >= 64, use IRQ compression
|
* For GSI >= 64, use IRQ compression
|
||||||
*/
|
*/
|
||||||
@@ -1079,7 +1091,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|||||||
return gsi;
|
return gsi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
|
io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
|
||||||
triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
||||||
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
||||||
|
@@ -685,6 +685,8 @@ void __init find_smp_config(void)
|
|||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
|
|
||||||
#define MP_ISA_BUS 0
|
#define MP_ISA_BUS 0
|
||||||
#define MP_MAX_IOAPIC_PIN 127
|
#define MP_MAX_IOAPIC_PIN 127
|
||||||
|
|
||||||
@@ -770,7 +772,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
|
|||||||
int ioapic = -1;
|
int ioapic = -1;
|
||||||
int pin = -1;
|
int pin = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert 'gsi' to 'ioapic.pin'.
|
* Convert 'gsi' to 'ioapic.pin'.
|
||||||
*/
|
*/
|
||||||
ioapic = mp_find_ioapic(gsi);
|
ioapic = mp_find_ioapic(gsi);
|
||||||
@@ -780,7 +782,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* TBD: This check is for faulty timer entries, where the override
|
* TBD: This check is for faulty timer entries, where the override
|
||||||
* erroneously sets the trigger to level, resulting in a HUGE
|
* erroneously sets the trigger to level, resulting in a HUGE
|
||||||
* increase of timer interrupts!
|
* increase of timer interrupts!
|
||||||
*/
|
*/
|
||||||
if ((bus_irq == 0) && (trigger == 3))
|
if ((bus_irq == 0) && (trigger == 3))
|
||||||
@@ -886,9 +888,22 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|||||||
int ioapic = -1;
|
int ioapic = -1;
|
||||||
int ioapic_pin = 0;
|
int ioapic_pin = 0;
|
||||||
int idx, bit = 0;
|
int idx, bit = 0;
|
||||||
|
#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)
|
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
|
||||||
return gsi;
|
return gsi;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Don't set up the ACPI SCI because it's already set up */
|
/* Don't set up the ACPI SCI because it's already set up */
|
||||||
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
||||||
@@ -902,8 +917,13 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|||||||
|
|
||||||
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
|
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
|
||||||
|
|
||||||
/*
|
#ifdef CONFIG_X86_32
|
||||||
* Avoid pin reprogramming. PRTs typically include entries
|
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);
|
* with redundant pin->gsi mappings (but unique PCI devices);
|
||||||
* we only program the IOAPIC on the first.
|
* we only program the IOAPIC on the first.
|
||||||
*/
|
*/
|
||||||
@@ -918,14 +938,54 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|||||||
if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
|
if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
|
||||||
Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
|
Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
|
||||||
mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
|
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;
|
return gsi;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
|
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
|
||||||
|
#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,
|
io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
|
||||||
triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
||||||
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
||||||
return gsi;
|
return gsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_X86_IO_APIC */
|
||||||
#endif /* CONFIG_ACPI */
|
#endif /* CONFIG_ACPI */
|
||||||
|
Reference in New Issue
Block a user