Merge master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-drm-fsl-dcu.git] / arch / i386 / kernel / smpboot.c
index a9447c3e86dda2f40096b5e022737f6a7163c0a6..b92cc4e8b3bbd13e066757fec67a0666a298ac30 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
-#include <linux/smp_lock.h>
 #include <linux/bootmem.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
 #include <asm/nmi.h>
-#include <asm/pda.h>
 
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
 #include <asm/vmi.h>
+#include <asm/mtrr.h>
 
 /* Set if we find a B stepping CPU */
 static int __devinitdata smp_b_stepping;
@@ -99,6 +98,9 @@ EXPORT_SYMBOL(x86_cpu_to_apicid);
 
 u8 apicid_2_node[MAX_APICID];
 
+DEFINE_PER_CPU(unsigned long, this_cpu_off);
+EXPORT_PER_CPU_SYMBOL(this_cpu_off);
+
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -155,7 +157,7 @@ static void __cpuinit smp_store_cpu_info(int id)
 
        *c = boot_cpu_data;
        if (id!=0)
-               identify_cpu(c);
+               identify_secondary_cpu(c);
        /*
         * Mask B, Pentium, but not Pentium MMX
         */
@@ -378,14 +380,14 @@ set_cpu_sibling_map(int cpu)
 static void __cpuinit start_secondary(void *unused)
 {
        /*
-        * Don't put *anything* before secondary_cpu_init(), SMP
-        * booting is too fragile that we want to limit the
-        * things done here to the most necessary things.
+        * Don't put *anything* before cpu_init(), SMP booting is too
+        * fragile that we want to limit the things done here to the
+        * most necessary things.
         */
 #ifdef CONFIG_VMI
        vmi_bringup();
 #endif
-       secondary_cpu_init();
+       cpu_init();
        preempt_disable();
        smp_callin();
        while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
@@ -456,7 +458,6 @@ extern struct {
        void * esp;
        unsigned short ss;
 } stack_start;
-extern struct i386_pda *start_pda;
 
 #ifdef CONFIG_NUMA
 
@@ -514,12 +515,12 @@ static void unmap_cpu_to_logical_apicid(int cpu)
        unmap_cpu_to_node(cpu);
 }
 
-#if APIC_DEBUG
 static inline void __inquire_remote_apic(int apicid)
 {
        int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
        char *names[] = { "ID", "VERSION", "SPIV" };
-       int timeout, status;
+       int timeout;
+       unsigned long status;
 
        printk("Inquiring remote APIC #%d...\n", apicid);
 
@@ -529,7 +530,9 @@ static inline void __inquire_remote_apic(int apicid)
                /*
                 * Wait for idle.
                 */
-               apic_wait_icr_idle();
+               status = safe_apic_wait_icr_idle();
+               if (status)
+                       printk("a previous APIC delivery may have failed\n");
 
                apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
                apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
@@ -543,14 +546,13 @@ static inline void __inquire_remote_apic(int apicid)
                switch (status) {
                case APIC_ICR_RR_VALID:
                        status = apic_read(APIC_RRR);
-                       printk("%08x\n", status);
+                       printk("%lx\n", status);
                        break;
                default:
                        printk("failed\n");
                }
        }
 }
-#endif
 
 #ifdef WAKE_SECONDARY_VIA_NMI
 /* 
@@ -561,8 +563,8 @@ static inline void __inquire_remote_apic(int apicid)
 static int __devinit
 wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
 {
-       unsigned long send_status = 0, accept_status = 0;
-       int timeout, maxlvt;
+       unsigned long send_status, accept_status = 0;
+       int maxlvt;
 
        /* Target chip */
        apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
@@ -572,12 +574,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
        apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        /*
         * Give the other CPU some time to accept the IPI.
@@ -607,8 +604,8 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
 static int __devinit
 wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
 {
-       unsigned long send_status = 0, accept_status = 0;
-       int maxlvt, timeout, num_starts, j;
+       unsigned long send_status, accept_status = 0;
+       int maxlvt, num_starts, j;
 
        /*
         * Be paranoid about clearing APIC errors.
@@ -633,12 +630,7 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
                                | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        mdelay(10);
 
@@ -651,12 +643,7 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
        apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        atomic_set(&init_deasserted, 1);
 
@@ -712,12 +699,7 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
                Dprintk("Startup point 1.\n");
 
                Dprintk("Waiting for send to finish...\n");
-               timeout = 0;
-               do {
-                       Dprintk("+");
-                       udelay(100);
-                       send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-               } while (send_status && (timeout++ < 1000));
+               send_status = safe_apic_wait_icr_idle();
 
                /*
                 * Give the other CPU some time to accept the IPI.
@@ -784,24 +766,17 @@ static inline struct task_struct * alloc_idle_task(int cpu)
 /* Initialize the CPU's GDT.  This is either the boot CPU doing itself
    (still using the master per-cpu area), or a CPU doing it for a
    secondary which will soon come up. */
-static __cpuinit void init_gdt(int cpu, struct task_struct *idle)
+static __cpuinit void init_gdt(int cpu)
 {
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
-       struct desc_struct *gdt = per_cpu(cpu_gdt, cpu);
-       struct i386_pda *pda = &per_cpu(_cpu_pda, cpu);
-
-       cpu_gdt_descr->address = (unsigned long)gdt;
-       cpu_gdt_descr->size = GDT_SIZE - 1;
-
-       pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a,
-                       (u32 *)&gdt[GDT_ENTRY_PDA].b,
-                       (unsigned long)pda, sizeof(*pda) - 1,
-                       0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */
-
-       memset(pda, 0, sizeof(*pda));
-       pda->_pda = pda;
-       pda->cpu_number = cpu;
-       pda->pcurrent = idle;
+       struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+       pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a,
+                       (u32 *)&gdt[GDT_ENTRY_PERCPU].b,
+                       __per_cpu_offset[cpu], 0xFFFFF,
+                       0x80 | DESCTYPE_S | 0x2, 0x8);
+
+       per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
+       per_cpu(cpu_number, cpu) = cpu;
 }
 
 /* Defined in head.S */
@@ -820,6 +795,12 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
        unsigned long start_eip;
        unsigned short nmi_high = 0, nmi_low = 0;
 
+       /*
+        * Save current MTRR state in case it was changed since early boot
+        * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+        */
+       mtrr_save_state();
+
        /*
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
@@ -828,9 +809,9 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
        if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
 
-       init_gdt(cpu, idle);
+       init_gdt(cpu);
+       per_cpu(current_task, cpu) = idle;
        early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
-       start_pda = cpu_pda(cpu);
 
        idle->thread.eip = (unsigned long) start_secondary;
        /* start_eip had better be page-aligned! */
@@ -1175,7 +1156,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
 
 /* These are wrappers to interface to the new boot process.  Someone
    who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init native_smp_prepare_cpus(unsigned int max_cpus)
 {
        smp_commenced_mask = cpumask_of_cpu(0);
        cpu_callin_map = cpumask_of_cpu(0);
@@ -1183,19 +1164,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        smp_boot_cpus(max_cpus);
 }
 
-/* Current gdt points %fs at the "master" per-cpu area: after this,
- * it's on the real one. */
-static inline void switch_to_new_gdt(void)
-{
-       load_gdt(&per_cpu(cpu_gdt_descr, smp_processor_id()));
-       asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory");
-}
-
-void __init smp_prepare_boot_cpu(void)
+void __init native_smp_prepare_boot_cpu(void)
 {
        unsigned int cpu = smp_processor_id();
 
-       init_gdt(cpu, current);
+       init_gdt(cpu);
        switch_to_new_gdt();
 
        cpu_set(cpu, cpu_online_map);
@@ -1292,7 +1265,7 @@ void __cpu_die(unsigned int cpu)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit native_cpu_up(unsigned int cpu)
 {
        unsigned long flags;
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1337,7 +1310,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
        return 0;
 }
 
-void __init smp_cpus_done(unsigned int max_cpus)
+void __init native_smp_cpus_done(unsigned int max_cpus)
 {
 #ifdef CONFIG_X86_IO_APIC
        setup_ioapic_dest();