s390/cpcmd,vmcp: avoid GFP_DMA allocations
According to the CP Programming Services manual Diagnose Code 8 "Virtual Console Function" can be used in all addressing modes. Also the input and output buffers do not have a limitation which specifies they need to be below the 2GB line. This is true at least since z/VM 5.4. Therefore remove the sam31/64 instructions and allow for simple GFP_KERNEL allocations. This makes it easier to allocate a 1MB page if the user requested such a large return buffer. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
267239cc10
commit
cd4386a931
@ -10,9 +10,8 @@
|
||||
|
||||
/*
|
||||
* 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);
|
||||
int __cpcmd(const char *cmd, char *response, int rlen, int *response_code);
|
||||
|
||||
/*
|
||||
* cpcmd is the in-kernel interface for issuing CP commands
|
||||
@ -25,8 +24,8 @@ extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code
|
||||
* response_code: return pointer for VM's error code
|
||||
* return value: the size of the response. The caller can check if the buffer
|
||||
* was large enough by comparing the return value and rlen
|
||||
* NOTE: If the response buffer is not below 2 GB, cpcmd can sleep
|
||||
* NOTE: If the response buffer is not in real storage, cpcmd can sleep
|
||||
*/
|
||||
extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code);
|
||||
int cpcmd(const char *cmd, char *response, int rlen, int *response_code);
|
||||
|
||||
#endif /* _ASM_S390_CPCMD_H */
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/diag.h>
|
||||
#include <asm/ebcdic.h>
|
||||
#include <asm/cpcmd.h>
|
||||
@ -28,9 +29,7 @@ static int diag8_noresponse(int cmdlen)
|
||||
register unsigned long reg3 asm ("3") = cmdlen;
|
||||
|
||||
asm volatile(
|
||||
" sam31\n"
|
||||
" diag %1,%0,0x8\n"
|
||||
" sam64\n"
|
||||
: "+d" (reg3) : "d" (reg2) : "cc");
|
||||
return reg3;
|
||||
}
|
||||
@ -43,9 +42,7 @@ static int diag8_response(int cmdlen, char *response, int *rlen)
|
||||
register unsigned long reg5 asm ("5") = *rlen;
|
||||
|
||||
asm volatile(
|
||||
" sam31\n"
|
||||
" diag %2,%0,0x8\n"
|
||||
" sam64\n"
|
||||
" brc 8,1f\n"
|
||||
" agr %1,%4\n"
|
||||
"1:\n"
|
||||
@ -57,7 +54,6 @@ static int diag8_response(int cmdlen, char *response, int *rlen)
|
||||
|
||||
/*
|
||||
* __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)
|
||||
@ -88,13 +84,12 @@ EXPORT_SYMBOL(__cpcmd);
|
||||
|
||||
int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
|
||||
{
|
||||
unsigned long flags;
|
||||
char *lowbuf;
|
||||
int len;
|
||||
unsigned long flags;
|
||||
|
||||
if ((virt_to_phys(response) != (unsigned long) response) ||
|
||||
(((unsigned long)response + rlen) >> 31)) {
|
||||
lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
|
||||
if (is_vmalloc_or_module_addr(response)) {
|
||||
lowbuf = kmalloc(rlen, GFP_KERNEL);
|
||||
if (!lowbuf) {
|
||||
pr_warn("The cpcmd kernel function failed to allocate a response buffer\n");
|
||||
return -ENOMEM;
|
||||
|
@ -98,7 +98,7 @@ vmcp_write(struct file *file, const char __user *buff, size_t count,
|
||||
}
|
||||
if (!session->response)
|
||||
session->response = (char *)__get_free_pages(GFP_KERNEL
|
||||
| __GFP_RETRY_MAYFAIL | GFP_DMA,
|
||||
| __GFP_RETRY_MAYFAIL,
|
||||
get_order(session->bufsize));
|
||||
if (!session->response) {
|
||||
mutex_unlock(&session->mutex);
|
||||
|
Loading…
Reference in New Issue
Block a user