s390/pci: do not read data after failed load
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Tue, 16 Apr 2013 12:17:15 +0000 (14:17 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 17 Apr 2013 12:07:38 +0000 (14:07 +0200)
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>
arch/s390/include/asm/pci_io.h
arch/s390/pci/pci.c
arch/s390/pci/pci_insn.c

index 0e0bec9..83a9caa 100644 (file)
@@ -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;
 }
 
index 2b21749..51d16f1 100644 (file)
@@ -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;
 }
index 4bc32f3..22eeb9d 100644 (file)
@@ -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;
 }