Skip to content

Commit

Permalink
[S390] cpcmd <-> __cpcmd calling issues
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Heiko Carstens authored and Martin Schwidefsky committed Dec 4, 2006
1 parent a1a392f commit 740b570
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 24 deletions.
18 changes: 11 additions & 7 deletions arch/s390/kernel/cpcmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ static DEFINE_SPINLOCK(cpcmd_lock);
static char cpcmd_buf[241];

/*
* the caller of __cpcmd has to ensure that the response buffer is below 2 GB
* __cpcmd has some restrictions over cpcmd
* - the response buffer must reside below 2GB (if any)
* - __cpcmd is unlocked and therefore not SMP-safe
*/
int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
unsigned long flags, cmdlen;
unsigned cmdlen;
int return_code, return_len;

spin_lock_irqsave(&cpcmd_lock, flags);
cmdlen = strlen(cmd);
BUG_ON(cmdlen > 240);
memcpy(cpcmd_buf, cmd, cmdlen);
Expand Down Expand Up @@ -74,36 +75,39 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
: "+d" (reg3) : "d" (reg2) : "cc");
return_code = (int) reg3;
}
spin_unlock_irqrestore(&cpcmd_lock, flags);
if (response_code != NULL)
*response_code = return_code;
return return_len;
}

EXPORT_SYMBOL(__cpcmd);

#ifdef CONFIG_64BIT
int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
char *lowbuf;
int len;
unsigned long flags;

if ((rlen == 0) || (response == NULL)
|| !((unsigned long)response >> 31))
|| !((unsigned long)response >> 31)) {
spin_lock_irqsave(&cpcmd_lock, flags);
len = __cpcmd(cmd, response, rlen, response_code);
spin_unlock_irqrestore(&cpcmd_lock, flags);
}
else {
lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
if (!lowbuf) {
printk(KERN_WARNING
"cpcmd: could not allocate response buffer\n");
return -ENOMEM;
}
spin_lock_irqsave(&cpcmd_lock, flags);
len = __cpcmd(cmd, lowbuf, rlen, response_code);
spin_unlock_irqrestore(&cpcmd_lock, flags);
memcpy(response, lowbuf, rlen);
kfree(lowbuf);
}
return len;
}

EXPORT_SYMBOL(cpcmd);
#endif /* CONFIG_64BIT */
10 changes: 5 additions & 5 deletions arch/s390/kernel/ipl.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ void do_reipl(void)
else
sprintf(buf, "IPL %X LOADPARM '%s'",
reipl_block_ccw->ipl_info.ccw.devno, loadparm);
cpcmd(buf, NULL, 0, NULL);
__cpcmd(buf, NULL, 0, NULL);
break;
case IPL_METHOD_CCW_DIAG:
diag308(DIAG308_SET, reipl_block_ccw);
Expand All @@ -691,12 +691,12 @@ void do_reipl(void)
diag308(DIAG308_IPL, NULL);
break;
case IPL_METHOD_FCP_RO_VM:
cpcmd("IPL", NULL, 0, NULL);
__cpcmd("IPL", NULL, 0, NULL);
break;
case IPL_METHOD_NONE:
default:
if (MACHINE_IS_VM)
cpcmd("IPL", NULL, 0, NULL);
__cpcmd("IPL", NULL, 0, NULL);
diag308(DIAG308_IPL, NULL);
break;
}
Expand Down Expand Up @@ -732,9 +732,9 @@ static void do_dump(void)
case IPL_METHOD_CCW_VM:
dump_smp_stop_all();
sprintf(buf, "STORE STATUS");
cpcmd(buf, NULL, 0, NULL);
__cpcmd(buf, NULL, 0, NULL);
sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
cpcmd(buf, NULL, 0, NULL);
__cpcmd(buf, NULL, 0, NULL);
break;
case IPL_METHOD_CCW_DIAG:
diag308(DIAG308_SET, dump_block_ccw);
Expand Down
10 changes: 5 additions & 5 deletions arch/s390/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@ static void __init conmode_default(void)
char *ptr;

if (MACHINE_IS_VM) {
__cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
ptr = strstr(query_buffer, "SUBCHANNEL =");
console_irq = simple_strtoul(ptr + 13, NULL, 16);
__cpcmd("QUERY TERM", query_buffer, 1024, NULL);
cpcmd("QUERY TERM", query_buffer, 1024, NULL);
ptr = strstr(query_buffer, "CONMODE");
/*
* Set the conmode to 3215 so that the device recognition
Expand All @@ -242,7 +242,7 @@ static void __init conmode_default(void)
* 3215 and the 3270 driver will try to access the console
* device (3215 as console and 3270 as normal tty).
*/
__cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
if (ptr == NULL) {
#if defined(CONFIG_SCLP_CONSOLE)
SET_CONSOLE_SCLP;
Expand Down Expand Up @@ -299,14 +299,14 @@ static void do_machine_restart_nonsmp(char * __unused)
static void do_machine_halt_nonsmp(void)
{
if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
cpcmd(vmhalt_cmd, NULL, 0, NULL);
__cpcmd(vmhalt_cmd, NULL, 0, NULL);
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
}

static void do_machine_power_off_nonsmp(void)
{
if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
cpcmd(vmpoff_cmd, NULL, 0, NULL);
__cpcmd(vmpoff_cmd, NULL, 0, NULL);
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
}

Expand Down
10 changes: 3 additions & 7 deletions include/asm-s390/cpcmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@
* Christian Borntraeger (cborntra@de.ibm.com),
*/

#ifndef __CPCMD__
#define __CPCMD__
#ifndef _ASM_S390_CPCMD_H
#define _ASM_S390_CPCMD_H

/*
* the lowlevel function for cpcmd
* the caller of __cpcmd has to ensure that the response buffer is below 2 GB
*/
extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code);

#ifndef __s390x__
#define cpcmd __cpcmd
#else
/*
* cpcmd is the in-kernel interface for issuing CP commands
*
Expand All @@ -33,6 +30,5 @@ extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code
* NOTE: If the response buffer is not below 2 GB, cpcmd can sleep
*/
extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code);
#endif /*__s390x__*/

#endif
#endif /* _ASM_S390_CPCMD_H */

0 comments on commit 740b570

Please sign in to comment.