Commit 9b028b69 authored by Christian Bornträger's avatar Christian Bornträger Committed by Linus Torvalds

[PATCH] s390: cpcmd interface

- Diagnose 8 needs a response buffer below 2GB real storage.
  As the caller cannot always allocate the buffer with GFP_DMA the best
  solution is to rewrite cpcmd to use a bounce buffer if necessary.
  The old function was renamed to __cpcmd and can be called if appropriate.
  The early boot code does not provide kmalloc but need cpcmd functionality.
  These places have been converted to use __cpcmd, as the init code and data
  are below 2GB.
- In case of an 31 bit system, cpcmd is defined as __cpcmd.
- EXPORT_SYMBOL(cpcmd) moved into cpcmd.c
- some whitespace fixes in cpcmd.[c/h]
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 1fb75b8f
...@@ -4,34 +4,41 @@ ...@@ -4,34 +4,41 @@
* S390 version * S390 version
* Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Christian Borntraeger (cborntra@de.ibm.com),
*/ */
#include <linux/stddef.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <linux/spinlock.h>
#include <asm/cpcmd.h> #include <asm/cpcmd.h>
#include <asm/system.h> #include <asm/system.h>
static DEFINE_SPINLOCK(cpcmd_lock); static DEFINE_SPINLOCK(cpcmd_lock);
static char cpcmd_buf[240]; static char cpcmd_buf[240];
void cpcmd(char *cmd, char *response, int rlen) /*
* the caller of __cpcmd has to ensure that the response buffer is below 2 GB
*/
void __cpcmd(char *cmd, char *response, int rlen)
{ {
const int mask = 0x40000000L; const int mask = 0x40000000L;
unsigned long flags; unsigned long flags;
int cmdlen; int cmdlen;
spin_lock_irqsave(&cpcmd_lock, flags); spin_lock_irqsave(&cpcmd_lock, flags);
cmdlen = strlen(cmd); cmdlen = strlen(cmd);
BUG_ON(cmdlen>240); BUG_ON(cmdlen > 240);
strcpy(cpcmd_buf, cmd); strcpy(cpcmd_buf, cmd);
ASCEBC(cpcmd_buf, cmdlen); ASCEBC(cpcmd_buf, cmdlen);
if (response != NULL && rlen > 0) { if (response != NULL && rlen > 0) {
memset(response, 0, rlen);
#ifndef CONFIG_ARCH_S390X #ifndef CONFIG_ARCH_S390X
asm volatile ("LRA 2,0(%0)\n\t" asm volatile ("LRA 2,0(%0)\n\t"
"LR 4,%1\n\t" "LR 4,%1\n\t"
"O 4,%4\n\t" "O 4,%4\n\t"
"LRA 3,0(%2)\n\t" "LRA 3,0(%2)\n\t"
...@@ -78,3 +85,27 @@ void cpcmd(char *cmd, char *response, int rlen) ...@@ -78,3 +85,27 @@ void cpcmd(char *cmd, char *response, int rlen)
spin_unlock_irqrestore(&cpcmd_lock, flags); spin_unlock_irqrestore(&cpcmd_lock, flags);
} }
EXPORT_SYMBOL(__cpcmd);
#ifdef CONFIG_ARCH_S390X
void cpcmd(char *cmd, char *response, int rlen)
{
char *lowbuf;
if ((rlen == 0) || (response == NULL)
|| !((unsigned long)response >> 31))
__cpcmd(cmd, response, rlen);
else {
lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
if (!lowbuf) {
printk(KERN_WARNING
"cpcmd: could not allocate response buffer\n");
return;
}
__cpcmd(cmd, lowbuf, rlen);
memcpy(response, lowbuf, rlen);
kfree(lowbuf);
}
}
EXPORT_SYMBOL(cpcmd);
#endif /* CONFIG_ARCH_S390X */
...@@ -63,4 +63,3 @@ EXPORT_SYMBOL(console_mode); ...@@ -63,4 +63,3 @@ EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_devno); EXPORT_SYMBOL(console_devno);
EXPORT_SYMBOL(console_irq); EXPORT_SYMBOL(console_irq);
EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(sys_wait4);
EXPORT_SYMBOL(cpcmd);
...@@ -191,11 +191,11 @@ static void __init conmode_default(void) ...@@ -191,11 +191,11 @@ static void __init conmode_default(void)
char *ptr; char *ptr;
if (MACHINE_IS_VM) { if (MACHINE_IS_VM) {
cpcmd("QUERY CONSOLE", query_buffer, 1024); __cpcmd("QUERY CONSOLE", query_buffer, 1024);
console_devno = simple_strtoul(query_buffer + 5, NULL, 16); console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
ptr = strstr(query_buffer, "SUBCHANNEL ="); ptr = strstr(query_buffer, "SUBCHANNEL =");
console_irq = simple_strtoul(ptr + 13, NULL, 16); console_irq = simple_strtoul(ptr + 13, NULL, 16);
cpcmd("QUERY TERM", query_buffer, 1024); __cpcmd("QUERY TERM", query_buffer, 1024);
ptr = strstr(query_buffer, "CONMODE"); ptr = strstr(query_buffer, "CONMODE");
/* /*
* Set the conmode to 3215 so that the device recognition * Set the conmode to 3215 so that the device recognition
...@@ -204,7 +204,7 @@ static void __init conmode_default(void) ...@@ -204,7 +204,7 @@ static void __init conmode_default(void)
* 3215 and the 3270 driver will try to access the console * 3215 and the 3270 driver will try to access the console
* device (3215 as console and 3270 as normal tty). * device (3215 as console and 3270 as normal tty).
*/ */
cpcmd("TERM CONMODE 3215", NULL, 0); __cpcmd("TERM CONMODE 3215", NULL, 0);
if (ptr == NULL) { if (ptr == NULL) {
#if defined(CONFIG_SCLP_CONSOLE) #if defined(CONFIG_SCLP_CONSOLE)
SET_CONSOLE_SCLP; SET_CONSOLE_SCLP;
......
...@@ -576,8 +576,8 @@ segment_save(char *name) ...@@ -576,8 +576,8 @@ segment_save(char *name)
segtype_string[seg->range[i].start & 0xff]); segtype_string[seg->range[i].start & 0xff]);
} }
sprintf(cmd2, "SAVESEG %s", name); sprintf(cmd2, "SAVESEG %s", name);
cpcmd(cmd1, NULL, 80); cpcmd(cmd1, NULL, 0);
cpcmd(cmd2, NULL, 80); cpcmd(cmd2, NULL, 0);
spin_unlock(&dcss_lock); spin_unlock(&dcss_lock);
} }
......
...@@ -4,11 +4,21 @@ ...@@ -4,11 +4,21 @@
* S390 version * S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Christian Borntraeger (cborntra@de.ibm.com),
*/ */
#ifndef __CPCMD__ #ifndef __CPCMD__
#define __CPCMD__ #define __CPCMD__
/*
* the caller of __cpcmd has to ensure that the response buffer is below 2 GB
*/
extern void __cpcmd(char *cmd, char *response, int rlen);
#ifndef __s390x__
#define cpcmd __cpcmd
#else
extern void cpcmd(char *cmd, char *response, int rlen); extern void cpcmd(char *cmd, char *response, int rlen);
#endif /*__s390x__*/
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment