[PATCH] IPMI: watchdog handle panic properly
[safe/jmp/linux-2.6] / arch / i386 / kernel / mpparse.c
index 3751bb4..6b1392d 100644 (file)
@@ -104,21 +104,6 @@ static int __init mpf_checksum(unsigned char *mp, int len)
 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
-
 static void __devinit MP_processor_info (struct mpc_config_processor *m)
 {
        int ver, apicid;
@@ -182,47 +167,56 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
                boot_cpu_physical_apicid = m->mpc_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); 
-               return;
-       }
-       ver = m->mpc_apicver;
-
-       if (!MP_valid_apicid(apicid, ver)) {
-               printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
-                       m->mpc_apicid, MAX_APICS);
+                       " Processor ignored.\n", maxcpus);
                return;
        }
 
        cpu_set(num_processors, cpu_possible_map);
        num_processors++;
-       phys_cpu = apicid_to_cpu_present(apicid);
-       physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
 
        /*
-        * 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;
-       if ((num_processors > 8) &&
-           APIC_XAPIC(ver) &&
-           (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
-               def_to_bigsmp = 1;
-       else
-               def_to_bigsmp = 0;
-
        bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
 }
 
@@ -235,6 +229,13 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
 
        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) {
@@ -696,7 +697,7 @@ void __init get_smp_config (void)
                 * 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");
@@ -814,6 +815,8 @@ void __init find_smp_config (void)
                smp_scan_config(address, 0x400);
 }
 
+int es7000_plat;
+
 /* --------------------------------------------------------------------------
                             ACPI-based MP Configuration
    -------------------------------------------------------------------------- */
@@ -901,6 +904,7 @@ void __init mp_register_ioapic (
        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 "
@@ -920,10 +924,16 @@ void __init mp_register_ioapic (
        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) && (boot_cpu_data.x86 < 15))
-               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
-               mp_ioapics[idx].mpc_apicid = id;
+               tmpid = id;
+       if (tmpid == -1) {
+               nr_ioapics--;
+               return;
+       }
+       mp_ioapics[idx].mpc_apicid = tmpid;
        mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
        
        /* 
@@ -991,8 +1001,6 @@ void __init mp_override_legacy_irq (
        return;
 }
 
-int es7000_plat;
-
 void __init mp_config_acpi_legacy_irqs (void)
 {
        struct mpc_config_intsrc intsrc;
@@ -1066,7 +1074,7 @@ void __init mp_config_acpi_legacy_irqs (void)
 
 #define MAX_GSI_NUM    4096
 
-int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
+int mp_register_gsi (u32 gsi, int triggering, int polarity)
 {
        int                     ioapic = -1;
        int                     ioapic_pin = 0;
@@ -1115,14 +1123,24 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
 
        mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
-       if (edge_level) {
+       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) {
-                       if (gsi > 15)
+                       /*
+                        * 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
@@ -1137,8 +1155,8 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
        }
 
        io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
-                   edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
-                   active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
+                   triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+                   polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
        return gsi;
 }