x86: use same index for processor maps
[sfrench/cifs-2.6.git] / arch / x86 / kernel / mpparse_32.c
index 7a05a7f6099a4ee31b7bb72e6c11c956282588da..1b225cea5d7bd58d24ebf8be692a058c883c8699 100644 (file)
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/io_apic.h>
+#include <asm/bios_ebda.h>
 
 #include <mach_apic.h>
 #include <mach_apicdef.h>
 #include <mach_mpparse.h>
-#include <bios_ebda.h>
 
 /* Have we found an MP table */
 int smp_found_config;
@@ -42,10 +42,10 @@ unsigned int __cpuinitdata maxcpus = NR_CPUS;
  * MP-table.
  */
 int apic_version [MAX_APICS];
+#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
 int mp_bus_id_to_type [MAX_MP_BUSSES];
-int mp_bus_id_to_node [MAX_MP_BUSSES];
-int mp_bus_id_to_local [MAX_MP_BUSSES];
-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+#endif
+DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 static int mp_current_pci_id;
 
@@ -68,12 +68,16 @@ unsigned int def_to_bigsmp = 0;
 /* Processor that is doing the boot up */
 unsigned int boot_cpu_physical_apicid = -1U;
 /* Internal processor count */
-unsigned int __cpuinitdata num_processors;
+unsigned int num_processors;
+
+unsigned disabled_cpus __cpuinitdata;
 
 /* Bitmask of physically existing CPUs */
 physid_mask_t phys_cpu_present_map;
 
-u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+#ifndef CONFIG_SMP
+DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
+#endif
 
 /*
  * Intel MP BIOS table parsing routines:
@@ -94,6 +98,7 @@ static int __init mpf_checksum(unsigned char *mp, int len)
        return sum & 0xFF;
 }
 
+#ifdef CONFIG_X86_NUMAQ
 /*
  * Have to match translation table entries to main table entries by counter
  * hence the mpc_record variable .... can't see a less disgusting way of
@@ -102,16 +107,29 @@ static int __init mpf_checksum(unsigned char *mp, int len)
 
 static int mpc_record; 
 static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
+#endif
 
 static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
 {
-       int ver, apicid;
+       int ver, apicid, cpu;
+       cpumask_t tmp_map;
        physid_mask_t phys_cpu;
        
-       if (!(m->mpc_cpuflag & CPU_ENABLED))
+       if (!(m->mpc_cpuflag & CPU_ENABLED)) {
+               disabled_cpus++;
                return;
+       }
 
+#ifdef CONFIG_X86_NUMAQ
        apicid = mpc_apic_id(m, translation_table[mpc_record]);
+#else
+       Dprintk("Processor #%d %u:%u APIC version %d\n",
+               m->mpc_apicid,
+               (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+               (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+               m->mpc_apicver);
+       apicid = m->mpc_apicid;
+#endif
 
        if (m->mpc_featureflag&(1<<0))
                Dprintk("    Floating point unit present.\n");
@@ -194,8 +212,17 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
                return;
        }
 
-       cpu_set(num_processors, cpu_possible_map);
        num_processors++;
+       cpus_complement(tmp_map, cpu_present_map);
+       cpu = first_cpu(tmp_map);
+
+       if (m->mpc_cpuflag & CPU_BOOTPROCESSOR)
+               /*
+                * x86_bios_cpu_apicid is required to have processors listed
+                * in same order as logical cpu numbers. Hence the first
+                * entry is BSP, and so on.
+                */
+               cpu = 0;
 
        /*
         * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
@@ -216,7 +243,21 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
                        def_to_bigsmp = 1;
                }
        }
-       bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+#ifdef CONFIG_SMP
+       /* are we being called early in kernel startup? */
+       if (x86_cpu_to_apicid_early_ptr) {
+               u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
+               u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
+
+               cpu_to_apicid[cpu] = m->mpc_apicid;
+               bios_cpu_apicid[cpu] = m->mpc_apicid;
+       } else {
+               per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
+               per_cpu(x86_bios_cpu_apicid, cpu) = m->mpc_apicid;
+       }
+#endif
+       cpu_set(cpu, cpu_possible_map);
+       cpu_set(cpu, cpu_present_map);
 }
 
 static void __init MP_bus_info (struct mpc_config_bus *m)
@@ -226,7 +267,11 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
        memcpy(str, m->mpc_bustype, 6);
        str[6] = 0;
 
+#ifdef CONFIG_X86_NUMAQ
        mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+#else
+       Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+#endif
 
 #if MAX_MP_BUSSES < 256
        if (m->mpc_busid >= MAX_MP_BUSSES) {
@@ -237,39 +282,54 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
        }
 #endif
 
-       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) {
-               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
-       } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
+       set_bit(m->mpc_busid, mp_bus_not_pci);
+       if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
+#ifdef CONFIG_X86_NUMAQ
                mpc_oem_pci_bus(m, translation_table[mpc_record]);
-               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+#endif
+               clear_bit(m->mpc_busid, mp_bus_not_pci);
                mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
                mp_current_pci_id++;
+#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
+               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+       } else 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) {
+               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
        } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
        } else {
                printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+#endif
        }
 }
 
+static int bad_ioapic(unsigned long address)
+{
+       if (nr_ioapics >= MAX_IO_APICS) {
+               printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+                      "(found %d)\n", MAX_IO_APICS, nr_ioapics);
+               panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+       }
+       if (!address) {
+               printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+                      " found in table, skipping!\n");
+               return 1;
+       }
+       return 0;
+}
+
 static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
 {
        if (!(m->mpc_flags & MPC_APIC_USABLE))
                return;
 
-       printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n",
+       printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
                m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
-       if (nr_ioapics >= MAX_IO_APICS) {
-               printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
-                       MAX_IO_APICS, nr_ioapics);
-               panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
-       }
-       if (!m->mpc_apicaddr) {
-               printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
-                       " found in MP table, skipping!\n");
+
+       if (bad_ioapic(m->mpc_apicaddr))
                return;
-       }
+
        mp_ioapics[nr_ioapics] = *m;
        nr_ioapics++;
 }
@@ -405,9 +465,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
 
        mps_oem_check(mpc, oem, str);
 
-       printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
+       printk("APIC at: 0x%X\n", mpc->mpc_lapic);
 
-       /* 
+       /*
         * Save the local APIC address (it might be non-default) -- but only
         * if we're not using ACPI.
         */
@@ -417,7 +477,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
        /*
         *      Now process the configuration blocks.
         */
+#ifdef CONFIG_X86_NUMAQ
        mpc_record = 0;
+#endif
        while (count < mpc->mpc_length) {
                switch(*mpt) {
                        case MP_PROCESSOR:
@@ -474,7 +536,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                                break;
                        }
                }
+#ifdef CONFIG_X86_NUMAQ
                ++mpc_record;
+#endif
        }
        setup_apic_routing();
        if (!num_processors)
@@ -721,7 +785,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
        unsigned long *bp = phys_to_virt(base);
        struct intel_mp_floating *mpf;
 
-       Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
+       printk(KERN_INFO "Scan SMP from %p for %ld bytes.\n", bp,length);
        if (sizeof(*mpf) != 16)
                printk("Error: MPF size\n");
 
@@ -734,9 +798,10 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
                                || (mpf->mpf_specification == 4)) ) {
 
                        smp_found_config = 1;
-                       printk(KERN_INFO "found SMP MP-table at %08lx\n",
-                                               virt_to_phys(mpf));
-                       reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
+                       printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+                               mpf, virt_to_phys(mpf));
+                       reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
+                                       BOOTMEM_DEFAULT);
                        if (mpf->mpf_physptr) {
                                /*
                                 * We cannot access to MPC table to compute
@@ -751,7 +816,8 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
                                unsigned long end = max_low_pfn * PAGE_SIZE;
                                if (mpf->mpf_physptr + size > end)
                                        size = end - mpf->mpf_physptr;
-                               reserve_bootmem(mpf->mpf_physptr, size);
+                               reserve_bootmem(mpf->mpf_physptr, size,
+                                               BOOTMEM_DEFAULT);
                        }
 
                        mpf_found = mpf;
@@ -877,39 +943,30 @@ static int mp_find_ioapic (int gsi)
        return -1;
 }
 
+static u8 uniq_ioapic_id(u8 id)
+{
+       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;
+}
+
 void __init mp_register_ioapic(u8 id, u32 address, 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 "
-                       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
-               panic("Recompile kernel with bigger MAX_IO_APICS!\n");
-       }
-       if (!address) {
-               printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
-                       " found in MADT table, skipping!\n");
+       if (bad_ioapic(address))
                return;
-       }
 
-       idx = nr_ioapics++;
+       idx = nr_ioapics;
 
        mp_ioapics[idx].mpc_type = MP_IOAPIC;
        mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
        mp_ioapics[idx].mpc_apicaddr = address;
 
        set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
-       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_apicid = uniq_ioapic_id(id);
        mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
        
        /* 
@@ -918,14 +975,17 @@ void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
         */
        mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
        mp_ioapic_routing[idx].gsi_base = gsi_base;
-       mp_ioapic_routing[idx].gsi_end = gsi_base + 
+       mp_ioapic_routing[idx].gsi_end = gsi_base +
                io_apic_get_redir_entries(idx);
 
-       printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, "
-               "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
-               mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
-               mp_ioapic_routing[idx].gsi_base,
-               mp_ioapic_routing[idx].gsi_end);
+       printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+              "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
+              mp_ioapics[idx].mpc_apicver,
+              mp_ioapics[idx].mpc_apicaddr,
+              mp_ioapic_routing[idx].gsi_base,
+              mp_ioapic_routing[idx].gsi_end);
+
+       nr_ioapics++;
 }
 
 void __init
@@ -975,10 +1035,13 @@ void __init mp_config_acpi_legacy_irqs (void)
        int i = 0;
        int ioapic = -1;
 
+#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
        /* 
         * Fabricate the legacy ISA bus (bus #31).
         */
        mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
+#endif
+       set_bit(MP_ISA_BUS, mp_bus_not_pci);
        Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
 
        /*
@@ -1041,15 +1104,16 @@ 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 ioapic = -1;
        int ioapic_pin = 0;
        int idx, bit = 0;
-       static int pci_irq = 16;
+       static int pci_irq = IRQ_COMPRESSION_START;
        /*
-        * Mapping between Global System Interrups, which
+        * Mapping between Global System Interrupts, which
         * represent all possible interrupts, and IRQs
         * assigned to actual devices.
         */
@@ -1086,12 +1150,16 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
        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];
+               return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
        }
 
        mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
-       if (triggering == ACPI_LEVEL_SENSITIVE) {
+       /*
+        * 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.
@@ -1108,8 +1176,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
                         * 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++;
+                       gsi = pci_irq++;
                        /*
                         * Don't assign IRQ used by ACPI SCI
                         */