aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/sigp.h100
-rw-r--r--arch/s390/kernel/ipl.c2
-rw-r--r--arch/s390/kernel/smp.c54
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. */
21extern int __cpu_logical_map[]; 16extern unsigned short __cpu_logical_map[];
22 17
23static inline int cpu_logical_map(int cpu) 18static 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
32typedef enum 27enum {
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
52typedef __u32 sigp_status_word;
53 45
54typedef enum 46enum {
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 56enum {
67/* 'Bit' signals, asynchronous */ 57 ec_schedule = 0,
68typedef 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 */
79static inline sigp_ccode 66static inline int raw_sigp(u16 cpu, int order)
80signal_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 */
98static inline sigp_ccode 84static inline int raw_sigp_p(u32 parameter, u16 cpu, int order)
99signal_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 */
117static inline sigp_ccode 102static inline int raw_sigp_ps(u32 *status, u32 parm, u16 cpu, int order)
118signal_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__ */ 118static inline int sigp(int cpu, int order)
119{
120 return raw_sigp(cpu_logical_map(cpu), order);
121}
122
123static inline int sigp_p(u32 parameter, int cpu, int order)
124{
125 return raw_sigp_p(parameter, cpu_logical_map(cpu), order);
126}
127
128static 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 */
56int __cpu_logical_map[NR_CPUS]; 56unsigned short __cpu_logical_map[NR_CPUS];
57 57
58static struct task_struct *current_set[NR_CPUS]; 58static struct task_struct *current_set[NR_CPUS];
59 59
@@ -72,13 +72,13 @@ static int cpu_management;
72 72
73static DEFINE_PER_CPU(struct cpu, cpu_devices); 73static DEFINE_PER_CPU(struct cpu, cpu_devices);
74 74
75static void smp_ext_bitcall(int, ec_bit_sig); 75static void smp_ext_bitcall(int, int);
76 76
77static int cpu_stopped(int cpu) 77static 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
93static inline int cpu_stopped(int cpu)
94{
95 return raw_cpu_stopped(cpu_logical_map(cpu));
96}
97
93void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) 98void 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 */
175static void smp_ext_bitcall(int cpu, ec_bit_sig sig) 180static 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}
273EXPORT_SYMBOL(smp_ctl_clear_bit); 278EXPORT_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
284static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) 282static 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 */
554int __cpuinit __cpu_up(unsigned int cpu) 548int __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)
669void cpu_die(void) 663void 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}