|
@@ -85,6 +85,9 @@ int nr_ioapic_registers[MAX_IO_APICS];
|
|
struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
|
|
struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
|
|
int nr_ioapics;
|
|
int nr_ioapics;
|
|
|
|
|
|
|
|
+/* IO APIC gsi routing info */
|
|
|
|
+struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS];
|
|
|
|
+
|
|
/* MP IRQ source entries */
|
|
/* MP IRQ source entries */
|
|
struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
|
|
struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
|
|
|
|
|
|
@@ -3941,11 +3944,28 @@ int io_apic_set_pci_routing(struct device *dev, int irq,
|
|
return __io_apic_set_pci_routing(dev, irq, irq_attr);
|
|
return __io_apic_set_pci_routing(dev, irq, irq_attr);
|
|
}
|
|
}
|
|
|
|
|
|
-/* --------------------------------------------------------------------------
|
|
|
|
- ACPI-based IOAPIC Configuration
|
|
|
|
- -------------------------------------------------------------------------- */
|
|
|
|
|
|
+u8 __init io_apic_unique_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);
|
|
|
|
|
|
-#ifdef CONFIG_ACPI
|
|
|
|
|
|
+ bitmap_zero(used, 256);
|
|
|
|
+ for (i = 0; i < nr_ioapics; i++) {
|
|
|
|
+ struct mpc_ioapic *ia = &mp_ioapics[i];
|
|
|
|
+ __set_bit(ia->apicid, used);
|
|
|
|
+ }
|
|
|
|
+ if (!test_bit(id, used))
|
|
|
|
+ return id;
|
|
|
|
+ return find_first_zero_bit(used, 256);
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
#ifdef CONFIG_X86_32
|
|
int __init io_apic_get_unique_id(int ioapic, int apic_id)
|
|
int __init io_apic_get_unique_id(int ioapic, int apic_id)
|
|
@@ -4054,8 +4074,6 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-#endif /* CONFIG_ACPI */
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* This function currently is only a helper for the i386 smp boot process where
|
|
* This function currently is only a helper for the i386 smp boot process where
|
|
* we need to reprogram the ioredtbls to cater for the cpus which have come online
|
|
* we need to reprogram the ioredtbls to cater for the cpus which have come online
|
|
@@ -4201,3 +4219,76 @@ void __init ioapic_insert_resources(void)
|
|
r++;
|
|
r++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+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_gsi_routing[i].gsi_base)
|
|
|
|
+ && (gsi <= mp_gsi_routing[i].gsi_end))
|
|
|
|
+ return i;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
|
|
|
|
+ return -1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int mp_find_ioapic_pin(int ioapic, int gsi)
|
|
|
|
+{
|
|
|
|
+ if (WARN_ON(ioapic == -1))
|
|
|
|
+ return -1;
|
|
|
|
+ if (WARN_ON(gsi > mp_gsi_routing[ioapic].gsi_end))
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ return gsi - mp_gsi_routing[ioapic].gsi_base;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int bad_ioapic(unsigned long address)
|
|
|
|
+{
|
|
|
|
+ if (nr_ioapics >= MAX_IO_APICS) {
|
|
|
|
+ printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
|
|
|
|
+ "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ if (!address) {
|
|
|
|
+ printk(KERN_WARNING "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].type = MP_IOAPIC;
|
|
|
|
+ mp_ioapics[idx].flags = MPC_APIC_USABLE;
|
|
|
|
+ mp_ioapics[idx].apicaddr = address;
|
|
|
|
+
|
|
|
|
+ set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
|
|
|
|
+ mp_ioapics[idx].apicid = io_apic_unique_id(id);
|
|
|
|
+ mp_ioapics[idx].apicver = io_apic_get_version(idx);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Build basic GSI lookup table to facilitate gsi->io_apic lookups
|
|
|
|
+ * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
|
|
|
|
+ */
|
|
|
|
+ mp_gsi_routing[idx].gsi_base = gsi_base;
|
|
|
|
+ mp_gsi_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].apicid,
|
|
|
|
+ mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
|
|
|
|
+ mp_gsi_routing[idx].gsi_base, mp_gsi_routing[idx].gsi_end);
|
|
|
|
+
|
|
|
|
+ nr_ioapics++;
|
|
|
|
+}
|