|
@@ -93,6 +93,53 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
|
|
|
enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+ * ISA irqs by default are the first 16 gsis but can be
|
|
|
+ * any gsi as specified by an interrupt source override.
|
|
|
+ */
|
|
|
+static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
|
|
|
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
|
|
+};
|
|
|
+
|
|
|
+static unsigned int gsi_to_irq(unsigned int gsi)
|
|
|
+{
|
|
|
+ unsigned int irq = gsi + NR_IRQS_LEGACY;
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ for (i = 0; i < NR_IRQS_LEGACY; i++) {
|
|
|
+ if (isa_irq_to_gsi[i] == gsi) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Provide an identity mapping of gsi == irq
|
|
|
+ * except on truly weird platforms that have
|
|
|
+ * non isa irqs in the first 16 gsis.
|
|
|
+ */
|
|
|
+ if (gsi >= NR_IRQS_LEGACY)
|
|
|
+ irq = gsi;
|
|
|
+ else
|
|
|
+ irq = gsi_end + 1 + gsi;
|
|
|
+
|
|
|
+ return irq;
|
|
|
+}
|
|
|
+
|
|
|
+static u32 irq_to_gsi(int irq)
|
|
|
+{
|
|
|
+ unsigned int gsi;
|
|
|
+
|
|
|
+ if (irq < NR_IRQS_LEGACY)
|
|
|
+ gsi = isa_irq_to_gsi[irq];
|
|
|
+ else if (irq <= gsi_end)
|
|
|
+ gsi = irq;
|
|
|
+ else if (irq <= (gsi_end + NR_IRQS_LEGACY))
|
|
|
+ gsi = irq - gsi_end;
|
|
|
+ else
|
|
|
+ gsi = 0xffffffff;
|
|
|
+
|
|
|
+ return gsi;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
|
|
|
* to map the target physical address. The problem is that set_fixmap()
|
|
@@ -313,7 +360,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
|
|
|
/*
|
|
|
* Parse Interrupt Source Override for the ACPI SCI
|
|
|
*/
|
|
|
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
|
|
|
+static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi)
|
|
|
{
|
|
|
if (trigger == 0) /* compatible SCI trigger is level */
|
|
|
trigger = 3;
|
|
@@ -333,7 +380,7 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
|
|
|
* If GSI is < 16, this will update its flags,
|
|
|
* else it will create a new mp_irqs[] entry.
|
|
|
*/
|
|
|
- mp_override_legacy_irq(gsi, polarity, trigger, gsi);
|
|
|
+ mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
|
|
|
|
|
/*
|
|
|
* stash over-ride to indicate we've been here
|
|
@@ -357,9 +404,10 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
|
|
|
acpi_table_print_madt_entry(header);
|
|
|
|
|
|
if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
|
|
|
- acpi_sci_ioapic_setup(intsrc->global_irq,
|
|
|
+ acpi_sci_ioapic_setup(intsrc->source_irq,
|
|
|
intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
|
|
|
- (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
|
|
|
+ (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2,
|
|
|
+ intsrc->global_irq);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -448,7 +496,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
|
|
|
|
|
|
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
|
|
|
{
|
|
|
- *irq = gsi;
|
|
|
+ *irq = gsi_to_irq(gsi);
|
|
|
|
|
|
#ifdef CONFIG_X86_IO_APIC
|
|
|
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
|
|
@@ -458,6 +506,14 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
|
|
|
+{
|
|
|
+ if (isa_irq >= 16)
|
|
|
+ return -1;
|
|
|
+ *gsi = irq_to_gsi(isa_irq);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* success: return IRQ number (>=0)
|
|
|
* failure: return < 0
|
|
@@ -482,7 +538,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
|
|
plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
|
|
|
}
|
|
|
#endif
|
|
|
- irq = plat_gsi;
|
|
|
+ irq = gsi_to_irq(plat_gsi);
|
|
|
|
|
|
return irq;
|
|
|
}
|
|
@@ -867,29 +923,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
|
|
extern int es7000_plat;
|
|
|
#endif
|
|
|
|
|
|
-int __init acpi_probe_gsi(void)
|
|
|
-{
|
|
|
- int idx;
|
|
|
- int gsi;
|
|
|
- int max_gsi = 0;
|
|
|
-
|
|
|
- if (acpi_disabled)
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (!acpi_ioapic)
|
|
|
- return 0;
|
|
|
-
|
|
|
- max_gsi = 0;
|
|
|
- for (idx = 0; idx < nr_ioapics; idx++) {
|
|
|
- gsi = mp_gsi_routing[idx].gsi_end;
|
|
|
-
|
|
|
- if (gsi > max_gsi)
|
|
|
- max_gsi = gsi;
|
|
|
- }
|
|
|
-
|
|
|
- return max_gsi + 1;
|
|
|
-}
|
|
|
-
|
|
|
static void assign_to_mp_irq(struct mpc_intsrc *m,
|
|
|
struct mpc_intsrc *mp_irq)
|
|
|
{
|
|
@@ -947,13 +980,13 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
|
|
|
mp_irq.dstirq = pin; /* INTIN# */
|
|
|
|
|
|
save_mp_irq(&mp_irq);
|
|
|
+
|
|
|
+ isa_irq_to_gsi[bus_irq] = gsi;
|
|
|
}
|
|
|
|
|
|
void __init mp_config_acpi_legacy_irqs(void)
|
|
|
{
|
|
|
int i;
|
|
|
- int ioapic;
|
|
|
- unsigned int dstapic;
|
|
|
struct mpc_intsrc mp_irq;
|
|
|
|
|
|
#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
|
|
@@ -973,20 +1006,28 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|
|
return;
|
|
|
#endif
|
|
|
|
|
|
- /*
|
|
|
- * Locate the IOAPIC that manages the ISA IRQs (0-15).
|
|
|
- */
|
|
|
- ioapic = mp_find_ioapic(0);
|
|
|
- if (ioapic < 0)
|
|
|
- return;
|
|
|
- dstapic = mp_ioapics[ioapic].apicid;
|
|
|
-
|
|
|
/*
|
|
|
* Use the default configuration for the IRQs 0-15. Unless
|
|
|
* overridden by (MADT) interrupt source override entries.
|
|
|
*/
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
+ int ioapic, pin;
|
|
|
+ unsigned int dstapic;
|
|
|
int idx;
|
|
|
+ u32 gsi;
|
|
|
+
|
|
|
+ /* Locate the gsi that irq i maps to. */
|
|
|
+ if (acpi_isa_irq_to_gsi(i, &gsi))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Locate the IOAPIC that manages the ISA IRQ.
|
|
|
+ */
|
|
|
+ ioapic = mp_find_ioapic(gsi);
|
|
|
+ if (ioapic < 0)
|
|
|
+ continue;
|
|
|
+ pin = mp_find_ioapic_pin(ioapic, gsi);
|
|
|
+ dstapic = mp_ioapics[ioapic].apicid;
|
|
|
|
|
|
for (idx = 0; idx < mp_irq_entries; idx++) {
|
|
|
struct mpc_intsrc *irq = mp_irqs + idx;
|
|
@@ -996,7 +1037,7 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|
|
break;
|
|
|
|
|
|
/* Do we already have a mapping for this IOAPIC pin */
|
|
|
- if (irq->dstapic == dstapic && irq->dstirq == i)
|
|
|
+ if (irq->dstapic == dstapic && irq->dstirq == pin)
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -1011,7 +1052,7 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|
|
mp_irq.dstapic = dstapic;
|
|
|
mp_irq.irqtype = mp_INT;
|
|
|
mp_irq.srcbusirq = i; /* Identity mapped */
|
|
|
- mp_irq.dstirq = i;
|
|
|
+ mp_irq.dstirq = pin;
|
|
|
|
|
|
save_mp_irq(&mp_irq);
|
|
|
}
|
|
@@ -1076,11 +1117,6 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
|
|
|
|
|
ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
|
|
|
|
|
|
-#ifdef CONFIG_X86_32
|
|
|
- if (ioapic_renumber_irq)
|
|
|
- gsi = ioapic_renumber_irq(ioapic, gsi);
|
|
|
-#endif
|
|
|
-
|
|
|
if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
|
|
|
printk(KERN_ERR "Invalid reference to IOAPIC pin "
|
|
|
"%d-%d\n", mp_ioapics[ioapic].apicid,
|
|
@@ -1094,7 +1130,7 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
|
|
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
|
|
|
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
|
|
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
|
|
- io_apic_set_pci_routing(dev, gsi, &irq_attr);
|
|
|
+ io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
|
|
|
|
|
|
return gsi;
|
|
|
}
|
|
@@ -1154,7 +1190,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
|
|
* pretend we got one so we can set the SCI flags.
|
|
|
*/
|
|
|
if (!acpi_sci_override_gsi)
|
|
|
- acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
|
|
|
+ acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0,
|
|
|
+ acpi_gbl_FADT.sci_interrupt);
|
|
|
|
|
|
/* Fill in identity legacy mappings where no override */
|
|
|
mp_config_acpi_legacy_irqs();
|