diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 16 |
1 files changed, 7 insertions, 9 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index e01408429ad6..dc602a61233f 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -273,26 +273,24 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), | |||
273 | void *data, unsigned long stack) | 273 | void *data, unsigned long stack) |
274 | { | 274 | { |
275 | struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; | 275 | struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; |
276 | struct { | 276 | unsigned long source_cpu = stap(); |
277 | unsigned long stack; | ||
278 | void *func; | ||
279 | void *data; | ||
280 | unsigned long source; | ||
281 | } restart = { stack, func, data, stap() }; | ||
282 | 277 | ||
283 | __load_psw_mask(psw_kernel_bits); | 278 | __load_psw_mask(psw_kernel_bits); |
284 | if (pcpu->address == restart.source) | 279 | if (pcpu->address == source_cpu) |
285 | func(data); /* should not return */ | 280 | func(data); /* should not return */ |
286 | /* Stop target cpu (if func returns this stops the current cpu). */ | 281 | /* Stop target cpu (if func returns this stops the current cpu). */ |
287 | pcpu_sigp_retry(pcpu, SIGP_STOP, 0); | 282 | pcpu_sigp_retry(pcpu, SIGP_STOP, 0); |
288 | /* Restart func on the target cpu and stop the current cpu. */ | 283 | /* Restart func on the target cpu and stop the current cpu. */ |
289 | memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart)); | 284 | mem_assign_absolute(lc->restart_stack, stack); |
285 | mem_assign_absolute(lc->restart_fn, (unsigned long) func); | ||
286 | mem_assign_absolute(lc->restart_data, (unsigned long) data); | ||
287 | mem_assign_absolute(lc->restart_source, source_cpu); | ||
290 | asm volatile( | 288 | asm volatile( |
291 | "0: sigp 0,%0,%2 # sigp restart to target cpu\n" | 289 | "0: sigp 0,%0,%2 # sigp restart to target cpu\n" |
292 | " brc 2,0b # busy, try again\n" | 290 | " brc 2,0b # busy, try again\n" |
293 | "1: sigp 0,%1,%3 # sigp stop to current cpu\n" | 291 | "1: sigp 0,%1,%3 # sigp stop to current cpu\n" |
294 | " brc 2,1b # busy, try again\n" | 292 | " brc 2,1b # busy, try again\n" |
295 | : : "d" (pcpu->address), "d" (restart.source), | 293 | : : "d" (pcpu->address), "d" (source_cpu), |
296 | "K" (SIGP_RESTART), "K" (SIGP_STOP) | 294 | "K" (SIGP_RESTART), "K" (SIGP_STOP) |
297 | : "0", "1", "cc"); | 295 | : "0", "1", "cc"); |
298 | for (;;) ; | 296 | for (;;) ; |