aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-03-07 21:54:50 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-04-01 00:37:31 -0400
commit734796f12351f9a0f38c47b981414f82d852f222 (patch)
tree6a159233b7ab08b420a59e518ce2b99bb2002b07 /arch/powerpc/platforms/powermac
parentd72944457bb7d5c4be43aa1b741cb93c69484c20 (diff)
powerpc/pmac/smp: Fix CPU hotplug crashes on some machines
On some machines that use i2c to synchronize the timebases (such as PowerMac7,2/7,3 G5 machines), hotplug CPU would crash when putting back a new CPU online due to the underlying i2c bus being closed. This uses the newly added bringup_done() callback to move the close along with other housekeeping calls, and adds a CPU notifier to re-open the i2c bus around subsequent hotplug operations Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac')
-rw-r--r--arch/powerpc/platforms/powermac/smp.c71
1 files changed, 55 insertions, 16 deletions
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 837989e72ca..74a43c65204 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -840,30 +840,68 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
840 840
841 /* Setup openpic */ 841 /* Setup openpic */
842 mpic_setup_this_cpu(); 842 mpic_setup_this_cpu();
843}
843 844
844 if (cpu_nr == 0) { 845#ifdef CONFIG_HOTPLUG_CPU
845#ifdef CONFIG_PPC64 846static int smp_core99_cpu_notify(struct notifier_block *self,
846 extern void g5_phy_disable_cpu1(void); 847 unsigned long action, void *hcpu)
848{
849 int rc;
847 850
848 /* Close i2c bus if it was used for tb sync */ 851 switch(action) {
852 case CPU_UP_PREPARE:
853 case CPU_UP_PREPARE_FROZEN:
854 /* Open i2c bus if it was used for tb sync */
849 if (pmac_tb_clock_chip_host) { 855 if (pmac_tb_clock_chip_host) {
850 pmac_i2c_close(pmac_tb_clock_chip_host); 856 rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1);
851 pmac_tb_clock_chip_host = NULL; 857 if (rc) {
858 pr_err("Failed to open i2c bus for time sync\n");
859 return notifier_from_errno(rc);
860 }
852 } 861 }
862 break;
863 case CPU_ONLINE:
864 case CPU_UP_CANCELED:
865 /* Close i2c bus if it was used for tb sync */
866 if (pmac_tb_clock_chip_host)
867 pmac_i2c_close(pmac_tb_clock_chip_host);
868 break;
869 default:
870 break;
871 }
872 return NOTIFY_OK;
873}
853 874
854 /* If we didn't start the second CPU, we must take 875static struct notifier_block __cpuinitdata smp_core99_cpu_nb = {
855 * it off the bus 876 .notifier_call = smp_core99_cpu_notify,
856 */ 877};
857 if (of_machine_is_compatible("MacRISC4") && 878#endif /* CONFIG_HOTPLUG_CPU */
858 num_online_cpus() < 2)
859 g5_phy_disable_cpu1();
860#endif /* CONFIG_PPC64 */
861 879
862 if (ppc_md.progress) 880static void __init smp_core99_bringup_done(void)
863 ppc_md.progress("core99_setup_cpu 0 done", 0x349); 881{
882#ifdef CONFIG_PPC64
883 extern void g5_phy_disable_cpu1(void);
884
885 /* Close i2c bus if it was used for tb sync */
886 if (pmac_tb_clock_chip_host)
887 pmac_i2c_close(pmac_tb_clock_chip_host);
888
889 /* If we didn't start the second CPU, we must take
890 * it off the bus.
891 */
892 if (of_machine_is_compatible("MacRISC4") &&
893 num_online_cpus() < 2) {
894 set_cpu_present(1, false);
895 g5_phy_disable_cpu1();
864 } 896 }
865} 897#endif /* CONFIG_PPC64 */
866 898
899#ifdef CONFIG_HOTPLUG_CPU
900 register_cpu_notifier(&smp_core99_cpu_nb);
901#endif
902 if (ppc_md.progress)
903 ppc_md.progress("smp_core99_bringup_done", 0x349);
904}
867 905
868#ifdef CONFIG_HOTPLUG_CPU 906#ifdef CONFIG_HOTPLUG_CPU
869 907
@@ -940,6 +978,7 @@ static void pmac_cpu_die(void)
940struct smp_ops_t core99_smp_ops = { 978struct smp_ops_t core99_smp_ops = {
941 .message_pass = smp_mpic_message_pass, 979 .message_pass = smp_mpic_message_pass,
942 .probe = smp_core99_probe, 980 .probe = smp_core99_probe,
981 .bringup_done = smp_core99_bringup_done,
943 .kick_cpu = smp_core99_kick_cpu, 982 .kick_cpu = smp_core99_kick_cpu,
944 .setup_cpu = smp_core99_setup_cpu, 983 .setup_cpu = smp_core99_setup_cpu,
945 .give_timebase = smp_core99_give_timebase, 984 .give_timebase = smp_core99_give_timebase,