]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/kernel/smpboot.c
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
[karo-tx-linux.git] / arch / x86 / kernel / smpboot.c
index d3010aa79dafaff14e74b140e12daa2756f03160..892ee2e5ecbce417df506715f7b28d28c403ef91 100644 (file)
@@ -97,8 +97,6 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
 DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
 EXPORT_PER_CPU_SYMBOL(cpu_info);
 
-atomic_t init_deasserted;
-
 static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 {
        unsigned long flags;
@@ -146,16 +144,11 @@ static void smp_callin(void)
 
        /*
         * If waken up by an INIT in an 82489DX configuration
-        * we may get here before an INIT-deassert IPI reaches
-        * our local APIC.  We have to wait for the IPI or we'll
-        * lock up on an APIC access.
-        *
-        * Since CPU0 is not wakened up by INIT, it doesn't wait for the IPI.
+        * cpu_callout_mask guarantees we don't get here before
+        * an INIT_deassert IPI reaches our local APIC, so it is
+        * now safe to touch our local APIC.
         */
        cpuid = smp_processor_id();
-       if (apic->wait_for_init_deassert && cpuid)
-               while (!atomic_read(&init_deasserted))
-                       cpu_relax();
 
        /*
         * (This works even if the APIC is not enabled.)
@@ -516,7 +509,7 @@ void __inquire_remote_apic(int apicid)
  */
 #define UDELAY_10MS_DEFAULT 10000
 
-static unsigned int init_udelay = UDELAY_10MS_DEFAULT;
+static unsigned int init_udelay = INT_MAX;
 
 static int __init cpu_init_udelay(char *str)
 {
@@ -529,13 +522,16 @@ early_param("cpu_init_udelay", cpu_init_udelay);
 static void __init smp_quirk_init_udelay(void)
 {
        /* if cmdline changed it from default, leave it alone */
-       if (init_udelay != UDELAY_10MS_DEFAULT)
+       if (init_udelay != INT_MAX)
                return;
 
        /* if modern processor, use no delay */
        if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
            ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
                init_udelay = 0;
+
+       /* else, use legacy delay */
+       init_udelay = UDELAY_10MS_DEFAULT;
 }
 
 /*
@@ -620,7 +616,6 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
        send_status = safe_apic_wait_icr_idle();
 
        mb();
-       atomic_set(&init_deasserted, 1);
 
        /*
         * Should we send STARTUP IPIs ?
@@ -665,7 +660,10 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                /*
                 * Give the other CPU some time to accept the IPI.
                 */
-               udelay(300);
+               if (init_udelay == 0)
+                       udelay(10);
+               else
+                       udelay(300);
 
                pr_debug("Startup point 1\n");
 
@@ -675,7 +673,10 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                /*
                 * Give the other CPU some time to accept the IPI.
                 */
-               udelay(200);
+               if (init_udelay == 0)
+                       udelay(10);
+               else
+                       udelay(200);
 
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP.  */
                        apic_write(APIC_ESR, 0);
@@ -859,8 +860,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
         * the targeted processor.
         */
 
-       atomic_set(&init_deasserted, 0);
-
        if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
 
                pr_debug("Setting warm reset code and vector.\n");
@@ -898,7 +897,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
 
        if (!boot_error) {
                /*
-                * Wait 10s total for a response from AP
+                * Wait 10s total for first sign of life from AP
                 */
                boot_error = -1;
                timeout = jiffies + 10*HZ;
@@ -911,7 +910,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                                boot_error = 0;
                                break;
                        }
-                       udelay(100);
                        schedule();
                }
        }
@@ -927,7 +925,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                         * for the MTRR work(triggered by the AP coming online)
                         * to be completed in the stop machine context.
                         */
-                       udelay(100);
                        schedule();
                }
        }
@@ -992,8 +989,17 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
 
        common_cpu_up(cpu, tidle);
 
+       /*
+        * We have to walk the irq descriptors to setup the vector
+        * space for the cpu which comes online.  Prevent irq
+        * alloc/free across the bringup.
+        */
+       irq_lock_sparse();
+
        err = do_boot_cpu(apicid, cpu, tidle);
+
        if (err) {
+               irq_unlock_sparse();
                pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu);
                return -EIO;
        }
@@ -1011,6 +1017,8 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
                touch_nmi_watchdog();
        }
 
+       irq_unlock_sparse();
+
        return 0;
 }
 
@@ -1347,7 +1355,7 @@ static void remove_siblinginfo(int cpu)
        cpumask_clear_cpu(cpu, cpu_sibling_setup_mask);
 }
 
-static void __ref remove_cpu_from_maps(int cpu)
+static void remove_cpu_from_maps(int cpu)
 {
        set_cpu_online(cpu, false);
        cpumask_clear_cpu(cpu, cpu_callout_mask);