diff options
| author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2013-04-16 14:17:15 +0200 | 
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-04-17 14:07:38 +0200 | 
| commit | b170bad40dab1a1684d629b37cb65a5281d35bd8 (patch) | |
| tree | 40f24811118d28edda9a99b40599f59913f01615 | |
| parent | f0bacb7fc4f7defb15a6575d92f8ea4342f8f09e (diff) | |
| download | olio-linux-3.10-b170bad40dab1a1684d629b37cb65a5281d35bd8.tar.xz olio-linux-3.10-b170bad40dab1a1684d629b37cb65a5281d35bd8.zip  | |
s390/pci: do not read data after failed load
If a pci load instruction fails the content of the register where the
data is stored is possibly unchanged. Fix the inline assembly wrapper
__pcilg to not return stale data. Additionally fix the callers of this
function who access uninitialized variables.
Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -rw-r--r-- | arch/s390/include/asm/pci_io.h | 4 | ||||
| -rw-r--r-- | arch/s390/pci/pci.c | 8 | ||||
| -rw-r--r-- | arch/s390/pci/pci_insn.c | 4 | 
3 files changed, 11 insertions, 5 deletions
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h index 0e0bec9a3fb..83a9caa6ae5 100644 --- a/arch/s390/include/asm/pci_io.h +++ b/arch/s390/include/asm/pci_io.h @@ -92,6 +92,9 @@ static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)  	int cc;  	cc = s390pci_load(&data, req, offset); +	if (cc) +		goto out; +  	switch (len) {  	case 1:  		*((u8 *) dst) = (u8) data; @@ -106,6 +109,7 @@ static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)  		*((u64 *) dst) = (u64) data;  		break;  	} +out:  	return cc;  } diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 2b21749cc2b..51d16f1fb5e 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -281,11 +281,11 @@ static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)  	int rc;  	rc = s390pci_load(&data, req, offset); -	data = data << ((8 - len) * 8); -	data = le64_to_cpu(data); -	if (!rc) +	if (!rc) { +		data = data << ((8 - len) * 8); +		data = le64_to_cpu(data);  		*val = (u32) data; -	else +	} else  		*val = 0xffffffff;  	return rc;  } diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c index 4bc32f368f7..22eeb9d7ffe 100644 --- a/arch/s390/pci/pci_insn.c +++ b/arch/s390/pci/pci_insn.c @@ -103,7 +103,9 @@ static inline int __pcilg(u64 *data, u64 req, u64 offset, u8 *status)  		:  "d" (__offset)  		: "cc");  	*status = __req >> 24 & 0xff; -	*data = __data; +	if (!cc) +		*data = __data; +  	return cc;  }  |