diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2010-02-26 16:37:35 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-02-26 16:37:30 -0500 |
commit | a93b8ec1df1f0ad75d036dbc0fdef2e0ccb7be02 (patch) | |
tree | a68ab05bfd48eb637e50e2294005d6e079098a7e | |
parent | 2c2df118a6440748e6fd71a510a66ee708c31494 (diff) |
[S390] smp: rework sigp code
Rename signal_processor* functions to sigp*.
Add raw variants of each version, so we can get rid of the hacks played
in smp code which establish temporary cpu logical mappings so they could
call the sigp functions.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/include/asm/sigp.h | 100 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 54 |
3 files changed, 74 insertions, 82 deletions
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h index f72d611f7e13..8aa46ce4229c 100644 --- a/arch/s390/include/asm/sigp.h +++ b/arch/s390/include/asm/sigp.h | |||
@@ -1,24 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * include/asm-s390/sigp.h | 2 | * Routines and structures for signalling other processors. |
3 | * | 3 | * |
4 | * S390 version | 4 | * Copyright IBM Corp. 1999,2010 |
5 | * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Author(s): Denis Joseph Barrow, |
6 | * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com>, |
7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 7 | * Heiko Carstens <heiko.carstens@de.ibm.com>, |
8 | * Heiko Carstens (heiko.carstens@de.ibm.com) | ||
9 | * | ||
10 | * sigp.h by D.J. Barrow (c) IBM 1999 | ||
11 | * contains routines / structures for signalling other S/390 processors in an | ||
12 | * SMP configuration. | ||
13 | */ | 8 | */ |
14 | 9 | ||
15 | #ifndef __SIGP__ | 10 | #ifndef __ASM_SIGP_H |
16 | #define __SIGP__ | 11 | #define __ASM_SIGP_H |
17 | 12 | ||
18 | #include <asm/system.h> | 13 | #include <asm/system.h> |
19 | 14 | ||
20 | /* get real cpu address from logical cpu number */ | 15 | /* Get real cpu address from logical cpu number. */ |
21 | extern int __cpu_logical_map[]; | 16 | extern unsigned short __cpu_logical_map[]; |
22 | 17 | ||
23 | static inline int cpu_logical_map(int cpu) | 18 | static inline int cpu_logical_map(int cpu) |
24 | { | 19 | { |
@@ -29,8 +24,7 @@ static inline int cpu_logical_map(int cpu) | |||
29 | #endif | 24 | #endif |
30 | } | 25 | } |
31 | 26 | ||
32 | typedef enum | 27 | enum { |
33 | { | ||
34 | sigp_unassigned=0x0, | 28 | sigp_unassigned=0x0, |
35 | sigp_sense, | 29 | sigp_sense, |
36 | sigp_external_call, | 30 | sigp_external_call, |
@@ -47,89 +41,93 @@ typedef enum | |||
47 | sigp_set_prefix, | 41 | sigp_set_prefix, |
48 | sigp_store_status_at_address, | 42 | sigp_store_status_at_address, |
49 | sigp_store_extended_status_at_address | 43 | sigp_store_extended_status_at_address |
50 | } sigp_order_code; | 44 | }; |
51 | |||
52 | typedef __u32 sigp_status_word; | ||
53 | 45 | ||
54 | typedef enum | 46 | enum { |
55 | { | ||
56 | sigp_order_code_accepted=0, | 47 | sigp_order_code_accepted=0, |
57 | sigp_status_stored, | 48 | sigp_status_stored, |
58 | sigp_busy, | 49 | sigp_busy, |
59 | sigp_not_operational | 50 | sigp_not_operational |
60 | } sigp_ccode; | 51 | }; |
61 | |||
62 | 52 | ||
63 | /* | 53 | /* |
64 | * Definitions for the external call | 54 | * Definitions for external call. |
65 | */ | 55 | */ |
66 | 56 | enum { | |
67 | /* 'Bit' signals, asynchronous */ | 57 | ec_schedule = 0, |
68 | typedef enum | ||
69 | { | ||
70 | ec_schedule=0, | ||
71 | ec_call_function, | 58 | ec_call_function, |
72 | ec_call_function_single, | 59 | ec_call_function_single, |
73 | ec_bit_last | 60 | ec_bit_last |
74 | } ec_bit_sig; | 61 | }; |
75 | 62 | ||
76 | /* | 63 | /* |
77 | * Signal processor | 64 | * Signal processor. |
78 | */ | 65 | */ |
79 | static inline sigp_ccode | 66 | static inline int raw_sigp(u16 cpu, int order) |
80 | signal_processor(__u16 cpu_addr, sigp_order_code order_code) | ||
81 | { | 67 | { |
82 | register unsigned long reg1 asm ("1") = 0; | 68 | register unsigned long reg1 asm ("1") = 0; |
83 | sigp_ccode ccode; | 69 | int ccode; |
84 | 70 | ||
85 | asm volatile( | 71 | asm volatile( |
86 | " sigp %1,%2,0(%3)\n" | 72 | " sigp %1,%2,0(%3)\n" |
87 | " ipm %0\n" | 73 | " ipm %0\n" |
88 | " srl %0,28\n" | 74 | " srl %0,28\n" |
89 | : "=d" (ccode) | 75 | : "=d" (ccode) |
90 | : "d" (reg1), "d" (cpu_logical_map(cpu_addr)), | 76 | : "d" (reg1), "d" (cpu), |
91 | "a" (order_code) : "cc" , "memory"); | 77 | "a" (order) : "cc" , "memory"); |
92 | return ccode; | 78 | return ccode; |
93 | } | 79 | } |
94 | 80 | ||
95 | /* | 81 | /* |
96 | * Signal processor with parameter | 82 | * Signal processor with parameter. |
97 | */ | 83 | */ |
98 | static inline sigp_ccode | 84 | static inline int raw_sigp_p(u32 parameter, u16 cpu, int order) |
99 | signal_processor_p(__u32 parameter, __u16 cpu_addr, sigp_order_code order_code) | ||
100 | { | 85 | { |
101 | register unsigned int reg1 asm ("1") = parameter; | 86 | register unsigned int reg1 asm ("1") = parameter; |
102 | sigp_ccode ccode; | 87 | int ccode; |
103 | 88 | ||
104 | asm volatile( | 89 | asm volatile( |
105 | " sigp %1,%2,0(%3)\n" | 90 | " sigp %1,%2,0(%3)\n" |
106 | " ipm %0\n" | 91 | " ipm %0\n" |
107 | " srl %0,28\n" | 92 | " srl %0,28\n" |
108 | : "=d" (ccode) | 93 | : "=d" (ccode) |
109 | : "d" (reg1), "d" (cpu_logical_map(cpu_addr)), | 94 | : "d" (reg1), "d" (cpu), |
110 | "a" (order_code) : "cc" , "memory"); | 95 | "a" (order) : "cc" , "memory"); |
111 | return ccode; | 96 | return ccode; |
112 | } | 97 | } |
113 | 98 | ||
114 | /* | 99 | /* |
115 | * Signal processor with parameter and return status | 100 | * Signal processor with parameter and return status. |
116 | */ | 101 | */ |
117 | static inline sigp_ccode | 102 | static inline int raw_sigp_ps(u32 *status, u32 parm, u16 cpu, int order) |
118 | signal_processor_ps(__u32 *statusptr, __u32 parameter, __u16 cpu_addr, | ||
119 | sigp_order_code order_code) | ||
120 | { | 103 | { |
121 | register unsigned int reg1 asm ("1") = parameter; | 104 | register unsigned int reg1 asm ("1") = parm; |
122 | sigp_ccode ccode; | 105 | int ccode; |
123 | 106 | ||
124 | asm volatile( | 107 | asm volatile( |
125 | " sigp %1,%2,0(%3)\n" | 108 | " sigp %1,%2,0(%3)\n" |
126 | " ipm %0\n" | 109 | " ipm %0\n" |
127 | " srl %0,28\n" | 110 | " srl %0,28\n" |
128 | : "=d" (ccode), "+d" (reg1) | 111 | : "=d" (ccode), "+d" (reg1) |
129 | : "d" (cpu_logical_map(cpu_addr)), "a" (order_code) | 112 | : "d" (cpu), "a" (order) |
130 | : "cc" , "memory"); | 113 | : "cc" , "memory"); |
131 | *statusptr = reg1; | 114 | *status = reg1; |
132 | return ccode; | 115 | return ccode; |
133 | } | 116 | } |
134 | 117 | ||
135 | #endif /* __SIGP__ */ | 118 | static inline int sigp(int cpu, int order) |
119 | { | ||
120 | return raw_sigp(cpu_logical_map(cpu), order); | ||
121 | } | ||
122 | |||
123 | static inline int sigp_p(u32 parameter, int cpu, int order) | ||
124 | { | ||
125 | return raw_sigp_p(parameter, cpu_logical_map(cpu), order); | ||
126 | } | ||
127 | |||
128 | static inline int sigp_ps(u32 *status, u32 parm, int cpu, int order) | ||
129 | { | ||
130 | return raw_sigp_ps(status, parm, cpu_logical_map(cpu), order); | ||
131 | } | ||
132 | |||
133 | #endif /* __ASM_SIGP_H */ | ||
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 0a7c39dee6b7..ae9c564e375d 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -1610,7 +1610,7 @@ static void stop_run(struct shutdown_trigger *trigger) | |||
1610 | { | 1610 | { |
1611 | if (strcmp(trigger->name, ON_PANIC_STR) == 0) | 1611 | if (strcmp(trigger->name, ON_PANIC_STR) == 0) |
1612 | disabled_wait((unsigned long) __builtin_return_address(0)); | 1612 | disabled_wait((unsigned long) __builtin_return_address(0)); |
1613 | while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy) | 1613 | while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) |
1614 | cpu_relax(); | 1614 | cpu_relax(); |
1615 | for (;;); | 1615 | for (;;); |
1616 | } | 1616 | } |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index b39f596d71bd..d8a0b115c7c1 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -53,7 +53,7 @@ | |||
53 | #include "entry.h" | 53 | #include "entry.h" |
54 | 54 | ||
55 | /* logical cpu to cpu address */ | 55 | /* logical cpu to cpu address */ |
56 | int __cpu_logical_map[NR_CPUS]; | 56 | unsigned short __cpu_logical_map[NR_CPUS]; |
57 | 57 | ||
58 | static struct task_struct *current_set[NR_CPUS]; | 58 | static struct task_struct *current_set[NR_CPUS]; |
59 | 59 | ||
@@ -72,13 +72,13 @@ static int cpu_management; | |||
72 | 72 | ||
73 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | 73 | static DEFINE_PER_CPU(struct cpu, cpu_devices); |
74 | 74 | ||
75 | static void smp_ext_bitcall(int, ec_bit_sig); | 75 | static void smp_ext_bitcall(int, int); |
76 | 76 | ||
77 | static int cpu_stopped(int cpu) | 77 | static int raw_cpu_stopped(int cpu) |
78 | { | 78 | { |
79 | __u32 status; | 79 | u32 status; |
80 | 80 | ||
81 | switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) { | 81 | switch (raw_sigp_ps(&status, 0, cpu, sigp_sense)) { |
82 | case sigp_status_stored: | 82 | case sigp_status_stored: |
83 | /* Check for stopped and check stop state */ | 83 | /* Check for stopped and check stop state */ |
84 | if (status & 0x50) | 84 | if (status & 0x50) |
@@ -90,6 +90,11 @@ static int cpu_stopped(int cpu) | |||
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | static inline int cpu_stopped(int cpu) | ||
94 | { | ||
95 | return raw_cpu_stopped(cpu_logical_map(cpu)); | ||
96 | } | ||
97 | |||
93 | void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) | 98 | void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) |
94 | { | 99 | { |
95 | struct _lowcore *lc, *current_lc; | 100 | struct _lowcore *lc, *current_lc; |
@@ -110,7 +115,7 @@ void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) | |||
110 | lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu; | 115 | lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu; |
111 | if (!cpu_online(0)) | 116 | if (!cpu_online(0)) |
112 | smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]); | 117 | smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]); |
113 | while (signal_processor(0, sigp_stop_and_store_status) == sigp_busy) | 118 | while (sigp(0, sigp_stop_and_store_status) == sigp_busy) |
114 | cpu_relax(); | 119 | cpu_relax(); |
115 | sp = lc->panic_stack; | 120 | sp = lc->panic_stack; |
116 | sp -= sizeof(struct pt_regs); | 121 | sp -= sizeof(struct pt_regs); |
@@ -136,7 +141,7 @@ void smp_send_stop(void) | |||
136 | if (cpu == smp_processor_id()) | 141 | if (cpu == smp_processor_id()) |
137 | continue; | 142 | continue; |
138 | do { | 143 | do { |
139 | rc = signal_processor(cpu, sigp_stop); | 144 | rc = sigp(cpu, sigp_stop); |
140 | } while (rc == sigp_busy); | 145 | } while (rc == sigp_busy); |
141 | 146 | ||
142 | while (!cpu_stopped(cpu)) | 147 | while (!cpu_stopped(cpu)) |
@@ -172,13 +177,13 @@ static void do_ext_call_interrupt(__u16 code) | |||
172 | * Send an external call sigp to another cpu and return without waiting | 177 | * Send an external call sigp to another cpu and return without waiting |
173 | * for its completion. | 178 | * for its completion. |
174 | */ | 179 | */ |
175 | static void smp_ext_bitcall(int cpu, ec_bit_sig sig) | 180 | static void smp_ext_bitcall(int cpu, int sig) |
176 | { | 181 | { |
177 | /* | 182 | /* |
178 | * Set signaling bit in lowcore of target cpu and kick it | 183 | * Set signaling bit in lowcore of target cpu and kick it |
179 | */ | 184 | */ |
180 | set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); | 185 | set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); |
181 | while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy) | 186 | while (sigp(cpu, sigp_emergency_signal) == sigp_busy) |
182 | udelay(10); | 187 | udelay(10); |
183 | } | 188 | } |
184 | 189 | ||
@@ -272,13 +277,6 @@ void smp_ctl_clear_bit(int cr, int bit) | |||
272 | } | 277 | } |
273 | EXPORT_SYMBOL(smp_ctl_clear_bit); | 278 | EXPORT_SYMBOL(smp_ctl_clear_bit); |
274 | 279 | ||
275 | /* | ||
276 | * In early ipl state a temp. logically cpu number is needed, so the sigp | ||
277 | * functions can be used to sense other cpus. Since NR_CPUS is >= 2 on | ||
278 | * CONFIG_SMP and the ipl cpu is logical cpu 0, it must be 1. | ||
279 | */ | ||
280 | #define CPU_INIT_NO 1 | ||
281 | |||
282 | #ifdef CONFIG_ZFCPDUMP | 280 | #ifdef CONFIG_ZFCPDUMP |
283 | 281 | ||
284 | static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) | 282 | static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) |
@@ -291,9 +289,7 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) | |||
291 | return; | 289 | return; |
292 | } | 290 | } |
293 | zfcpdump_save_areas[cpu] = kmalloc(sizeof(struct save_area), GFP_KERNEL); | 291 | zfcpdump_save_areas[cpu] = kmalloc(sizeof(struct save_area), GFP_KERNEL); |
294 | __cpu_logical_map[CPU_INIT_NO] = (__u16) phy_cpu; | 292 | while (raw_sigp(phy_cpu, sigp_stop_and_store_status) == sigp_busy) |
295 | while (signal_processor(CPU_INIT_NO, sigp_stop_and_store_status) == | ||
296 | sigp_busy) | ||
297 | cpu_relax(); | 293 | cpu_relax(); |
298 | memcpy(zfcpdump_save_areas[cpu], | 294 | memcpy(zfcpdump_save_areas[cpu], |
299 | (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE, | 295 | (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE, |
@@ -409,8 +405,7 @@ static void __init smp_detect_cpus(void) | |||
409 | for (cpu = 0; cpu <= MAX_CPU_ADDRESS; cpu++) { | 405 | for (cpu = 0; cpu <= MAX_CPU_ADDRESS; cpu++) { |
410 | if (cpu == boot_cpu_addr) | 406 | if (cpu == boot_cpu_addr) |
411 | continue; | 407 | continue; |
412 | __cpu_logical_map[CPU_INIT_NO] = cpu; | 408 | if (!raw_cpu_stopped(cpu)) |
413 | if (!cpu_stopped(CPU_INIT_NO)) | ||
414 | continue; | 409 | continue; |
415 | smp_get_save_area(c_cpus, cpu); | 410 | smp_get_save_area(c_cpus, cpu); |
416 | c_cpus++; | 411 | c_cpus++; |
@@ -433,8 +428,7 @@ static void __init smp_detect_cpus(void) | |||
433 | cpu_addr = info->cpu[cpu].address; | 428 | cpu_addr = info->cpu[cpu].address; |
434 | if (cpu_addr == boot_cpu_addr) | 429 | if (cpu_addr == boot_cpu_addr) |
435 | continue; | 430 | continue; |
436 | __cpu_logical_map[CPU_INIT_NO] = cpu_addr; | 431 | if (!raw_cpu_stopped(cpu_addr)) { |
437 | if (!cpu_stopped(CPU_INIT_NO)) { | ||
438 | s_cpus++; | 432 | s_cpus++; |
439 | continue; | 433 | continue; |
440 | } | 434 | } |
@@ -553,18 +547,18 @@ static void smp_free_lowcore(int cpu) | |||
553 | /* Upping and downing of CPUs */ | 547 | /* Upping and downing of CPUs */ |
554 | int __cpuinit __cpu_up(unsigned int cpu) | 548 | int __cpuinit __cpu_up(unsigned int cpu) |
555 | { | 549 | { |
556 | struct task_struct *idle; | ||
557 | struct _lowcore *cpu_lowcore; | 550 | struct _lowcore *cpu_lowcore; |
551 | struct task_struct *idle; | ||
558 | struct stack_frame *sf; | 552 | struct stack_frame *sf; |
559 | sigp_ccode ccode; | ||
560 | u32 lowcore; | 553 | u32 lowcore; |
554 | int ccode; | ||
561 | 555 | ||
562 | if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) | 556 | if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) |
563 | return -EIO; | 557 | return -EIO; |
564 | if (smp_alloc_lowcore(cpu)) | 558 | if (smp_alloc_lowcore(cpu)) |
565 | return -ENOMEM; | 559 | return -ENOMEM; |
566 | do { | 560 | do { |
567 | ccode = signal_processor(cpu, sigp_initial_cpu_reset); | 561 | ccode = sigp(cpu, sigp_initial_cpu_reset); |
568 | if (ccode == sigp_busy) | 562 | if (ccode == sigp_busy) |
569 | udelay(10); | 563 | udelay(10); |
570 | if (ccode == sigp_not_operational) | 564 | if (ccode == sigp_not_operational) |
@@ -572,7 +566,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
572 | } while (ccode == sigp_busy); | 566 | } while (ccode == sigp_busy); |
573 | 567 | ||
574 | lowcore = (u32)(unsigned long)lowcore_ptr[cpu]; | 568 | lowcore = (u32)(unsigned long)lowcore_ptr[cpu]; |
575 | while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) | 569 | while (sigp_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) |
576 | udelay(10); | 570 | udelay(10); |
577 | 571 | ||
578 | idle = current_set[cpu]; | 572 | idle = current_set[cpu]; |
@@ -598,7 +592,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
598 | cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; | 592 | cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; |
599 | eieio(); | 593 | eieio(); |
600 | 594 | ||
601 | while (signal_processor(cpu, sigp_restart) == sigp_busy) | 595 | while (sigp(cpu, sigp_restart) == sigp_busy) |
602 | udelay(10); | 596 | udelay(10); |
603 | 597 | ||
604 | while (!cpu_online(cpu)) | 598 | while (!cpu_online(cpu)) |
@@ -660,7 +654,7 @@ void __cpu_die(unsigned int cpu) | |||
660 | /* Wait until target cpu is down */ | 654 | /* Wait until target cpu is down */ |
661 | while (!cpu_stopped(cpu)) | 655 | while (!cpu_stopped(cpu)) |
662 | cpu_relax(); | 656 | cpu_relax(); |
663 | while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy) | 657 | while (sigp_p(0, cpu, sigp_set_prefix) == sigp_busy) |
664 | udelay(10); | 658 | udelay(10); |
665 | smp_free_lowcore(cpu); | 659 | smp_free_lowcore(cpu); |
666 | pr_info("Processor %d stopped\n", cpu); | 660 | pr_info("Processor %d stopped\n", cpu); |
@@ -669,7 +663,7 @@ void __cpu_die(unsigned int cpu) | |||
669 | void cpu_die(void) | 663 | void cpu_die(void) |
670 | { | 664 | { |
671 | idle_task_exit(); | 665 | idle_task_exit(); |
672 | while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy) | 666 | while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) |
673 | cpu_relax(); | 667 | cpu_relax(); |
674 | for (;;); | 668 | for (;;); |
675 | } | 669 | } |