Message ID | 1443715012-18236-1-git-send-email-mrochs@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
"Matthew R. Ochs" <mrochs@linux.vnet.ibm.com> writes: > 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. > > + 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; I'm confused by this if statement. If afu->interface_version + 1 == 0, and interface_version is a 64bit unsigned int, that would mean that afu->interface_version was 0xFFFF FFFF FFFF FFFF. Are you trying to check against all Fs? Is that value significant in the hardware? Regards, Daniel > + } 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 63bf394..8425d1a 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; > }; > > -- > 2.1.0 > > _______________________________________________ > Linuxppc-dev mailing list > Linuxppc-dev@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/linuxppc-dev -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> On Oct 1, 2015, at 7:56 PM, Daniel Axtens <dja@axtens.net> wrote: > > "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com> writes: > >> 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. >> >> + 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; > > I'm confused by this if statement. If afu->interface_version + 1 == 0, > and interface_version is a 64bit unsigned int, that would mean that > afu->interface_version was 0xFFFF FFFF FFFF FFFF. > > Are you trying to check against all Fs? Is that value significant in the > hardware? Correct, downlevel (unsupported) AFUs don't implement the interface_version register and thus will return -1 at that offset. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
"Matthew R. Ochs" <mrochs@linux.vnet.ibm.com> writes: > Correct, downlevel (unsupported) AFUs don't implement the interface_version > register and thus will return -1 at that offset. Cool. It would be good to document that somewhere, either the comment or the commit message, but it's not worth holding up the series for it. I also tend to use the form (var == ~0ULL) for tests like this but that's an aesthetic thing. Reviewed-by: Daniel Axtens <dja@axtens.net> Regards, Daniel
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index faf7f56..3be5754 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 c25efc3..c1d5c88 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 63bf394..8425d1a 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; };