summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMatthew R. Ochs <mrochs@linux.vnet.ibm.com>2015-10-21 22:14:01 +0200
committerJames Bottomley <JBottomley@Odin.com>2015-10-30 09:14:41 +0100
commite5ce067b7b6e123a88929a18a8a58811ffcec279 (patch)
tree605d97ad36ed048531a6326bf85644c8f3f50670 /drivers/scsi
parentcxlflash: Remove dual port online dependency (diff)
downloadlinux-e5ce067b7b6e123a88929a18a8a58811ffcec279.tar.xz
linux-e5ce067b7b6e123a88929a18a8a58811ffcec279.zip
cxlflash: Fix AFU version access/storage and add check
The AFU version is stored as a non-terminated string of bytes within a 64-bit little-endian register. Presently the value is read directly (no MMIO accessor) and is stored in a buffer that is not big enough to contain a NULL terminator. Additionally the version obtained is not evaluated against a known value to prevent usage with unsupported AFUs. All of these deficiencies can lead to a variety of problems. To remedy, use the correct MMIO accessor to read the version value into a null-terminated buffer and add a check to prevent an incompatible AFU from being used with this driver. Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Signed-off-by: Manoj N. Kumar <manoj@linux.vnet.ibm.com> Reviewed-by: Brian King <brking@linux.vnet.ibm.com> Reviewed-by: Daniel Axtens <dja@axtens.net> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/cxlflash/common.h2
-rw-r--r--drivers/scsi/cxlflash/main.c18
-rw-r--r--drivers/scsi/cxlflash/sislite.h2
3 files changed, 14 insertions, 8 deletions
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index faf7f56f0fb3..3be57549fe44 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -179,7 +179,7 @@ struct afu {
u32 cmd_couts; /* Number of command checkouts */
u32 internal_lun; /* User-desired LUN mode for this AFU */
- char version[8];
+ char version[16];
u64 interface_version;
struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index c25efc31c3fc..c1d5c886b375 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -1751,14 +1751,20 @@ static int init_afu(struct cxlflash_cfg *cfg)
goto err1;
}
- /* don't byte reverse on reading afu_version, else the string form */
- /* will be backwards */
- reg = afu->afu_map->global.regs.afu_version;
- memcpy(afu->version, &reg, 8);
+ /* No byte reverse on reading afu_version or string will be backwards */
+ reg = readq(&afu->afu_map->global.regs.afu_version);
+ memcpy(afu->version, &reg, sizeof(reg));
afu->interface_version =
readq_be(&afu->afu_map->global.regs.interface_version);
- pr_debug("%s: afu version %s, interface version 0x%llX\n",
- __func__, afu->version, afu->interface_version);
+ if ((afu->interface_version + 1) == 0) {
+ pr_err("Back level AFU, please upgrade. AFU version %s "
+ "interface version 0x%llx\n", afu->version,
+ afu->interface_version);
+ rc = -EINVAL;
+ goto err1;
+ } else
+ pr_debug("%s: afu version %s, interface version 0x%llX\n",
+ __func__, afu->version, afu->interface_version);
rc = start_afu(cfg);
if (rc) {
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index 63bf394fe78c..8425d1ab65ef 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -340,7 +340,7 @@ struct sisl_global_regs {
#define SISL_AFUCONF_MBOX_CLR_READ 0x0010ULL
__be64 afu_config;
__be64 rsvd[0xf8];
- __be64 afu_version;
+ __le64 afu_version;
__be64 interface_version;
};