/*
  * 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
  * 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 */
 
 #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>
        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;
 }
        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"
 
 /*
  * __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)
 
 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;
 
        }
        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);