diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/Kconfig | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/pmac.h | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/setup.c | 56 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/smp.c | 154 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/offline_states.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/smp.c | 17 |
7 files changed, 121 insertions, 113 deletions
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 20576829eca5..f7b07720aa30 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -46,7 +46,7 @@ config PPC_OF_BOOT_TRAMPOLINE | |||
46 | help | 46 | help |
47 | Support from booting from Open Firmware or yaboot using an | 47 | Support from booting from Open Firmware or yaboot using an |
48 | Open Firmware client interface. This enables the kernel to | 48 | Open Firmware client interface. This enables the kernel to |
49 | communicate with open firmware to retrieve system informations | 49 | communicate with open firmware to retrieve system information |
50 | such as the device tree. | 50 | such as the device tree. |
51 | 51 | ||
52 | In case of doubt, say Y | 52 | In case of doubt, say Y |
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index f0bc08f6c1f0..20468f49aec0 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h | |||
@@ -33,7 +33,6 @@ extern void pmac_setup_pci_dma(void); | |||
33 | extern void pmac_check_ht_link(void); | 33 | extern void pmac_check_ht_link(void); |
34 | 34 | ||
35 | extern void pmac_setup_smp(void); | 35 | extern void pmac_setup_smp(void); |
36 | extern void pmac32_cpu_die(void); | ||
37 | extern void low_cpu_die(void) __attribute__((noreturn)); | 36 | extern void low_cpu_die(void) __attribute__((noreturn)); |
38 | 37 | ||
39 | extern int pmac_nvram_init(void); | 38 | extern int pmac_nvram_init(void); |
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index d5aceb7fb125..aa45281bd296 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -650,51 +650,6 @@ static int pmac_pci_probe_mode(struct pci_bus *bus) | |||
650 | return PCI_PROBE_NORMAL; | 650 | return PCI_PROBE_NORMAL; |
651 | return PCI_PROBE_DEVTREE; | 651 | return PCI_PROBE_DEVTREE; |
652 | } | 652 | } |
653 | |||
654 | #ifdef CONFIG_HOTPLUG_CPU | ||
655 | /* access per cpu vars from generic smp.c */ | ||
656 | DECLARE_PER_CPU(int, cpu_state); | ||
657 | |||
658 | static void pmac64_cpu_die(void) | ||
659 | { | ||
660 | /* | ||
661 | * turn off as much as possible, we'll be | ||
662 | * kicked out as this will only be invoked | ||
663 | * on core99 platforms for now ... | ||
664 | */ | ||
665 | |||
666 | printk(KERN_INFO "CPU#%d offline\n", smp_processor_id()); | ||
667 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
668 | smp_wmb(); | ||
669 | |||
670 | /* | ||
671 | * during the path that leads here preemption is disabled, | ||
672 | * reenable it now so that when coming up preempt count is | ||
673 | * zero correctly | ||
674 | */ | ||
675 | preempt_enable(); | ||
676 | |||
677 | /* | ||
678 | * hard-disable interrupts for the non-NAP case, the NAP code | ||
679 | * needs to re-enable interrupts (but soft-disables them) | ||
680 | */ | ||
681 | hard_irq_disable(); | ||
682 | |||
683 | while (1) { | ||
684 | /* let's not take timer interrupts too often ... */ | ||
685 | set_dec(0x7fffffff); | ||
686 | |||
687 | /* should always be true at this point */ | ||
688 | if (cpu_has_feature(CPU_FTR_CAN_NAP)) | ||
689 | power4_cpu_offline_powersave(); | ||
690 | else { | ||
691 | HMT_low(); | ||
692 | HMT_very_low(); | ||
693 | } | ||
694 | } | ||
695 | } | ||
696 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
697 | |||
698 | #endif /* CONFIG_PPC64 */ | 653 | #endif /* CONFIG_PPC64 */ |
699 | 654 | ||
700 | define_machine(powermac) { | 655 | define_machine(powermac) { |
@@ -726,15 +681,4 @@ define_machine(powermac) { | |||
726 | .pcibios_after_init = pmac_pcibios_after_init, | 681 | .pcibios_after_init = pmac_pcibios_after_init, |
727 | .phys_mem_access_prot = pci_phys_mem_access_prot, | 682 | .phys_mem_access_prot = pci_phys_mem_access_prot, |
728 | #endif | 683 | #endif |
729 | #ifdef CONFIG_HOTPLUG_CPU | ||
730 | #ifdef CONFIG_PPC64 | ||
731 | .cpu_die = pmac64_cpu_die, | ||
732 | #endif | ||
733 | #ifdef CONFIG_PPC32 | ||
734 | .cpu_die = pmac32_cpu_die, | ||
735 | #endif | ||
736 | #endif | ||
737 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) | ||
738 | .cpu_die = generic_mach_cpu_die, | ||
739 | #endif | ||
740 | }; | 684 | }; |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index c95215f4f8b6..a830c5e80657 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -840,92 +840,149 @@ 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 | 846 | static 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 | 875 | static 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) | 879 | |
859 | g5_phy_disable_cpu1(); | 880 | static void __init smp_core99_bringup_done(void) |
860 | #endif /* CONFIG_PPC64 */ | 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); | ||
861 | 888 | ||
862 | if (ppc_md.progress) | 889 | /* If we didn't start the second CPU, we must take |
863 | ppc_md.progress("core99_setup_cpu 0 done", 0x349); | 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 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) | 906 | #ifdef CONFIG_HOTPLUG_CPU |
869 | 907 | ||
870 | int smp_core99_cpu_disable(void) | 908 | static int smp_core99_cpu_disable(void) |
871 | { | 909 | { |
872 | set_cpu_online(smp_processor_id(), false); | 910 | int rc = generic_cpu_disable(); |
911 | if (rc) | ||
912 | return rc; | ||
873 | 913 | ||
874 | /* XXX reset cpu affinity here */ | ||
875 | mpic_cpu_set_priority(0xf); | 914 | mpic_cpu_set_priority(0xf); |
876 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | 915 | |
877 | mb(); | ||
878 | udelay(20); | ||
879 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
880 | return 0; | 916 | return 0; |
881 | } | 917 | } |
882 | 918 | ||
883 | static int cpu_dead[NR_CPUS]; | 919 | #ifdef CONFIG_PPC32 |
884 | 920 | ||
885 | void pmac32_cpu_die(void) | 921 | static void pmac_cpu_die(void) |
886 | { | 922 | { |
923 | int cpu = smp_processor_id(); | ||
924 | |||
887 | local_irq_disable(); | 925 | local_irq_disable(); |
888 | cpu_dead[smp_processor_id()] = 1; | 926 | idle_task_exit(); |
927 | pr_debug("CPU%d offline\n", cpu); | ||
928 | generic_set_cpu_dead(cpu); | ||
929 | smp_wmb(); | ||
889 | mb(); | 930 | mb(); |
890 | low_cpu_die(); | 931 | low_cpu_die(); |
891 | } | 932 | } |
892 | 933 | ||
893 | void smp_core99_cpu_die(unsigned int cpu) | 934 | #else /* CONFIG_PPC32 */ |
935 | |||
936 | static void pmac_cpu_die(void) | ||
894 | { | 937 | { |
895 | int timeout; | 938 | int cpu = smp_processor_id(); |
896 | 939 | ||
897 | timeout = 1000; | 940 | local_irq_disable(); |
898 | while (!cpu_dead[cpu]) { | 941 | idle_task_exit(); |
899 | if (--timeout == 0) { | 942 | |
900 | printk("CPU %u refused to die!\n", cpu); | 943 | /* |
901 | break; | 944 | * turn off as much as possible, we'll be |
902 | } | 945 | * kicked out as this will only be invoked |
903 | msleep(1); | 946 | * on core99 platforms for now ... |
947 | */ | ||
948 | |||
949 | printk(KERN_INFO "CPU#%d offline\n", cpu); | ||
950 | generic_set_cpu_dead(cpu); | ||
951 | smp_wmb(); | ||
952 | |||
953 | /* | ||
954 | * Re-enable interrupts. The NAP code needs to enable them | ||
955 | * anyways, do it now so we deal with the case where one already | ||
956 | * happened while soft-disabled. | ||
957 | * We shouldn't get any external interrupts, only decrementer, and the | ||
958 | * decrementer handler is safe for use on offline CPUs | ||
959 | */ | ||
960 | local_irq_enable(); | ||
961 | |||
962 | while (1) { | ||
963 | /* let's not take timer interrupts too often ... */ | ||
964 | set_dec(0x7fffffff); | ||
965 | |||
966 | /* Enter NAP mode */ | ||
967 | power4_idle(); | ||
904 | } | 968 | } |
905 | cpu_dead[cpu] = 0; | ||
906 | } | 969 | } |
907 | 970 | ||
908 | #endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */ | 971 | #endif /* else CONFIG_PPC32 */ |
972 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
909 | 973 | ||
910 | /* Core99 Macs (dual G4s and G5s) */ | 974 | /* Core99 Macs (dual G4s and G5s) */ |
911 | struct smp_ops_t core99_smp_ops = { | 975 | struct smp_ops_t core99_smp_ops = { |
912 | .message_pass = smp_mpic_message_pass, | 976 | .message_pass = smp_mpic_message_pass, |
913 | .probe = smp_core99_probe, | 977 | .probe = smp_core99_probe, |
978 | .bringup_done = smp_core99_bringup_done, | ||
914 | .kick_cpu = smp_core99_kick_cpu, | 979 | .kick_cpu = smp_core99_kick_cpu, |
915 | .setup_cpu = smp_core99_setup_cpu, | 980 | .setup_cpu = smp_core99_setup_cpu, |
916 | .give_timebase = smp_core99_give_timebase, | 981 | .give_timebase = smp_core99_give_timebase, |
917 | .take_timebase = smp_core99_take_timebase, | 982 | .take_timebase = smp_core99_take_timebase, |
918 | #if defined(CONFIG_HOTPLUG_CPU) | 983 | #if defined(CONFIG_HOTPLUG_CPU) |
919 | # if defined(CONFIG_PPC32) | ||
920 | .cpu_disable = smp_core99_cpu_disable, | 984 | .cpu_disable = smp_core99_cpu_disable, |
921 | .cpu_die = smp_core99_cpu_die, | ||
922 | # endif | ||
923 | # if defined(CONFIG_PPC64) | ||
924 | .cpu_disable = generic_cpu_disable, | ||
925 | .cpu_die = generic_cpu_die, | 985 | .cpu_die = generic_cpu_die, |
926 | /* intentionally do *NOT* assign cpu_enable, | ||
927 | * the generic code will use kick_cpu then! */ | ||
928 | # endif | ||
929 | #endif | 986 | #endif |
930 | }; | 987 | }; |
931 | 988 | ||
@@ -957,5 +1014,10 @@ void __init pmac_setup_smp(void) | |||
957 | smp_ops = &psurge_smp_ops; | 1014 | smp_ops = &psurge_smp_ops; |
958 | } | 1015 | } |
959 | #endif /* CONFIG_PPC32 */ | 1016 | #endif /* CONFIG_PPC32 */ |
1017 | |||
1018 | #ifdef CONFIG_HOTPLUG_CPU | ||
1019 | ppc_md.cpu_die = pmac_cpu_die; | ||
1020 | #endif | ||
960 | } | 1021 | } |
961 | 1022 | ||
1023 | |||
diff --git a/arch/powerpc/platforms/pseries/offline_states.h b/arch/powerpc/platforms/pseries/offline_states.h index 75a6f480d931..08672d9136ab 100644 --- a/arch/powerpc/platforms/pseries/offline_states.h +++ b/arch/powerpc/platforms/pseries/offline_states.h | |||
@@ -34,6 +34,4 @@ static inline void set_default_offline_state(int cpu) | |||
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | extern enum cpu_state_vals get_preferred_offline_state(int cpu); | 36 | extern enum cpu_state_vals get_preferred_offline_state(int cpu); |
37 | extern int start_secondary(void); | ||
38 | extern void start_secondary_resume(void); | ||
39 | #endif | 37 | #endif |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index c319d04aa799..000724149089 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -378,7 +378,7 @@ static int __init pSeries_init_panel(void) | |||
378 | 378 | ||
379 | return 0; | 379 | return 0; |
380 | } | 380 | } |
381 | arch_initcall(pSeries_init_panel); | 381 | machine_arch_initcall(pseries, pSeries_init_panel); |
382 | 382 | ||
383 | static int pseries_set_dabr(unsigned long dabr) | 383 | static int pseries_set_dabr(unsigned long dabr) |
384 | { | 384 | { |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index d6479f9738f0..a509c5292a67 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -112,10 +112,10 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) | |||
112 | 112 | ||
113 | /* Fixup atomic count: it exited inside IRQ handler. */ | 113 | /* Fixup atomic count: it exited inside IRQ handler. */ |
114 | task_thread_info(paca[lcpu].__current)->preempt_count = 0; | 114 | task_thread_info(paca[lcpu].__current)->preempt_count = 0; |
115 | 115 | #ifdef CONFIG_HOTPLUG_CPU | |
116 | if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE) | 116 | if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE) |
117 | goto out; | 117 | goto out; |
118 | 118 | #endif | |
119 | /* | 119 | /* |
120 | * If the RTAS start-cpu token does not exist then presume the | 120 | * If the RTAS start-cpu token does not exist then presume the |
121 | * cpu is already spinning. | 121 | * cpu is already spinning. |
@@ -130,7 +130,9 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) | |||
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | #ifdef CONFIG_HOTPLUG_CPU | ||
133 | out: | 134 | out: |
135 | #endif | ||
134 | return 1; | 136 | return 1; |
135 | } | 137 | } |
136 | 138 | ||
@@ -144,16 +146,15 @@ static void __devinit smp_xics_setup_cpu(int cpu) | |||
144 | vpa_init(cpu); | 146 | vpa_init(cpu); |
145 | 147 | ||
146 | cpumask_clear_cpu(cpu, of_spin_mask); | 148 | cpumask_clear_cpu(cpu, of_spin_mask); |
149 | #ifdef CONFIG_HOTPLUG_CPU | ||
147 | set_cpu_current_state(cpu, CPU_STATE_ONLINE); | 150 | set_cpu_current_state(cpu, CPU_STATE_ONLINE); |
148 | set_default_offline_state(cpu); | 151 | set_default_offline_state(cpu); |
149 | 152 | #endif | |
150 | } | 153 | } |
151 | #endif /* CONFIG_XICS */ | 154 | #endif /* CONFIG_XICS */ |
152 | 155 | ||
153 | static void __devinit smp_pSeries_kick_cpu(int nr) | 156 | static void __devinit smp_pSeries_kick_cpu(int nr) |
154 | { | 157 | { |
155 | long rc; | ||
156 | unsigned long hcpuid; | ||
157 | BUG_ON(nr < 0 || nr >= NR_CPUS); | 158 | BUG_ON(nr < 0 || nr >= NR_CPUS); |
158 | 159 | ||
159 | if (!smp_startup_cpu(nr)) | 160 | if (!smp_startup_cpu(nr)) |
@@ -165,16 +166,20 @@ static void __devinit smp_pSeries_kick_cpu(int nr) | |||
165 | * the processor will continue on to secondary_start | 166 | * the processor will continue on to secondary_start |
166 | */ | 167 | */ |
167 | paca[nr].cpu_start = 1; | 168 | paca[nr].cpu_start = 1; |
168 | 169 | #ifdef CONFIG_HOTPLUG_CPU | |
169 | set_preferred_offline_state(nr, CPU_STATE_ONLINE); | 170 | set_preferred_offline_state(nr, CPU_STATE_ONLINE); |
170 | 171 | ||
171 | if (get_cpu_current_state(nr) == CPU_STATE_INACTIVE) { | 172 | if (get_cpu_current_state(nr) == CPU_STATE_INACTIVE) { |
173 | long rc; | ||
174 | unsigned long hcpuid; | ||
175 | |||
172 | hcpuid = get_hard_smp_processor_id(nr); | 176 | hcpuid = get_hard_smp_processor_id(nr); |
173 | rc = plpar_hcall_norets(H_PROD, hcpuid); | 177 | rc = plpar_hcall_norets(H_PROD, hcpuid); |
174 | if (rc != H_SUCCESS) | 178 | if (rc != H_SUCCESS) |
175 | printk(KERN_ERR "Error: Prod to wake up processor %d " | 179 | printk(KERN_ERR "Error: Prod to wake up processor %d " |
176 | "Ret= %ld\n", nr, rc); | 180 | "Ret= %ld\n", nr, rc); |
177 | } | 181 | } |
182 | #endif | ||
178 | } | 183 | } |
179 | 184 | ||
180 | static int smp_pSeries_cpu_bootable(unsigned int nr) | 185 | static int smp_pSeries_cpu_bootable(unsigned int nr) |