diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 45 |
1 files changed, 10 insertions, 35 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 647ba9425893..15cca26ccb6c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -297,26 +297,27 @@ static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data) | |||
297 | static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), | 297 | static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), |
298 | void *data, unsigned long stack) | 298 | void *data, unsigned long stack) |
299 | { | 299 | { |
300 | struct _lowcore *lc = pcpu->lowcore; | 300 | struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; |
301 | unsigned short this_cpu; | 301 | struct { |
302 | unsigned long stack; | ||
303 | void *func; | ||
304 | void *data; | ||
305 | unsigned long source; | ||
306 | } restart = { stack, func, data, stap() }; | ||
302 | 307 | ||
303 | __load_psw_mask(psw_kernel_bits); | 308 | __load_psw_mask(psw_kernel_bits); |
304 | this_cpu = stap(); | 309 | if (pcpu->address == restart.source) |
305 | if (pcpu->address == this_cpu) | ||
306 | func(data); /* should not return */ | 310 | func(data); /* should not return */ |
307 | /* Stop target cpu (if func returns this stops the current cpu). */ | 311 | /* Stop target cpu (if func returns this stops the current cpu). */ |
308 | pcpu_sigp_retry(pcpu, sigp_stop, 0); | 312 | pcpu_sigp_retry(pcpu, sigp_stop, 0); |
309 | /* Restart func on the target cpu and stop the current cpu. */ | 313 | /* Restart func on the target cpu and stop the current cpu. */ |
310 | lc->restart_stack = stack; | 314 | memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart)); |
311 | lc->restart_fn = (unsigned long) func; | ||
312 | lc->restart_data = (unsigned long) data; | ||
313 | lc->restart_source = (unsigned long) this_cpu; | ||
314 | asm volatile( | 315 | asm volatile( |
315 | "0: sigp 0,%0,6 # sigp restart to target cpu\n" | 316 | "0: sigp 0,%0,6 # sigp restart to target cpu\n" |
316 | " brc 2,0b # busy, try again\n" | 317 | " brc 2,0b # busy, try again\n" |
317 | "1: sigp 0,%1,5 # sigp stop to current cpu\n" | 318 | "1: sigp 0,%1,5 # sigp stop to current cpu\n" |
318 | " brc 2,1b # busy, try again\n" | 319 | " brc 2,1b # busy, try again\n" |
319 | : : "d" (pcpu->address), "d" (this_cpu) : "0", "1", "cc"); | 320 | : : "d" (pcpu->address), "d" (restart.source) : "0", "1", "cc"); |
320 | for (;;) ; | 321 | for (;;) ; |
321 | } | 322 | } |
322 | 323 | ||
@@ -800,17 +801,6 @@ void __noreturn cpu_die(void) | |||
800 | 801 | ||
801 | #endif /* CONFIG_HOTPLUG_CPU */ | 802 | #endif /* CONFIG_HOTPLUG_CPU */ |
802 | 803 | ||
803 | static void smp_call_os_info_init_fn(void) | ||
804 | { | ||
805 | int (*init_fn)(void); | ||
806 | unsigned long size; | ||
807 | |||
808 | init_fn = os_info_old_entry(OS_INFO_INIT_FN, &size); | ||
809 | if (!init_fn) | ||
810 | return; | ||
811 | init_fn(); | ||
812 | } | ||
813 | |||
814 | void __init smp_prepare_cpus(unsigned int max_cpus) | 804 | void __init smp_prepare_cpus(unsigned int max_cpus) |
815 | { | 805 | { |
816 | /* request the 0x1201 emergency signal external interrupt */ | 806 | /* request the 0x1201 emergency signal external interrupt */ |
@@ -819,7 +809,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
819 | /* request the 0x1202 external call external interrupt */ | 809 | /* request the 0x1202 external call external interrupt */ |
820 | if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0) | 810 | if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0) |
821 | panic("Couldn't request external interrupt 0x1202"); | 811 | panic("Couldn't request external interrupt 0x1202"); |
822 | smp_call_os_info_init_fn(); | ||
823 | smp_detect_cpus(); | 812 | smp_detect_cpus(); |
824 | } | 813 | } |
825 | 814 | ||
@@ -943,19 +932,6 @@ static struct attribute_group cpu_common_attr_group = { | |||
943 | .attrs = cpu_common_attrs, | 932 | .attrs = cpu_common_attrs, |
944 | }; | 933 | }; |
945 | 934 | ||
946 | static ssize_t show_capability(struct device *dev, | ||
947 | struct device_attribute *attr, char *buf) | ||
948 | { | ||
949 | unsigned int capability; | ||
950 | int rc; | ||
951 | |||
952 | rc = get_cpu_capability(&capability); | ||
953 | if (rc) | ||
954 | return rc; | ||
955 | return sprintf(buf, "%u\n", capability); | ||
956 | } | ||
957 | static DEVICE_ATTR(capability, 0444, show_capability, NULL); | ||
958 | |||
959 | static ssize_t show_idle_count(struct device *dev, | 935 | static ssize_t show_idle_count(struct device *dev, |
960 | struct device_attribute *attr, char *buf) | 936 | struct device_attribute *attr, char *buf) |
961 | { | 937 | { |
@@ -993,7 +969,6 @@ static ssize_t show_idle_time(struct device *dev, | |||
993 | static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); | 969 | static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); |
994 | 970 | ||
995 | static struct attribute *cpu_online_attrs[] = { | 971 | static struct attribute *cpu_online_attrs[] = { |
996 | &dev_attr_capability.attr, | ||
997 | &dev_attr_idle_count.attr, | 972 | &dev_attr_idle_count.attr, |
998 | &dev_attr_idle_time_us.attr, | 973 | &dev_attr_idle_time_us.attr, |
999 | NULL, | 974 | NULL, |