From: Hans-Joachim Picht <hpicht@redhat.com> Date: Fri, 27 Feb 2009 20:53:19 +0100 Subject: [s390] kernel: cpcmd with vmalloc addresses Message-id: 20090227195319.GU2447@redhat.com O-Subject: [RHEL5 U4 PATCH 7/7] s390 - kernel: cpcmd with vmalloc addresses Bugzilla: 487697 Description ============ 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. Bugzilla ========= BZ 487697 https://bugzilla.redhat.com/show_bug.cgi?id=487697 Upstream status of the patch: ============================= This patch is included in linux-2.6 as git commit bda3563fb28e3a4260ac3566cf11700792a336bb Test status: ============ The patch has been tested and fixes the problem. The fix has been verified by the IBM test department. Please ACK. With best regards, --Hans diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index 24a7e23..2eac2a3 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -16,6 +16,7 @@ #include <asm/ebcdic.h> #include <asm/cpcmd.h> #include <asm/system.h> +#include <asm/io.h> static DEFINE_SPINLOCK(cpcmd_lock); static char cpcmd_buf[241]; @@ -93,10 +94,8 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) char *lowbuf; int len; - if ((rlen == 0) || (response == NULL) - || !((unsigned long)response >> 31)) - len = __cpcmd(cmd, response, rlen, response_code); - else { + if ((virt_to_phys(response) != (unsigned long) response) || + (((unsigned long)response + rlen) >> 31)) { lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); if (!lowbuf) { printk(KERN_WARNING @@ -106,7 +105,9 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) len = __cpcmd(cmd, lowbuf, rlen, response_code); memcpy(response, lowbuf, rlen); kfree(lowbuf); - } + } else + len = __cpcmd(cmd, response, rlen, response_code); + return len; }