diff options
author | Matthew R. Ochs <mrochs@linux.vnet.ibm.com> | 2015-10-21 22:14:01 +0200 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-10-30 09:14:41 +0100 |
commit | e5ce067b7b6e123a88929a18a8a58811ffcec279 (patch) | |
tree | 605d97ad36ed048531a6326bf85644c8f3f50670 /drivers/scsi | |
parent | cxlflash: Remove dual port online dependency (diff) | |
download | linux-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.h | 2 | ||||
-rw-r--r-- | drivers/scsi/cxlflash/main.c | 18 | ||||
-rw-r--r-- | drivers/scsi/cxlflash/sislite.h | 2 |
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, ®, 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, ®, 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; }; |