#include <linux/smp_lock.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
+#include <linux/bitops.h>
#include <asm/smp.h>
#include <asm/acpi.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
-#include <asm/pgalloc.h>
#include <asm/io_apic.h>
#include <mach_apic.h>
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
+#ifdef CONFIG_X86_NUMAQ
+static int MP_valid_apicid(int apicid, int version)
+{
+ return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
+}
+#else
+static int MP_valid_apicid(int apicid, int version)
+{
+ if (version >= 0x14)
+ return apicid < 0xff;
+ else
+ return apicid < 0xf;
+}
+#endif
+
void __init MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
return;
}
num_processors++;
+ ver = m->mpc_apicver;
- if (MAX_APICS - m->mpc_apicid <= 0) {
+ if (!MP_valid_apicid(apicid, ver)) {
printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
m->mpc_apicid, MAX_APICS);
--num_processors;
return;
}
- ver = m->mpc_apicver;
tmp = apicid_to_cpu_present(apicid);
physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
MP_processor_info(&processor);
}
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
#define MP_ISA_BUS 0
#define MP_MAX_IOAPIC_PIN 127
} mp_ioapic_routing[MAX_IO_APICS];
-static int __init mp_find_ioapic (
+static int mp_find_ioapic (
int gsi)
{
int i = 0;
for (i = 0; i < 16; i++) {
int idx;
- for (idx = 0; idx < mp_irq_entries; idx++)
- if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS &&
- (mp_irqs[idx].mpc_srcbusirq == i ||
- mp_irqs[idx].mpc_dstirq == i))
- break;
+ for (idx = 0; idx < mp_irq_entries; idx++) {
+ struct mpc_config_intsrc *irq = mp_irqs + idx;
- if (idx != mp_irq_entries)
- continue; /* IRQ already used */
+ /* 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 */
}
}
-extern FADT_DESCRIPTOR acpi_fadt;
-
-#ifdef CONFIG_ACPI_PCI
-
int (*platform_rename_gsi)(int ioapic, int gsi);
-void __init mp_parse_prt (void)
+void mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
{
- struct list_head *node = NULL;
- struct acpi_prt_entry *entry = NULL;
int ioapic = -1;
int ioapic_pin = 0;
- int gsi = 0;
int idx, bit = 0;
- int edge_level = 0;
- int active_high_low = 0;
- /*
- * Parsing through the PCI Interrupt Routing Table (PRT) and program
- * routing for all entries.
- */
- list_for_each(node, &acpi_prt.entries) {
- entry = list_entry(node, struct acpi_prt_entry, node);
-
- /* Need to get gsi for dynamic entry */
- if (entry->link.handle) {
- gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
- if (!gsi)
- continue;
- }
- else {
- /* Hardwired GSI. Assume PCI standard settings */
- gsi = entry->link.index;
- edge_level = 1;
- active_high_low = 1;
- }
+#ifdef CONFIG_ACPI_BUS
+ /* Don't set up the ACPI SCI because it's already set up */
+ if (acpi_fadt.sci_int == gsi)
+ return;
+#endif
- /* Don't set up the ACPI SCI because it's already set up */
- if (acpi_fadt.sci_int == gsi) {
- /* we still need to set entry's irq */
- acpi_gsi_to_irq(gsi, &entry->irq);
- continue;
- }
-
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0)
- continue;
- ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
-
- if (platform_rename_gsi)
- gsi = platform_rename_gsi(ioapic, gsi);
-
- /*
- * Avoid pin reprogramming. PRTs typically include entries
- * with redundant pin->gsi mappings (but unique PCI devices);
- * we only only program the IOAPIC on the first.
- */
- bit = ioapic_pin % 32;
- idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
- if (idx > 3) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
- ioapic_pin);
- continue;
- }
- if ((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);
- acpi_gsi_to_irq(gsi, &entry->irq);
- continue;
- }
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0) {
+ printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+ return;
+ }
- mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+ ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
- if (!io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, edge_level, active_high_low)) {
- acpi_gsi_to_irq(gsi, &entry->irq);
- }
- printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d %s %s\n",
- entry->id.segment, entry->id.bus,
- entry->id.device, ('A' + entry->pin),
- mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
- entry->irq, edge_level ? "level" : "edge",
- active_high_low ? "low" : "high");
+ if (platform_rename_gsi)
+ gsi = platform_rename_gsi(ioapic, gsi);
+
+ /*
+ * Avoid pin reprogramming. PRTs typically include entries
+ * with redundant pin->gsi mappings (but unique PCI devices);
+ * we only program the IOAPIC on the first.
+ */
+ bit = ioapic_pin % 32;
+ idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+ if (idx > 3) {
+ printk(KERN_ERR "Invalid reference to IOAPIC pin "
+ "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
+ ioapic_pin);
+ return;
+ }
+ if ((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;
}
- print_IO_APIC();
+ mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
- return;
+ io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+ edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
+ active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
}
-#endif /*CONFIG_ACPI_PCI*/
-#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
+#endif /*CONFIG_X86_IO_APIC && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)*/
#endif /*CONFIG_ACPI_BOOT*/