Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3147

kernel-2.6.18-194.11.1.el5.src.rpm

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;
 }