Merge branch 'stable/bug-fixes-rc2' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / arch / powerpc / platforms / powermac / smp.c
index 837989e..a830c5e 100644 (file)
@@ -840,30 +840,68 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
 
        /* Setup openpic */
        mpic_setup_this_cpu();
+}
 
-       if (cpu_nr == 0) {
-#ifdef CONFIG_PPC64
-               extern void g5_phy_disable_cpu1(void);
+#ifdef CONFIG_HOTPLUG_CPU
+static int smp_core99_cpu_notify(struct notifier_block *self,
+                                unsigned long action, void *hcpu)
+{
+       int rc;
 
-               /* Close i2c bus if it was used for tb sync */
+       switch(action) {
+       case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
+               /* Open i2c bus if it was used for tb sync */
                if (pmac_tb_clock_chip_host) {
-                       pmac_i2c_close(pmac_tb_clock_chip_host);
-                       pmac_tb_clock_chip_host = NULL;
+                       rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1);
+                       if (rc) {
+                               pr_err("Failed to open i2c bus for time sync\n");
+                               return notifier_from_errno(rc);
+                       }
                }
+               break;
+       case CPU_ONLINE:
+       case CPU_UP_CANCELED:
+               /* Close i2c bus if it was used for tb sync */
+               if (pmac_tb_clock_chip_host)
+                       pmac_i2c_close(pmac_tb_clock_chip_host);
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
+}
 
-               /* If we didn't start the second CPU, we must take
-                * it off the bus
-                */
-               if (of_machine_is_compatible("MacRISC4") &&
-                   num_online_cpus() < 2)              
-                       g5_phy_disable_cpu1();
-#endif /* CONFIG_PPC64 */
+static struct notifier_block __cpuinitdata smp_core99_cpu_nb = {
+       .notifier_call  = smp_core99_cpu_notify,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static void __init smp_core99_bringup_done(void)
+{
+#ifdef CONFIG_PPC64
+       extern void g5_phy_disable_cpu1(void);
+
+       /* Close i2c bus if it was used for tb sync */
+       if (pmac_tb_clock_chip_host)
+               pmac_i2c_close(pmac_tb_clock_chip_host);
 
-               if (ppc_md.progress)
-                       ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+       /* If we didn't start the second CPU, we must take
+        * it off the bus.
+        */
+       if (of_machine_is_compatible("MacRISC4") &&
+           num_online_cpus() < 2) {
+               set_cpu_present(1, false);
+               g5_phy_disable_cpu1();
        }
-}
+#endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_HOTPLUG_CPU
+       register_cpu_notifier(&smp_core99_cpu_nb);
+#endif
+       if (ppc_md.progress)
+               ppc_md.progress("smp_core99_bringup_done", 0x349);
+}
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -882,10 +920,12 @@ static int smp_core99_cpu_disable(void)
 
 static void pmac_cpu_die(void)
 {
+       int cpu = smp_processor_id();
+
        local_irq_disable();
        idle_task_exit();
-       printk(KERN_DEBUG "CPU%d offline\n", smp_processor_id());
-       __get_cpu_var(cpu_state) = CPU_DEAD;
+       pr_debug("CPU%d offline\n", cpu);
+       generic_set_cpu_dead(cpu);
        smp_wmb();
        mb();
        low_cpu_die();
@@ -895,6 +935,8 @@ static void pmac_cpu_die(void)
 
 static void pmac_cpu_die(void)
 {
+       int cpu = smp_processor_id();
+
        local_irq_disable();
        idle_task_exit();
 
@@ -904,17 +946,10 @@ static void pmac_cpu_die(void)
         * on core99 platforms for now ...
         */
 
-       printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
-       __get_cpu_var(cpu_state) = CPU_DEAD;
+       printk(KERN_INFO "CPU#%d offline\n", cpu);
+       generic_set_cpu_dead(cpu);
        smp_wmb();
 
-       /*
-        * during the path that leads here preemption is disabled,
-        * reenable it now so that when coming up preempt count is
-        * zero correctly
-        */
-       preempt_enable();
-
        /*
         * Re-enable interrupts. The NAP code needs to enable them
         * anyways, do it now so we deal with the case where one already
@@ -940,6 +975,7 @@ static void pmac_cpu_die(void)
 struct smp_ops_t core99_smp_ops = {
        .message_pass   = smp_mpic_message_pass,
        .probe          = smp_core99_probe,
+       .bringup_done   = smp_core99_bringup_done,
        .kick_cpu       = smp_core99_kick_cpu,
        .setup_cpu      = smp_core99_setup_cpu,
        .give_timebase  = smp_core99_give_timebase,