aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2006-12-04 09:40:30 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-12-04 09:40:30 -0500
commit740b5706b9c4b3767f597b3ea76654c6f2a800b2 (patch)
tree370dc09ec8f3abaecc742003ed9d28eecf636c3b
parenta1a392f0b4f27604811bf8aa8d7636b3b4bc3803 (diff)
[S390] cpcmd <-> __cpcmd calling issues
In case of reipl cpcmd gets called when all other cpus are not running anymore. To prevent deadlocks change __cpcmd so that it doesn't take any locks and call cpcmd or __cpcmd, whatever is correct in the current context. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/kernel/cpcmd.c18
-rw-r--r--arch/s390/kernel/ipl.c10
-rw-r--r--arch/s390/kernel/setup.c10
-rw-r--r--include/asm-s390/cpcmd.h10
4 files changed, 24 insertions, 24 deletions
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 1eae74e72f95..a5972f1541fe 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -21,14 +21,15 @@ static DEFINE_SPINLOCK(cpcmd_lock);
21static char cpcmd_buf[241]; 21static char cpcmd_buf[241];
22 22
23/* 23/*
24 * the caller of __cpcmd has to ensure that the response buffer is below 2 GB 24 * __cpcmd has some restrictions over cpcmd
25 * - the response buffer must reside below 2GB (if any)
26 * - __cpcmd is unlocked and therefore not SMP-safe
25 */ 27 */
26int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) 28int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
27{ 29{
28 unsigned long flags, cmdlen; 30 unsigned cmdlen;
29 int return_code, return_len; 31 int return_code, return_len;
30 32
31 spin_lock_irqsave(&cpcmd_lock, flags);
32 cmdlen = strlen(cmd); 33 cmdlen = strlen(cmd);
33 BUG_ON(cmdlen > 240); 34 BUG_ON(cmdlen > 240);
34 memcpy(cpcmd_buf, cmd, cmdlen); 35 memcpy(cpcmd_buf, cmd, cmdlen);
@@ -74,7 +75,6 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
74 : "+d" (reg3) : "d" (reg2) : "cc"); 75 : "+d" (reg3) : "d" (reg2) : "cc");
75 return_code = (int) reg3; 76 return_code = (int) reg3;
76 } 77 }
77 spin_unlock_irqrestore(&cpcmd_lock, flags);
78 if (response_code != NULL) 78 if (response_code != NULL)
79 *response_code = return_code; 79 *response_code = return_code;
80 return return_len; 80 return return_len;
@@ -82,15 +82,18 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
82 82
83EXPORT_SYMBOL(__cpcmd); 83EXPORT_SYMBOL(__cpcmd);
84 84
85#ifdef CONFIG_64BIT
86int cpcmd(const char *cmd, char *response, int rlen, int *response_code) 85int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
87{ 86{
88 char *lowbuf; 87 char *lowbuf;
89 int len; 88 int len;
89 unsigned long flags;
90 90
91 if ((rlen == 0) || (response == NULL) 91 if ((rlen == 0) || (response == NULL)
92 || !((unsigned long)response >> 31)) 92 || !((unsigned long)response >> 31)) {
93 spin_lock_irqsave(&cpcmd_lock, flags);
93 len = __cpcmd(cmd, response, rlen, response_code); 94 len = __cpcmd(cmd, response, rlen, response_code);
95 spin_unlock_irqrestore(&cpcmd_lock, flags);
96 }
94 else { 97 else {
95 lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); 98 lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
96 if (!lowbuf) { 99 if (!lowbuf) {
@@ -98,7 +101,9 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
98 "cpcmd: could not allocate response buffer\n"); 101 "cpcmd: could not allocate response buffer\n");
99 return -ENOMEM; 102 return -ENOMEM;
100 } 103 }
104 spin_lock_irqsave(&cpcmd_lock, flags);
101 len = __cpcmd(cmd, lowbuf, rlen, response_code); 105 len = __cpcmd(cmd, lowbuf, rlen, response_code);
106 spin_unlock_irqrestore(&cpcmd_lock, flags);
102 memcpy(response, lowbuf, rlen); 107 memcpy(response, lowbuf, rlen);
103 kfree(lowbuf); 108 kfree(lowbuf);
104 } 109 }
@@ -106,4 +111,3 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
106} 111}
107 112
108EXPORT_SYMBOL(cpcmd); 113EXPORT_SYMBOL(cpcmd);
109#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 77f4aff630fe..101b003cfabf 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -677,7 +677,7 @@ void do_reipl(void)
677 else 677 else
678 sprintf(buf, "IPL %X LOADPARM '%s'", 678 sprintf(buf, "IPL %X LOADPARM '%s'",
679 reipl_block_ccw->ipl_info.ccw.devno, loadparm); 679 reipl_block_ccw->ipl_info.ccw.devno, loadparm);
680 cpcmd(buf, NULL, 0, NULL); 680 __cpcmd(buf, NULL, 0, NULL);
681 break; 681 break;
682 case IPL_METHOD_CCW_DIAG: 682 case IPL_METHOD_CCW_DIAG:
683 diag308(DIAG308_SET, reipl_block_ccw); 683 diag308(DIAG308_SET, reipl_block_ccw);
@@ -691,12 +691,12 @@ void do_reipl(void)
691 diag308(DIAG308_IPL, NULL); 691 diag308(DIAG308_IPL, NULL);
692 break; 692 break;
693 case IPL_METHOD_FCP_RO_VM: 693 case IPL_METHOD_FCP_RO_VM:
694 cpcmd("IPL", NULL, 0, NULL); 694 __cpcmd("IPL", NULL, 0, NULL);
695 break; 695 break;
696 case IPL_METHOD_NONE: 696 case IPL_METHOD_NONE:
697 default: 697 default:
698 if (MACHINE_IS_VM) 698 if (MACHINE_IS_VM)
699 cpcmd("IPL", NULL, 0, NULL); 699 __cpcmd("IPL", NULL, 0, NULL);
700 diag308(DIAG308_IPL, NULL); 700 diag308(DIAG308_IPL, NULL);
701 break; 701 break;
702 } 702 }
@@ -732,9 +732,9 @@ static void do_dump(void)
732 case IPL_METHOD_CCW_VM: 732 case IPL_METHOD_CCW_VM:
733 dump_smp_stop_all(); 733 dump_smp_stop_all();
734 sprintf(buf, "STORE STATUS"); 734 sprintf(buf, "STORE STATUS");
735 cpcmd(buf, NULL, 0, NULL); 735 __cpcmd(buf, NULL, 0, NULL);
736 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); 736 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
737 cpcmd(buf, NULL, 0, NULL); 737 __cpcmd(buf, NULL, 0, NULL);
738 break; 738 break;
739 case IPL_METHOD_CCW_DIAG: 739 case IPL_METHOD_CCW_DIAG:
740 diag308(DIAG308_SET, dump_block_ccw); 740 diag308(DIAG308_SET, dump_block_ccw);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 2aa13e8e000a..9bbef0c65584 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -229,11 +229,11 @@ static void __init conmode_default(void)
229 char *ptr; 229 char *ptr;
230 230
231 if (MACHINE_IS_VM) { 231 if (MACHINE_IS_VM) {
232 __cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL); 232 cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
233 console_devno = simple_strtoul(query_buffer + 5, NULL, 16); 233 console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
234 ptr = strstr(query_buffer, "SUBCHANNEL ="); 234 ptr = strstr(query_buffer, "SUBCHANNEL =");
235 console_irq = simple_strtoul(ptr + 13, NULL, 16); 235 console_irq = simple_strtoul(ptr + 13, NULL, 16);
236 __cpcmd("QUERY TERM", query_buffer, 1024, NULL); 236 cpcmd("QUERY TERM", query_buffer, 1024, NULL);
237 ptr = strstr(query_buffer, "CONMODE"); 237 ptr = strstr(query_buffer, "CONMODE");
238 /* 238 /*
239 * Set the conmode to 3215 so that the device recognition 239 * Set the conmode to 3215 so that the device recognition
@@ -242,7 +242,7 @@ static void __init conmode_default(void)
242 * 3215 and the 3270 driver will try to access the console 242 * 3215 and the 3270 driver will try to access the console
243 * device (3215 as console and 3270 as normal tty). 243 * device (3215 as console and 3270 as normal tty).
244 */ 244 */
245 __cpcmd("TERM CONMODE 3215", NULL, 0, NULL); 245 cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
246 if (ptr == NULL) { 246 if (ptr == NULL) {
247#if defined(CONFIG_SCLP_CONSOLE) 247#if defined(CONFIG_SCLP_CONSOLE)
248 SET_CONSOLE_SCLP; 248 SET_CONSOLE_SCLP;
@@ -299,14 +299,14 @@ static void do_machine_restart_nonsmp(char * __unused)
299static void do_machine_halt_nonsmp(void) 299static void do_machine_halt_nonsmp(void)
300{ 300{
301 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) 301 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
302 cpcmd(vmhalt_cmd, NULL, 0, NULL); 302 __cpcmd(vmhalt_cmd, NULL, 0, NULL);
303 signal_processor(smp_processor_id(), sigp_stop_and_store_status); 303 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
304} 304}
305 305
306static void do_machine_power_off_nonsmp(void) 306static void do_machine_power_off_nonsmp(void)
307{ 307{
308 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) 308 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
309 cpcmd(vmpoff_cmd, NULL, 0, NULL); 309 __cpcmd(vmpoff_cmd, NULL, 0, NULL);
310 signal_processor(smp_processor_id(), sigp_stop_and_store_status); 310 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
311} 311}
312 312
diff --git a/include/asm-s390/cpcmd.h b/include/asm-s390/cpcmd.h
index 1fcf65be7a23..48a9eab16429 100644
--- a/include/asm-s390/cpcmd.h
+++ b/include/asm-s390/cpcmd.h
@@ -7,8 +7,8 @@
7 * Christian Borntraeger (cborntra@de.ibm.com), 7 * Christian Borntraeger (cborntra@de.ibm.com),
8 */ 8 */
9 9
10#ifndef __CPCMD__ 10#ifndef _ASM_S390_CPCMD_H
11#define __CPCMD__ 11#define _ASM_S390_CPCMD_H
12 12
13/* 13/*
14 * the lowlevel function for cpcmd 14 * the lowlevel function for cpcmd
@@ -16,9 +16,6 @@
16 */ 16 */
17extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code); 17extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code);
18 18
19#ifndef __s390x__
20#define cpcmd __cpcmd
21#else
22/* 19/*
23 * cpcmd is the in-kernel interface for issuing CP commands 20 * cpcmd is the in-kernel interface for issuing CP commands
24 * 21 *
@@ -33,6 +30,5 @@ extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code
33 * NOTE: If the response buffer is not below 2 GB, cpcmd can sleep 30 * NOTE: If the response buffer is not below 2 GB, cpcmd can sleep
34 */ 31 */
35extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code); 32extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code);
36#endif /*__s390x__*/
37 33
38#endif 34#endif /* _ASM_S390_CPCMD_H */