Commit bda3563f authored by Christian Borntraeger's avatar Christian Borntraeger Committed by Martin Schwidefsky

[S390] cpcmd with vmalloc addresses.

Change the bounce buffer logic of cpcmd. diag8 needs _real_ memory below
2GB. Therefore vmalloced data does not work. As the data might cross a
page boundary, we cannot use virt_to_page either. The solution is to use
virt_to_page only in the check for a bounce buffer.

There was a redundant check for response==NULL. response < 2GB contains
this check as well.

I also removed the rlen==0 check, since rlen=0 and response!=NULL would
be a caller bug and response==NULL is already checked.
Signed-off-by: default avatarChristian Borntraeger <cborntra@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 60383201
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/cpcmd.h> #include <asm/cpcmd.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h>
static DEFINE_SPINLOCK(cpcmd_lock); static DEFINE_SPINLOCK(cpcmd_lock);
static char cpcmd_buf[241]; static char cpcmd_buf[241];
...@@ -88,13 +89,8 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) ...@@ -88,13 +89,8 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
int len; int len;
unsigned long flags; unsigned long flags;
if ((rlen == 0) || (response == NULL) if ((virt_to_phys(response) != (unsigned long) response) ||
|| !((unsigned long)response >> 31)) { (((unsigned long)response + rlen) >> 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); lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
if (!lowbuf) { if (!lowbuf) {
printk(KERN_WARNING printk(KERN_WARNING
...@@ -106,6 +102,10 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) ...@@ -106,6 +102,10 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
spin_unlock_irqrestore(&cpcmd_lock, flags); spin_unlock_irqrestore(&cpcmd_lock, flags);
memcpy(response, lowbuf, rlen); memcpy(response, lowbuf, rlen);
kfree(lowbuf); kfree(lowbuf);
} else {
spin_lock_irqsave(&cpcmd_lock, flags);
len = __cpcmd(cmd, response, rlen, response_code);
spin_unlock_irqrestore(&cpcmd_lock, flags);
} }
return len; return len;
} }
......
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