*/
#include <linux/mm.h>
-#include <linux/irq.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/delay.h>
-#include <linux/config.h>
#include <linux/bootmem.h>
#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>
int mp_bus_id_to_local [MAX_MP_BUSSES];
int quad_local_to_mp_bus_id [NR_CPUS/4][4];
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-int mp_current_pci_id;
+static int mp_current_pci_id;
/* I/O APIC entries */
struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
int pic_mode;
unsigned long mp_lapic_addr;
+unsigned int def_to_bigsmp = 0;
+
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
-unsigned int boot_cpu_logical_apicid = -1U;
/* Internal processor count */
-static unsigned int __initdata num_processors;
+static unsigned int __devinitdata num_processors;
/* Bitmask of physically existing CPUs */
physid_mask_t phys_cpu_present_map;
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
-void __init MP_processor_info (struct mpc_config_processor *m)
+static void __devinit MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
- physid_mask_t tmp;
+ physid_mask_t phys_cpu;
if (!(m->mpc_cpuflag & CPU_ENABLED))
return;
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
Dprintk(" Bootup CPU\n");
boot_cpu_physical_apicid = m->mpc_apicid;
- boot_cpu_logical_apicid = apicid;
}
+ ver = m->mpc_apicver;
+
+ /*
+ * Validate version
+ */
+ if (ver == 0x0) {
+ printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
+ "fixing up to 0x10. (tell your hw vendor)\n",
+ m->mpc_apicid);
+ ver = 0x10;
+ }
+ apic_version[m->mpc_apicid] = ver;
+
+ phys_cpu = apicid_to_cpu_present(apicid);
+ physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
+
if (num_processors >= NR_CPUS) {
printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
- " Processor ignored.\n", NR_CPUS);
+ " Processor ignored.\n", NR_CPUS);
return;
}
if (num_processors >= maxcpus) {
printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
- " Processor ignored.\n", maxcpus);
+ " Processor ignored.\n", maxcpus);
return;
}
- num_processors++;
- if (MAX_APICS - m->mpc_apicid <= 0) {
- printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
- m->mpc_apicid, MAX_APICS);
- --num_processors;
- return;
- }
- ver = m->mpc_apicver;
+ cpu_set(num_processors, cpu_possible_map);
+ num_processors++;
- tmp = apicid_to_cpu_present(apicid);
- physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
-
/*
- * Validate version
+ * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+ * but we need to work other dependencies like SMP_SUSPEND etc
+ * before this can be done without some confusion.
+ * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+ * - Ashok Raj <ashok.raj@intel.com>
*/
- if (ver == 0x0) {
- printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
- ver = 0x10;
+ if (num_processors > 8) {
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_INTEL:
+ if (!APIC_XAPIC(ver)) {
+ def_to_bigsmp = 0;
+ break;
+ }
+ /* If P4 and above fall through */
+ case X86_VENDOR_AMD:
+ def_to_bigsmp = 1;
+ }
}
- apic_version[m->mpc_apicid] = ver;
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
}
mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+ if (m->mpc_busid >= MAX_MP_BUSSES) {
+ printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+ " is too large, max. supported is %d\n",
+ m->mpc_busid, str, MAX_MP_BUSSES - 1);
+ return;
+ }
+
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
else
translation_table[mpc_record] = m; /* stash this for later */
- if (m->trans_quad+1 > numnodes)
- numnodes = m->trans_quad+1;
+ if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+ node_set_online(m->trans_quad);
}
/*
struct intel_mp_floating *mpf = mpf_found;
/*
- * ACPI may be used to obtain the entire SMP configuration or just to
- * enumerate/configure processors (CONFIG_ACPI_BOOT). Note that
* ACPI supports both logical (e.g. Hyper-Threading) and physical
* processors, where MPS only supports physical.
*/
* Read the physical hardware table. Anything here will
* override the defaults.
*/
- if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
+ if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {
smp_found_config = 0;
printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
smp_scan_config(address, 0x400);
}
+int es7000_plat;
/* --------------------------------------------------------------------------
ACPI-based MP Configuration
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
void __init mp_register_lapic_address (
u64 address)
}
-void __init mp_register_lapic (
+void __devinit mp_register_lapic (
u8 id,
u8 enabled)
{
MP_processor_info(&processor);
}
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+#ifdef CONFIG_X86_IO_APIC
#define MP_ISA_BUS 0
#define MP_MAX_IOAPIC_PIN 127
-struct mp_ioapic_routing {
+static struct mp_ioapic_routing {
int apic_id;
int gsi_base;
int gsi_end;
} mp_ioapic_routing[MAX_IO_APICS];
-static int __init mp_find_ioapic (
+static int mp_find_ioapic (
int gsi)
{
int i = 0;
u32 gsi_base)
{
int idx = 0;
+ int tmpid;
if (nr_ioapics >= MAX_IO_APICS) {
printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
mp_ioapics[idx].mpc_apicaddr = address;
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
- mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ && !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+ tmpid = io_apic_get_unique_id(idx, id);
+ else
+ tmpid = id;
+ if (tmpid == -1) {
+ nr_ioapics--;
+ return;
+ }
+ mp_ioapics[idx].mpc_apicid = tmpid;
mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
/*
return;
}
-
void __init mp_config_acpi_legacy_irqs (void)
{
struct mpc_config_intsrc intsrc;
mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+ /*
+ * Older generations of ES7000 have no legacy identity mappings
+ */
+ if (es7000_plat == 1)
+ return;
+
/*
* Locate the IOAPIC that manages the ISA IRQs (0-15).
*/
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;
+
+ /* Do we already have a mapping for this ISA IRQ? */
+ if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+ break;
- if (idx != mp_irq_entries)
- continue; /* IRQ already used */
+ /* 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;
+#define MAX_GSI_NUM 4096
-#ifdef CONFIG_ACPI_PCI
-
-void __init mp_parse_prt (void)
+int mp_register_gsi (u32 gsi, int triggering, int polarity)
{
- 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;
-
+ static int pci_irq = 16;
/*
- * Parsing through the PCI Interrupt Routing Table (PRT) and program
- * routing for all entries.
+ * Mapping between Global System Interrups, which
+ * represent all possible interrupts, and IRQs
+ * assigned to actual devices.
*/
- 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;
- }
+ static int gsi_to_irq[MAX_GSI_NUM];
- /* 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 (es7000_plat) {
- if (!ioapic && (gsi < 16))
- gsi += 16;
- }
+ /* Don't set up the ACPI SCI because it's already set up */
+ if (acpi_fadt.sci_int == gsi)
+ return 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 gsi;
+ }
- 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 (ioapic_renumber_irq)
+ gsi = ioapic_renumber_irq(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 gsi;
+ }
+ 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 gsi_to_irq[gsi];
}
- print_IO_APIC();
+ mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
- return;
+ if (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.
+ */
+ if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
+ gsi = pci_irq++;
+ /*
+ * Don't assign IRQ used by ACPI SCI
+ */
+ if (gsi == acpi_fadt.sci_int)
+ 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,
+ triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+ polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+ return gsi;
}
-#endif /*CONFIG_ACPI_PCI*/
-#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
-#endif /*CONFIG_ACPI_BOOT*/
+#endif /* CONFIG_X86_IO_APIC */
+#endif /* CONFIG_ACPI */