From a359ed4904abaca9de7118d3f8343edabf4afb8b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:11:31 +0000 Subject: [PATCH 01/42] scst/include/backport.h: Port recent changes to RHEL 6 and RHEL 7 git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8195 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/backport.h | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/scst/include/backport.h b/scst/include/backport.h index 5e79f7b0b..61051f5d3 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -43,6 +43,7 @@ #include /* struct scsi_cmnd */ struct scsi_target; #include /* struct fc_bsg_job */ +#include /* get_unaligned_be64() */ /* */ @@ -1544,13 +1545,30 @@ static inline void *vzalloc(unsigned long size) #endif /* */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) +/* + * See also commit 35a2af94c7ce ("sched/wait: Make the __wait_event*() + * interface more friendly") # v3.13. + */ +#define ___wait_cond_timeout_backport(condition)\ +({ \ + bool __cond = (condition); \ + if (__cond && !__ret) \ + __ret = 1; \ + __cond || !__ret; \ +}) +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) +#define ___wait_cond_timeout_backport ___wait_cond_timeout +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) /* * See also commit 25ab0bc334b4 ("scsi: sched/wait: Add * wait_event_lock_irq_timeout for TASK_UNINTERRUPTIBLE usage") # v4.20. */ #define __wait_event_lock_irq_timeout(wq_head, condition, lock, timeout, state)\ - ___wait_event(wq_head, ___wait_cond_timeout(condition), \ + ___wait_event(wq_head, ___wait_cond_timeout_backport(condition),\ state, 0, timeout, \ spin_unlock_irq(&lock); \ __ret = schedule_timeout(__ret); \ @@ -1559,7 +1577,7 @@ static inline void *vzalloc(unsigned long size) #define wait_event_lock_irq_timeout(wq_head, condition, lock, timeout) \ ({ \ long __ret = timeout; \ - if (!___wait_cond_timeout(condition)) \ + if (!___wait_cond_timeout_backport(condition)) \ __ret = __wait_event_lock_irq_timeout( \ wq_head, condition, lock, timeout,\ TASK_UNINTERRUPTIBLE); \ @@ -1639,7 +1657,8 @@ enum { }; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0) && \ + (!defined(RHEL_MAJOR) || RHEL_MAJOR -0 < 7) /* * See also commit cc019a5a3b58 ("scsi: scsi_transport_fc: fix typos on 64/128 * GBit define names") # v4.16. From e1b2d90bffd4000350e96ee35b851c62abb11339 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:12:50 +0000 Subject: [PATCH 02/42] qla2xxx: Add fw_attr and port_no sysfs attributes This patch adds new sysfs attributes for the firmware attributes and port number. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8196 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index f928c4d3a..8cc4d6589 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -2164,6 +2164,32 @@ qla2x00_dif_bundle_statistics_show(struct device *dev, ha->dif_bundle_dma_allocs, ha->pool.unusable.count); } +static ssize_t +qla2x00_fw_attr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA27XX(ha)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%llx\n", + (uint64_t)ha->fw_attributes_ext[1] << 48 | + (uint64_t)ha->fw_attributes_ext[0] << 32 | + (uint64_t)ha->fw_attributes_h << 16 | + (uint64_t)ha->fw_attributes); +} + +static ssize_t +qla2x00_port_no_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + + return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no); +} + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); @@ -2221,6 +2247,8 @@ static DEVICE_ATTR(dif_bundle_statistics, 0444, qla2x00_dif_bundle_statistics_show, NULL); static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show, qla2x00_port_speed_store); +static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL); +static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL); struct device_attribute *qla2x00_host_attrs[] = { @@ -2261,6 +2289,8 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_zio_threshold, &dev_attr_dif_bundle_statistics, &dev_attr_port_speed, + &dev_attr_port_no, + &dev_attr_fw_attr, NULL, /* reserve for qlini_mode */ NULL, /* reserve for ql2xiniexchg */ NULL, /* reserve for ql2xexchoffld */ From fa72f713e02ac28a4234c836d6cd18a3b2f71da7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:13:19 +0000 Subject: [PATCH 03/42] qla2xxx: Remove FW default template This patch removes FW default template as there will never be case where the default template would be invoked. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8197 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_gbl.h | 2 - qla2x00t-32gbit/qla_init.c | 94 +++++---------------------------- qla2x00t-32gbit/qla_tmpl.c | 104 +------------------------------------ 3 files changed, 13 insertions(+), 187 deletions(-) diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index a611c093b..96d446ecf 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -615,8 +615,6 @@ extern void qla27xx_fwdump(scsi_qla_host_t *, int); extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *); extern int qla27xx_fwdt_template_valid(void *); extern ulong qla27xx_fwdt_template_size(void *); -extern const void *qla27xx_fwdt_template_default(void); -extern ulong qla27xx_fwdt_template_default_size(void); extern void qla2x00_dump_regs(scsi_qla_host_t *); extern void qla2x00_dump_buffer(uint8_t *, uint32_t); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index cb1fde02d..af1547a49 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -7393,7 +7393,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, ql_dbg(ql_dbg_init, vha, 0x0162, "-> array size %x dwords\n", risc_size); if (risc_size == 0 || risc_size == ~0) - goto default_template; + goto failed; dlen = (risc_size - 8) * sizeof(*dcode); ql_dbg(ql_dbg_init, vha, 0x0163, @@ -7402,7 +7402,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, if (!ha->fw_dump_template) { ql_log(ql_log_warn, vha, 0x0164, "Failed fwdump template allocate %x bytes.\n", risc_size); - goto default_template; + goto failed; } faddr += 7; @@ -7415,7 +7415,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, if (!qla27xx_fwdt_template_valid(dcode)) { ql_log(ql_log_warn, vha, 0x0165, "Failed fwdump template validate\n"); - goto default_template; + goto failed; } dlen = qla27xx_fwdt_template_size(dcode); @@ -7425,48 +7425,13 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, ql_log(ql_log_warn, vha, 0x0167, "Failed fwdump template exceeds array by %zx bytes\n", (size_t)(dlen - risc_size * sizeof(*dcode))); - goto default_template; + goto failed; } ha->fw_dump_template_len = dlen; return rval; -default_template: - ql_log(ql_log_warn, vha, 0x0168, "Using default fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - - dlen = qla27xx_fwdt_template_default_size(); - ql_dbg(ql_dbg_init, vha, 0x0169, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x016a, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto failed_template; - } - - dcode = ha->fw_dump_template; - risc_size = dlen / sizeof(*dcode); - memcpy(dcode, qla27xx_fwdt_template_default(), dlen); - for (i = 0; i < risc_size; i++) - dcode[i] = be32_to_cpu(dcode[i]); - - if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) { - ql_log(ql_log_warn, vha, 0x016b, - "Failed fwdump template validate\n"); - goto failed_template; - } - - dlen = qla27xx_fwdt_template_size(ha->fw_dump_template); - ql_dbg(ql_dbg_init, vha, 0x016c, - "-> template size %x bytes\n", dlen); - ha->fw_dump_template_len = dlen; - return rval; - -failed_template: - ql_log(ql_log_warn, vha, 0x016d, "Failed default fwdump template\n"); +failed: + ql_log(ql_log_warn, vha, 0x016d, "Failed fwdump template\n"); if (ha->fw_dump_template) vfree(ha->fw_dump_template); ha->fw_dump_template = NULL; @@ -7696,7 +7661,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) ql_dbg(ql_dbg_init, vha, 0x172, "-> array size %x dwords\n", risc_size); if (risc_size == 0 || risc_size == ~0) - goto default_template; + goto failed; dlen = (risc_size - 8) * sizeof(*fwcode); ql_dbg(ql_dbg_init, vha, 0x0173, @@ -7705,7 +7670,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) if (!ha->fw_dump_template) { ql_log(ql_log_warn, vha, 0x0174, "Failed fwdump template allocate %x bytes.\n", risc_size); - goto default_template; + goto failed; } fwcode += 7; @@ -7717,7 +7682,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) if (!qla27xx_fwdt_template_valid(dcode)) { ql_log(ql_log_warn, vha, 0x0175, "Failed fwdump template validate\n"); - goto default_template; + goto failed; } dlen = qla27xx_fwdt_template_size(dcode); @@ -7727,48 +7692,13 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) ql_log(ql_log_warn, vha, 0x0177, "Failed fwdump template exceeds array by %zx bytes\n", (size_t)(dlen - risc_size * sizeof(*fwcode))); - goto default_template; + goto failed; } ha->fw_dump_template_len = dlen; return rval; -default_template: - ql_log(ql_log_warn, vha, 0x0178, "Using default fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - - dlen = qla27xx_fwdt_template_default_size(); - ql_dbg(ql_dbg_init, vha, 0x0179, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x017a, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto failed_template; - } - - dcode = ha->fw_dump_template; - risc_size = dlen / sizeof(*fwcode); - fwcode = qla27xx_fwdt_template_default(); - for (i = 0; i < risc_size; i++) - dcode[i] = be32_to_cpu(fwcode[i]); - - if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) { - ql_log(ql_log_warn, vha, 0x017b, - "Failed fwdump template validate\n"); - goto failed_template; - } - - dlen = qla27xx_fwdt_template_size(ha->fw_dump_template); - ql_dbg(ql_dbg_init, vha, 0x017c, - "-> template size %x bytes\n", dlen); - ha->fw_dump_template_len = dlen; - return rval; - -failed_template: - ql_log(ql_log_warn, vha, 0x017d, "Failed default fwdump template\n"); +failed: + ql_log(ql_log_warn, vha, 0x017d, "Failed fwdump template\n"); if (ha->fw_dump_template) vfree(ha->fw_dump_template); ha->fw_dump_template = NULL; diff --git a/qla2x00t-32gbit/qla_tmpl.c b/qla2x00t-32gbit/qla_tmpl.c index 9e52500ca..70f227f59 100644 --- a/qla2x00t-32gbit/qla_tmpl.c +++ b/qla2x00t-32gbit/qla_tmpl.c @@ -7,97 +7,7 @@ #include "qla_def.h" #include "qla_tmpl.h" -/* note default template is in big endian */ -static const uint32_t ql27xx_fwdt_default_template[] = { - 0x63000000, 0xa4000000, 0x7c050000, 0x00000000, - 0x30000000, 0x01000000, 0x00000000, 0xc0406eb4, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x04010000, 0x14000000, 0x00000000, - 0x02000000, 0x44000000, 0x09010000, 0x10000000, - 0x00000000, 0x02000000, 0x01010000, 0x1c000000, - 0x00000000, 0x02000000, 0x00600000, 0x00000000, - 0xc0000000, 0x01010000, 0x1c000000, 0x00000000, - 0x02000000, 0x00600000, 0x00000000, 0xcc000000, - 0x01010000, 0x1c000000, 0x00000000, 0x02000000, - 0x10600000, 0x00000000, 0xd4000000, 0x01010000, - 0x1c000000, 0x00000000, 0x02000000, 0x700f0000, - 0x00000060, 0xf0000000, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00700000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10700000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x40700000, 0x041000c0, - 0x01010000, 0x1c000000, 0x00000000, 0x02000000, - 0x007c0000, 0x01000000, 0xc0000000, 0x00010000, - 0x18000000, 0x00000000, 0x02000000, 0x007c0000, - 0x040300c4, 0x00010000, 0x18000000, 0x00000000, - 0x02000000, 0x007c0000, 0x040100c0, 0x01010000, - 0x1c000000, 0x00000000, 0x02000000, 0x007c0000, - 0x00000000, 0xc0000000, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x007c0000, 0x04200000, - 0x0b010000, 0x18000000, 0x00000000, 0x02000000, - 0x0c000000, 0x00000000, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000000b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000010b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000020b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000030b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000040b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000050b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000060b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000070b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000080b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000090b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x0000a0b0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x0a000000, 0x040100c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x0a000000, 0x04200080, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00be0000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10be0000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x20be0000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x30be0000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00b00000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10b00000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x20b00000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x30b00000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00300000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10300000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x20300000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x30300000, 0x041000c0, 0x0a010000, 0x10000000, - 0x00000000, 0x02000000, 0x06010000, 0x1c000000, - 0x00000000, 0x02000000, 0x01000000, 0x00000200, - 0xff230200, 0x06010000, 0x1c000000, 0x00000000, - 0x02000000, 0x02000000, 0x00001000, 0x00000000, - 0x07010000, 0x18000000, 0x00000000, 0x02000000, - 0x00000000, 0x01000000, 0x07010000, 0x18000000, - 0x00000000, 0x02000000, 0x00000000, 0x02000000, - 0x07010000, 0x18000000, 0x00000000, 0x02000000, - 0x00000000, 0x03000000, 0x0d010000, 0x14000000, - 0x00000000, 0x02000000, 0x00000000, 0xff000000, - 0x10000000, 0x00000000, 0x00000080, -}; +#define IOBASE(reg) offsetof(typeof(*reg), iobase_addr) static inline void __iomem * qla27xx_isp_reg(struct scsi_qla_host *vha) @@ -1032,18 +942,6 @@ qla27xx_fwdt_template_size(void *p) return tmp->template_size; } -ulong -qla27xx_fwdt_template_default_size(void) -{ - return sizeof(ql27xx_fwdt_default_template); -} - -const void * -qla27xx_fwdt_template_default(void) -{ - return ql27xx_fwdt_default_template; -} - int qla27xx_fwdt_template_valid(void *p) { From 51847532361e9b3fe83e0d255c415c9897428676 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:13:40 +0000 Subject: [PATCH 04/42] qla2xxx: Fix routine qla27xx_dump_{mpi|ram}() This patch fixes qla27xx_dump_{mpi|ram} api for ISP27XX. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8198 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_dbg.c | 166 +++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 85 deletions(-) diff --git a/qla2x00t-32gbit/qla_dbg.c b/qla2x00t-32gbit/qla_dbg.c index c7533fa7f..ec5bad0b0 100644 --- a/qla2x00t-32gbit/qla_dbg.c +++ b/qla2x00t-32gbit/qla_dbg.c @@ -111,30 +111,25 @@ int qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, uint32_t ram_dwords, void **nxt) { - int rval; - uint32_t cnt, stat, timer, dwords, idx; - uint16_t mb0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; dma_addr_t dump_dma = ha->gid_list_dma; - uint32_t *dump = (uint32_t *)ha->gid_list; + uint32_t *chunk = (void *)ha->gid_list; + uint32_t dwords = qla2x00_gid_list_size(ha) / 4; + uint32_t stat; + ulong i, j, timer = 6000000; + int rval = QLA_FUNCTION_FAILED; - rval = QLA_SUCCESS; - mb0 = 0; - - WRT_REG_WORD(®->mailbox0, MBC_LOAD_DUMP_MPI_RAM); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + for (i = 0; i < ram_dwords; i += dwords, addr += dwords) { + if (i + dwords > ram_dwords) + dwords = ram_dwords - i; - dwords = qla2x00_gid_list_size(ha) / 4; - for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS; - cnt += dwords, addr += dwords) { - if (cnt + dwords > ram_dwords) - dwords = ram_dwords - cnt; - + WRT_REG_WORD(®->mailbox0, MBC_LOAD_DUMP_MPI_RAM); WRT_REG_WORD(®->mailbox1, LSW(addr)); WRT_REG_WORD(®->mailbox8, MSW(addr)); - WRT_REG_WORD(®->mailbox2, MSW(dump_dma)); - WRT_REG_WORD(®->mailbox3, LSW(dump_dma)); + WRT_REG_WORD(®->mailbox2, MSW(LSD(dump_dma))); + WRT_REG_WORD(®->mailbox3, LSW(LSD(dump_dma))); WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma))); WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma))); @@ -145,76 +140,75 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); ha->flags.mbox_int = 0; - for (timer = 6000000; timer; timer--) { - /* Check for pending interrupts. */ + while (timer--) { + udelay(5); + stat = RD_REG_DWORD(®->host_status); - if (stat & HSRX_RISC_INT) { - stat &= 0xff; + /* Check for pending interrupts. */ + if (!(stat & HSRX_RISC_INT)) + continue; - if (stat == 0x1 || stat == 0x2 || - stat == 0x10 || stat == 0x11) { - set_bit(MBX_INTERRUPT, - &ha->mbx_cmd_flags); - - mb0 = RD_REG_WORD(®->mailbox0); - RD_REG_WORD(®->mailbox1); - - WRT_REG_DWORD(®->hccr, - HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - break; - } + stat &= 0xff; + if (stat != 0x1 && stat != 0x2 && + stat != 0x10 && stat != 0x11) { /* Clear this intr; it wasn't a mailbox intr */ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); RD_REG_DWORD(®->hccr); + continue; } - udelay(5); + + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + rval = RD_REG_WORD(®->mailbox0) & MBS_MASK; + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + break; } ha->flags.mbox_int = 1; + *nxt = ram + i; - if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { - rval = mb0 & MBS_MASK; - for (idx = 0; idx < dwords; idx++) - ram[cnt + idx] = IS_QLA27XX(ha) ? - le32_to_cpu(dump[idx]) : swab32(dump[idx]); - } else { - rval = QLA_FUNCTION_FAILED; + if (!test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { + /* no interrupt, timed out*/ + return rval; + } + if (rval) { + /* error completion status */ + return rval; + } + for (j = 0; j < dwords; j++) { + ram[i + j] = IS_QLA27XX(ha) ? + chunk[j] : swab32(chunk[j]); } } - *nxt = rval == QLA_SUCCESS ? &ram[cnt] : NULL; - return rval; + *nxt = ram + i; + return QLA_SUCCESS; } int qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, uint32_t ram_dwords, void **nxt) { - int rval; - uint32_t cnt, stat, timer, dwords, idx; - uint16_t mb0; + int rval = QLA_FUNCTION_FAILED; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; dma_addr_t dump_dma = ha->gid_list_dma; - uint32_t *dump = (uint32_t *)ha->gid_list; + uint32_t *chunk = (void *)ha->gid_list; + uint32_t dwords = qla2x00_gid_list_size(ha) / 4; + uint32_t stat; + ulong i, j, timer = 6000000; - rval = QLA_SUCCESS; - mb0 = 0; - - WRT_REG_WORD(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - dwords = qla2x00_gid_list_size(ha) / 4; - for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS; - cnt += dwords, addr += dwords) { - if (cnt + dwords > ram_dwords) - dwords = ram_dwords - cnt; + for (i = 0; i < ram_dwords; i += dwords, addr += dwords) { + if (i + dwords > ram_dwords) + dwords = ram_dwords - i; + WRT_REG_WORD(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED); WRT_REG_WORD(®->mailbox1, LSW(addr)); WRT_REG_WORD(®->mailbox8, MSW(addr)); - WRT_REG_WORD(®->mailbox2, MSW(dump_dma)); - WRT_REG_WORD(®->mailbox3, LSW(dump_dma)); + WRT_REG_WORD(®->mailbox2, MSW(LSD(dump_dma))); + WRT_REG_WORD(®->mailbox3, LSW(LSD(dump_dma))); WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma))); WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma))); @@ -223,45 +217,47 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); ha->flags.mbox_int = 0; - for (timer = 6000000; timer; timer--) { - /* Check for pending interrupts. */ + while (timer--) { + udelay(5); stat = RD_REG_DWORD(®->host_status); - if (stat & HSRX_RISC_INT) { - stat &= 0xff; - if (stat == 0x1 || stat == 0x2 || - stat == 0x10 || stat == 0x11) { - set_bit(MBX_INTERRUPT, - &ha->mbx_cmd_flags); + /* Check for pending interrupts. */ + if (!(stat & HSRX_RISC_INT)) + continue; - mb0 = RD_REG_WORD(®->mailbox0); - - WRT_REG_DWORD(®->hccr, - HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - break; - } - - /* Clear this intr; it wasn't a mailbox intr */ + stat &= 0xff; + if (stat != 0x1 && stat != 0x2 && + stat != 0x10 && stat != 0x11) { WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); RD_REG_DWORD(®->hccr); + continue; } - udelay(5); + + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + rval = RD_REG_WORD(®->mailbox0) & MBS_MASK; + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + break; } ha->flags.mbox_int = 1; + *nxt = ram + i; - if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { - rval = mb0 & MBS_MASK; - for (idx = 0; idx < dwords; idx++) - ram[cnt + idx] = IS_QLA27XX(ha) ? - le32_to_cpu(dump[idx]) : swab32(dump[idx]); - } else { - rval = QLA_FUNCTION_FAILED; + if (!test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { + /* no interrupt, timed out*/ + return rval; + } + if (rval) { + /* error completion status */ + return rval; + } + for (j = 0; j < dwords; j++) { + ram[i + j] = IS_QLA27XX(ha) ? + chunk[j] : swab32(chunk[j]); } } - *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL; - return rval; + *nxt = ram + i; + return QLA_SUCCESS; } static int From 6e708764f74d65fddaf86f2e2930ab1afc39d532 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:14:12 +0000 Subject: [PATCH 05/42] qla2xxx: Add Device ID for ISP28XX This patch adds PCI device ID ISP28XX for Gen7 support. Also signature determination for primary/secondary flash image for ISP27XX/28XX is added as part of Gen7 support. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8199 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 30 +++++++----- qla2x00t-32gbit/qla_bsg.c | 12 +++-- qla2x00t-32gbit/qla_dbg.c | 9 ++-- qla2x00t-32gbit/qla_def.h | 62 +++++++++++++++++-------- qla2x00t-32gbit/qla_dfs.c | 6 +-- qla2x00t-32gbit/qla_fw.h | 5 +- qla2x00t-32gbit/qla_gs.c | 4 +- qla2x00t-32gbit/qla_init.c | 51 +++++++++++++-------- qla2x00t-32gbit/qla_iocb.c | 5 +- qla2x00t-32gbit/qla_isr.c | 14 +++--- qla2x00t-32gbit/qla_mbx.c | 76 ++++++++++++++++-------------- qla2x00t-32gbit/qla_os.c | 89 +++++++++++++++++++++++++++++------- qla2x00t-32gbit/qla_sup.c | 49 +++++++++++--------- qla2x00t-32gbit/qla_target.c | 7 +-- 14 files changed, 272 insertions(+), 147 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 8cc4d6589..f035251a8 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -427,7 +427,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, valid = 1; else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) - || IS_QLA27XX(ha)) + || IS_QLA27XX(ha) || IS_QLA28XX(ha)) valid = 1; if (!valid) { ql_log(ql_log_warn, vha, 0x7065, @@ -514,7 +514,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, if (IS_NOCACHE_VPD_TYPE(ha)) { faddr = ha->flt_region_vpd << 2; - if (IS_QLA27XX(ha) && + if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) faddr = ha->flt_region_vpd_sec << 2; @@ -682,7 +682,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, ql_log(ql_log_info, vha, 0x706f, "Issuing MPI reset.\n"); - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { uint32_t idc_control; qla83xx_idc_lock(vha, 0); @@ -991,7 +991,8 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon) continue; if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw))) continue; - if (iter->is4GBp_only == 0x27 && !IS_QLA27XX(vha->hw)) + if (iter->is4GBp_only == 0x27 && + (!IS_QLA27XX(vha->hw) || !IS_QLA28XX(ha))) continue; sysfs_remove_bin_file(&host->shost_gendev.kobj, @@ -1336,7 +1337,8 @@ qla2x00_optrom_gold_fw_version_show(struct device *dev, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n", @@ -1383,7 +1385,7 @@ qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, struct qla_hw_data *ha = vha->hw; if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", @@ -1596,7 +1598,7 @@ qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", @@ -1610,7 +1612,7 @@ qla2x00_min_link_speed_show(struct device *dev, struct device_attribute *attr, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%s\n", @@ -1628,7 +1630,7 @@ qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%s\n", @@ -1645,7 +1647,7 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr, int mode = QLA_SET_DATA_RATE_LR; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA27XX(vha->hw)) { + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) { ql_log(ql_log_warn, vha, 0x70d8, "Speed setting not supported \n"); return -EINVAL; @@ -2171,7 +2173,7 @@ qla2x00_fw_attr_show(struct device *dev, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%llx\n", @@ -2357,6 +2359,9 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) case PORT_SPEED_32GB: speed = FC_PORTSPEED_32GBIT; break; + case PORT_SPEED_64GB: + speed = FC_PORTSPEED_64GBIT; + break; } fc_host_speed(shost) = speed; } @@ -3036,6 +3041,9 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) else if (IS_QLA27XX(ha)) speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT; + else if (IS_QLA28XX(ha)) + speed = FC_PORTSPEED_64GBIT | FC_PORTSPEED_32GBIT | + FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT; else speed = FC_PORTSPEED_1GBIT; fc_host_supported_speeds(vha->host) = speed; diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index f21369148..1e6ac3da3 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -1469,7 +1469,8 @@ static int qla2x00_optrom_setup(struct bsg_job *bsg_job, start == (ha->flt_region_fw * 4)) valid = 1; else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || - IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) + IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) valid = 1; if (!valid) { ql_log(ql_log_warn, vha, 0x7058, @@ -2250,7 +2251,7 @@ static int qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job) struct qla_hw_data *ha = vha->hw; struct qla_flash_update_caps cap; - if (!(IS_QLA27XX(ha))) + if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha)) return -EPERM; memset(&cap, 0, sizeof(cap)); @@ -2286,7 +2287,7 @@ static int qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job) uint64_t online_fw_attr = 0; struct qla_flash_update_caps cap; - if (!(IS_QLA27XX(ha))) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return -EPERM; memset(&cap, 0, sizeof(cap)); @@ -2337,7 +2338,7 @@ static int qla27xx_get_bbcr_data(struct bsg_job *bsg_job) uint8_t domain, area, al_pa, state; int rval; - if (!(IS_QLA27XX(ha))) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return -EPERM; memset(&bbcr, 0, sizeof(bbcr)); @@ -2458,7 +2459,8 @@ static int qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job) int rval; struct qla_dport_diag *dd; - if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw)) + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) return -EPERM; dd = kmalloc(sizeof(*dd), GFP_KERNEL); diff --git a/qla2x00t-32gbit/qla_dbg.c b/qla2x00t-32gbit/qla_dbg.c index ec5bad0b0..3cfd846cd 100644 --- a/qla2x00t-32gbit/qla_dbg.c +++ b/qla2x00t-32gbit/qla_dbg.c @@ -176,7 +176,8 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, return rval; } for (j = 0; j < dwords; j++) { - ram[i + j] = IS_QLA27XX(ha) ? + ram[i + j] = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? chunk[j] : swab32(chunk[j]); } } @@ -251,7 +252,8 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, return rval; } for (j = 0; j < dwords; j++) { - ram[i + j] = IS_QLA27XX(ha) ? + ram[i + j] = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? chunk[j] : swab32(chunk[j]); } } @@ -665,7 +667,8 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) struct qla2xxx_mq_chain *mq = ptr; device_reg_t *reg; - if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) return ptr; mq = ptr; diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index b396d2dfe..e4ac4f93b 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1221,6 +1221,7 @@ struct mbx_cmd_32 { #define QLA27XX_IMG_STATUS_VER_MAJOR 0x01 #define QLA27XX_IMG_STATUS_VER_MINOR 0x00 #define QLA27XX_IMG_STATUS_SIGN 0xFACEFADE +#define QLA28XX_IMG_STATUS_SIGN 0xFACEFADF #define QLA27XX_PRIMARY_IMAGE 1 #define QLA27XX_SECONDARY_IMAGE 2 @@ -2691,6 +2692,7 @@ struct ct_fdmiv2_hba_attributes { #define FDMI_PORT_SPEED_8GB 0x10 #define FDMI_PORT_SPEED_16GB 0x20 #define FDMI_PORT_SPEED_32GB 0x40 +#define FDMI_PORT_SPEED_64GB 0x80 #define FDMI_PORT_SPEED_UNKNOWN 0x8000 #define FC_CLASS_2 0x04 @@ -3387,7 +3389,8 @@ struct qla_tc_param { #define QLA_MQ_SIZE 32 #define QLA_MAX_QUEUES 256 #define ISP_QUE_REG(ha, id) \ - ((ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ? \ + ((ha->mqenable || IS_QLA83XX(ha) || \ + IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? \ ((void __iomem *)ha->mqiobase + (QLA_QUE_PAGE * id)) :\ ((void __iomem *)ha->iobase)) #define QLA_REQ_QUE_ID(tag) \ @@ -3722,6 +3725,7 @@ struct qla_hw_data { #define PORT_SPEED_8GB 0x04 #define PORT_SPEED_16GB 0x05 #define PORT_SPEED_32GB 0x06 +#define PORT_SPEED_64GB 0x07 #define PORT_SPEED_10GB 0x13 uint16_t link_data_rate; /* F/W operating speed */ uint16_t set_data_rate; /* Set by user */ @@ -3748,6 +3752,11 @@ struct qla_hw_data { #define PCI_DEVICE_ID_QLOGIC_ISP2071 0x2071 #define PCI_DEVICE_ID_QLOGIC_ISP2271 0x2271 #define PCI_DEVICE_ID_QLOGIC_ISP2261 0x2261 +#define PCI_DEVICE_ID_QLOGIC_ISP2061 0x2061 +#define PCI_DEVICE_ID_QLOGIC_ISP2081 0x2081 +#define PCI_DEVICE_ID_QLOGIC_ISP2089 0x2089 +#define PCI_DEVICE_ID_QLOGIC_ISP2281 0x2281 +#define PCI_DEVICE_ID_QLOGIC_ISP2289 0x2289 uint32_t isp_type; #define DT_ISP2100 BIT_0 @@ -3772,7 +3781,12 @@ struct qla_hw_data { #define DT_ISP2071 BIT_19 #define DT_ISP2271 BIT_20 #define DT_ISP2261 BIT_21 -#define DT_ISP_LAST (DT_ISP2261 << 1) +#define DT_ISP2061 BIT_22 +#define DT_ISP2081 BIT_23 +#define DT_ISP2089 BIT_24 +#define DT_ISP2281 BIT_25 +#define DT_ISP2289 BIT_26 +#define DT_ISP_LAST (DT_ISP2289 << 1) uint32_t device_type; #define DT_T10_PI BIT_25 @@ -3807,6 +3821,8 @@ struct qla_hw_data { #define IS_QLA2071(ha) (DT_MASK(ha) & DT_ISP2071) #define IS_QLA2271(ha) (DT_MASK(ha) & DT_ISP2271) #define IS_QLA2261(ha) (DT_MASK(ha) & DT_ISP2261) +#define IS_QLA2081(ha) (DT_MASK(ha) & DT_ISP2081) +#define IS_QLA2281(ha) (DT_MASK(ha) & DT_ISP2281) #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ IS_QLA6312(ha) || IS_QLA6322(ha)) @@ -3816,6 +3832,7 @@ struct qla_hw_data { #define IS_QLA83XX(ha) (IS_QLA2031(ha) || IS_QLA8031(ha)) #define IS_QLA84XX(ha) (IS_QLA8432(ha)) #define IS_QLA27XX(ha) (IS_QLA2071(ha) || IS_QLA2271(ha) || IS_QLA2261(ha)) +#define IS_QLA28XX(ha) (IS_QLA2081(ha) || IS_QLA2281(ha)) #define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \ IS_QLA84XX(ha)) #define IS_CNA_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA82XX(ha) || \ @@ -3824,14 +3841,15 @@ struct qla_hw_data { #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \ IS_QLA25XX(ha) || IS_QLA81XX(ha) || \ IS_QLA82XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA8044(ha) || IS_QLA27XX(ha)) + IS_QLA8044(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_NOPOLLING_TYPE(ha) (IS_QLA81XX(ha) && (ha)->flags.msix_enabled) #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha)) #define IS_T10_PI_CAPABLE(ha) ((ha)->device_type & DT_T10_PI) @@ -3842,28 +3860,34 @@ struct qla_hw_data { #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) #define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED) #define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) -#define IS_BIDI_CAPABLE(ha) ((IS_QLA25XX(ha) || IS_QLA2031(ha))) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BIDI_CAPABLE(ha) \ + (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) /* Bit 21 of fw_attributes decides the MCTP capabilities */ #define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \ ((ha)->fw_attributes_ext[0] & BIT_0)) #define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_PI_DIFB_DIX0_CAPABLE(ha) (0) -#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) +#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \ (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22)) -#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) +#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length) -#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha)) -#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) -#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) +#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) +#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_EXCHG_OFFLD_CAPABLE(ha) \ - (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_EXLOGIN_OFFLD_CAPABLE(ha) \ - (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\ - IS_QLA83XX(ha) || IS_QLA27XX(ha)) + IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) /* HBA serial number */ uint8_t serial0; @@ -4614,6 +4638,7 @@ struct qla2_sgx { #define OPTROM_SIZE_81XX 0x400000 #define OPTROM_SIZE_82XX 0x800000 #define OPTROM_SIZE_83XX 0x1000000 +#define OPTROM_SIZE_28XX 0x2000000 #define OPTROM_BURST_SIZE 0x1000 #define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) @@ -4710,10 +4735,11 @@ struct sff_8247_a0 { #define AUTO_DETECT_SFP_SUPPORT(_vha)\ (ql2xautodetectsfp && !_vha->vp_idx && \ (IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\ - IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw))) + IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \ + IS_QLA28XX(_vha->hw))) #define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \ - (IS_QLA27XX(_ha) || IS_QLA83XX(_ha))) + (IS_QLA27XX(_ha) || IS_QLA28XX(_ha) || IS_QLA83XX(_ha))) #define SAVE_TOPO(_ha) { \ if (_ha->current_topology) \ diff --git a/qla2x00t-32gbit/qla_dfs.c b/qla2x00t-32gbit/qla_dfs.c index 5cecfdbb1..b3803e74a 100644 --- a/qla2x00t-32gbit/qla_dfs.c +++ b/qla2x00t-32gbit/qla_dfs.c @@ -386,7 +386,7 @@ qla_dfs_naqp_write(struct file *file, const char __user *buffer, int rc = 0; unsigned long num_act_qp; - if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha))) { + if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))) { pr_err("host%ld: this adapter does not support Multi Q.", vha->host_no); return -EINVAL; @@ -438,7 +438,7 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto out; if (!ha->fce) goto out; @@ -474,7 +474,7 @@ create_nodes: ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess", S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops); - if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) ha->tgt.dfs_naqp = debugfs_create_file("naqp", 0400, ha->dfs_dir, vha, &dfs_naqp_ops); out: diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index e4b7ae4c9..d47920c1c 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -2016,6 +2016,8 @@ struct ex_init_cb_81xx { #define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000 #define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000 +#define FARX_ACCESS_FLASH_CONF_28XX 0x7FFD0000 +#define FARX_ACCESS_FLASH_DATA_28XX 0x7F7D0000 /* FCP priority config defines *************************************/ /* operations */ @@ -2090,6 +2092,7 @@ struct qla_fcp_prio_cfg { #define FA_NPIV_CONF1_ADDR_81 0xD2000 /* 83XX Flash locations -- occupies second 8MB region. */ -#define FA_FLASH_LAYOUT_ADDR_83 0xFC400 +#define FA_FLASH_LAYOUT_ADDR_83 (0x3F1000/4) +#define FA_FLASH_LAYOUT_ADDR_28 (0x11000/4) #endif diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index e6bf55b4c..af4b38306 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -1794,7 +1794,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha) if (IS_CNA_CAPABLE(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha)) + else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_32GB| FDMI_PORT_SPEED_16GB| @@ -2373,7 +2373,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) if (IS_CNA_CAPABLE(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha)) + else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_32GB| FDMI_PORT_SPEED_16GB| diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index af1547a49..571351f8f 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3015,7 +3015,7 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t *vha) if (IS_FWI2_CAPABLE(ha)) { /* Allocate memory for Fibre Channel Event Buffer. */ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto try_eft; if (ha->fce) @@ -3103,7 +3103,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mem_size = (ha->fw_memory_size - 0x11000 + 1) * sizeof(uint16_t); } else if (IS_FWI2_CAPABLE(ha)) { - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem); else if (IS_QLA81XX(ha)) fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); @@ -3115,7 +3115,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mem_size = (ha->fw_memory_size - 0x100000 + 1) * sizeof(uint32_t); if (ha->mqenable) { - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && + !IS_QLA28XX(ha)) mq_size = sizeof(struct qla2xxx_mq_chain); /* * Allocate maximum buffer size for all queues. @@ -3130,7 +3131,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mq_size += ha->tgt.atio_q_length * sizeof(request_t); /* Allocate memory for Fibre Channel Event Buffer. */ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto try_eft; fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE; @@ -3140,7 +3141,7 @@ try_eft: eft_size = EFT_SIZE; } - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (!ha->fw_dump_template) { ql_log(ql_log_warn, vha, 0x00ba, "Failed missing fwdump template\n"); @@ -3183,7 +3184,7 @@ allocate: "Allocated (%d KB) for firmware dump.\n", dump_size / 1024); - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) return; ha->fw_dump->signature[0] = 'Q'; @@ -3495,7 +3496,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) if (rval == QLA_SUCCESS) { qla24xx_detect_sfp(vha); - if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) && + if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) && (ha->zio_mode == QLA_ZIO_MODE_6)) qla27xx_set_zio_threshold(vha, ha->last_zio_threshold); @@ -3567,7 +3569,7 @@ enable_82xx_npiv: spin_unlock_irqrestore(&ha->hardware_lock, flags); } - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ha->flags.fac_supported = 1; else if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) { uint32_t size; @@ -3582,7 +3584,8 @@ enable_82xx_npiv: ha->fw_major_version, ha->fw_minor_version, ha->fw_subminor_version); - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { ha->flags.fac_supported = 0; rval = QLA_SUCCESS; } @@ -3735,7 +3738,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) /* Move PUREX, ABTS RX & RIDA to ATIOQ */ if (ql2xmvasynctoatio && - (IS_QLA83XX(ha) || IS_QLA27XX(ha))) { + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) { if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) ha->fw_options[2] |= BIT_11; @@ -3743,7 +3746,8 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] &= ~BIT_11; } - if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { /* * Tell FW to track each exchange to prevent * driver from using stale exchange. @@ -3840,7 +3844,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha) if (IS_SHADOW_REG_CAPABLE(ha)) icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29); - if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS); icb->rid = cpu_to_le16(rid); if (ha->flags.msix_enabled) { @@ -7211,6 +7216,7 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) uint32_t *wptr; uint32_t cnt, chksum, size; struct qla_hw_data *ha = vha->hw; + uint32_t signature; valid_pri_image = valid_sec_image = 1; ha->active_image = 0; @@ -7224,7 +7230,9 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status), ha->flt_region_img_status_pri, size); - if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) { + signature = le32_to_cpu(pri_image_status.signature); + if (signature != QLA27XX_IMG_STATUS_SIGN && + signature != QLA28XX_IMG_STATUS_SIGN) { ql_dbg(ql_dbg_init, vha, 0x018b, "Primary image signature (0x%x) not valid\n", pri_image_status.signature); @@ -7254,7 +7262,9 @@ check_sec_image: qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status), ha->flt_region_img_status_sec, size); - if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) { + signature = le32_to_cpu(sec_image_status.signature); + if (signature != QLA27XX_IMG_STATUS_SIGN && + signature != QLA28XX_IMG_STATUS_SIGN) { ql_dbg(ql_dbg_init, vha, 0x018d, "Secondary image signature(0x%x) not valid\n", sec_image_status.signature); @@ -7314,7 +7324,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, dcode = (uint32_t *)req->ring; *srisc_addr = 0; - if (IS_QLA27XX(ha) && + if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) faddr = ha->flt_region_fw_sec; @@ -7378,7 +7388,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, segments--; } - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return rval; if (ha->fw_dump_template) @@ -7646,7 +7656,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) segments--; } - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return rval; if (ha->fw_dump_template) @@ -8151,7 +8161,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ha->login_retry_count = ql2xloginretrycount; /* if not running MSI-X we need handshaking on interrupts */ - if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha))) + if (!vha->hw->flags.msix_enabled && + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) icb->firmware_options_2 |= cpu_to_le32(BIT_22); /* Enable ZIO. */ @@ -8184,7 +8195,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) /* N2N: driver will initiate Login instead of FW */ icb->firmware_options_3 |= BIT_8; - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { icb->firmware_options_3 |= BIT_8; ql_dbg(ql_log_info, vha, 0x0075, "Enabling direct connection.\n"); @@ -8597,7 +8608,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, qpair->msix->in_use = 1; list_add_tail(&qpair->qp_list_elem, &vha->qp_list); qpair->pdev = ha->pdev; - if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) qpair->reqq_start_iocbs = qla_83xx_start_iocbs; mutex_unlock(&ha->mq_lock); diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index a2c7d0f52..86de44202 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -467,7 +467,7 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) req->ring_ptr++; /* Set chip new ring index. */ - if (ha->mqenable || IS_QLA27XX(ha)) { + if (ha->mqenable || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { WRT_REG_DWORD(req->req_q_in, req->ring_index); } else if (IS_QLA83XX(ha)) { WRT_REG_DWORD(req->req_q_in, req->ring_index); @@ -2332,7 +2332,8 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) if (req->cnt < req_cnt + 2) { if (qpair->use_shadow_reg) cnt = *req->out_ptr; - else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) cnt = RD_REG_DWORD(®->isp25mq.req_q_out); else if (IS_P3P_TYPE(ha)) cnt = RD_REG_DWORD(®->isp82.req_q_out); diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 6bcfd6c8d..1c0ee5d92 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -720,7 +720,8 @@ skip_rio: break; case MBA_SYSTEM_ERR: /* System Error */ - mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ? + mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) ? RD_REG_WORD(®24->mailbox7) : 0; ql_log(ql_log_warn, vha, 0x5003, "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " @@ -3038,7 +3039,8 @@ process_err: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; case ABTS_RECV_24XX: - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { /* ensure that the ATIO queue is empty */ qlt_handle_abts_recv(vha, rsp, (response_t *)pkt); @@ -3111,7 +3113,7 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha) struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return; rval = QLA_SUCCESS; @@ -3644,7 +3646,7 @@ msix_register_fail: } /* Enable MSI-X vector for response queue update for queue 0 */ - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (ha->msixbase && ha->mqiobase && (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 || ql2xmqsupport)) @@ -3686,7 +3688,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) /* If possible, enable MSI-X. */ if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && - !IS_QLAFX00(ha) && !IS_QLA27XX(ha))) + !IS_QLAFX00(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))) goto skip_msi; if (ql2xenablemsix == 2) @@ -3725,7 +3727,7 @@ skip_msix: if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && !IS_QLA8001(ha) && !IS_P3P_TYPE(ha) && !IS_QLAFX00(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto skip_msi; #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 4504f7111..4f2dd9ae4 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -660,7 +660,7 @@ static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) { uint16_t mb4 = BIT_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mb4 |= ha->long_range_distance << LR_DIST_FW_POS; return mb4; @@ -670,7 +670,7 @@ static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha) { uint16_t mb4 = BIT_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { struct nvram_81xx *nv = ha->nvram; mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features); @@ -715,7 +715,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[4] = 0; ha->flags.using_lr_setting = 0; if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha)) { + IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (ql2xautodetectsfp) { if (ha->flags.detected_lr_sfp) { mcp->mb[4] |= @@ -734,10 +734,10 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) } } - if (ql2xnvmeenable && IS_QLA27XX(ha)) + if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha))) mcp->mb[4] |= NVME_ENABLE_FLAG; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { struct nvram_81xx *nv = ha->nvram; /* set minimum speed if specified in nvram */ if (nv->min_link_speed >= 2 && @@ -781,7 +781,8 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) "fw_ability_mask=%x.\n", ha->fw_ability_mask); ql_dbg(ql_dbg_mbx, vha, 0x1027, "exchanges=%x.\n", mcp->mb[1]); - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { ha->max_speed_sup = mcp->mb[2] & BIT_0; ql_dbg(ql_dbg_mbx, vha, 0x119b, "Maximum speed supported=%s.\n", @@ -1057,7 +1058,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8; if (IS_FWI2_CAPABLE(ha)) mcp->in_mb |= MBX_17|MBX_16|MBX_15; - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18| MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8; @@ -1126,7 +1127,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) } } - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { ha->mpi_version[0] = mcp->mb[10] & 0xff; ha->mpi_version[1] = mcp->mb[11] >> 8; ha->mpi_version[2] = mcp->mb[11] & 0xff; @@ -1642,7 +1643,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; if (IS_FWI2_CAPABLE(vha->hw)) mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; - if (IS_QLA27XX(vha->hw)) + if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) mcp->in_mb |= MBX_15; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -1696,7 +1697,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, } } - if (IS_QLA27XX(vha->hw)) + if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) vha->bbcr = mcp->mb[15]; } @@ -1812,7 +1813,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) } /* 1 and 2 should normally be captured. */ mcp->in_mb = MBX_2|MBX_1|MBX_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) /* mb3 is additional info about the installed SFP. */ mcp->in_mb |= MBX_3; mcp->buf_size = size; @@ -1826,7 +1827,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); } else { - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (mcp->mb[2] == 6 || mcp->mb[3] == 2) ql_dbg(ql_dbg_mbx, vha, 0x119d, "Invalid SFP/Validation Failed\n"); @@ -2080,7 +2081,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval); } else { - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (mcp->mb[2] == 6 || mcp->mb[3] == 2) ql_dbg(ql_dbg_mbx, vha, 0x119e, "Invalid SFP/Validation Failed\n"); @@ -2863,7 +2864,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha) mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; mcp->out_mb = MBX_0; mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || IS_QLA27XX(vha->hw)) + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || + IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_12; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -2888,7 +2890,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha) ha->orig_fw_iocb_count = mcp->mb[10]; if (ha->flags.npiv_supported) ha->max_npiv_vports = mcp->mb[11]; - if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) ha->fw_max_fcf_count = mcp->mb[12]; } @@ -3327,7 +3330,7 @@ qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data) mbx_cmd_t *mcp = &mc; if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182, @@ -3366,7 +3369,7 @@ qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data) mbx_cmd_t *mcp = &mc; if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185, @@ -3635,7 +3638,8 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, "Entered %s.\n", __func__); if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) && - !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw)) + !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; if (unlikely(pci_channel_offline(vha->hw->pdev))) @@ -4319,7 +4323,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) mcp->mb[12] = req->qos; mcp->mb[11] = req->vp_idx; mcp->mb[13] = req->rid; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->mb[15] = 0; mcp->mb[4] = req->id; @@ -4333,9 +4337,10 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) mcp->flags = MBX_DMA_OUT; mcp->tov = MBX_TOV_SECONDS * 2; - if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) mcp->in_mb |= MBX_1; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { mcp->out_mb |= MBX_15; /* debug q create issue in SR-IOV */ mcp->in_mb |= MBX_9 | MBX_8 | MBX_7; @@ -4344,7 +4349,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) spin_lock_irqsave(&ha->hardware_lock, flags); if (!(req->options & BIT_0)) { WRT_REG_DWORD(req->req_q_in, 0); - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) WRT_REG_DWORD(req->req_q_out, 0); } spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -4388,7 +4393,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) mcp->mb[5] = rsp->length; mcp->mb[14] = rsp->msix->entry; mcp->mb[13] = rsp->rid; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->mb[15] = 0; mcp->mb[4] = rsp->id; @@ -4405,7 +4410,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) if (IS_QLA81XX(ha)) { mcp->out_mb |= MBX_12|MBX_11|MBX_10; mcp->in_mb |= MBX_1; - } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10; mcp->in_mb |= MBX_1; /* debug q create issue in SR-IOV */ @@ -4415,7 +4420,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) spin_lock_irqsave(&ha->hardware_lock, flags); if (!(rsp->options & BIT_0)) { WRT_REG_DWORD(rsp->rsp_q_out, 0); - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) WRT_REG_DWORD(rsp->rsp_q_in, 0); } @@ -4473,7 +4478,7 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) "Entered %s.\n", __func__); if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; @@ -4505,7 +4510,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) mbx_cmd_t *mcp = &mc; if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df, @@ -4540,7 +4545,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) mbx_cmd_t *mcp = &mc; if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, @@ -5279,7 +5284,7 @@ qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode) mcp->out_mb = MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_2|MBX_1|MBX_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_4|MBX_3; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -5317,7 +5322,7 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) mcp->mb[1] = QLA_GET_DATA_RATE; mcp->out_mb = MBX_1|MBX_0; mcp->in_mb = MBX_2|MBX_1|MBX_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_3; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -5347,7 +5352,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) "Entered %s.\n", __func__); if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA8044(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_GET_PORT_CONFIG; mcp->out_mb = MBX_0; @@ -5843,7 +5848,7 @@ qla83xx_wr_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130, @@ -5918,7 +5923,7 @@ qla83xx_rd_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t *data) struct qla_hw_data *ha = vha->hw; unsigned long retry_max_time = jiffies + (2 * HZ); - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx, vha, 0x114b, "Entered %s.\n", __func__); @@ -5968,7 +5973,7 @@ qla83xx_restart_nic_firmware(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__); @@ -6102,7 +6107,8 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha, mbx_cmd_t *mcp = &mc; dma_addr_t dd_dma; - if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw)) + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f, diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 7f0cfb78d..19cce3439 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -467,7 +467,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, qla_cpu_update(rsp->qpair, raw_smp_processor_id()); ha->base_qpair->pdev = ha->pdev; - if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) ha->base_qpair->reqq_start_iocbs = qla_83xx_start_iocbs; } @@ -2809,6 +2809,24 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type |= DT_T10_PI; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; + case PCI_DEVICE_ID_QLOGIC_ISP2081: + case PCI_DEVICE_ID_QLOGIC_ISP2089: + ha->isp_type |= DT_ISP2081; + ha->device_type |= DT_ZIO_SUPPORTED; + ha->device_type |= DT_FWI2; + ha->device_type |= DT_IIDMA; + ha->device_type |= DT_T10_PI; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2281: + case PCI_DEVICE_ID_QLOGIC_ISP2289: + ha->isp_type |= DT_ISP2281; + ha->device_type |= DT_ZIO_SUPPORTED; + ha->device_type |= DT_FWI2; + ha->device_type |= DT_IIDMA; + ha->device_type |= DT_T10_PI; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; + break; } if (IS_QLA82XX(ha)) @@ -2816,7 +2834,8 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) else { /* Get adapter physical port no from interrupt pin register. */ pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no); - if (IS_QLA27XX(ha)) + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || + IS_QLA27XX(ha) || IS_QLA28XX(ha)) ha->port_no--; else ha->port_no = !(ha->port_no & 1); @@ -2913,7 +2932,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8044 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2071 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2271 || - pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261) { + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2081 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2281 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2089 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2289) { bars = pci_select_bars(pdev, IORESOURCE_MEM); mem_only = 1; ql_dbg_pci(ql_dbg_init, pdev, 0x0007, @@ -2962,7 +2985,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Set EEH reset type to fundamental if required by hba */ if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha) || - IS_QLA83XX(ha) || IS_QLA27XX(ha)) + IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) pdev->needs_freset = 1; ha->prev_topology = 0; @@ -3141,6 +3164,23 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; ha->nvram_conf_off = ~0; ha->nvram_data_off = ~0; + } else if (IS_QLA28XX(ha)) { + ha->portnum = PCI_FUNC(ha->pdev->devfn); + ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; + ha->mbx_count = MAILBOX_REGISTER_COUNT; + req_length = REQUEST_ENTRY_CNT_24XX; + rsp_length = RESPONSE_ENTRY_CNT_2300; + ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; + ha->max_loop_id = SNS_LAST_LOOP_ID_2300; + ha->init_cb_size = sizeof(struct mid_init_cb_81xx); + ha->gid_list_info_size = 8; + ha->optrom_size = OPTROM_SIZE_28XX; + ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; + ha->isp_ops = &qla27xx_isp_ops; + ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_28XX; + ha->flash_data_off = FARX_ACCESS_FLASH_DATA_28XX; + ha->nvram_conf_off = ~0; + ha->nvram_data_off = ~0; } ql_dbg_pci(ql_dbg_init, pdev, 0x001e, @@ -3308,7 +3348,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) req->req_q_out = &ha->iobase->isp24.req_q_out; rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in; rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out; - if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { req->req_q_in = &ha->mqiobase->isp25mq.req_q_in; req->req_q_out = &ha->mqiobase->isp25mq.req_q_out; rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in; @@ -3634,7 +3675,8 @@ qla2x00_shutdown(struct pci_dev *pdev) if (ha->eft) qla2x00_disable_eft_trace(vha); - if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { if (ha->flags.fw_started) qla2x00_abort_isp_cleanup(vha); } else { @@ -3739,7 +3781,8 @@ qla2x00_unmap_iobases(struct qla_hw_data *ha) if (ha->mqiobase) iounmap(ha->mqiobase); - if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) && ha->msixbase) + if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + ha->msixbase) iounmap(ha->msixbase); } } @@ -3790,7 +3833,8 @@ qla2x00_remove_one(struct pci_dev *pdev) } qla2x00_wait_for_hba_ready(base_vha); - if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { if (ha->flags.fw_started) qla2x00_abort_isp_cleanup(base_vha); } else if (!IS_QLAFX00(ha)) { @@ -4280,7 +4324,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, ha->npiv_info = NULL; /* Get consistent memory allocated for EX-INIT-CB. */ - if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &ha->ex_init_cb_dma); if (!ha->ex_init_cb) @@ -6756,7 +6801,7 @@ qla2x00_timer(struct timer_list *t) if (!vha->vp_idx && (atomic_read(&ha->zio_threshold) != ha->last_zio_threshold) && (ha->zio_mode == QLA_ZIO_MODE_6) && - (IS_QLA83XX(ha) || IS_QLA27XX(ha))) { + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) { ql_log(ql_log_info, vha, 0x3002, "Sched: Set ZIO exchange threshold to %d.\n", ha->last_zio_threshold); @@ -6802,7 +6847,6 @@ qla2x00_timer(struct timer_list *t) /* Firmware interface routines. */ -#define FW_BLOBS 11 #define FW_ISP21XX 0 #define FW_ISP22XX 1 #define FW_ISP2300 2 @@ -6814,6 +6858,7 @@ qla2x00_timer(struct timer_list *t) #define FW_ISP2031 8 #define FW_ISP8031 9 #define FW_ISP27XX 10 +#define FW_ISP28XX 11 #define FW_FILE_ISP21XX "ql2100_fw.bin" #define FW_FILE_ISP22XX "ql2200_fw.bin" @@ -6826,11 +6871,12 @@ qla2x00_timer(struct timer_list *t) #define FW_FILE_ISP2031 "ql2600_fw.bin" #define FW_FILE_ISP8031 "ql8300_fw.bin" #define FW_FILE_ISP27XX "ql2700_fw.bin" +#define FW_FILE_ISP28XX "ql2800_fw.bin" static DEFINE_MUTEX(qla_fw_lock); -static struct fw_blob qla_fw_blobs[FW_BLOBS] = { +static struct fw_blob qla_fw_blobs[] = { { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, }, { .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, }, { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, }, @@ -6842,6 +6888,8 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = { { .name = FW_FILE_ISP2031, }, { .name = FW_FILE_ISP8031, }, { .name = FW_FILE_ISP27XX, }, + { .name = FW_FILE_ISP28XX, }, + { .name = NULL, }, }; struct fw_blob * @@ -6872,10 +6920,15 @@ qla2x00_request_firmware(scsi_qla_host_t *vha) blob = &qla_fw_blobs[FW_ISP8031]; } else if (IS_QLA27XX(ha)) { blob = &qla_fw_blobs[FW_ISP27XX]; + } else if (IS_QLA28XX(ha)) { + blob = &qla_fw_blobs[FW_ISP28XX]; } else { return NULL; } + if (!blob->name) + return NULL; + mutex_lock(&qla_fw_lock); if (blob->fw) goto out; @@ -6885,7 +6938,6 @@ qla2x00_request_firmware(scsi_qla_host_t *vha) "Failed to load firmware image (%s).\n", blob->name); blob->fw = NULL; blob = NULL; - goto out; } out: @@ -6896,11 +6948,11 @@ out: static void qla2x00_release_firmware(void) { - int idx; + struct fw_blob *blob; mutex_lock(&qla_fw_lock); - for (idx = 0; idx < FW_BLOBS; idx++) - release_firmware(qla_fw_blobs[idx].fw); + for (blob = qla_fw_blobs; blob->name; blob++) + release_firmware(blob->fw); mutex_unlock(&qla_fw_lock); } @@ -7335,6 +7387,11 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2071) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2271) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2261) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2061) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2081) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2281) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2089) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2289) }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index 2a3055c79..579d6a8c7 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -571,6 +571,9 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { *start = FA_FLASH_LAYOUT_ADDR_83; goto end; + } else if (IS_QLA28XX(ha)) { + *start = FA_FLASH_LAYOUT_ADDR_28; + goto end; } /* Begin with first PCI expansion ROM header. */ buf = (uint8_t *)req->ring; @@ -753,13 +756,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ha->flt_region_vpd = start; break; case FLT_REG_VPD_2: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 2) ha->flt_region_vpd = start; break; case FLT_REG_VPD_3: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 3) ha->flt_region_vpd = start; @@ -777,13 +780,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ha->flt_region_nvram = start; break; case FLT_REG_NVRAM_2: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 2) ha->flt_region_nvram = start; break; case FLT_REG_NVRAM_3: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 3) ha->flt_region_nvram = start; @@ -847,35 +850,35 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ha->flt_region_nvram = start; break; case FLT_REG_IMG_PRI_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_img_status_pri = start; break; case FLT_REG_IMG_SEC_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_img_status_sec = start; break; case FLT_REG_FW_SEC_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_fw_sec = start; break; case FLT_REG_BOOTLOAD_SEC_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_boot_sec = start; break; case FLT_REG_VPD_SEC_27XX_0: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_vpd_sec = start; break; case FLT_REG_VPD_SEC_27XX_1: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_vpd_sec = start; break; case FLT_REG_VPD_SEC_27XX_2: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_vpd_sec = start; break; case FLT_REG_VPD_SEC_27XX_3: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_vpd_sec = start; break; } @@ -1045,7 +1048,8 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && - !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha)) + !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_SUCCESS; ret = qla2xxx_find_flt_start(vha, &flt_addr); @@ -1248,7 +1252,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, /* Prepare burst-capable write on supported ISPs. */ if ((IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha)) && + IS_QLA27XX(ha) || IS_QLA28XX(ha)) && !(faddr & 0xfff) && dwords > OPTROM_BURST_DWORDS) { optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, &optrom_dma, GFP_KERNEL); @@ -1728,7 +1732,7 @@ qla83xx_select_led_port(struct qla_hw_data *ha) { uint32_t led_select_value = 0; - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto out; if (ha->port_no == 0) @@ -1749,13 +1753,14 @@ qla83xx_beacon_blink(struct scsi_qla_host *vha) uint16_t orig_led_cfg[6]; uint32_t led_10_value, led_43_value; - if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha) && + !IS_QLA28XX(ha)) return; if (!ha->beacon_blink_led) return; - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { qla2x00_write_ram_word(vha, 0x1003, 0x40000230); qla2x00_write_ram_word(vha, 0x1004, 0x40000230); } else if (IS_QLA2031(ha)) { @@ -1845,7 +1850,7 @@ qla24xx_beacon_on(struct scsi_qla_host *vha) return QLA_FUNCTION_FAILED; } - if (IS_QLA2031(ha) || IS_QLA27XX(ha)) + if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) goto skip_gpio; spin_lock_irqsave(&ha->hardware_lock, flags); @@ -1885,7 +1890,7 @@ qla24xx_beacon_off(struct scsi_qla_host *vha) ha->beacon_blink_led = 0; - if (IS_QLA2031(ha) || IS_QLA27XX(ha)) + if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) goto set_fw_options; if (IS_QLA8031(ha) || IS_QLA81XX(ha)) @@ -2620,7 +2625,7 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, struct qla_hw_data *ha = vha->hw; if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) goto try_fast; if (offset & 0xfff) goto slow_read; @@ -3042,7 +3047,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) dcode = mbuf; pcihdr = ha->flt_region_boot << 2; - if (IS_QLA27XX(ha) && + if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) pcihdr = ha->flt_region_boot_sec << 2; @@ -3119,7 +3124,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dcode = mbuf; faddr = ha->flt_region_fw; - if (IS_QLA27XX(ha) && + if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) faddr = ha->flt_region_fw_sec; diff --git a/qla2x00t-32gbit/qla_target.c b/qla2x00t-32gbit/qla_target.c index d6331a5e6..a320732a4 100644 --- a/qla2x00t-32gbit/qla_target.c +++ b/qla2x00t-32gbit/qla_target.c @@ -6985,7 +6985,7 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha) RD_REG_DWORD(ISP_ATIO_Q_OUT(vha)); if (ha->flags.msix_enabled) { - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (IS_QLA2071(ha)) { /* 4 ports Baker: Enable Interrupt Handshake */ icb->msix_atio = 0; @@ -7000,7 +7000,7 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha) } } else { /* INTx|MSI */ - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { icb->msix_atio = 0; icb->firmware_options_2 |= BIT_26; ql_dbg(ql_dbg_init, vha, 0xf072, @@ -7249,7 +7249,8 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) if (!QLA_TGT_MODE_ENABLED()) return; - if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in; ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out; } else { From e2ded798c0e767609f1b57b969bb81add625c798 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:14:38 +0000 Subject: [PATCH 06/42] qla2xxx: Add Serdes support for ISP28XX This patch adds sysfs node for serdes_version and also cleans up port_speed display. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8200 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 43 +++++++++++++++------ qla2x00t-32gbit/qla_def.h | 4 +- qla2x00t-32gbit/qla_gs.c | 77 ++++++++++++++------------------------ qla2x00t-32gbit/qla_isr.c | 4 +- qla2x00t-32gbit/qla_mbx.c | 25 ++++++++----- 5 files changed, 82 insertions(+), 71 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index f035251a8..93da79a0c 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -1377,6 +1377,21 @@ qla24xx_84xx_fw_version_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "\n"); } +static ssize_t +qla2x00_serdes_version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", + ha->serdes_version[0], ha->serdes_version[1], + ha->serdes_version[2]); +} + static ssize_t qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2220,6 +2235,7 @@ static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show, NULL); static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, NULL); +static DEVICE_ATTR(serdes_version, 0444, qla2x00_serdes_version_show, NULL); static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL); static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show, @@ -2272,6 +2288,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_optrom_fw_version, &dev_attr_84xx_fw_version, &dev_attr_total_isp_aborts, + &dev_attr_serdes_version, &dev_attr_mpi_version, &dev_attr_phy_version, &dev_attr_flash_block_size, @@ -2328,16 +2345,15 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost) static void qla2x00_get_host_speed(struct Scsi_Host *shost) { - struct qla_hw_data *ha = ((struct scsi_qla_host *) - (shost_priv(shost)))->hw; - u32 speed = FC_PORTSPEED_UNKNOWN; + scsi_qla_host_t *vha = shost_priv(shost); + u32 speed; - if (IS_QLAFX00(ha)) { + if (IS_QLAFX00(vha->hw)) { qlafx00_get_host_speed(shost); return; } - switch (ha->link_data_rate) { + switch (vha->hw->link_data_rate) { case PORT_SPEED_1GB: speed = FC_PORTSPEED_1GBIT; break; @@ -2362,7 +2378,11 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) case PORT_SPEED_64GB: speed = FC_PORTSPEED_64GBIT; break; + default: + speed = FC_PORTSPEED_UNKNOWN; + break; } + fc_host_speed(shost) = speed; } @@ -2370,7 +2390,7 @@ static void qla2x00_get_host_port_type(struct Scsi_Host *shost) { scsi_qla_host_t *vha = shost_priv(shost); - uint32_t port_type = FC_PORTTYPE_UNKNOWN; + uint32_t port_type; if (vha->vp_idx) { fc_host_port_type(shost) = FC_PORTTYPE_NPIV; @@ -2389,7 +2409,11 @@ qla2x00_get_host_port_type(struct Scsi_Host *shost) case ISP_CFG_F: port_type = FC_PORTTYPE_NPORT; break; + default: + port_type = FC_PORTTYPE_UNKNOWN; + break; } + fc_host_port_type(shost) = port_type; } @@ -2451,13 +2475,10 @@ qla2x00_get_starget_port_id(struct scsi_target *starget) fc_starget_port_id(starget) = port_id; } -static void +static inline void qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { - if (timeout) - rport->dev_loss_tmo = timeout; - else - rport->dev_loss_tmo = 1; + rport->dev_loss_tmo = timeout ? timeout : 1; } static void diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index e4ac4f93b..4d28e1921 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4042,6 +4042,7 @@ struct qla_hw_data { uint8_t fw_seriallink_options[4]; uint16_t fw_seriallink_options24[4]; + uint8_t serdes_version[3]; uint8_t mpi_version[3]; uint32_t mpi_capabilities; uint8_t phy_version[3]; @@ -4053,7 +4054,8 @@ struct qla_hw_data { /* Firmware dump information. */ struct qla2xxx_fw_dump *fw_dump; uint32_t fw_dump_len; - int fw_dumped; + bool fw_dumped; + bool fw_dump_mpi; unsigned long fw_dump_cap_flags; #define RISC_PAUSE_CMPL 0 #define DMA_SHUTDOWN_CMPL 1 diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index af4b38306..a2665b0ff 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -2783,6 +2783,31 @@ qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd, return &p->p.req; } +static uint16_t +qla2x00_port_speed_capability(uint16_t speed) +{ + switch (speed) { + case BIT_15: + return PORT_SPEED_1GB; + case BIT_14: + return PORT_SPEED_2GB; + case BIT_13: + return PORT_SPEED_4GB; + case BIT_12: + return PORT_SPEED_10GB; + case BIT_11: + return PORT_SPEED_8GB; + case BIT_10: + return PORT_SPEED_16GB; + case BIT_8: + return PORT_SPEED_32GB; + case BIT_7: + return PORT_SPEED_64GB; + default: + return PORT_SPEED_UNKNOWN; + } +} + /** * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query. * @vha: HA context @@ -2855,31 +2880,8 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list) } rval = QLA_FUNCTION_FAILED; } else { - /* Save port-speed */ - switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) { - case BIT_15: - list[i].fp_speed = PORT_SPEED_1GB; - break; - case BIT_14: - list[i].fp_speed = PORT_SPEED_2GB; - break; - case BIT_13: - list[i].fp_speed = PORT_SPEED_4GB; - break; - case BIT_12: - list[i].fp_speed = PORT_SPEED_10GB; - break; - case BIT_11: - list[i].fp_speed = PORT_SPEED_8GB; - break; - case BIT_10: - list[i].fp_speed = PORT_SPEED_16GB; - break; - case BIT_8: - list[i].fp_speed = PORT_SPEED_32GB; - break; - } - + list->fp_speed = qla2x00_port_speed_capability( + be16_to_cpu(ct_rsp->rsp.gpsc.speed)); ql_dbg(ql_dbg_disc, vha, 0x205b, "GPSC ext entry - fpn " "%8phN speeds=%04x speed=%04x.\n", @@ -3047,29 +3049,8 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res) goto done; } } else { - switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) { - case BIT_15: - fcport->fp_speed = PORT_SPEED_1GB; - break; - case BIT_14: - fcport->fp_speed = PORT_SPEED_2GB; - break; - case BIT_13: - fcport->fp_speed = PORT_SPEED_4GB; - break; - case BIT_12: - fcport->fp_speed = PORT_SPEED_10GB; - break; - case BIT_11: - fcport->fp_speed = PORT_SPEED_8GB; - break; - case BIT_10: - fcport->fp_speed = PORT_SPEED_16GB; - break; - case BIT_8: - fcport->fp_speed = PORT_SPEED_32GB; - break; - } + fcport->fp_speed = qla2x00_port_speed_capability( + be16_to_cpu(ct_rsp->rsp.gpsc.speed)); ql_dbg(ql_dbg_disc, vha, 0x2054, "Async-%s OUT WWPN %s speeds=%04x speed=%04x.\n", diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 1c0ee5d92..a8771b741 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -726,7 +726,9 @@ skip_rio: ql_log(ql_log_warn, vha, 0x5003, "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); - + ha->fw_dump_mpi = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + RD_REG_WORD(®24->mailbox7) & BIT_8; ha->isp_ops->fw_dump(vha, 1); ha->flags.fw_init_done = 0; QLA_FW_STOPPED(ha); diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 4f2dd9ae4..0973d3eab 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -638,14 +638,15 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, mcp->out_mb |= MBX_4; } - mcp->in_mb = MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1023, - "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + "Failed=%x mb[0]=%x mb[1]=%x.\n", + rval, mcp->mb[0], mcp->mb[1]); } else { ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024, "Done %s.\n", __func__); @@ -1061,7 +1062,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18| - MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8; + MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7; mcp->flags = 0; mcp->tov = MBX_TOV_SECONDS; @@ -1128,6 +1129,9 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) } if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->serdes_version[0] = mcp->mb[7] & 0xff; + ha->serdes_version[1] = mcp->mb[8] >> 8; + ha->serdes_version[2] = mcp->mb[8] & 0xff; ha->mpi_version[0] = mcp->mb[10] & 0xff; ha->mpi_version[1] = mcp->mb[11] >> 8; ha->mpi_version[2] = mcp->mb[11] & 0xff; @@ -3752,7 +3756,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, rval = qla2x00_mailbox_command(vha, mcp); /* Return mailbox statuses. */ - if (mb != NULL) { + if (mb) { mb[0] = mcp->mb[0]; mb[1] = mcp->mb[1]; mb[3] = mcp->mb[3]; @@ -3787,7 +3791,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, mcp->mb[0] = MBC_PORT_PARAMS; mcp->mb[1] = loop_id; mcp->mb[2] = BIT_0; - mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0); + mcp->mb[3] = port_speed & 0x3F; mcp->mb[9] = vha->vp_idx; mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_3|MBX_1|MBX_0; @@ -3796,7 +3800,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, rval = qla2x00_mailbox_command(vha, mcp); /* Return mailbox statuses. */ - if (mb != NULL) { + if (mb) { mb[0] = mcp->mb[0]; mb[1] = mcp->mb[1]; mb[3] = mcp->mb[3]; @@ -4824,10 +4828,10 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x10e9, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); - if (mcp->mb[0] == MBS_COMMAND_ERROR && - mcp->mb[1] == 0x22) + if (mcp->mb[0] == MBS_COMMAND_ERROR && mcp->mb[1] == 0x22) { /* sfp is not there */ rval = QLA_INTERFACE_ERROR; + } } else { ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, "Done %s.\n", __func__); @@ -5167,13 +5171,14 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) mcp->mb[3] = MSW(data); mcp->mb[8] = MSW(risc_addr); mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1101, - "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + "Failed=%x mb[0]=%x mb[1]=%x.\n", + rval, mcp->mb[0], mcp->mb[1]); } else { ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102, "Done %s.\n", __func__); From e8995d41eec8cd1d40dc6dde66e0a96ab55eb0eb Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:15:08 +0000 Subject: [PATCH 07/42] qla2xxx: Correctly report max/min supported speeds This patch fixes reported speed for min_link and max_supported speed. Also rename sysfs nodes link_speed and max_supported to be consistent with {min|max}_suuported_speed. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8201 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 94 +++++++++++++++++++++++--------------- qla2x00t-32gbit/qla_def.h | 7 +-- qla2x00t-32gbit/qla_fw.h | 2 +- qla2x00t-32gbit/qla_mbx.c | 67 ++++++++++++++------------- 4 files changed, 99 insertions(+), 71 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 93da79a0c..e762e60ae 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -1621,8 +1621,8 @@ qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr, } static ssize_t -qla2x00_min_link_speed_show(struct device *dev, struct device_attribute *attr, - char *buf) +qla2x00_min_supported_speed_show(struct device *dev, + struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; @@ -1631,16 +1631,17 @@ qla2x00_min_link_speed_show(struct device *dev, struct device_attribute *attr, return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%s\n", - ha->min_link_speed == 5 ? "32Gps" : - ha->min_link_speed == 4 ? "16Gps" : - ha->min_link_speed == 3 ? "8Gps" : - ha->min_link_speed == 2 ? "4Gps" : - ha->min_link_speed != 0 ? "unknown" : ""); + ha->min_supported_speed == 6 ? "64Gps" : + ha->min_supported_speed == 5 ? "32Gps" : + ha->min_supported_speed == 4 ? "16Gps" : + ha->min_supported_speed == 3 ? "8Gps" : + ha->min_supported_speed == 2 ? "4Gps" : + ha->min_supported_speed != 0 ? "unknown" : ""); } static ssize_t -qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr, - char *buf) +qla2x00_max_supported_speed_show(struct device *dev, + struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; @@ -1649,7 +1650,9 @@ qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr, return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%s\n", - ha->max_speed_sup ? "32Gps" : "16Gps"); + ha->max_supported_speed == 2 ? "64Gps" : + ha->max_supported_speed == 1 ? "32Gps" : + ha->max_supported_speed == 0 ? "16Gps" : "unknown"); } static ssize_t @@ -2253,8 +2256,10 @@ static DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR, qla2x00_allow_cna_fw_dump_show, qla2x00_allow_cna_fw_dump_store); static DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL); -static DEVICE_ATTR(min_link_speed, S_IRUGO, qla2x00_min_link_speed_show, NULL); -static DEVICE_ATTR(max_speed_sup, S_IRUGO, qla2x00_max_speed_sup_show, NULL); +static DEVICE_ATTR(min_supported_speed, 0444, + qla2x00_min_supported_speed_show, NULL); +static DEVICE_ATTR(max_supported_speed, 0444, + qla2x00_max_supported_speed_show, NULL); static DEVICE_ATTR(zio_threshold, 0644, qla_zio_threshold_show, qla_zio_threshold_store); @@ -2303,8 +2308,8 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_fw_dump_size, &dev_attr_allow_cna_fw_dump, &dev_attr_pep_version, - &dev_attr_min_link_speed, - &dev_attr_max_speed_sup, + &dev_attr_min_supported_speed, + &dev_attr_max_supported_speed, &dev_attr_zio_threshold, &dev_attr_dif_bundle_statistics, &dev_attr_port_speed, @@ -3033,7 +3038,7 @@ void qla2x00_init_host_attr(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - u32 speed = FC_PORTSPEED_UNKNOWN; + u32 speeds = FC_PORTSPEED_UNKNOWN; fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); @@ -3044,28 +3049,45 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; if (IS_CNA_CAPABLE(ha)) - speed = FC_PORTSPEED_10GBIT; - else if (IS_QLA2031(ha)) - speed = FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT | - FC_PORTSPEED_4GBIT; - else if (IS_QLA25XX(ha)) - speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | - FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; + speeds = FC_PORTSPEED_10GBIT; + else if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= FC_PORTSPEED_64GBIT; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= FC_PORTSPEED_32GBIT; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= FC_PORTSPEED_16GBIT; + } + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= FC_PORTSPEED_8GBIT; + } + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= FC_PORTSPEED_4GBIT; + } + } else if (IS_QLA2031(ha)) + speeds = FC_PORTSPEED_16GBIT|FC_PORTSPEED_8GBIT| + FC_PORTSPEED_4GBIT; + else if (IS_QLA25XX(ha) || IS_QLAFX00(ha)) + speeds = FC_PORTSPEED_8GBIT|FC_PORTSPEED_4GBIT| + FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT; else if (IS_QLA24XX_TYPE(ha)) - speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT | - FC_PORTSPEED_1GBIT; + speeds = FC_PORTSPEED_4GBIT|FC_PORTSPEED_2GBIT| + FC_PORTSPEED_1GBIT; else if (IS_QLA23XX(ha)) - speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; - else if (IS_QLAFX00(ha)) - speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | - FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; - else if (IS_QLA27XX(ha)) - speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT | - FC_PORTSPEED_8GBIT; - else if (IS_QLA28XX(ha)) - speed = FC_PORTSPEED_64GBIT | FC_PORTSPEED_32GBIT | - FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT; + speeds = FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT; else - speed = FC_PORTSPEED_1GBIT; - fc_host_supported_speeds(vha->host) = speed; + speeds = FC_PORTSPEED_1GBIT; + + fc_host_supported_speeds(vha->host) = speeds; } diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 4d28e1921..cd835c995 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4242,8 +4242,8 @@ struct qla_hw_data { struct qlt_hw_data tgt; int allow_cna_fw_dump; uint32_t fw_ability_mask; - uint16_t min_link_speed; - uint16_t max_speed_sup; + uint16_t min_supported_speed; + uint16_t max_supported_speed; /* DMA pool for the DIF bundling buffers */ struct dma_pool *dif_bundl_pool; @@ -4474,7 +4474,7 @@ typedef struct scsi_qla_host { int fcport_count; wait_queue_head_t fcport_waitQ; wait_queue_head_t vref_waitq; - uint8_t min_link_speed_feat; + uint8_t min_supported_speed; uint8_t n2n_node_name[WWN_SIZE]; uint8_t n2n_port_name[WWN_SIZE]; uint16_t n2n_id; @@ -4757,4 +4757,5 @@ struct sff_8247_a0 { #include "qla_gbl.h" #include "qla_dbg.h" #include "qla_inline.h" + #endif diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index d47920c1c..2a7691f05 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -1768,7 +1768,7 @@ struct nvram_81xx { uint16_t reserved_6_3[14]; /* Offset 192. */ - uint8_t min_link_speed; + uint8_t min_supported_speed; uint8_t reserved_7_0; uint16_t reserved_7[31]; diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 0973d3eab..f699c8312 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -741,13 +741,14 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { struct nvram_81xx *nv = ha->nvram; /* set minimum speed if specified in nvram */ - if (nv->min_link_speed >= 2 && - nv->min_link_speed <= 5) { + if (nv->min_supported_speed >= 2 && + nv->min_supported_speed <= 5) { mcp->mb[4] |= BIT_4; - mcp->mb[11] = nv->min_link_speed; + mcp->mb[11] |= nv->min_supported_speed & 0xF; mcp->out_mb |= MBX_11; mcp->in_mb |= BIT_5; - vha->min_link_speed_feat = nv->min_link_speed; + vha->min_supported_speed = + nv->min_supported_speed; } } @@ -775,35 +776,39 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1026, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); - } else { - if (IS_FWI2_CAPABLE(ha)) { - ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2]; - ql_dbg(ql_dbg_mbx, vha, 0x119a, - "fw_ability_mask=%x.\n", ha->fw_ability_mask); - ql_dbg(ql_dbg_mbx, vha, 0x1027, - "exchanges=%x.\n", mcp->mb[1]); - if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || - IS_QLA28XX(ha)) { - ha->max_speed_sup = mcp->mb[2] & BIT_0; - ql_dbg(ql_dbg_mbx, vha, 0x119b, - "Maximum speed supported=%s.\n", - ha->max_speed_sup ? "32Gps" : "16Gps"); - if (vha->min_link_speed_feat) { - ha->min_link_speed = mcp->mb[5]; - ql_dbg(ql_dbg_mbx, vha, 0x119c, - "Minimum speed set=%s.\n", - mcp->mb[5] == 5 ? "32Gps" : - mcp->mb[5] == 4 ? "16Gps" : - mcp->mb[5] == 3 ? "8Gps" : - mcp->mb[5] == 2 ? "4Gps" : - "unknown"); - } - } - } - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028, - "Done.\n"); + return rval; } + if (!IS_FWI2_CAPABLE(ha)) + goto done; + + ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2]; + ql_dbg(ql_dbg_mbx, vha, 0x119a, + "fw_ability_mask=%x.\n", ha->fw_ability_mask); + ql_dbg(ql_dbg_mbx, vha, 0x1027, "exchanges=%x.\n", mcp->mb[1]); + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->max_supported_speed = mcp->mb[2] & (BIT_0|BIT_1); + ql_dbg(ql_dbg_mbx, vha, 0x119b, "max_supported_speed=%s.\n", + ha->max_supported_speed == 0 ? "16Gps" : + ha->max_supported_speed == 1 ? "32Gps" : + ha->max_supported_speed == 2 ? "64Gps" : "unknown"); + if (vha->min_supported_speed) { + ha->min_supported_speed = mcp->mb[5] & + (BIT_0 | BIT_1 | BIT_2); + ql_dbg(ql_dbg_mbx, vha, 0x119c, + "min_supported_speed=%s.\n", + ha->min_supported_speed == 6 ? "64Gps" : + ha->min_supported_speed == 5 ? "32Gps" : + ha->min_supported_speed == 4 ? "16Gps" : + ha->min_supported_speed == 3 ? "8Gps" : + ha->min_supported_speed == 2 ? "4Gps" : "unknown"); + } + } + +done: + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028, + "Done %s.\n", __func__); + return rval; } From 201e9ba1360a9b276f2f507adfd35dd5e8607944 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:15:41 +0000 Subject: [PATCH 08/42] qla2xxx: Cleanups for NVRAM/Flash read/write path This patch does following: - Clean up NVRAM code. - Optimizes reading of primary/secondary flash image validation. - Remove 0xff mask and make correct width in FLT structure. - Use endian macros to assign static fields in fwdump header. - Correct fdwt checksum calculation. - Simplify ql_dump_buffer() interface usage. - Add endianizers to 27xx firmware image validator. - fixes compiler warnings for big endian architecture. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8202 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_bsg.c | 6 +- qla2x00t-32gbit/qla_dbg.c | 19 ++-- qla2x00t-32gbit/qla_dbg.h | 10 +- qla2x00t-32gbit/qla_def.h | 2 +- qla2x00t-32gbit/qla_fw.h | 4 +- qla2x00t-32gbit/qla_gbl.h | 10 +- qla2x00t-32gbit/qla_gs.c | 4 +- qla2x00t-32gbit/qla_init.c | 143 +++++++++++++--------------- qla2x00t-32gbit/qla_isr.c | 12 +-- qla2x00t-32gbit/qla_mbx.c | 16 +++- qla2x00t-32gbit/qla_mr.c | 39 ++++---- qla2x00t-32gbit/qla_os.c | 2 +- qla2x00t-32gbit/qla_sup.c | 41 +++------ qla2x00t-32gbit/qla_tmpl.c | 184 ++++++++++++++++++++++--------------- qla2x00t-32gbit/qla_tmpl.h | 74 +++++++-------- 15 files changed, 292 insertions(+), 274 deletions(-) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 1e6ac3da3..dfc771a17 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -2046,7 +2046,7 @@ static int qlafx00_mgmt_cmd(struct bsg_job *bsg_job) /* Dump the vendor information */ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf, - (uint8_t *)piocb_rqst, sizeof(struct qla_mt_iocb_rqst_fx00)); + piocb_rqst, sizeof(*piocb_rqst)); if (!vha->flags.online) { ql_log(ql_log_warn, vha, 0x70d0, @@ -2426,8 +2426,8 @@ static int qla2x00_get_priv_stats(struct bsg_job *bsg_job) rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options); if (rval == QLA_SUCCESS) { - ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3, - (uint8_t *)stats, sizeof(*stats)); + ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e5, + stats, sizeof(*stats)); sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats)); } diff --git a/qla2x00t-32gbit/qla_dbg.c b/qla2x00t-32gbit/qla_dbg.c index 3cfd846cd..94da4b992 100644 --- a/qla2x00t-32gbit/qla_dbg.c +++ b/qla2x00t-32gbit/qla_dbg.c @@ -2520,7 +2520,7 @@ qla83xx_fw_dump_failed: /****************************************************************************/ static inline int -ql_mask_match(uint32_t level) +ql_mask_match(uint level) { return (level & ql2xextended_error_logging) == level; } @@ -2539,7 +2539,7 @@ ql_mask_match(uint32_t level) * msg: The message to be displayed. */ void -ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) +ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2582,8 +2582,7 @@ ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) * msg: The message to be displayed. */ void -ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, - const char *fmt, ...) +ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2619,7 +2618,7 @@ ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, * msg: The message to be displayed. */ void -ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) +ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2677,8 +2676,7 @@ ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) * msg: The message to be displayed. */ void -ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, - const char *fmt, ...) +ql_log_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2718,7 +2716,7 @@ ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, } void -ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id) +ql_dump_regs(uint level, scsi_qla_host_t *vha, uint id) { int i; struct qla_hw_data *ha = vha->hw; @@ -2740,13 +2738,12 @@ ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id) ql_dbg(level, vha, id, "Mailbox registers:\n"); for (i = 0; i < 6; i++, mbx_reg++) ql_dbg(level, vha, id, - "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg)); + "mbox[%d] %#04x\n", i, RD_REG_WORD(mbx_reg)); } void -ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id, - uint8_t *buf, uint size) +ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, void *buf, uint size) { uint cnt; diff --git a/qla2x00t-32gbit/qla_dbg.h b/qla2x00t-32gbit/qla_dbg.h index 8877aa97d..bb01b680c 100644 --- a/qla2x00t-32gbit/qla_dbg.h +++ b/qla2x00t-32gbit/qla_dbg.h @@ -318,20 +318,20 @@ struct qla2xxx_fw_dump { * as compared to other log levels. */ -extern int ql_errlev; +extern uint ql_errlev; void __attribute__((format (printf, 4, 5))) -ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); +ql_dbg(uint, scsi_qla_host_t *vha, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) -ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); +ql_dbg_pci(uint, struct pci_dev *pdev, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) ql_dbg_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) -ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); +ql_log(uint, scsi_qla_host_t *vha, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) -ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); +ql_log_pci(uint, struct pci_dev *pdev, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...); diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index cd835c995..aa17ea89f 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4486,7 +4486,7 @@ typedef struct scsi_qla_host { struct qla27xx_image_status { uint8_t image_status_mask; - uint16_t generation_number; + uint16_t generation; uint8_t reserved[3]; uint8_t ver_minor; uint8_t ver_major; diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index 2a7691f05..0b2419187 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -1527,7 +1527,9 @@ struct qla_flt_header { #define FLT_REG_VPD_SEC_27XX_3 0xDA struct qla_flt_region { - uint32_t code; + uint16_t code; + uint8_t attribute; + uint8_t reserved; uint32_t size; uint32_t start; uint32_t end; diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 96d446ecf..54b3fed28 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -118,6 +118,7 @@ int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); int qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *); void qla_rscn_replay(fc_port_t *fcport); +extern bool qla24xx_risc_firmware_invalid(uint32_t *); /* * Global Data in qla_os.c source file. @@ -616,14 +617,9 @@ extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *); extern int qla27xx_fwdt_template_valid(void *); extern ulong qla27xx_fwdt_template_size(void *); -extern void qla2x00_dump_regs(scsi_qla_host_t *); -extern void qla2x00_dump_buffer(uint8_t *, uint32_t); -extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t); -extern void ql_dump_regs(uint32_t, scsi_qla_host_t *, int32_t); -extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t, - uint8_t *, uint32_t); extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int); - +extern void ql_dump_regs(uint, scsi_qla_host_t *, uint); +extern void ql_dump_buffer(uint, scsi_qla_host_t *, uint, void *, uint); /* * Global Function Prototypes in qla_gs.c source file. */ diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index a2665b0ff..824651ecd 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -152,8 +152,8 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt, vha->d_id.b.area, vha->d_id.b.al_pa, comp_status, ct_rsp->header.response); ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, - 0x2078, (uint8_t *)&ct_rsp->header, - sizeof(struct ct_rsp_hdr)); + 0x2078, ct_rsp, + offsetof(typeof(*ct_rsp), rsp)); rval = QLA_INVALID_COMMAND; } else rval = QLA_SUCCESS; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 571351f8f..df0758ef8 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3647,8 +3647,7 @@ qla2x00_update_fw_options(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115, "Serial link options.\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109, - (uint8_t *)&ha->fw_seriallink_options, - sizeof(ha->fw_seriallink_options)); + ha->fw_seriallink_options, sizeof(ha->fw_seriallink_options)); ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; if (ha->fw_seriallink_options[3] & BIT_2) { @@ -4359,7 +4358,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) rval = QLA_SUCCESS; /* Determine NVRAM starting address. */ - ha->nvram_size = sizeof(nvram_t); + ha->nvram_size = sizeof(*nv); ha->nvram_base = 0; if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) if ((RD_REG_WORD(®->ctrl_status) >> 14) == 1) @@ -4373,7 +4372,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f, "Contents of NVRAM.\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110, - (uint8_t *)nv, ha->nvram_size); + nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || @@ -4947,8 +4946,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) ql_dbg(ql_dbg_disc, vha, 0x2011, "Entries in ID list (%d).\n", entries); ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075, - (uint8_t *)ha->gid_list, - entries * sizeof(struct gid_list_info)); + ha->gid_list, entries * sizeof(*ha->gid_list)); if (entries == 0) { spin_lock_irqsave(&vha->work_lock, flags); @@ -6973,7 +6971,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ha->vpd_base = FA_NVRAM_VPD1_ADDR; } - ha->nvram_size = sizeof(struct nvram_24xx); + ha->nvram_size = sizeof(*nv); ha->vpd_size = FA_NVRAM_VPD_SIZE; /* Get VPD data into cache */ @@ -6991,7 +6989,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a, "Contents of NVRAM\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d, - (uint8_t *)nv, ha->nvram_size); + nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' @@ -7001,6 +6999,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ql_log(ql_log_warn, vha, 0x006b, "Inconsistent NVRAM detected: checksum=0x%x id=%c " "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); + ql_dump_buffer(ql_dbg_init, vha, 0x006b, nv, 32); ql_log(ql_log_warn, vha, 0x006c, "Falling back to functioning (yet invalid -- WWPN) " "defaults.\n"); @@ -7212,18 +7211,16 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) { struct qla27xx_image_status pri_image_status, sec_image_status; - uint8_t valid_pri_image, valid_sec_image; + bool valid_pri_image = true, valid_sec_image = true; uint32_t *wptr; - uint32_t cnt, chksum, size; + uint chksum, cnt, size = sizeof(pri_image_status) / sizeof(*wptr); struct qla_hw_data *ha = vha->hw; uint32_t signature; - valid_pri_image = valid_sec_image = 1; ha->active_image = 0; - size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t); if (!ha->flt_region_img_status_pri) { - valid_pri_image = 0; + valid_pri_image = false; goto check_sec_image; } @@ -7234,9 +7231,9 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) if (signature != QLA27XX_IMG_STATUS_SIGN && signature != QLA28XX_IMG_STATUS_SIGN) { ql_dbg(ql_dbg_init, vha, 0x018b, - "Primary image signature (0x%x) not valid\n", - pri_image_status.signature); - valid_pri_image = 0; + "Primary image signature (%#x) not valid\n", + le32_to_cpu(pri_image_status.signature)); + valid_pri_image = false; goto check_sec_image; } @@ -7248,14 +7245,13 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) if (chksum) { ql_dbg(ql_dbg_init, vha, 0x018c, - "Checksum validation failed for primary image (0x%x)\n", - chksum); - valid_pri_image = 0; + "Primary image checksum failed (%#x)\n", chksum); + valid_pri_image = false; } check_sec_image: if (!ha->flt_region_img_status_sec) { - valid_sec_image = 0; + valid_sec_image = false; goto check_valid_image; } @@ -7266,9 +7262,9 @@ check_sec_image: if (signature != QLA27XX_IMG_STATUS_SIGN && signature != QLA28XX_IMG_STATUS_SIGN) { ql_dbg(ql_dbg_init, vha, 0x018d, - "Secondary image signature(0x%x) not valid\n", - sec_image_status.signature); - valid_sec_image = 0; + "Secondary image signature (%#x) not valid\n", + le32_to_cpu(sec_image_status.signature)); + valid_sec_image = false; goto check_valid_image; } @@ -7278,19 +7274,20 @@ check_sec_image: chksum += le32_to_cpu(*wptr); if (chksum) { ql_dbg(ql_dbg_init, vha, 0x018e, - "Checksum validation failed for secondary image (0x%x)\n", - chksum); - valid_sec_image = 0; + "Secondary image checksum failed (%#x)\n", chksum); + valid_sec_image = false; } check_valid_image: - if (valid_pri_image && (pri_image_status.image_status_mask & 0x1)) + if (valid_pri_image && (pri_image_status.image_status_mask & 1)) ha->active_image = QLA27XX_PRIMARY_IMAGE; - if (valid_sec_image && (sec_image_status.image_status_mask & 0x1)) { + + if (valid_sec_image && (sec_image_status.image_status_mask & 1)) { if (!ha->active_image || - pri_image_status.generation_number < - sec_image_status.generation_number) + le16_to_cpu(pri_image_status.generation) < + le16_to_cpu(sec_image_status.generation)) { ha->active_image = QLA27XX_SECONDARY_IMAGE; + } } ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x018f, "%s image\n", @@ -7302,6 +7299,13 @@ check_valid_image: return ha->active_image; } +bool qla24xx_risc_firmware_invalid(uint32_t *dword) +{ + return + !(dword[4] | dword[5] | dword[6] | dword[7]) || + !(~dword[4] | ~dword[5] | ~dword[6] | ~dword[7]); +} + static int qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, uint32_t faddr) @@ -7318,24 +7322,9 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, ql_dbg(ql_dbg_init, vha, 0x008b, "FW: Loading firmware from flash (%x).\n", faddr); - rval = QLA_SUCCESS; - - segments = FA_RISC_CODE_SEGMENTS; - dcode = (uint32_t *)req->ring; - *srisc_addr = 0; - - if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && - qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) - faddr = ha->flt_region_fw_sec; - - /* Validate firmware image by checking version. */ - qla24xx_read_flash_data(vha, dcode, faddr + 4, 4); - for (i = 0; i < 4; i++) - dcode[i] = be32_to_cpu(dcode[i]); - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { + dcode = (void *)req->ring; + qla24xx_read_flash_data(vha, dcode, faddr, 8); + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_fatal, vha, 0x008c, "Unable to verify the integrity of flash firmware " "image.\n"); @@ -7560,7 +7549,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) uint32_t risc_size; uint32_t i; struct fw_blob *blob; - const uint32_t *fwcode; + uint32_t *fwcode; uint32_t fwclen; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; @@ -7577,19 +7566,9 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) return QLA_FUNCTION_FAILED; } - ql_dbg(ql_dbg_init, vha, 0x0092, - "FW: Loading via request-firmware.\n"); - - rval = QLA_SUCCESS; - - segments = FA_RISC_CODE_SEGMENTS; - dcode = (uint32_t *)req->ring; - *srisc_addr = 0; - fwcode = (uint32_t *)blob->fw->data; - fwclen = 0; - - /* Validate firmware image by checking version. */ - if (blob->fw->size < 8 * sizeof(uint32_t)) { + fwcode = (void *)blob->fw->data; + dcode = fwcode; + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_fatal, vha, 0x0093, "Unable to verify integrity of firmware image (%zd).\n", blob->fw->size); @@ -7746,28 +7725,43 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) if (ql2xfwloadbin == 2) goto try_blob_fw; - /* - * FW Load priority: + /* FW Load priority: * 1) Firmware residing in flash. * 2) Firmware via request-firmware interface (.bin file). - * 3) Golden-Firmware residing in flash -- limited operation. + * 3) Golden-Firmware residing in flash -- (limited operation). */ + + if (!IS_QLA27XX(ha) || !IS_QLA28XX(ha)) + goto try_primary_fw; + + if (qla27xx_find_valid_image(vha) != QLA27XX_SECONDARY_IMAGE) + goto try_primary_fw; + + ql_dbg(ql_dbg_init, vha, 0x008b, + "Loading secondary firmware image.\n"); + rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw_sec); + if (!rval) + return rval; + +try_primary_fw: + ql_dbg(ql_dbg_init, vha, 0x008b, + "Loading primary firmware image.\n"); rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw); - if (rval == QLA_SUCCESS) + if (!rval) return rval; try_blob_fw: rval = qla24xx_load_risc_blob(vha, srisc_addr); - if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw) + if (!rval || !ha->flt_region_gold_fw) return rval; ql_log(ql_log_info, vha, 0x0099, "Attempting to fallback to golden firmware.\n"); rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw); - if (rval != QLA_SUCCESS) + if (rval) return rval; - ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n"); + ql_log(ql_log_info, vha, 0x009a, "Need firmware flash update.\n"); ha->flags.running_gold_fw = 1; return rval; } @@ -7942,7 +7936,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) nv = ha->nvram; /* Determine NVRAM starting address. */ - ha->nvram_size = sizeof(struct nvram_81xx); + ha->nvram_size = sizeof(*nv); ha->vpd_size = FA_NVRAM_VPD_SIZE; if (IS_P3P_TYPE(ha) || IS_QLA8031(ha)) ha->vpd_size = FA_VPD_SIZE_82XX; @@ -7962,7 +7956,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111, "Contents of NVRAM:\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112, - (uint8_t *)nv, ha->nvram_size); + nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' @@ -7973,6 +7967,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) "Inconsistent NVRAM detected: checksum=0x%x id=%c " "version=0x%x.\n", chksum, nv->id[0], le16_to_cpu(nv->nvram_version)); + ql_dump_buffer(ql_dbg_init, vha, 0x0073, nv, 32); ql_log(ql_log_info, vha, 0x0074, "Falling back to functioning (yet invalid -- WWPN) " "defaults.\n"); @@ -8195,12 +8190,6 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) /* N2N: driver will initiate Login instead of FW */ icb->firmware_options_3 |= BIT_8; - if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - icb->firmware_options_3 |= BIT_8; - ql_dbg(ql_log_info, vha, 0x0075, - "Enabling direct connection.\n"); - } - if (rval) { ql_log(ql_log_warn, vha, 0x0076, "NVRAM configuration failed.\n"); diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index a8771b741..feea37414 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -1387,7 +1387,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, le16_to_cpu(mbx->status_flags)); ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5029, - (uint8_t *)mbx, sizeof(*mbx)); + mbx, sizeof(*mbx)); goto logio_done; } @@ -1535,7 +1535,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, bsg_reply->reply_payload_rcv_len = 0; } ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035, - (uint8_t *)pkt, sizeof(*pkt)); + pkt, sizeof(*pkt)); } else { res = DID_OK << 16; bsg_reply->reply_payload_rcv_len = @@ -1679,7 +1679,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), fw_status, sizeof(fw_status)); ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056, - (uint8_t *)pkt, sizeof(*pkt)); + pkt, sizeof(*pkt)); } else { res = DID_OK << 16; @@ -1723,7 +1723,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, fcport->d_id.b.area, fcport->d_id.b.al_pa, logio->entry_status); ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d, - (uint8_t *)logio, sizeof(*logio)); + logio, sizeof(*logio)); goto logio_done; } @@ -1869,8 +1869,8 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) } if (iocb->u.tmf.data != QLA_SUCCESS) - ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055, - (uint8_t *)sts, sizeof(*sts)); + ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, sp->vha, 0x5055, + sts, sizeof(*sts)); sp->done(sp, 0); } diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index f699c8312..3b4c9778b 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -1833,8 +1833,18 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) if (rval != QLA_SUCCESS) { /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x104d, - "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n", + "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); + if (ha->init_cb) { + ql_dbg(ql_dbg_mbx, vha, 0x104d, "init_cb:\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, + 0x0104d, ha->init_cb, sizeof(*ha->init_cb)); + } + if (ha->ex_init_cb && ha->ex_init_cb->ex_version) { + ql_dbg(ql_dbg_mbx, vha, 0x104d, "ex_init_cb:\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, + 0x0104d, ha->ex_init_cb, sizeof(*ha->ex_init_cb)); + } } else { if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (mcp->mb[2] == 6 || mcp->mb[3] == 2) @@ -4244,7 +4254,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c, "Dump of Verify Request.\n"); ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e, - (uint8_t *)mn, sizeof(*mn)); + mn, sizeof(*mn)); rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120); if (rval != QLA_SUCCESS) { @@ -4256,7 +4266,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110, "Dump of Verify Response.\n"); ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118, - (uint8_t *)mn, sizeof(*mn)); + mn, sizeof(*mn)); status[0] = le16_to_cpu(mn->p.rsp.comp_status); status[1] = status[0] == CS_VCS_CHIP_FAILURE ? diff --git a/qla2x00t-32gbit/qla_mr.c b/qla2x00t-32gbit/qla_mr.c index 2f2a20309..a006c3e94 100644 --- a/qla2x00t-32gbit/qla_mr.c +++ b/qla2x00t-32gbit/qla_mr.c @@ -1137,8 +1137,8 @@ qlafx00_find_all_targets(scsi_qla_host_t *vha, ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x2088, "Listing Target bit map...\n"); - ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha, - 0x2089, (uint8_t *)ha->gid_list, 32); + ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha, 0x2089, + ha->gid_list, 32); /* Allocate temporary rmtport for any new rmtports discovered. */ new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); @@ -1922,8 +1922,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) phost_info->domainname, phost_info->hostdriver); ql_dump_buffer(ql_dbg_init + ql_dbg_disc, vha, 0x014d, - (uint8_t *)phost_info, - sizeof(struct host_system_info)); + phost_info, sizeof(*phost_info)); } } @@ -1977,7 +1976,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) vha->d_id.b.al_pa = pinfo->port_id[2]; qlafx00_update_host_attr(vha, pinfo); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0141, - (uint8_t *)pinfo, 16); + pinfo, 16); } else if (fx_type == FXDISC_GET_TGT_NODE_INFO) { struct qlafx00_tgt_node_info *pinfo = (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr; @@ -1985,12 +1984,12 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) memcpy(fcport->port_name, pinfo->tgt_node_wwpn, WWN_SIZE); fcport->port_type = FCT_TARGET; ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0144, - (uint8_t *)pinfo, 16); + pinfo, 16); } else if (fx_type == FXDISC_GET_TGT_NODE_LIST) { struct qlafx00_tgt_node_info *pinfo = (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr; ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0146, - (uint8_t *)pinfo, 16); + pinfo, 16); memcpy(vha->hw->gid_list, pinfo, QLAFX00_TGT_NODE_LIST_SIZE); } else if (fx_type == FXDISC_ABORT_IOCTL) fdisc->u.fxiocb.result = @@ -2262,18 +2261,16 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, fw_sts_ptr = bsg_job_sense(bsg_job) + sizeof(struct fc_bsg_reply); - memcpy(fw_sts_ptr, (uint8_t *)&fstatus, - sizeof(struct qla_mt_iocb_rsp_fx00)); + memcpy(fw_sts_ptr, &fstatus, sizeof(fstatus)); bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(struct qla_mt_iocb_rsp_fx00) + sizeof(uint8_t); ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, - sp->fcport->vha, 0x5080, - (uint8_t *)pkt, sizeof(struct ioctl_iocb_entry_fx00)); + sp->vha, 0x5080, pkt, sizeof(*pkt)); ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, - sp->fcport->vha, 0x5074, - (uint8_t *)fw_sts_ptr, sizeof(struct qla_mt_iocb_rsp_fx00)); + sp->vha, 0x5074, + fw_sts_ptr, sizeof(fstatus)); res = bsg_reply->result = DID_OK << 16; bsg_reply->reply_payload_rcv_len = @@ -2611,7 +2608,7 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) /* Move sense data. */ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304e, - (uint8_t *)pkt, sizeof(sts_cont_entry_t)); + pkt, sizeof(*pkt)); memcpy(sense_ptr, pkt->data, sense_sz); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304a, sense_ptr, sense_sz); @@ -3070,13 +3067,13 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, if (avail_dsds == 0 && cont == 1) { cont = 0; memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt, - REQUEST_ENTRY_SIZE); + sizeof(lcont_pkt)); } } if (avail_dsds != 0 && cont == 1) { memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt, - REQUEST_ENTRY_SIZE); + sizeof(lcont_pkt)); } } @@ -3186,9 +3183,9 @@ qlafx00_start_scsi(srb_t *sp) lcmd_pkt.entry_status = (uint8_t) rsp->id; ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e, - (uint8_t *)cmd->cmnd, cmd->cmd_len); + cmd->cmnd, cmd->cmd_len); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3032, - (uint8_t *)&lcmd_pkt, REQUEST_ENTRY_SIZE); + &lcmd_pkt, sizeof(lcmd_pkt)); memcpy_toio((void __iomem *)cmd_pkt, &lcmd_pkt, REQUEST_ENTRY_SIZE); wmb(); @@ -3472,10 +3469,8 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) } ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, - sp->vha, 0x3047, - (uint8_t *)&fx_iocb, sizeof(struct fxdisc_entry_fx00)); + sp->vha, 0x3047, &fx_iocb, sizeof(fx_iocb)); - memcpy_toio((void __iomem *)pfxiocb, &fx_iocb, - sizeof(struct fxdisc_entry_fx00)); + memcpy_toio((void __iomem *)pfxiocb, &fx_iocb, sizeof(fx_iocb)); wmb(); } diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 19cce3439..d906d77f2 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -55,7 +55,7 @@ static struct kmem_cache *ctx_cachep; /* * error level for logging */ -int ql_errlev = ql_log_all; +uint ql_errlev = ql_log_all; static int ql2xenableclass2; module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR); diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index 579d6a8c7..0e3de0637 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -619,7 +619,7 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) ql_log(ql_log_fatal, vha, 0x0045, "Inconsistent FLTL detected: checksum=0x%x.\n", chksum); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010e, - buf, sizeof(struct qla_flt_location)); + fltl, sizeof(*fltl)); return QLA_FUNCTION_FAILED; } @@ -721,12 +721,12 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) /* Store addresses as DWORD offsets. */ start = le32_to_cpu(region->start) >> 2; ql_dbg(ql_dbg_init, vha, 0x0049, - "FLT[%02x]: start=0x%x " - "end=0x%x size=0x%x.\n", le32_to_cpu(region->code) & 0xff, + "FLT[%#x]: start=%#x end=%#x size=%#x.\n", + le16_to_cpu(region->code), start, le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)); - switch (le32_to_cpu(region->code) & 0xff) { + switch (le16_to_cpu(region->code)) { case FLT_REG_FCOE_FW: if (!IS_QLA8031(ha)) break; @@ -941,7 +941,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) " checksum=0x%x id=%c version0x%x.\n", chksum, fdt->sig[0], le16_to_cpu(fdt->version)); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0113, - (uint8_t *)fdt, sizeof(*fdt)); + fdt, sizeof(*fdt)); goto no_flash_data; } @@ -2879,7 +2879,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf) "Dumping fw " "ver from flash:.\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010b, - (uint8_t *)dbyte, 8); + dbyte, 8); if ((dcode[0] == 0xffff && dcode[1] == 0xffff && dcode[2] == 0xffff && dcode[3] == 0xffff) || @@ -3128,24 +3128,16 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) faddr = ha->flt_region_fw_sec; - qla24xx_read_flash_data(vha, dcode, faddr + 4, 4); - for (i = 0; i < 4; i++) - dcode[i] = be32_to_cpu(dcode[i]); - - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { + qla24xx_read_flash_data(vha, dcode, faddr, 8); + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_warn, vha, 0x005f, "Unrecognized fw revision at %x.\n", ha->flt_region_fw * 4); } else { - ha->fw_revision[0] = dcode[0]; - ha->fw_revision[1] = dcode[1]; - ha->fw_revision[2] = dcode[2]; - ha->fw_revision[3] = dcode[3]; + for (i = 0; i < 4; i++) + ha->fw_revision[i] = be32_to_cpu(dcode[4+i]); ql_dbg(ql_dbg_init, vha, 0x0060, - "Firmware revision %d.%d.%d (%x).\n", + "Firmware revision (flash) %d.%d.%d (%x).\n", ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], ha->fw_revision[3]); } @@ -3158,19 +3150,16 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version)); dcode = mbuf; - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, - ha->flt_region_gold_fw << 2, 32); - - if (dcode[4] == 0xFFFFFFFF && dcode[5] == 0xFFFFFFFF && - dcode[6] == 0xFFFFFFFF && dcode[7] == 0xFFFFFFFF) { + qla24xx_read_flash_data(vha, dcode, ha->flt_region_gold_fw, 8); + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_warn, vha, 0x0056, "Unrecognized golden fw at 0x%x.\n", ha->flt_region_gold_fw * 4); return ret; } - for (i = 4; i < 8; i++) - ha->gold_fw_version[i-4] = be32_to_cpu(dcode[i]); + for (i = 0; i < 4; i++) + ha->gold_fw_version[i] = be32_to_cpu(dcode[4+i]); return ret; } diff --git a/qla2x00t-32gbit/qla_tmpl.c b/qla2x00t-32gbit/qla_tmpl.c index 70f227f59..c6a09d368 100644 --- a/qla2x00t-32gbit/qla_tmpl.c +++ b/qla2x00t-32gbit/qla_tmpl.c @@ -134,7 +134,7 @@ qla27xx_skip_entry(struct qla27xx_fwdt_entry *ent, void *buf) static inline struct qla27xx_fwdt_entry * qla27xx_next_entry(struct qla27xx_fwdt_entry *ent) { - return (void *)ent + ent->hdr.size; + return (void *)ent + le32_to_cpu(ent->hdr.size); } static struct qla27xx_fwdt_entry * @@ -165,11 +165,14 @@ qla27xx_fwdt_entry_t256(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong addr = le32_to_cpu(ent->t256.base_addr); + uint offset = ent->t256.pci_offset; + ulong count = le16_to_cpu(ent->t256.reg_count); + uint width = ent->t256.reg_width; ql_dbg(ql_dbg_misc, vha, 0xd200, "%s: rdio t1 [%lx]\n", __func__, *len); - qla27xx_read_window(reg, ent->t256.base_addr, ent->t256.pci_offset, - ent->t256.reg_count, ent->t256.reg_width, buf, len); + qla27xx_read_window(reg, addr, offset, count, width, buf, len); return qla27xx_next_entry(ent); } @@ -179,11 +182,14 @@ qla27xx_fwdt_entry_t257(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong addr = le32_to_cpu(ent->t257.base_addr); + uint offset = ent->t257.pci_offset; + ulong data = le32_to_cpu(ent->t257.write_data); ql_dbg(ql_dbg_misc, vha, 0xd201, "%s: wrio t1 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, ent->t257.base_addr, buf); - qla27xx_write_reg(reg, ent->t257.pci_offset, ent->t257.write_data, buf); + qla27xx_write_reg(reg, IOBASE(reg), addr, buf); + qla27xx_write_reg(reg, offset, data, buf); return qla27xx_next_entry(ent); } @@ -193,12 +199,17 @@ qla27xx_fwdt_entry_t258(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint banksel = ent->t258.banksel_offset; + ulong bank = le32_to_cpu(ent->t258.bank); + ulong addr = le32_to_cpu(ent->t258.base_addr); + uint offset = ent->t258.pci_offset; + uint count = le16_to_cpu(ent->t258.reg_count); + uint width = ent->t258.reg_width; ql_dbg(ql_dbg_misc, vha, 0xd202, "%s: rdio t2 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t258.banksel_offset, ent->t258.bank, buf); - qla27xx_read_window(reg, ent->t258.base_addr, ent->t258.pci_offset, - ent->t258.reg_count, ent->t258.reg_width, buf, len); + qla27xx_write_reg(reg, banksel, bank, buf); + qla27xx_read_window(reg, addr, offset, count, width, buf, len); return qla27xx_next_entry(ent); } @@ -208,12 +219,17 @@ qla27xx_fwdt_entry_t259(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong addr = le32_to_cpu(ent->t259.base_addr); + uint banksel = ent->t259.banksel_offset; + ulong bank = le32_to_cpu(ent->t259.bank); + uint offset = ent->t259.pci_offset; + ulong data = le32_to_cpu(ent->t259.write_data); ql_dbg(ql_dbg_misc, vha, 0xd203, "%s: wrio t2 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, ent->t259.base_addr, buf); - qla27xx_write_reg(reg, ent->t259.banksel_offset, ent->t259.bank, buf); - qla27xx_write_reg(reg, ent->t259.pci_offset, ent->t259.write_data, buf); + qla27xx_write_reg(reg, IOBASE(reg), addr, buf); + qla27xx_write_reg(reg, banksel, bank, buf); + qla27xx_write_reg(reg, offset, data, buf); return qla27xx_next_entry(ent); } @@ -223,11 +239,12 @@ qla27xx_fwdt_entry_t260(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint offset = ent->t260.pci_offset; ql_dbg(ql_dbg_misc, vha, 0xd204, "%s: rdpci [%lx]\n", __func__, *len); - qla27xx_insert32(ent->t260.pci_offset, buf, len); - qla27xx_read_reg(reg, ent->t260.pci_offset, buf, len); + qla27xx_insert32(offset, buf, len); + qla27xx_read_reg(reg, offset, buf, len); return qla27xx_next_entry(ent); } @@ -237,10 +254,12 @@ qla27xx_fwdt_entry_t261(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint offset = ent->t261.pci_offset; + ulong data = le32_to_cpu(ent->t261.write_data); ql_dbg(ql_dbg_misc, vha, 0xd205, "%s: wrpci [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t261.pci_offset, ent->t261.write_data, buf); + qla27xx_write_reg(reg, offset, data, buf); return qla27xx_next_entry(ent); } @@ -249,51 +268,50 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t262(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + uint area = ent->t262.ram_area; + ulong start = le32_to_cpu(ent->t262.start_addr); + ulong end = le32_to_cpu(ent->t262.end_addr); ulong dwords; - ulong start; - ulong end; ql_dbg(ql_dbg_misc, vha, 0xd206, "%s: rdram(%x) [%lx]\n", __func__, ent->t262.ram_area, *len); - start = ent->t262.start_addr; - end = ent->t262.end_addr; - if (ent->t262.ram_area == T262_RAM_AREA_CRITICAL_RAM) { + if (area == T262_RAM_AREA_CRITICAL_RAM) { ; - } else if (ent->t262.ram_area == T262_RAM_AREA_EXTERNAL_RAM) { + } else if (area == T262_RAM_AREA_EXTERNAL_RAM) { end = vha->hw->fw_memory_size; if (buf) - ent->t262.end_addr = end; - } else if (ent->t262.ram_area == T262_RAM_AREA_SHARED_RAM) { + ent->t262.end_addr = cpu_to_le32(end); + } else if (area == T262_RAM_AREA_SHARED_RAM) { start = vha->hw->fw_shared_ram_start; end = vha->hw->fw_shared_ram_end; if (buf) { - ent->t262.start_addr = start; - ent->t262.end_addr = end; + ent->t262.start_addr = cpu_to_le32(start); + ent->t262.end_addr = cpu_to_le32(end); } - } else if (ent->t262.ram_area == T262_RAM_AREA_DDR_RAM) { + } else if (area == T262_RAM_AREA_DDR_RAM) { start = vha->hw->fw_ddr_ram_start; end = vha->hw->fw_ddr_ram_end; if (buf) { - ent->t262.start_addr = start; - ent->t262.end_addr = end; + ent->t262.start_addr = cpu_to_le32(start); + ent->t262.end_addr = cpu_to_le32(end); } - } else if (ent->t262.ram_area == T262_RAM_AREA_MISC) { + } else if (area == T262_RAM_AREA_MISC) { if (buf) { - ent->t262.start_addr = start; - ent->t262.end_addr = end; + ent->t262.start_addr = cpu_to_le32(start); + ent->t262.end_addr = cpu_to_le32(end); } } else { ql_dbg(ql_dbg_misc, vha, 0xd022, - "%s: unknown area %x\n", __func__, ent->t262.ram_area); + "%s: unknown area %x\n", __func__, area); qla27xx_skip_entry(ent, buf); goto done; } if (end < start || start == 0 || end == 0) { ql_dbg(ql_dbg_misc, vha, 0xd023, - "%s: unusable range (start=%x end=%x)\n", __func__, - ent->t262.end_addr, ent->t262.start_addr); + "%s: unusable range (start=%lx end=%lx)\n", + __func__, start, end); qla27xx_skip_entry(ent, buf); goto done; } @@ -312,13 +330,14 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + uint type = ent->t263.queue_type; uint count = 0; uint i; uint length; - ql_dbg(ql_dbg_misc, vha, 0xd207, - "%s: getq(%x) [%lx]\n", __func__, ent->t263.queue_type, *len); - if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) { + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd207, + "%s: getq(%x) [%lx]\n", __func__, type, *len); + if (type == T263_QUEUE_TYPE_REQ) { for (i = 0; i < vha->hw->max_req_queues; i++) { struct req_que *req = vha->hw->req_q_map[i]; @@ -332,7 +351,7 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, count++; } } - } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) { + } else if (type == T263_QUEUE_TYPE_RSP) { for (i = 0; i < vha->hw->max_rsp_queues; i++) { struct rsp_que *rsp = vha->hw->rsp_q_map[i]; @@ -360,7 +379,7 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, } } else { ql_dbg(ql_dbg_misc, vha, 0xd026, - "%s: unknown queue %x\n", __func__, ent->t263.queue_type); + "%s: unknown queue %x\n", __func__, type); qla27xx_skip_entry(ent, buf); } @@ -433,10 +452,12 @@ qla27xx_fwdt_entry_t267(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint offset = ent->t267.pci_offset; + ulong data = le32_to_cpu(ent->t267.data); ql_dbg(ql_dbg_misc, vha, 0xd20b, "%s: dis intr [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t267.pci_offset, ent->t267.data, buf); + qla27xx_write_reg(reg, offset, data, buf); return qla27xx_next_entry(ent); } @@ -533,8 +554,8 @@ qla27xx_fwdt_entry_t270(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); - ulong dwords = ent->t270.count; - ulong addr = ent->t270.addr; + ulong addr = le32_to_cpu(ent->t270.addr); + ulong dwords = le32_to_cpu(ent->t270.count); ql_dbg(ql_dbg_misc, vha, 0xd20e, "%s: rdremreg [%lx]\n", __func__, *len); @@ -554,8 +575,8 @@ qla27xx_fwdt_entry_t271(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); - ulong addr = ent->t271.addr; - ulong data = ent->t271.data; + ulong addr = le32_to_cpu(ent->t271.addr); + ulong data = le32_to_cpu(ent->t271.data); ql_dbg(ql_dbg_misc, vha, 0xd20f, "%s: wrremreg [%lx]\n", __func__, *len); @@ -570,8 +591,8 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t272(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - ulong dwords = ent->t272.count; - ulong start = ent->t272.addr; + ulong dwords = le32_to_cpu(ent->t272.count); + ulong start = le32_to_cpu(ent->t272.addr); ql_dbg(ql_dbg_misc, vha, 0xd210, "%s: rdremram [%lx]\n", __func__, *len); @@ -590,8 +611,8 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t273(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - ulong dwords = ent->t273.count; - ulong addr = ent->t273.addr; + ulong dwords = le32_to_cpu(ent->t273.count); + ulong addr = le32_to_cpu(ent->t273.addr); uint32_t value; ql_dbg(ql_dbg_misc, vha, 0xd211, @@ -613,12 +634,13 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + ulong type = ent->t274.queue_type; uint count = 0; uint i; - ql_dbg(ql_dbg_misc, vha, 0xd212, - "%s: getqsh(%x) [%lx]\n", __func__, ent->t274.queue_type, *len); - if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) { + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd212, + "%s: getqsh(%lx) [%lx]\n", __func__, type, *len); + if (type == T274_QUEUE_TYPE_REQ_SHAD) { for (i = 0; i < vha->hw->max_req_queues; i++) { struct req_que *req = vha->hw->req_q_map[i]; @@ -630,7 +652,7 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, count++; } } - } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) { + } else if (type == T274_QUEUE_TYPE_RSP_SHAD) { for (i = 0; i < vha->hw->max_rsp_queues; i++) { struct rsp_que *rsp = vha->hw->rsp_q_map[i]; @@ -656,7 +678,7 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, } } else { ql_dbg(ql_dbg_misc, vha, 0xd02f, - "%s: unknown queue %x\n", __func__, ent->t274.queue_type); + "%s: unknown queue %lx\n", __func__, type); qla27xx_skip_entry(ent, buf); } @@ -675,23 +697,26 @@ qla27xx_fwdt_entry_t275(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { ulong offset = offsetof(typeof(*ent), t275.buffer); + ulong length = le32_to_cpu(ent->t275.length); + ulong size = le32_to_cpu(ent->hdr.size); + void *buffer = ent->t275.buffer; - ql_dbg(ql_dbg_misc, vha, 0xd213, - "%s: buffer(%x) [%lx]\n", __func__, ent->t275.length, *len); - if (!ent->t275.length) { + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd213, + "%s: buffer(%lx) [%lx]\n", __func__, length, *len); + if (!length) { ql_dbg(ql_dbg_misc, vha, 0xd020, "%s: buffer zero length\n", __func__); qla27xx_skip_entry(ent, buf); goto done; } - if (offset + ent->t275.length > ent->hdr.size) { + if (offset + length > size) { ql_dbg(ql_dbg_misc, vha, 0xd030, "%s: buffer overflow\n", __func__); qla27xx_skip_entry(ent, buf); goto done; } - qla27xx_insertbuf(ent->t275.buffer, ent->t275.length, buf, len); + qla27xx_insertbuf(buffer, length, buf, len); done: return qla27xx_next_entry(ent); } @@ -700,13 +725,15 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t276(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + ulong cond1 = le32_to_cpu(ent->t276.cond1); + ulong cond2 = le32_to_cpu(ent->t276.cond2); uint type = vha->hw->pdev->device >> 4 & 0xf; uint func = vha->hw->port_no & 0x3; ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd214, "%s: cond [%lx]\n", __func__, *len); - if (type != ent->t276.cond1 || func != ent->t276.cond2) { + if (type != cond1 || func != cond2) { ent = qla27xx_next_entry(ent); qla27xx_skip_entry(ent, buf); } @@ -719,12 +746,15 @@ qla27xx_fwdt_entry_t277(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong cmd_addr = le32_to_cpu(ent->t277.cmd_addr); + ulong wr_cmd_data = le32_to_cpu(ent->t277.wr_cmd_data); + ulong data_addr = le32_to_cpu(ent->t277.data_addr); ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd215, "%s: rdpep [%lx]\n", __func__, *len); - qla27xx_insert32(ent->t277.wr_cmd_data, buf, len); - qla27xx_write_reg(reg, ent->t277.cmd_addr, ent->t277.wr_cmd_data, buf); - qla27xx_read_reg(reg, ent->t277.data_addr, buf, len); + qla27xx_insert32(wr_cmd_data, buf, len); + qla27xx_write_reg(reg, cmd_addr, wr_cmd_data, buf); + qla27xx_read_reg(reg, data_addr, buf, len); return qla27xx_next_entry(ent); } @@ -734,11 +764,15 @@ qla27xx_fwdt_entry_t278(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong cmd_addr = le32_to_cpu(ent->t278.cmd_addr); + ulong wr_cmd_data = le32_to_cpu(ent->t278.wr_cmd_data); + ulong data_addr = le32_to_cpu(ent->t278.data_addr); + ulong wr_data = le32_to_cpu(ent->t278.wr_data); ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd216, "%s: wrpep [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t278.data_addr, ent->t278.wr_data, buf); - qla27xx_write_reg(reg, ent->t278.cmd_addr, ent->t278.wr_cmd_data, buf); + qla27xx_write_reg(reg, data_addr, wr_data, buf); + qla27xx_write_reg(reg, cmd_addr, wr_cmd_data, buf); return qla27xx_next_entry(ent); } @@ -747,8 +781,10 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_other(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + ulong type = le32_to_cpu(ent->hdr.type); + ql_dbg(ql_dbg_misc, vha, 0xd2ff, - "%s: type %x [%lx]\n", __func__, ent->hdr.type, *len); + "%s: other %lx [%lx]\n", __func__, type, *len); qla27xx_skip_entry(ent, buf); return qla27xx_next_entry(ent); @@ -803,13 +839,16 @@ static void qla27xx_walk_template(struct scsi_qla_host *vha, struct qla27xx_fwdt_template *tmp, void *buf, ulong *len) { - struct qla27xx_fwdt_entry *ent = (void *)tmp + tmp->entry_offset; - ulong count = tmp->entry_count; + struct qla27xx_fwdt_entry *ent = (void *)tmp + + le32_to_cpu(tmp->entry_offset); + ulong count = le32_to_cpu(tmp->entry_count); + ulong type = 0; ql_dbg(ql_dbg_misc, vha, 0xd01a, "%s: entry count %lx\n", __func__, count); while (count--) { - ent = qla27xx_find_entry(ent->hdr.type)(vha, ent, buf, len); + type = le32_to_cpu(ent->hdr.type); + ent = qla27xx_find_entry(type)(vha, ent, buf, len); if (!ent) break; } @@ -879,13 +918,13 @@ ql27xx_edit_template(struct scsi_qla_host *vha, static inline uint32_t qla27xx_template_checksum(void *p, ulong size) { - uint32_t *buf = p; + __le32 *buf = p; uint64_t sum = 0; size /= sizeof(*buf); - while (size--) - sum += *buf++; + for ( ; size--; buf++) + sum += le32_to_cpu(*buf); sum = (sum & 0xffffffff) + (sum >> 32); @@ -901,7 +940,7 @@ qla27xx_verify_template_checksum(struct qla27xx_fwdt_template *tmp) static inline int qla27xx_verify_template_header(struct qla27xx_fwdt_template *tmp) { - return tmp->template_type == TEMPLATE_TYPE_FWDUMP; + return le32_to_cpu(tmp->template_type) == TEMPLATE_TYPE_FWDUMP; } static void @@ -949,7 +988,8 @@ qla27xx_fwdt_template_valid(void *p) if (!qla27xx_verify_template_header(tmp)) { ql_log(ql_log_warn, NULL, 0xd01c, - "%s: template type %x\n", __func__, tmp->template_type); + "%s: template type %x\n", __func__, + le32_to_cpu(tmp->template_type)); return false; } diff --git a/qla2x00t-32gbit/qla_tmpl.h b/qla2x00t-32gbit/qla_tmpl.h index 5c2c2a8a1..6ce7fff01 100644 --- a/qla2x00t-32gbit/qla_tmpl.h +++ b/qla2x00t-32gbit/qla_tmpl.h @@ -11,12 +11,12 @@ #define IOBASE_ADDR offsetof(struct device_reg_24xx, iobase_addr) struct __packed qla27xx_fwdt_template { - uint32_t template_type; - uint32_t entry_offset; + __le32 template_type; + __le32 entry_offset; uint32_t template_size; uint32_t reserved_1; - uint32_t entry_count; + __le32 entry_count; uint32_t template_version; uint32_t capture_timestamp; uint32_t template_checksum; @@ -65,8 +65,8 @@ struct __packed qla27xx_fwdt_template { struct __packed qla27xx_fwdt_entry { struct __packed { - uint32_t type; - uint32_t size; + __le32 type; + __le32 size; uint32_t reserved_1; uint8_t capture_flags; @@ -81,36 +81,36 @@ struct __packed qla27xx_fwdt_entry { } t255; struct __packed { - uint32_t base_addr; + __le32 base_addr; uint8_t reg_width; - uint16_t reg_count; + __le16 reg_count; uint8_t pci_offset; } t256; struct __packed { - uint32_t base_addr; - uint32_t write_data; + __le32 base_addr; + __le32 write_data; uint8_t pci_offset; uint8_t reserved[3]; } t257; struct __packed { - uint32_t base_addr; + __le32 base_addr; uint8_t reg_width; - uint16_t reg_count; + __le16 reg_count; uint8_t pci_offset; uint8_t banksel_offset; uint8_t reserved[3]; - uint32_t bank; + __le32 bank; } t258; struct __packed { - uint32_t base_addr; - uint32_t write_data; + __le32 base_addr; + __le32 write_data; uint8_t reserved[2]; uint8_t pci_offset; uint8_t banksel_offset; - uint32_t bank; + __le32 bank; } t259; struct __packed { @@ -121,14 +121,14 @@ struct __packed qla27xx_fwdt_entry { struct __packed { uint8_t pci_offset; uint8_t reserved[3]; - uint32_t write_data; + __le32 write_data; } t261; struct __packed { uint8_t ram_area; uint8_t reserved[3]; - uint32_t start_addr; - uint32_t end_addr; + __le32 start_addr; + __le32 end_addr; } t262; struct __packed { @@ -158,7 +158,7 @@ struct __packed qla27xx_fwdt_entry { struct __packed { uint8_t pci_offset; uint8_t reserved[3]; - uint32_t data; + __le32 data; } t267; struct __packed { @@ -173,23 +173,23 @@ struct __packed qla27xx_fwdt_entry { } t269; struct __packed { - uint32_t addr; - uint32_t count; + __le32 addr; + __le32 count; } t270; struct __packed { - uint32_t addr; - uint32_t data; + __le32 addr; + __le32 data; } t271; struct __packed { - uint32_t addr; - uint32_t count; + __le32 addr; + __le32 count; } t272; struct __packed { - uint32_t addr; - uint32_t count; + __le32 addr; + __le32 count; } t273; struct __packed { @@ -199,26 +199,26 @@ struct __packed qla27xx_fwdt_entry { } t274; struct __packed { - uint32_t length; + __le32 length; uint8_t buffer[]; } t275; struct __packed { - uint32_t cond1; - uint32_t cond2; + __le32 cond1; + __le32 cond2; } t276; struct __packed { - uint32_t cmd_addr; - uint32_t wr_cmd_data; - uint32_t data_addr; + __le32 cmd_addr; + __le32 wr_cmd_data; + __le32 data_addr; } t277; struct __packed { - uint32_t cmd_addr; - uint32_t wr_cmd_data; - uint32_t data_addr; - uint32_t wr_data; + __le32 cmd_addr; + __le32 wr_cmd_data; + __le32 data_addr; + __le32 wr_data; } t278; }; }; From f4efe31dbcc121ed5c879659b602a96fcba225ff Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:16:05 +0000 Subject: [PATCH 09/42] qla2xxx: Add support for multiple fwdump templates/segments This patch adds multipe firmware dump template and segments support for ISP27XX/28XX. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8203 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_bsg.c | 3 +- qla2x00t-32gbit/qla_def.h | 9 +- qla2x00t-32gbit/qla_gbl.h | 2 +- qla2x00t-32gbit/qla_init.c | 412 +++++++++++++++++++++---------------- qla2x00t-32gbit/qla_os.c | 14 +- qla2x00t-32gbit/qla_sup.c | 2 + qla2x00t-32gbit/qla_tmpl.c | 89 ++++---- 7 files changed, 306 insertions(+), 225 deletions(-) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index dfc771a17..5402b8742 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -113,8 +113,7 @@ qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha, return 0; } - if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' || - bcode[3] != 'S') { + if (memcmp(bcode, "HQOS", 4)) { /* Invalid FCP priority data header*/ ql_dbg(ql_dbg_user, vha, 0x7052, "Invalid FCP Priority data header. bcode=0x%x.\n", diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index aa17ea89f..6f058c83a 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4049,9 +4049,11 @@ struct qla_hw_data { uint8_t pep_version[3]; /* Firmware dump template */ - void *fw_dump_template; - uint32_t fw_dump_template_len; - /* Firmware dump information. */ + struct fwdt { + void *template; + ulong length; + ulong dump_size; + } fwdt[2]; struct qla2xxx_fw_dump *fw_dump; uint32_t fw_dump_len; bool fw_dumped; @@ -4094,7 +4096,6 @@ struct qla_hw_data { uint16_t product_id[4]; uint8_t model_number[16+1]; -#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" char model_desc[80]; uint8_t adapter_id[16+1]; diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 54b3fed28..4c55257f0 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -613,7 +613,7 @@ extern void qla82xx_fw_dump(scsi_qla_host_t *, int); extern void qla8044_fw_dump(scsi_qla_host_t *, int); extern void qla27xx_fwdump(scsi_qla_host_t *, int); -extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *); +extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *, void *); extern int qla27xx_fwdt_template_valid(void *); extern ulong qla27xx_fwdt_template_size(void *); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index df0758ef8..6ffc09d22 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3086,12 +3086,15 @@ eft_err: void qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) { + int rval; uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, eft_size, fce_size, mq_size; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; struct rsp_que *rsp = ha->rsp_q_map[0]; struct qla2xxx_fw_dump *fw_dump; + dma_addr_t tc_dma; + void *tc; dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0; req_q_size = rsp_q_size = 0; @@ -3136,20 +3139,51 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE; try_eft: + if (ha->eft) + dma_free_coherent(&ha->pdev->dev, + EFT_SIZE, ha->eft, ha->eft_dma); + + /* Allocate memory for Extended Trace Buffer. */ + tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, + GFP_KERNEL); + if (!tc) { + ql_log(ql_log_warn, vha, 0x00c1, + "Unable to allocate (%d KB) for EFT.\n", + EFT_SIZE / 1024); + goto allocate; + } + + rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); + if (rval) { + ql_log(ql_log_warn, vha, 0x00c2, + "Unable to initialize EFT (%d).\n", rval); + dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, + tc_dma); + } ql_dbg(ql_dbg_init, vha, 0x00c3, "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024); eft_size = EFT_SIZE; } if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x00ba, - "Failed missing fwdump template\n"); - return; + struct fwdt *fwdt = ha->fwdt; + uint j; + + for (j = 0; j < 2; j++, fwdt++) { + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0x00ba, + "-> fwdt%u no template\n", j); + continue; + } + ql_dbg(ql_dbg_init, vha, 0x00fa, + "-> fwdt%u calculating fwdump size...\n", j); + fwdt->dump_size = qla27xx_fwdt_calculate_dump_size( + vha, fwdt->template); + ql_dbg(ql_dbg_init, vha, 0x00fa, + "-> fwdt%u calculated fwdump size = %#lx bytes\n", + j, fwdt->dump_size); + dump_size += fwdt->dump_size; } - dump_size = qla27xx_fwdt_calculate_dump_size(vha); - ql_dbg(ql_dbg_init, vha, 0x00fa, - "-> allocating fwdump (%x bytes)...\n", dump_size); goto allocate; } @@ -4267,11 +4301,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, { char *st, *en; uint16_t index; + uint64_t zero[2] = { 0 }; struct qla_hw_data *ha = vha->hw; int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha); - if (memcmp(model, BINZERO, len) != 0) { + if (len > sizeof(zero)) + len = sizeof(zero); + if (memcmp(model, &zero, len) != 0) { strncpy(ha->model_number, model, len); st = en = ha->model_number; en += len - 1; @@ -4375,8 +4412,8 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || - nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) { + if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) || + nv->nvram_version < 1) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x0064, "Inconsistent NVRAM " @@ -6992,9 +7029,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' - || nv->id[3] != ' ' || - nv->nvram_version < cpu_to_le16(ICB_VERSION)) { + if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) || + le16_to_cpu(nv->nvram_version) < ICB_VERSION) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x006b, "Inconsistent NVRAM detected: checksum=0x%x id=%c " @@ -7310,14 +7346,16 @@ static int qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, uint32_t faddr) { - int rval = QLA_SUCCESS; - int segments, fragment; - uint32_t *dcode, dlen; - uint32_t risc_addr; - uint32_t risc_size; - uint32_t i; + int rval; + uint templates, segments, fragment; + ulong i; + uint j; + ulong dlen; + uint32_t *dcode; + uint32_t risc_addr, risc_size, risc_attr = 0; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct fwdt *fwdt = ha->fwdt; ql_dbg(ql_dbg_init, vha, 0x008b, "FW: Loading firmware from flash (%x).\n", faddr); @@ -7335,34 +7373,36 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, return QLA_FUNCTION_FAILED; } - while (segments && rval == QLA_SUCCESS) { - /* Read segment's load information. */ - qla24xx_read_flash_data(vha, dcode, faddr, 4); - + dcode = (void *)req->ring; + *srisc_addr = 0; + segments = FA_RISC_CODE_SEGMENTS; + for (j = 0; j < segments; j++) { + ql_dbg(ql_dbg_init, vha, 0x008d, + "-> Loading segment %u...\n", j); + qla24xx_read_flash_data(vha, dcode, faddr, 10); risc_addr = be32_to_cpu(dcode[2]); - *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; risc_size = be32_to_cpu(dcode[3]); + if (!*srisc_addr) { + *srisc_addr = risc_addr; + risc_attr = be32_to_cpu(dcode[9]); + } - fragment = 0; - while (risc_size > 0 && rval == QLA_SUCCESS) { - dlen = (uint32_t)(ha->fw_transfer_size >> 2); + dlen = ha->fw_transfer_size >> 2; + for (fragment = 0; risc_size; fragment++) { if (dlen > risc_size) dlen = risc_size; ql_dbg(ql_dbg_init, vha, 0x008e, - "Loading risc segment@ risc addr %x " - "number of dwords 0x%x offset 0x%x.\n", - risc_addr, dlen, faddr); - + "-> Loading fragment %u: %#x <- %#x (%#lx dwords)...\n", + fragment, risc_addr, faddr, dlen); qla24xx_read_flash_data(vha, dcode, faddr, dlen); for (i = 0; i < dlen; i++) dcode[i] = swab32(dcode[i]); - rval = qla2x00_load_ram(vha, req->dma, risc_addr, - dlen); + rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen); if (rval) { ql_log(ql_log_fatal, vha, 0x008f, - "Failed to load segment %d of firmware.\n", + "-> Failed load firmware fragment %u.\n", fragment); return QLA_FUNCTION_FAILED; } @@ -7370,72 +7410,83 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, faddr += dlen; risc_addr += dlen; risc_size -= dlen; - fragment++; } - - /* Next segment. */ - segments--; } if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - return rval; + return QLA_SUCCESS; - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; + templates = (risc_attr & BIT_9) ? 2 : 1; + ql_dbg(ql_dbg_init, vha, 0x0160, "-> templates = %u\n", templates); + for (j = 0; j < templates; j++, fwdt++) { + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; - ql_dbg(ql_dbg_init, vha, 0x0161, - "Loading fwdump template from %x\n", faddr); - qla24xx_read_flash_data(vha, dcode, faddr, 7); - risc_size = be32_to_cpu(dcode[2]); - ql_dbg(ql_dbg_init, vha, 0x0162, - "-> array size %x dwords\n", risc_size); - if (risc_size == 0 || risc_size == ~0) - goto failed; + qla24xx_read_flash_data(vha, dcode, faddr, 7); + risc_size = be32_to_cpu(dcode[2]); + ql_dbg(ql_dbg_init, vha, 0x0161, + "-> fwdt%u template array at %#x (%#x dwords)\n", + j, faddr, risc_size); + if (!risc_size || !~risc_size) { + ql_dbg(ql_dbg_init, vha, 0x0162, + "-> fwdt%u failed to read array\n", j); + goto failed; + } - dlen = (risc_size - 8) * sizeof(*dcode); - ql_dbg(ql_dbg_init, vha, 0x0163, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x0164, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto failed; + /* skip header and ignore checksum */ + faddr += 7; + risc_size -= 8; + + ql_dbg(ql_dbg_init, vha, 0x0163, + "-> fwdt%u template allocate template %#x words...\n", + j, risc_size); + fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0x0164, + "-> fwdt%u failed allocate template.\n", j); + goto failed; + } + + dcode = fwdt->template; + qla24xx_read_flash_data(vha, dcode, faddr, risc_size); + for (i = 0; i < risc_size; i++) + dcode[i] = le32_to_cpu(dcode[i]); + + if (!qla27xx_fwdt_template_valid(dcode)) { + ql_log(ql_log_warn, vha, 0x0165, + "-> fwdt%u failed template validate\n", j); + goto failed; + } + + dlen = qla27xx_fwdt_template_size(dcode); + ql_dbg(ql_dbg_init, vha, 0x0166, + "-> fwdt%u template size %#lx bytes (%#lx words)\n", + j, dlen, dlen / sizeof(*dcode)); + if (dlen > risc_size * sizeof(*dcode)) { + ql_log(ql_log_warn, vha, 0x0167, + "-> fwdt%u template exceeds array (%-lu bytes)\n", + j, dlen - risc_size * sizeof(*dcode)); + goto failed; + } + + fwdt->length = dlen; + ql_dbg(ql_dbg_init, vha, 0x0168, + "-> fwdt%u loaded template ok\n", j); + + faddr += risc_size + 1; } - faddr += 7; - risc_size -= 8; - dcode = ha->fw_dump_template; - qla24xx_read_flash_data(vha, dcode, faddr, risc_size); - for (i = 0; i < risc_size; i++) - dcode[i] = le32_to_cpu(dcode[i]); - - if (!qla27xx_fwdt_template_valid(dcode)) { - ql_log(ql_log_warn, vha, 0x0165, - "Failed fwdump template validate\n"); - goto failed; - } - - dlen = qla27xx_fwdt_template_size(dcode); - ql_dbg(ql_dbg_init, vha, 0x0166, - "-> template size %x bytes\n", dlen); - if (dlen > risc_size * sizeof(*dcode)) { - ql_log(ql_log_warn, vha, 0x0167, - "Failed fwdump template exceeds array by %zx bytes\n", - (size_t)(dlen - risc_size * sizeof(*dcode))); - goto failed; - } - ha->fw_dump_template_len = dlen; - return rval; + return QLA_SUCCESS; failed: - ql_log(ql_log_warn, vha, 0x016d, "Failed fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - return rval; + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + + return QLA_SUCCESS; } #define QLA_FW_URL "http://ldriver.qlogic.com/firmware/" @@ -7543,31 +7594,31 @@ static int qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) { int rval; - int segments, fragment; - uint32_t *dcode, dlen; - uint32_t risc_addr; - uint32_t risc_size; - uint32_t i; + uint templates, segments, fragment; + uint32_t *dcode; + ulong dlen; + uint32_t risc_addr, risc_size, risc_attr = 0; + ulong i; + uint j; struct fw_blob *blob; uint32_t *fwcode; - uint32_t fwclen; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct fwdt *fwdt = ha->fwdt; + + ql_dbg(ql_dbg_init, vha, 0x0090, + "-> FW: Loading via request-firmware.\n"); - /* Load firmware blob. */ blob = qla2x00_request_firmware(vha); if (!blob) { - ql_log(ql_log_warn, vha, 0x0090, - "Firmware image unavailable.\n"); - ql_log(ql_log_warn, vha, 0x0091, - "Firmware images can be retrieved from: " - QLA_FW_URL ".\n"); + ql_log(ql_log_warn, vha, 0x0092, + "-> Firmware file not found.\n"); return QLA_FUNCTION_FAILED; } fwcode = (void *)blob->fw->data; - dcode = fwcode; + dcode = fwcode + 4; if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_fatal, vha, 0x0093, "Unable to verify integrity of firmware image (%zd).\n", @@ -7589,38 +7640,39 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) return QLA_FUNCTION_FAILED; } - while (segments && rval == QLA_SUCCESS) { + dcode = (void *)req->ring; + *srisc_addr = 0; + segments = FA_RISC_CODE_SEGMENTS; + for (j = 0; j < segments; j++) { + ql_dbg(ql_dbg_init, vha, 0x0096, + "-> Loading segment %u...\n", j); risc_addr = be32_to_cpu(fwcode[2]); - *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; risc_size = be32_to_cpu(fwcode[3]); - /* Validate firmware image size. */ - fwclen += risc_size * sizeof(uint32_t); - if (blob->fw->size < fwclen) { - ql_log(ql_log_fatal, vha, 0x0096, - "Unable to verify integrity of firmware image " - "(%zd).\n", blob->fw->size); - return QLA_FUNCTION_FAILED; + if (!*srisc_addr) { + *srisc_addr = risc_addr; + risc_attr = be32_to_cpu(fwcode[9]); } - fragment = 0; - while (risc_size > 0 && rval == QLA_SUCCESS) { + dlen = ha->fw_transfer_size >> 2; + for (fragment = 0; risc_size; fragment++) { dlen = (uint32_t)(ha->fw_transfer_size >> 2); if (dlen > risc_size) dlen = risc_size; ql_dbg(ql_dbg_init, vha, 0x0097, - "Loading risc segment@ risc addr %x " - "number of dwords 0x%x.\n", risc_addr, dlen); + "-> Loading fragment %u: %#x <- %#x (%#lx words)...\n", + fragment, risc_addr, + (uint32_t)(fwcode - (typeof(fwcode))blob->fw->data), + dlen); for (i = 0; i < dlen; i++) dcode[i] = swab32(fwcode[i]); - rval = qla2x00_load_ram(vha, req->dma, risc_addr, - dlen); + rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen); if (rval) { ql_log(ql_log_fatal, vha, 0x0098, - "Failed to load segment %d of firmware.\n", + "-> Failed load firmware fragment %u.\n", fragment); return QLA_FUNCTION_FAILED; } @@ -7628,71 +7680,82 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) fwcode += dlen; risc_addr += dlen; risc_size -= dlen; - fragment++; } - - /* Next segment. */ - segments--; } if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - return rval; + return QLA_SUCCESS; - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; + templates = (risc_attr & BIT_9) ? 2 : 1; + ql_dbg(ql_dbg_init, vha, 0x0170, "-> templates = %u\n", templates); + for (j = 0; j < templates; j++, fwdt++) { + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; - ql_dbg(ql_dbg_init, vha, 0x171, - "Loading fwdump template from %x\n", - (uint32_t)((void *)fwcode - (void *)blob->fw->data)); - risc_size = be32_to_cpu(fwcode[2]); - ql_dbg(ql_dbg_init, vha, 0x172, - "-> array size %x dwords\n", risc_size); - if (risc_size == 0 || risc_size == ~0) - goto failed; + risc_size = be32_to_cpu(fwcode[2]); + ql_dbg(ql_dbg_init, vha, 0x0171, + "-> fwdt%u template array at %#x (%#x dwords)\n", + j, (uint32_t)((void *)fwcode - (void *)blob->fw->data), + risc_size); + if (!risc_size || !~risc_size) { + ql_dbg(ql_dbg_init, vha, 0x0172, + "-> fwdt%u failed to read array\n", j); + goto failed; + } - dlen = (risc_size - 8) * sizeof(*fwcode); - ql_dbg(ql_dbg_init, vha, 0x0173, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x0174, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto failed; + /* skip header and ignore checksum */ + fwcode += 7; + risc_size -= 8; + + ql_dbg(ql_dbg_init, vha, 0x0173, + "-> fwdt%u template allocate template %#x words...\n", + j, risc_size); + fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0x0174, + "-> fwdt%u failed allocate template.\n", j); + goto failed; + } + + dcode = fwdt->template; + for (i = 0; i < risc_size; i++) + dcode[i] = le32_to_cpu(fwcode[i]); + + if (!qla27xx_fwdt_template_valid(dcode)) { + ql_log(ql_log_warn, vha, 0x0175, + "-> fwdt%u failed template validate\n", j); + goto failed; + } + + dlen = qla27xx_fwdt_template_size(dcode); + ql_dbg(ql_dbg_init, vha, 0x0176, + "-> fwdt%u template size %#lx bytes (%#lx words)\n", + j, dlen, dlen / sizeof(*dcode)); + if (dlen > risc_size * sizeof(*dcode)) { + ql_log(ql_log_warn, vha, 0x0177, + "-> fwdt%u template exceeds array (%-lu bytes)\n", + j, dlen - risc_size * sizeof(*dcode)); + goto failed; + } + + fwdt->length = dlen; + ql_dbg(ql_dbg_init, vha, 0x0178, + "-> fwdt%u loaded template ok\n", j); + + fwcode += risc_size + 1; } - fwcode += 7; - risc_size -= 8; - dcode = ha->fw_dump_template; - for (i = 0; i < risc_size; i++) - dcode[i] = le32_to_cpu(fwcode[i]); - - if (!qla27xx_fwdt_template_valid(dcode)) { - ql_log(ql_log_warn, vha, 0x0175, - "Failed fwdump template validate\n"); - goto failed; - } - - dlen = qla27xx_fwdt_template_size(dcode); - ql_dbg(ql_dbg_init, vha, 0x0176, - "-> template size %x bytes\n", dlen); - if (dlen > risc_size * sizeof(*fwcode)) { - ql_log(ql_log_warn, vha, 0x0177, - "Failed fwdump template exceeds array by %zx bytes\n", - (size_t)(dlen - risc_size * sizeof(*fwcode))); - goto failed; - } - ha->fw_dump_template_len = dlen; - return rval; + return QLA_SUCCESS; failed: - ql_log(ql_log_warn, vha, 0x017d, "Failed fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - return rval; + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + + return QLA_SUCCESS; } int @@ -7959,9 +8022,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' - || nv->id[3] != ' ' || - nv->nvram_version < cpu_to_le16(ICB_VERSION)) { + if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) || + le16_to_cpu(nv->nvram_version) < ICB_VERSION) { /* Reset NVRAM data. */ ql_log(ql_log_info, vha, 0x0073, "Inconsistent NVRAM detected: checksum=0x%x id=%c " diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index d906d77f2..44d3db4b5 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -4705,6 +4705,9 @@ qla2x00_free_exchoffld_buffer(struct qla_hw_data *ha) static void qla2x00_free_fw_dump(struct qla_hw_data *ha) { + struct fwdt *fwdt = ha->fwdt; + uint j; + if (ha->fce) dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, ha->fce_dma); @@ -4715,8 +4718,6 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha) if (ha->fw_dump) vfree(ha->fw_dump); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); ha->fce = NULL; ha->fce_dma = 0; @@ -4727,8 +4728,13 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha) ha->fw_dump_reading = 0; ha->fw_dump = NULL; ha->fw_dump_len = 0; - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; + + for (j = 0; j < 2; j++, fwdt++) { + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + } } /* diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index 0e3de0637..9c3abe2ba 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -2633,6 +2633,8 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, goto slow_read; try_fast: + if (offset & 0xff) + goto slow_read; optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, &optrom_dma, GFP_KERNEL); if (!optrom) { diff --git a/qla2x00t-32gbit/qla_tmpl.c b/qla2x00t-32gbit/qla_tmpl.c index c6a09d368..da1eb5644 100644 --- a/qla2x00t-32gbit/qla_tmpl.c +++ b/qla2x00t-32gbit/qla_tmpl.c @@ -38,7 +38,6 @@ qla27xx_insert32(uint32_t value, void *buf, ulong *len) static inline void qla27xx_insertbuf(void *mem, ulong size, void *buf, ulong *len) { - if (buf && mem && size) { buf += *len; memcpy(buf, mem, size); @@ -855,23 +854,11 @@ qla27xx_walk_template(struct scsi_qla_host *vha, if (count) ql_dbg(ql_dbg_misc, vha, 0xd018, - "%s: entry residual count (%lx)\n", __func__, count); + "%s: entry count residual=+%lu\n", __func__, count); if (ent) ql_dbg(ql_dbg_misc, vha, 0xd019, - "%s: missing end entry (%lx)\n", __func__, count); - - if (buf && *len != vha->hw->fw_dump_len) - ql_dbg(ql_dbg_misc, vha, 0xd01b, - "%s: length=%#lx residual=%+ld\n", - __func__, *len, vha->hw->fw_dump_len - *len); - - if (buf) { - ql_log(ql_log_warn, vha, 0xd015, - "Firmware dump saved to temp buffer (%lu/%p)\n", - vha->host_no, vha->hw->fw_dump); - qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); - } + "%s: missing end entry\n", __func__); } static void @@ -894,8 +881,8 @@ qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) } static void -qla27xx_firmware_info(struct qla27xx_fwdt_template *tmp, - struct scsi_qla_host *vha) +qla27xx_firmware_info(struct scsi_qla_host *vha, + struct qla27xx_fwdt_template *tmp) { tmp->firmware_version[0] = vha->hw->fw_major_version; tmp->firmware_version[1] = vha->hw->fw_minor_version; @@ -912,7 +899,7 @@ ql27xx_edit_template(struct scsi_qla_host *vha, { qla27xx_time_stamp(tmp); qla27xx_driver_info(tmp); - qla27xx_firmware_info(tmp, vha); + qla27xx_firmware_info(vha, tmp); } static inline uint32_t @@ -943,26 +930,26 @@ qla27xx_verify_template_header(struct qla27xx_fwdt_template *tmp) return le32_to_cpu(tmp->template_type) == TEMPLATE_TYPE_FWDUMP; } -static void -qla27xx_execute_fwdt_template(struct scsi_qla_host *vha) +static ulong +qla27xx_execute_fwdt_template(struct scsi_qla_host *vha, + struct qla27xx_fwdt_template *tmp, void *buf) { - struct qla27xx_fwdt_template *tmp = vha->hw->fw_dump_template; - ulong len; + ulong len = 0; if (qla27xx_fwdt_template_valid(tmp)) { len = tmp->template_size; - tmp = memcpy(vha->hw->fw_dump, tmp, len); + tmp = memcpy(buf, tmp, len); ql27xx_edit_template(vha, tmp); - qla27xx_walk_template(vha, tmp, tmp, &len); - vha->hw->fw_dump_len = len; - vha->hw->fw_dumped = 1; + qla27xx_walk_template(vha, tmp, buf, &len); } + + return len; } ulong -qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *vha) +qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *vha, void *p) { - struct qla27xx_fwdt_template *tmp = vha->hw->fw_dump_template; + struct qla27xx_fwdt_template *tmp = p; ulong len = 0; if (qla27xx_fwdt_template_valid(tmp)) { @@ -1012,17 +999,41 @@ qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) spin_lock_irqsave(&vha->hw->hardware_lock, flags); #endif - if (!vha->hw->fw_dump) - ql_log(ql_log_warn, vha, 0xd01e, "fwdump buffer missing.\n"); - else if (!vha->hw->fw_dump_template) - ql_log(ql_log_warn, vha, 0xd01f, "fwdump template missing.\n"); - else if (vha->hw->fw_dumped) - ql_log(ql_log_warn, vha, 0xd300, - "Firmware has been previously dumped (%p)," - " -- ignoring request\n", vha->hw->fw_dump); - else { - QLA_FW_STOPPED(vha->hw); - qla27xx_execute_fwdt_template(vha); + if (!vha->hw->fw_dump) { + ql_log(ql_log_warn, vha, 0xd01e, "-> fwdump no buffer\n"); + } else if (vha->hw->fw_dumped) { + ql_log(ql_log_warn, vha, 0xd01f, + "-> Firmware already dumped (%p) -- ignoring request\n", + vha->hw->fw_dump); + } else { + struct fwdt *fwdt = vha->hw->fwdt; + uint j; + ulong len; + void *buf = vha->hw->fw_dump; + + for (j = 0; j < 2; j++, fwdt++, buf += len) { + ql_log(ql_log_warn, vha, 0xd011, + "-> fwdt%u running...\n", j); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0xd012, + "-> fwdt%u no template\n", j); + break; + } + len = qla27xx_execute_fwdt_template(vha, + fwdt->template, buf); + if (len != fwdt->dump_size) { + ql_log(ql_log_warn, vha, 0xd013, + "-> fwdt%u fwdump residual=%+ld\n", + j, fwdt->dump_size - len); + } + } + vha->hw->fw_dump_len = buf - (void *)vha->hw->fw_dump; + vha->hw->fw_dumped = 1; + + ql_log(ql_log_warn, vha, 0xd015, + "-> Firmware dump saved to buffer (%lu/%p) <%lx>\n", + vha->host_no, vha->hw->fw_dump, vha->hw->fw_dump_cap_flags); + qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); } #ifndef __CHECKER__ From c4697a40e4201f819117966ae42c0dc956eb0597 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:16:28 +0000 Subject: [PATCH 10/42] qla2xxx: Fix read offset in qla24xx_load_risc_flash() Fixes: "qla2xxx: Cleanups for NVRAM/Flash read/write path" git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8204 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_init.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 6ffc09d22..742003569 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -7451,8 +7451,6 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, dcode = fwdt->template; qla24xx_read_flash_data(vha, dcode, faddr, risc_size); - for (i = 0; i < risc_size; i++) - dcode[i] = le32_to_cpu(dcode[i]); if (!qla27xx_fwdt_template_valid(dcode)) { ql_log(ql_log_warn, vha, 0x0165, @@ -7618,19 +7616,8 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) } fwcode = (void *)blob->fw->data; - dcode = fwcode + 4; + dcode = fwcode; if (qla24xx_risc_firmware_invalid(dcode)) { - ql_log(ql_log_fatal, vha, 0x0093, - "Unable to verify integrity of firmware image (%zd).\n", - blob->fw->size); - return QLA_FUNCTION_FAILED; - } - for (i = 0; i < 4; i++) - dcode[i] = be32_to_cpu(fwcode[i + 4]); - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { ql_log(ql_log_fatal, vha, 0x0094, "Unable to verify integrity of firmware image (%zd).\n", blob->fw->size); @@ -7656,7 +7643,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) dlen = ha->fw_transfer_size >> 2; for (fragment = 0; risc_size; fragment++) { - dlen = (uint32_t)(ha->fw_transfer_size >> 2); if (dlen > risc_size) dlen = risc_size; From cfe8d1022286156eb62c102704e1bdb5d67d8516 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:16:52 +0000 Subject: [PATCH 11/42] qla2xxx: Update flash read/write routine This patch makes following changes to flash access routines: - update return type for read_optrom - use void instead of uint32_t * for buffer parameter in read and write optrom routines - fix flash/nvram addressing git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8205 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 65 +++--- qla2x00t-32gbit/qla_def.h | 8 +- qla2x00t-32gbit/qla_gbl.h | 47 ++-- qla2x00t-32gbit/qla_init.c | 24 +- qla2x00t-32gbit/qla_nx.c | 13 +- qla2x00t-32gbit/qla_nx2.c | 8 +- qla2x00t-32gbit/qla_sup.c | 451 ++++++++++++++++++------------------- 7 files changed, 300 insertions(+), 316 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index e762e60ae..35f780468 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -223,9 +223,9 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj, } /* Write NVRAM. */ - ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count); - ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base, - count); + ha->isp_ops->write_nvram(vha, buf, ha->nvram_base, count); + ha->isp_ops->read_nvram(vha, ha->nvram, ha->nvram_base, + count); mutex_unlock(&ha->optrom_mutex); ql_dbg(ql_dbg_user, vha, 0x7060, @@ -511,22 +511,24 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, if (!capable(CAP_SYS_ADMIN)) return -EINVAL; - if (IS_NOCACHE_VPD_TYPE(ha)) { - faddr = ha->flt_region_vpd << 2; + if (IS_NOCACHE_VPD_TYPE(ha)) + goto skip; - if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && - qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) - faddr = ha->flt_region_vpd_sec << 2; + faddr = ha->flt_region_vpd << 2; - mutex_lock(&ha->optrom_mutex); - if (qla2x00_chip_is_down(vha)) { - mutex_unlock(&ha->optrom_mutex); - return -EAGAIN; - } - ha->isp_ops->read_optrom(vha, ha->vpd, faddr, - ha->vpd_size); + if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_vpd_sec << 2; + + mutex_lock(&ha->optrom_mutex); + if (qla2x00_chip_is_down(vha)) { mutex_unlock(&ha->optrom_mutex); + return -EAGAIN; } + + ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); + mutex_unlock(&ha->optrom_mutex); +skip: return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); } @@ -563,8 +565,8 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj, } /* Write NVRAM. */ - ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count); - ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count); + ha->isp_ops->write_nvram(vha, buf, ha->vpd_base, count); + ha->isp_ops->read_nvram(vha, ha->vpd, ha->vpd_base, count); /* Update flash version information for 4Gb & above. */ if (!IS_FWI2_CAPABLE(ha)) { @@ -934,7 +936,7 @@ static struct bin_attribute sysfs_dcbx_tlv_attr = { static struct sysfs_entry { char *name; struct bin_attribute *attr; - int is4GBp_only; + int type; } bin_file_entries[] = { { "fw_dump", &sysfs_fw_dump_attr, }, { "nvram", &sysfs_nvram_attr, }, @@ -957,11 +959,11 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha) int ret; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw)) + if (iter->type && !IS_FWI2_CAPABLE(vha->hw)) continue; - if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw)) + if (iter->type == 2 && !IS_QLA25XX(vha->hw)) continue; - if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw))) + if (iter->type == 3 && !(IS_CNA_CAPABLE(vha->hw))) continue; ret = sysfs_create_bin_file(&host->shost_gendev.kobj, @@ -985,14 +987,14 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon) struct qla_hw_data *ha = vha->hw; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) + if (iter->type && !IS_FWI2_CAPABLE(ha)) continue; - if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha)) + if (iter->type == 2 && !IS_QLA25XX(ha)) continue; - if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw))) + if (iter->type == 3 && !(IS_CNA_CAPABLE(ha))) continue; - if (iter->is4GBp_only == 0x27 && - (!IS_QLA27XX(vha->hw) || !IS_QLA28XX(ha))) + if (iter->type == 0x27 && + (!IS_QLA27XX(ha) || !IS_QLA28XX(ha))) continue; sysfs_remove_bin_file(&host->shost_gendev.kobj, @@ -1360,19 +1362,20 @@ qla24xx_84xx_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) { int rval = QLA_SUCCESS; - uint16_t status[2] = {0, 0}; + uint16_t status[2] = { 0 }; scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; if (!IS_QLA84XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); - if (ha->cs84xx->op_fw_version == 0) + if (!ha->cs84xx->op_fw_version) { rval = qla84xx_verify_chip(vha, status); - if ((rval == QLA_SUCCESS) && (status[0] == 0)) - return scnprintf(buf, PAGE_SIZE, "%u\n", - (uint32_t)ha->cs84xx->op_fw_version); + if (!rval && !status[0]) + return scnprintf(buf, PAGE_SIZE, "%u\n", + (uint32_t)ha->cs84xx->op_fw_version); + } return scnprintf(buf, PAGE_SIZE, "\n"); } diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 6f058c83a..66a6ca8c0 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3180,9 +3180,9 @@ struct isp_operations { void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t, uint32_t); - uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *, + uint8_t *(*read_nvram)(struct scsi_qla_host *, void *, uint32_t, uint32_t); - int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t, + int (*write_nvram)(struct scsi_qla_host *, void *, uint32_t, uint32_t); void (*fw_dump) (struct scsi_qla_host *, int); @@ -3191,9 +3191,9 @@ struct isp_operations { int (*beacon_off) (struct scsi_qla_host *); void (*beacon_blink) (struct scsi_qla_host *); - uint8_t * (*read_optrom) (struct scsi_qla_host *, uint8_t *, + void *(*read_optrom)(struct scsi_qla_host *, void *, uint32_t, uint32_t); - int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t, + int (*write_optrom)(struct scsi_qla_host *, void *, uint32_t, uint32_t); int (*get_flash_version) (struct scsi_qla_host *, void *); diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 4c55257f0..cd4281f51 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -545,19 +545,20 @@ fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); */ extern void qla2x00_release_nvram_protection(scsi_qla_host_t *); extern uint32_t *qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *, - uint32_t, uint32_t); -extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern int qla25xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); + uint32_t, uint32_t); +extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern int qla2x00_write_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern int qla24xx_write_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern int qla25xx_write_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); + extern int qla2x00_is_a_vp_did(scsi_qla_host_t *, uint32_t); bool qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *, uint32_t); bool qla2x00_check_reg16_for_disconnect(scsi_qla_host_t *, uint16_t); @@ -577,18 +578,18 @@ extern int qla83xx_restart_nic_firmware(scsi_qla_host_t *); extern int qla83xx_access_control(scsi_qla_host_t *, uint16_t, uint32_t, uint32_t, uint16_t *); -extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla2x00_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern int qla2x00_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla2x00_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla24xx_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla24xx_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla25xx_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern uint8_t *qla8044_read_optrom_data(struct scsi_qla_host *, - uint8_t *, uint32_t, uint32_t); +extern void *qla8044_read_optrom_data(struct scsi_qla_host *, + void *, uint32_t, uint32_t); extern void qla8044_watchdog(struct scsi_qla_host *vha); extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); @@ -768,9 +769,9 @@ extern int qla82xx_start_firmware(scsi_qla_host_t *); /* Firmware and flash related functions */ extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *); -extern uint8_t *qla82xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla82xx_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern int qla82xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla82xx_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); /* Mailbox related functions */ @@ -871,7 +872,7 @@ extern void qla8044_clear_drv_active(struct qla_hw_data *); void qla8044_get_minidump(struct scsi_qla_host *vha); int qla8044_collect_md_data(struct scsi_qla_host *vha); extern int qla8044_md_get_template(scsi_qla_host_t *); -extern int qla8044_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla8044_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); extern irqreturn_t qla8044_intr_handler(int, void *); extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 742003569..ac8485804 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -4416,9 +4416,8 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) nv->nvram_version < 1) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x0064, - "Inconsistent NVRAM " - "detected: checksum=0x%x id=%c version=0x%x.\n", - chksum, nv->id[0], nv->nvram_version); + "Inconsistent NVRAM detected: checksum=%#x id=%.4s version=%#x.\n", + chksum, nv->id, nv->nvram_version); ql_log(ql_log_warn, vha, 0x0065, "Falling back to " "functioning (yet invalid -- WWPN) defaults.\n"); @@ -7013,13 +7012,12 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) /* Get VPD data into cache */ ha->vpd = ha->nvram + VPD_OFFSET; - ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, + ha->isp_ops->read_nvram(vha, ha->vpd, ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4); /* Get NVRAM data into cache and calculate checksum. */ dptr = (uint32_t *)nv; - ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base, - ha->nvram_size); + ha->isp_ops->read_nvram(vha, dptr, ha->nvram_base, ha->nvram_size); for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++) chksum += le32_to_cpu(*dptr); @@ -7033,9 +7031,9 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) le16_to_cpu(nv->nvram_version) < ICB_VERSION) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x006b, - "Inconsistent NVRAM detected: checksum=0x%x id=%c " - "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); - ql_dump_buffer(ql_dbg_init, vha, 0x006b, nv, 32); + "Inconsistent NVRAM checksum=%#x id=%.4s version=%#x.\n", + chksum, nv->id, nv->nvram_version); + ql_dump_buffer(ql_dbg_init, vha, 0x006b, nv, sizeof(*nv)); ql_log(ql_log_warn, vha, 0x006c, "Falling back to functioning (yet invalid -- WWPN) " "defaults.\n"); @@ -7424,6 +7422,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, fwdt->template = NULL; fwdt->length = 0; + dcode = (void *)req->ring; qla24xx_read_flash_data(vha, dcode, faddr, 7); risc_size = be32_to_cpu(dcode[2]); ql_dbg(ql_dbg_init, vha, 0x0161, @@ -8012,10 +8011,9 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) le16_to_cpu(nv->nvram_version) < ICB_VERSION) { /* Reset NVRAM data. */ ql_log(ql_log_info, vha, 0x0073, - "Inconsistent NVRAM detected: checksum=0x%x id=%c " - "version=0x%x.\n", chksum, nv->id[0], - le16_to_cpu(nv->nvram_version)); - ql_dump_buffer(ql_dbg_init, vha, 0x0073, nv, 32); + "Inconsistent NVRAM checksum=%#x id=%.4s version=%#x.\n", + chksum, nv->id, le16_to_cpu(nv->nvram_version)); + ql_dump_buffer(ql_dbg_init, vha, 0x0073, nv, sizeof(*nv)); ql_log(ql_log_info, vha, 0x0074, "Falling back to functioning (yet invalid -- WWPN) " "defaults.\n"); diff --git a/qla2x00t-32gbit/qla_nx.c b/qla2x00t-32gbit/qla_nx.c index f2f54806f..d545d3441 100644 --- a/qla2x00t-32gbit/qla_nx.c +++ b/qla2x00t-32gbit/qla_nx.c @@ -2658,8 +2658,8 @@ done: /* * Address and length are byte address */ -uint8_t * -qla82xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla82xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { scsi_block_requests(vha->host); @@ -2767,15 +2767,14 @@ write_done: } int -qla82xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla82xx_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; /* Suspend HBA. */ scsi_block_requests(vha->host); - rval = qla82xx_write_flash_data(vha, (uint32_t *)buf, offset, - length >> 2); + rval = qla82xx_write_flash_data(vha, buf, offset, length >> 2); scsi_unblock_requests(vha->host); /* Convert return ISP82xx to generic */ @@ -3699,8 +3698,8 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Wait for pending cmds (physical and virtual) to complete */ - if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, - WAIT_HOST)) { + if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0, + WAIT_HOST) == QLA_SUCCESS) { ql_dbg(ql_dbg_init, vha, 0x00b3, "Done wait for " "pending commands.\n"); diff --git a/qla2x00t-32gbit/qla_nx2.c b/qla2x00t-32gbit/qla_nx2.c index fe856b602..691f81d7b 100644 --- a/qla2x00t-32gbit/qla_nx2.c +++ b/qla2x00t-32gbit/qla_nx2.c @@ -559,12 +559,12 @@ exit_lock_error: /* * Address and length are byte address */ -uint8_t * -qla8044_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla8044_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { scsi_block_requests(vha->host); - if (qla8044_read_flash_data(vha, (uint8_t *)buf, offset, length / 4) + if (qla8044_read_flash_data(vha, buf, offset, length / 4) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0xb08d, "%s: Failed to read from flash\n", @@ -3797,7 +3797,7 @@ qla8044_write_flash_dword_mode(scsi_qla_host_t *vha, uint32_t *dwptr, } int -qla8044_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla8044_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval = QLA_FUNCTION_FAILED, i, burst_iter_count; diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index 9c3abe2ba..eb4514a56 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -429,66 +429,64 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat) static inline uint32_t flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr) { - return ha->flash_conf_off | faddr; + return ha->flash_conf_off + faddr; } static inline uint32_t flash_data_addr(struct qla_hw_data *ha, uint32_t faddr) { - return ha->flash_data_off | faddr; + return ha->flash_data_off + faddr; } static inline uint32_t nvram_conf_addr(struct qla_hw_data *ha, uint32_t naddr) { - return ha->nvram_conf_off | naddr; + return ha->nvram_conf_off + naddr; } static inline uint32_t nvram_data_addr(struct qla_hw_data *ha, uint32_t naddr) { - return ha->nvram_data_off | naddr; + return ha->nvram_data_off + naddr; } -static uint32_t -qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr) +static int +qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t *data) { - int rval; - uint32_t cnt, data; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + ulong cnt = 30000; WRT_REG_DWORD(®->flash_addr, addr & ~FARX_DATA_FLAG); - /* Wait for READ cycle to complete. */ - rval = QLA_SUCCESS; - for (cnt = 3000; - (RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG) == 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(10); - else - rval = QLA_FUNCTION_TIMEOUT; + + while (cnt--) { + if (RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG) { + *data = RD_REG_DWORD(®->flash_data); + return QLA_SUCCESS; + } + udelay(10); cond_resched(); } - /* TODO: What happens if we time out? */ - data = 0xDEADDEAD; - if (rval == QLA_SUCCESS) - data = RD_REG_DWORD(®->flash_data); - - return data; + ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090, + "Flash read dword at %x timeout.\n", addr); + *data = 0xDEADDEAD; + return QLA_FUNCTION_TIMEOUT; } uint32_t * qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { - uint32_t i; + ulong i; struct qla_hw_data *ha = vha->hw; /* Dword reads to flash. */ - for (i = 0; i < dwords; i++, faddr++) - dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, - flash_data_addr(ha, faddr))); + faddr = flash_data_addr(ha, faddr); + for (i = 0; i < dwords; i++, faddr++, dwptr++) { + if (qla24xx_read_flash_dword(ha, faddr, dwptr)) + break; + cpu_to_le32s(dwptr); + } return dwptr; } @@ -496,35 +494,37 @@ qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, static int qla24xx_write_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t data) { - int rval; - uint32_t cnt; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + ulong cnt = 500000; WRT_REG_DWORD(®->flash_data, data); - RD_REG_DWORD(®->flash_data); /* PCI Posting. */ WRT_REG_DWORD(®->flash_addr, addr | FARX_DATA_FLAG); - /* Wait for Write cycle to complete. */ - rval = QLA_SUCCESS; - for (cnt = 500000; (RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG) && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(10); - else - rval = QLA_FUNCTION_TIMEOUT; + + while (cnt--) { + if (!(RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG)) + return QLA_SUCCESS; + udelay(10); cond_resched(); } - return rval; + + ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090, + "Flash write dword at %x timeout.\n", addr); + return QLA_FUNCTION_TIMEOUT; } static void qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id, uint8_t *flash_id) { - uint32_t ids; + uint32_t faddr, ids = 0; - ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x03ab)); - *man_id = LSB(ids); - *flash_id = MSB(ids); + *man_id = *flash_id = 0; + + faddr = flash_conf_addr(ha, 0x03ab); + if (!qla24xx_read_flash_dword(ha, faddr, &ids)) { + *man_id = LSB(ids); + *flash_id = MSB(ids); + } /* Check if man_id and flash_id are valid. */ if (ids != 0xDEADDEAD && (*man_id == 0 || *flash_id == 0)) { @@ -534,9 +534,11 @@ qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id, * Example: ATMEL 0x00 01 45 1F * Extract MFG and Dev ID from last two bytes. */ - ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x009f)); - *man_id = LSB(ids); - *flash_id = MSB(ids); + faddr = flash_conf_addr(ha, 0x009f); + if (!qla24xx_read_flash_dword(ha, faddr, &ids)) { + *man_id = LSB(ids); + *flash_id = MSB(ids); + } } } @@ -545,12 +547,12 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) { const char *loc, *locations[] = { "DEF", "PCI" }; uint32_t pcihdr, pcids; - uint32_t *dcode; - uint8_t *buf, *bcode, last_image; uint16_t cnt, chksum, *wptr; - struct qla_flt_location *fltl; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct qla_flt_location *fltl = (void *)req->ring; + uint32_t *dcode = (void *)req->ring; + uint8_t *buf = (void *)req->ring, *bcode, last_image; /* * FLT-location structure resides after the last PCI region. @@ -575,11 +577,9 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) *start = FA_FLASH_LAYOUT_ADDR_28; goto end; } + /* Begin with first PCI expansion ROM header. */ - buf = (uint8_t *)req->ring; - dcode = (uint32_t *)req->ring; pcihdr = 0; - last_image = 1; do { /* Verify PCI expansion ROM header. */ qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); @@ -604,15 +604,12 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) } while (!last_image); /* Now verify FLT-location structure. */ - fltl = (struct qla_flt_location *)req->ring; - qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, - sizeof(struct qla_flt_location) >> 2); - if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' || - fltl->sig[2] != 'L' || fltl->sig[3] != 'T') + qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, sizeof(*fltl) >> 2); + if (memcmp(fltl->sig, "QFLT", 4)) goto end; - wptr = (uint16_t *)req->ring; - cnt = sizeof(struct qla_flt_location) >> 1; + wptr = (void *)req->ring; + cnt = sizeof(*fltl) / sizeof(*wptr); for (chksum = 0; cnt--; wptr++) chksum += le16_to_cpu(*wptr); if (chksum) { @@ -915,22 +912,19 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) #define FLASH_BLK_SIZE_32K 0x8000 #define FLASH_BLK_SIZE_64K 0x10000 const char *loc, *locations[] = { "MID", "FDT" }; - uint16_t cnt, chksum; - uint16_t *wptr; - struct qla_fdt_layout *fdt; - uint8_t man_id, flash_id; - uint16_t mid = 0, fid = 0; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + uint16_t cnt, chksum; + uint16_t *wptr = (void *)req->ring; + struct qla_fdt_layout *fdt = (void *)req->ring; + uint8_t man_id, flash_id; + uint16_t mid = 0, fid = 0; - wptr = (uint16_t *)req->ring; - fdt = (struct qla_fdt_layout *)req->ring; - ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, - ha->flt_region_fdt << 2, OPTROM_BURST_SIZE); - if (*wptr == cpu_to_le16(0xffff)) + qla24xx_read_flash_data(vha, (void *)fdt, ha->flt_region_fdt, + OPTROM_BURST_DWORDS); + if (le16_to_cpu(*wptr) == 0xffff) goto no_flash_data; - if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || - fdt->sig[3] != 'D') + if (memcmp(fdt->sig, "QLID", 4)) goto no_flash_data; for (cnt = 0, chksum = 0; cnt < sizeof(*fdt) >> 1; cnt++, wptr++) @@ -1022,8 +1016,7 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha) return; wptr = (uint32_t *)req->ring; - ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, - QLA82XX_IDC_PARAM_ADDR , 8); + ha->isp_ops->read_optrom(vha, req->ring, QLA82XX_IDC_PARAM_ADDR, 8); if (*wptr == cpu_to_le32(0xffffffff)) { ha->fcoe_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT; @@ -1085,8 +1078,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) if (IS_QLA8044(ha)) return; - ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr, - ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header)); + ha->isp_ops->read_optrom(vha, &hdr, ha->flt_region_npiv_conf << 2, + sizeof(struct qla_npiv_header)); if (hdr.version == cpu_to_le16(0xffff)) return; if (hdr.version != cpu_to_le16(1)) { @@ -1105,8 +1098,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) return; } - ha->isp_ops->read_optrom(vha, (uint8_t *)data, - ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE); + ha->isp_ops->read_optrom(vha, data, ha->flt_region_npiv_conf << 2, + NPIV_CONFIG_SIZE); cnt = (sizeof(hdr) + le16_to_cpu(hdr.entries) * sizeof(*entry)) >> 1; for (wptr = data, chksum = 0; cnt--; wptr++) @@ -1143,10 +1136,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) vid.node_name = wwn_to_u64(entry->node_name); ql_dbg(ql_dbg_user, vha, 0x7093, - "NPIV[%02x]: wwpn=%llx " - "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt, - (unsigned long long)vid.port_name, - (unsigned long long)vid.node_name, + "NPIV[%02x]: wwpn=%llx wwnn=%llx vf_id=%#x Q_qos=%#x F_qos=%#x.\n", + cnt, vid.port_name, vid.node_name, le16_to_cpu(entry->vf_id), entry->q_qos, entry->f_qos); @@ -1154,10 +1145,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) vport = fc_vport_create(vha->host, 0, &vid); if (!vport) ql_log(ql_log_warn, vha, 0x7094, - "NPIV-Config Failed to create vport [%02x]: " - "wwpn=%llx wwnn=%llx.\n", cnt, - (unsigned long long)vid.port_name, - (unsigned long long)vid.node_name); + "NPIV-Config Failed to create vport [%02x]: wwpn=%llx wwnn=%llx.\n", + cnt, vid.port_name, vid.node_name); } } done: @@ -1192,9 +1181,10 @@ done: static int qla24xx_protect_flash(scsi_qla_host_t *vha) { - uint32_t cnt; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + ulong cnt = 300; + uint32_t faddr, dword; if (ha->flags.fac_supported) return qla81xx_fac_do_write_enable(vha, 0); @@ -1203,11 +1193,14 @@ qla24xx_protect_flash(scsi_qla_host_t *vha) goto skip_wrt_protect; /* Enable flash write-protection and wait for completion. */ - qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), - ha->fdt_wrt_disable); - for (cnt = 300; cnt && - qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x005)) & BIT_0; - cnt--) { + faddr = flash_conf_addr(ha, 0x101); + qla24xx_write_flash_dword(ha, faddr, ha->fdt_wrt_disable); + faddr = flash_conf_addr(ha, 0x5); + while (cnt--) { + if (!qla24xx_read_flash_dword(ha, faddr, &dword)) { + if (!(dword & BIT_0)) + break; + } udelay(10); } @@ -1215,7 +1208,6 @@ skip_wrt_protect: /* Disable flash write. */ WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); - RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ return QLA_SUCCESS; } @@ -1243,107 +1235,103 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { int ret; - uint32_t liter; - uint32_t sec_mask, rest_addr; - uint32_t fdata; + ulong liter; + ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */ + uint32_t sec_mask, rest_addr, fdata; dma_addr_t optrom_dma; void *optrom = NULL; struct qla_hw_data *ha = vha->hw; - /* Prepare burst-capable write on supported ISPs. */ - if ((IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha) || IS_QLA28XX(ha)) && - !(faddr & 0xfff) && dwords > OPTROM_BURST_DWORDS) { - optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, - &optrom_dma, GFP_KERNEL); - if (!optrom) { - ql_log(ql_log_warn, vha, 0x7095, - "Unable to allocate " - "memory for optrom burst write (%x KB).\n", - OPTROM_BURST_SIZE / 1024); - } + if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + goto next; + + /* Allocate dma buffer for burst write */ + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + ql_log(ql_log_warn, vha, 0x7095, + "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE); + } + +next: + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Unprotect flash...\n"); + ret = qla24xx_unprotect_flash(vha); + if (ret) { + ql_log(ql_log_warn, vha, 0x7096, + "Failed to unprotect flash.\n"); + goto done; } rest_addr = (ha->fdt_block_size >> 2) - 1; sec_mask = ~rest_addr; - - ret = qla24xx_unprotect_flash(vha); - if (ret != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x7096, - "Unable to unprotect flash for update.\n"); - goto done; - } - for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { fdata = (faddr & sec_mask) << 2; /* Are we at the beginning of a sector? */ - if ((faddr & rest_addr) == 0) { - /* Do sector unprotect. */ - if (ha->fdt_unprotect_sec_cmd) - qla24xx_write_flash_dword(ha, - ha->fdt_unprotect_sec_cmd, - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); + if (!(faddr & rest_addr)) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Erase sector %#x...\n", faddr); + ret = qla24xx_erase_sector(vha, fdata); - if (ret != QLA_SUCCESS) { + if (ret) { ql_dbg(ql_dbg_user, vha, 0x7007, - "Unable to erase erase sector: address=%x.\n", - faddr); + "Failed to erase sector %x.\n", faddr); break; } } - /* Go with burst-write. */ - if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) { - /* Copy data to DMA'ble buffer. */ - memcpy(optrom, dwptr, OPTROM_BURST_SIZE); + if (optrom) { + /* If smaller than a burst remaining */ + if (dwords - liter < dburst) + dburst = dwords - liter; + /* Copy to dma buffer */ + memcpy(optrom, dwptr, dburst << 2); + + /* Burst write */ + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Write burst (%#lx dwords)...\n", dburst); ret = qla2x00_load_ram(vha, optrom_dma, - flash_data_addr(ha, faddr), - OPTROM_BURST_DWORDS); - if (ret != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x7097, - "Unable to burst-write optrom segment " - "(%x/%x/%llx).\n", ret, - flash_data_addr(ha, faddr), - (unsigned long long)optrom_dma); - ql_log(ql_log_warn, vha, 0x7098, - "Reverting to slow-write.\n"); - - dma_free_coherent(&ha->pdev->dev, - OPTROM_BURST_SIZE, optrom, optrom_dma); - optrom = NULL; - } else { - liter += OPTROM_BURST_DWORDS - 1; - faddr += OPTROM_BURST_DWORDS - 1; - dwptr += OPTROM_BURST_DWORDS - 1; + flash_data_addr(ha, faddr), dburst); + if (!ret) { + liter += dburst - 1; + faddr += dburst - 1; + dwptr += dburst - 1; continue; } + + ql_log(ql_log_warn, vha, 0x7097, + "Failed burst-write at %x (%p/%#llx)....\n", + flash_data_addr(ha, faddr), optrom, + (u64)optrom_dma); + + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + optrom = NULL; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + break; + ql_log(ql_log_warn, vha, 0x7098, + "Reverting to slow write...\n"); } + /* Slow write */ ret = qla24xx_write_flash_dword(ha, flash_data_addr(ha, faddr), cpu_to_le32(*dwptr)); - if (ret != QLA_SUCCESS) { + if (ret) { ql_dbg(ql_dbg_user, vha, 0x7006, - "Unable to program flash address=%x data=%x.\n", - faddr, *dwptr); + "Failed slopw write %x (%x)\n", faddr, *dwptr); break; } - - /* Do sector protect. */ - if (ha->fdt_unprotect_sec_cmd && - ((faddr & rest_addr) == rest_addr)) - qla24xx_write_flash_dword(ha, - ha->fdt_protect_sec_cmd, - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); } + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Protect flash...\n"); ret = qla24xx_protect_flash(vha); - if (ret != QLA_SUCCESS) + if (ret) ql_log(ql_log_warn, vha, 0x7099, - "Unable to protect flash after update.\n"); + "Failed to protect flash\n"); done: if (optrom) dma_free_coherent(&ha->pdev->dev, @@ -1353,7 +1341,7 @@ done: } uint8_t * -qla2x00_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla2x00_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { uint32_t i; @@ -1372,27 +1360,30 @@ qla2x00_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, } uint8_t * -qla24xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla24xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { - uint32_t i; - uint32_t *dwptr; struct qla_hw_data *ha = vha->hw; + uint32_t *dwptr = buf; + uint32_t i; if (IS_P3P_TYPE(ha)) return buf; /* Dword reads to flash. */ - dwptr = (uint32_t *)buf; - for (i = 0; i < bytes >> 2; i++, naddr++) - dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, - nvram_data_addr(ha, naddr))); + naddr = nvram_data_addr(ha, naddr); + bytes >>= 2; + for (i = 0; i < bytes; i++, naddr++, dwptr++) { + if (qla24xx_read_flash_dword(ha, naddr, dwptr)) + break; + cpu_to_le32s(dwptr); + } return buf; } int -qla2x00_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla2x00_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { int ret, stat; @@ -1426,14 +1417,14 @@ qla2x00_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, } int -qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla24xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { - int ret; - uint32_t i; - uint32_t *dwptr; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + uint32_t *dwptr = buf; + uint32_t i; + int ret; ret = QLA_SUCCESS; @@ -1450,11 +1441,10 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0); /* Dword writes to flash. */ - dwptr = (uint32_t *)buf; - for (i = 0; i < bytes >> 2; i++, naddr++, dwptr++) { - ret = qla24xx_write_flash_dword(ha, - nvram_data_addr(ha, naddr), cpu_to_le32(*dwptr)); - if (ret != QLA_SUCCESS) { + naddr = nvram_data_addr(ha, naddr); + bytes >>= 2; + for (i = 0; i < bytes; i++, naddr++, dwptr++) { + if (qla24xx_write_flash_dword(ha, naddr, cpu_to_le32(*dwptr))) { ql_dbg(ql_dbg_user, vha, 0x709a, "Unable to program nvram address=%x data=%x.\n", naddr, *dwptr); @@ -1474,31 +1464,34 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, } uint8_t * -qla25xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla25xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { - uint32_t i; - uint32_t *dwptr; struct qla_hw_data *ha = vha->hw; + uint32_t *dwptr = buf; + uint32_t i; /* Dword reads to flash. */ - dwptr = (uint32_t *)buf; - for (i = 0; i < bytes >> 2; i++, naddr++) - dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, - flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr))); + naddr = flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr); + bytes >>= 2; + for (i = 0; i < bytes; i++, naddr++, dwptr++) { + if (qla24xx_read_flash_dword(ha, naddr, dwptr)) + break; + + cpu_to_le32s(dwptr); + } return buf; } +#define RMW_BUFFER_SIZE (64 * 1024) int -qla25xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla25xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { struct qla_hw_data *ha = vha->hw; -#define RMW_BUFFER_SIZE (64 * 1024) - uint8_t *dbuf; + uint8_t *dbuf = vmalloc(RMW_BUFFER_SIZE); - dbuf = vmalloc(RMW_BUFFER_SIZE); if (!dbuf) return QLA_MEMORY_ALLOC_FAILED; ha->isp_ops->read_optrom(vha, dbuf, ha->flt_region_vpd_nvram << 2, @@ -2319,8 +2312,8 @@ qla2x00_resume_hba(struct scsi_qla_host *vha) scsi_unblock_requests(vha->host); } -uint8_t * -qla2x00_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla2x00_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { uint32_t addr, midpoint; @@ -2354,12 +2347,12 @@ qla2x00_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, } int -qla2x00_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla2x00_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; - uint8_t man_id, flash_id, sec_number, data; + uint8_t man_id, flash_id, sec_number, *data; uint16_t wd; uint32_t addr, liter, sec_mask, rest_addr; struct qla_hw_data *ha = vha->hw; @@ -2488,7 +2481,7 @@ update_flash: for (addr = offset, liter = 0; liter < length; liter++, addr++) { - data = buf[liter]; + data = buf + liter; /* Are we at the beginning of a sector? */ if ((addr & rest_addr) == 0) { if (IS_QLA2322(ha) || IS_QLA6322(ha)) { @@ -2556,7 +2549,7 @@ update_flash: } } - if (qla2x00_program_flash_address(ha, addr, data, + if (qla2x00_program_flash_address(ha, addr, *data, man_id, flash_id)) { rval = QLA_FUNCTION_FAILED; break; @@ -2572,8 +2565,8 @@ update_flash: return rval; } -uint8_t * -qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla24xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { struct qla_hw_data *ha = vha->hw; @@ -2583,7 +2576,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with read. */ - qla24xx_read_flash_data(vha, (uint32_t *)buf, offset >> 2, length >> 2); + qla24xx_read_flash_data(vha, (void *)buf, offset >> 2, length >> 2); /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); @@ -2593,7 +2586,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, } int -qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla24xx_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; @@ -2604,7 +2597,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with write. */ - rval = qla24xx_write_flash_data(vha, (uint32_t *)buf, offset >> 2, + rval = qla24xx_write_flash_data(vha, buf, offset >> 2, length >> 2); clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); @@ -2613,8 +2606,8 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, return rval; } -uint8_t * -qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla25xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; @@ -2881,7 +2874,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf) "Dumping fw " "ver from flash:.\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010b, - dbyte, 8); + dbyte, 32); if ((dcode[0] == 0xffff && dcode[1] == 0xffff && dcode[2] == 0xffff && dcode[3] == 0xffff) || @@ -2912,8 +2905,8 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) { int ret = QLA_SUCCESS; uint32_t pcihdr, pcids; - uint32_t *dcode; - uint8_t *bcode; + uint32_t *dcode = mbuf; + uint8_t *bcode = mbuf; uint8_t code_type, last_image; struct qla_hw_data *ha = vha->hw; @@ -2925,17 +2918,14 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); - dcode = mbuf; - /* Begin with first PCI expansion ROM header. */ pcihdr = ha->flt_region_boot << 2; last_image = 1; do { /* Verify PCI expansion ROM header. */ - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, pcihdr, - 0x20 * 4); + ha->isp_ops->read_optrom(vha, dcode, pcihdr, 0x20 * 4); bcode = mbuf + (pcihdr % 4); - if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { + if (memcmp(bcode, "\x55\xaa", 2)) { /* No signature */ ql_log(ql_log_fatal, vha, 0x0154, "No matching ROM signature.\n"); @@ -2946,13 +2936,11 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) /* Locate PCI data structure. */ pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, pcids, - 0x20 * 4); + ha->isp_ops->read_optrom(vha, dcode, pcids, 0x20 * 4); bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ - if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || - bcode[0x2] != 'I' || bcode[0x3] != 'R') { + if (memcmp(bcode, "PCIR", 4)) { /* Incorrect header. */ ql_log(ql_log_fatal, vha, 0x0155, "PCI data struct not found pcir_adr=%x.\n", pcids); @@ -3003,8 +2991,7 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) /* Read firmware image information. */ memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dcode = mbuf; - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, ha->flt_region_fw << 2, - 0x20); + ha->isp_ops->read_optrom(vha, dcode, ha->flt_region_fw << 2, 0x20); bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ @@ -3026,16 +3013,14 @@ int qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) { int ret = QLA_SUCCESS; - uint32_t pcihdr, pcids; - uint32_t *dcode; - uint8_t *bcode; + uint32_t pcihdr = 0, pcids = 0; + uint32_t *dcode = mbuf; + uint8_t *bcode = mbuf; uint8_t code_type, last_image; int i; struct qla_hw_data *ha = vha->hw; uint32_t faddr = 0; - pcihdr = pcids = 0; - if (IS_P3P_TYPE(ha)) return ret; @@ -3047,18 +3032,16 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); - dcode = mbuf; pcihdr = ha->flt_region_boot << 2; if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) pcihdr = ha->flt_region_boot_sec << 2; - last_image = 1; do { /* Verify PCI expansion ROM header. */ qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); bcode = mbuf + (pcihdr % 4); - if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { + if (memcmp(bcode, "\x55\xaa", 2)) { /* No signature */ ql_log(ql_log_fatal, vha, 0x0059, "No matching ROM signature.\n"); @@ -3073,11 +3056,11 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ - if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || - bcode[0x2] != 'I' || bcode[0x3] != 'R') { + if (memcmp(bcode, "PCIR", 4)) { /* Incorrect header. */ ql_log(ql_log_fatal, vha, 0x005a, "PCI data struct not found pcir_adr=%x.\n", pcids); + ql_dump_buffer(ql_dbg_init, vha, 0x0059, dcode, 32); ret = QLA_FUNCTION_FAILED; break; } @@ -3124,7 +3107,6 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) /* Read firmware image information. */ memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); - dcode = mbuf; faddr = ha->flt_region_fw; if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) @@ -3135,11 +3117,12 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) ql_log(ql_log_warn, vha, 0x005f, "Unrecognized fw revision at %x.\n", ha->flt_region_fw * 4); + ql_dump_buffer(ql_dbg_init, vha, 0x005f, dcode, 32); } else { for (i = 0; i < 4; i++) ha->fw_revision[i] = be32_to_cpu(dcode[4+i]); ql_dbg(ql_dbg_init, vha, 0x0060, - "Firmware revision (flash) %d.%d.%d (%x).\n", + "Firmware revision (flash) %u.%u.%u (%x).\n", ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], ha->fw_revision[3]); } @@ -3151,12 +3134,12 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) } memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version)); - dcode = mbuf; - qla24xx_read_flash_data(vha, dcode, ha->flt_region_gold_fw, 8); + faddr = ha->flt_region_gold_fw; + qla24xx_read_flash_data(vha, (void *)dcode, ha->flt_region_gold_fw, 8); if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_warn, vha, 0x0056, - "Unrecognized golden fw at 0x%x.\n", - ha->flt_region_gold_fw * 4); + "Unrecognized golden fw at %#x.\n", faddr); + ql_dump_buffer(ql_dbg_init, vha, 0x0056, dcode, 32); return ret; } @@ -3233,7 +3216,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha) fcp_prio_addr = ha->flt_region_fcp_prio; /* first read the fcp priority data header from flash */ - ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg, + ha->isp_ops->read_optrom(vha, ha->fcp_prio_cfg, fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE); if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 0)) @@ -3244,7 +3227,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha) len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE; max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE; - ha->isp_ops->read_optrom(vha, (uint8_t *)&ha->fcp_prio_cfg->entry[0], + ha->isp_ops->read_optrom(vha, &ha->fcp_prio_cfg->entry[0], fcp_prio_addr << 2, (len < max_len ? len : max_len)); /* revalidate the entire FCP priority config data, including entries */ From f6fc5d84845ff4f0ae5ab3389579ed9bf027350c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:17:21 +0000 Subject: [PATCH 12/42] qla2xxx: Correction and improvement to fwdt processing This patch cleans up and fixes firmware dump template processing. These changes are added to support newer features for ISP27XX/ISP28XX. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8206 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_tmpl.c | 43 +++++++++++++++++++++----------------- qla2x00t-32gbit/qla_tmpl.h | 2 +- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/qla2x00t-32gbit/qla_tmpl.c b/qla2x00t-32gbit/qla_tmpl.c index da1eb5644..9f8a7a3d6 100644 --- a/qla2x00t-32gbit/qla_tmpl.c +++ b/qla2x00t-32gbit/qla_tmpl.c @@ -99,9 +99,9 @@ static inline void qla27xx_write_reg(__iomem struct device_reg_24xx *reg, uint offset, uint32_t data, void *buf) { - __iomem void *window = (void __iomem *)reg + offset; - if (buf) { + void __iomem *window = (void __iomem *)reg + offset; + WRT_REG_DWORD(window, data); } } @@ -709,10 +709,10 @@ qla27xx_fwdt_entry_t275(struct scsi_qla_host *vha, goto done; } if (offset + length > size) { + length = size - offset; ql_dbg(ql_dbg_misc, vha, 0xd030, - "%s: buffer overflow\n", __func__); - qla27xx_skip_entry(ent, buf); - goto done; + "%s: buffer overflow, truncate [%lx]\n", __func__, length); + ent->t275.length = cpu_to_le32(length); } qla27xx_insertbuf(buffer, length, buf, len); @@ -724,17 +724,22 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t276(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - ulong cond1 = le32_to_cpu(ent->t276.cond1); - ulong cond2 = le32_to_cpu(ent->t276.cond2); - uint type = vha->hw->pdev->device >> 4 & 0xf; - uint func = vha->hw->port_no & 0x3; - ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd214, "%s: cond [%lx]\n", __func__, *len); - if (type != cond1 || func != cond2) { - ent = qla27xx_next_entry(ent); - qla27xx_skip_entry(ent, buf); + if (buf) { + ulong cond1 = le32_to_cpu(ent->t276.cond1); + ulong cond2 = le32_to_cpu(ent->t276.cond2); + uint type = vha->hw->pdev->device >> 4 & 0xf; + uint func = vha->hw->port_no & 0x3; + + if (type != cond1 || func != cond2) { + struct qla27xx_fwdt_template *tmp = buf; + + tmp->count--; + ent = qla27xx_next_entry(ent); + qla27xx_skip_entry(ent, buf); + } } return qla27xx_next_entry(ent); @@ -840,21 +845,21 @@ qla27xx_walk_template(struct scsi_qla_host *vha, { struct qla27xx_fwdt_entry *ent = (void *)tmp + le32_to_cpu(tmp->entry_offset); - ulong count = le32_to_cpu(tmp->entry_count); - ulong type = 0; + ulong type; + tmp->count = le32_to_cpu(tmp->entry_count); ql_dbg(ql_dbg_misc, vha, 0xd01a, - "%s: entry count %lx\n", __func__, count); - while (count--) { + "%s: entry count %u\n", __func__, tmp->count); + while (ent && tmp->count--) { type = le32_to_cpu(ent->hdr.type); ent = qla27xx_find_entry(type)(vha, ent, buf, len); if (!ent) break; } - if (count) + if (tmp->count) ql_dbg(ql_dbg_misc, vha, 0xd018, - "%s: entry count residual=+%lu\n", __func__, count); + "%s: entry count residual=+%u\n", __func__, tmp->count); if (ent) ql_dbg(ql_dbg_misc, vha, 0xd019, diff --git a/qla2x00t-32gbit/qla_tmpl.h b/qla2x00t-32gbit/qla_tmpl.h index 6ce7fff01..d2a0014e8 100644 --- a/qla2x00t-32gbit/qla_tmpl.h +++ b/qla2x00t-32gbit/qla_tmpl.h @@ -14,7 +14,7 @@ struct __packed qla27xx_fwdt_template { __le32 template_type; __le32 entry_offset; uint32_t template_size; - uint32_t reserved_1; + uint32_t count; /* borrow field for running/residual count */ __le32 entry_count; uint32_t template_version; From 386626802fc926b8ecc60f0fd713e60c491e0ee3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:18:11 +0000 Subject: [PATCH 13/42] qla2xxx: Simplify register address used in qla_tmpl.c Reduce stack space on each fwdt routine by eliminating local variable reg. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8207 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_tmpl.c | 71 +++++++++++++++----------------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/qla2x00t-32gbit/qla_tmpl.c b/qla2x00t-32gbit/qla_tmpl.c index 9f8a7a3d6..de696a075 100644 --- a/qla2x00t-32gbit/qla_tmpl.c +++ b/qla2x00t-32gbit/qla_tmpl.c @@ -7,13 +7,9 @@ #include "qla_def.h" #include "qla_tmpl.h" -#define IOBASE(reg) offsetof(typeof(*reg), iobase_addr) - -static inline void __iomem * -qla27xx_isp_reg(struct scsi_qla_host *vha) -{ - return &vha->hw->iobase->isp24; -} +#define ISPREG(vha) (&(vha)->hw->iobase->isp24) +#define IOBAR(reg) offsetof(typeof(*(reg)), iobase_addr) +#define IOBASE(vha) IOBAR(ISPREG(vha)) static inline void qla27xx_insert16(uint16_t value, void *buf, ulong *len) @@ -114,7 +110,7 @@ qla27xx_read_window(__iomem struct device_reg_24xx *reg, void __iomem *window = (void __iomem *)reg + offset; void (*readn)(void __iomem*, void *, ulong *) = qla27xx_read_vector(width); - qla27xx_write_reg(reg, IOBASE_ADDR, addr, buf); + qla27xx_write_reg(reg, IOBAR(reg), addr, buf); while (count--) { qla27xx_insert32(addr, buf, len); readn(window, buf, len); @@ -163,7 +159,6 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t256(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); ulong addr = le32_to_cpu(ent->t256.base_addr); uint offset = ent->t256.pci_offset; ulong count = le16_to_cpu(ent->t256.reg_count); @@ -171,7 +166,7 @@ qla27xx_fwdt_entry_t256(struct scsi_qla_host *vha, ql_dbg(ql_dbg_misc, vha, 0xd200, "%s: rdio t1 [%lx]\n", __func__, *len); - qla27xx_read_window(reg, addr, offset, count, width, buf, len); + qla27xx_read_window(ISPREG(vha), addr, offset, count, width, buf, len); return qla27xx_next_entry(ent); } @@ -180,15 +175,14 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t257(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); ulong addr = le32_to_cpu(ent->t257.base_addr); uint offset = ent->t257.pci_offset; ulong data = le32_to_cpu(ent->t257.write_data); ql_dbg(ql_dbg_misc, vha, 0xd201, "%s: wrio t1 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE(reg), addr, buf); - qla27xx_write_reg(reg, offset, data, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE(vha), addr, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -197,7 +191,6 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t258(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); uint banksel = ent->t258.banksel_offset; ulong bank = le32_to_cpu(ent->t258.bank); ulong addr = le32_to_cpu(ent->t258.base_addr); @@ -207,8 +200,8 @@ qla27xx_fwdt_entry_t258(struct scsi_qla_host *vha, ql_dbg(ql_dbg_misc, vha, 0xd202, "%s: rdio t2 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, banksel, bank, buf); - qla27xx_read_window(reg, addr, offset, count, width, buf, len); + qla27xx_write_reg(ISPREG(vha), banksel, bank, buf); + qla27xx_read_window(ISPREG(vha), addr, offset, count, width, buf, len); return qla27xx_next_entry(ent); } @@ -217,7 +210,6 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t259(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); ulong addr = le32_to_cpu(ent->t259.base_addr); uint banksel = ent->t259.banksel_offset; ulong bank = le32_to_cpu(ent->t259.bank); @@ -226,9 +218,9 @@ qla27xx_fwdt_entry_t259(struct scsi_qla_host *vha, ql_dbg(ql_dbg_misc, vha, 0xd203, "%s: wrio t2 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE(reg), addr, buf); - qla27xx_write_reg(reg, banksel, bank, buf); - qla27xx_write_reg(reg, offset, data, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE(vha), addr, buf); + qla27xx_write_reg(ISPREG(vha), banksel, bank, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -237,13 +229,12 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t260(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); uint offset = ent->t260.pci_offset; ql_dbg(ql_dbg_misc, vha, 0xd204, "%s: rdpci [%lx]\n", __func__, *len); qla27xx_insert32(offset, buf, len); - qla27xx_read_reg(reg, offset, buf, len); + qla27xx_read_reg(ISPREG(vha), offset, buf, len); return qla27xx_next_entry(ent); } @@ -252,13 +243,12 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t261(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); uint offset = ent->t261.pci_offset; ulong data = le32_to_cpu(ent->t261.write_data); ql_dbg(ql_dbg_misc, vha, 0xd205, "%s: wrpci [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, offset, data, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -424,12 +414,10 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t265(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); - - ql_dbg(ql_dbg_misc, vha, 0xd209, + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd209, "%s: pause risc [%lx]\n", __func__, *len); if (buf) - qla24xx_pause_risc(reg, vha->hw); + qla24xx_pause_risc(ISPREG(vha), vha->hw); return qla27xx_next_entry(ent); } @@ -450,13 +438,12 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t267(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); uint offset = ent->t267.pci_offset; ulong data = le32_to_cpu(ent->t267.data); ql_dbg(ql_dbg_misc, vha, 0xd20b, "%s: dis intr [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, offset, data, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -552,17 +539,16 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t270(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); ulong addr = le32_to_cpu(ent->t270.addr); ulong dwords = le32_to_cpu(ent->t270.count); ql_dbg(ql_dbg_misc, vha, 0xd20e, "%s: rdremreg [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, 0x40, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE_ADDR, 0x40, buf); while (dwords--) { - qla27xx_write_reg(reg, 0xc0, addr|0x80000000, buf); + qla27xx_write_reg(ISPREG(vha), 0xc0, addr|0x80000000, buf); qla27xx_insert32(addr, buf, len); - qla27xx_read_reg(reg, 0xc4, buf, len); + qla27xx_read_reg(ISPREG(vha), 0xc4, buf, len); addr += sizeof(uint32_t); } @@ -573,15 +559,14 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t271(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); ulong addr = le32_to_cpu(ent->t271.addr); ulong data = le32_to_cpu(ent->t271.data); ql_dbg(ql_dbg_misc, vha, 0xd20f, "%s: wrremreg [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, 0x40, buf); - qla27xx_write_reg(reg, 0xc4, data, buf); - qla27xx_write_reg(reg, 0xc0, addr, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE(vha), 0x40, buf); + qla27xx_write_reg(ISPREG(vha), 0xc4, data, buf); + qla27xx_write_reg(ISPREG(vha), 0xc0, addr, buf); return qla27xx_next_entry(ent); } @@ -749,7 +734,6 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t277(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); ulong cmd_addr = le32_to_cpu(ent->t277.cmd_addr); ulong wr_cmd_data = le32_to_cpu(ent->t277.wr_cmd_data); ulong data_addr = le32_to_cpu(ent->t277.data_addr); @@ -757,8 +741,8 @@ qla27xx_fwdt_entry_t277(struct scsi_qla_host *vha, ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd215, "%s: rdpep [%lx]\n", __func__, *len); qla27xx_insert32(wr_cmd_data, buf, len); - qla27xx_write_reg(reg, cmd_addr, wr_cmd_data, buf); - qla27xx_read_reg(reg, data_addr, buf, len); + qla27xx_write_reg(ISPREG(vha), cmd_addr, wr_cmd_data, buf); + qla27xx_read_reg(ISPREG(vha), data_addr, buf, len); return qla27xx_next_entry(ent); } @@ -767,7 +751,6 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t278(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); ulong cmd_addr = le32_to_cpu(ent->t278.cmd_addr); ulong wr_cmd_data = le32_to_cpu(ent->t278.wr_cmd_data); ulong data_addr = le32_to_cpu(ent->t278.data_addr); @@ -775,8 +758,8 @@ qla27xx_fwdt_entry_t278(struct scsi_qla_host *vha, ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd216, "%s: wrpep [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, data_addr, wr_data, buf); - qla27xx_write_reg(reg, cmd_addr, wr_cmd_data, buf); + qla27xx_write_reg(ISPREG(vha), data_addr, wr_data, buf); + qla27xx_write_reg(ISPREG(vha), cmd_addr, wr_cmd_data, buf); return qla27xx_next_entry(ent); } From e273f3dedbe8b85e3909ef2e0be2ff37457e08cb Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:18:36 +0000 Subject: [PATCH 14/42] qla2xxx: Add 28xx flash primary/secondary status/image mechanism Includes the following: - correction to 27xx image status struct; - factoring of 27xx image status validating routines to make common; - image status generation compare that works across zero wrap; - bsg interface to report current active images (as loaded by driver). git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8208 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 34 +++- qla2x00t-32gbit/qla_bsg.c | 45 +++++ qla2x00t-32gbit/qla_bsg.h | 11 ++ qla2x00t-32gbit/qla_def.h | 63 +++++-- qla2x00t-32gbit/qla_fw.h | 12 ++ qla2x00t-32gbit/qla_gbl.h | 6 +- qla2x00t-32gbit/qla_init.c | 334 ++++++++++++++++++++++++++++++------- qla2x00t-32gbit/qla_sup.c | 71 ++++++-- 8 files changed, 476 insertions(+), 100 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 35f780468..868709019 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -154,6 +154,8 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj, struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); struct qla_hw_data *ha = vha->hw; + uint32_t faddr; + struct active_regions active_regions = { }; if (!capable(CAP_SYS_ADMIN)) return 0; @@ -164,11 +166,21 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj, return -EAGAIN; } - if (IS_NOCACHE_VPD_TYPE(ha)) - ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2, - ha->nvram_size); + if (!IS_NOCACHE_VPD_TYPE(ha)) { + mutex_unlock(&ha->optrom_mutex); + goto skip; + } + + faddr = ha->flt_region_nvram; + if (IS_QLA28XX(ha)) { + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_nvram_sec; + } + ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size); + mutex_unlock(&ha->optrom_mutex); +skip: return memory_read_from_buffer(buf, count, &off, ha->nvram, ha->nvram_size); } @@ -504,6 +516,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, struct device, kobj))); struct qla_hw_data *ha = vha->hw; uint32_t faddr; + struct active_regions active_regions = { }; if (unlikely(pci_channel_offline(ha->pdev))) return -EAGAIN; @@ -516,9 +529,16 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, faddr = ha->flt_region_vpd << 2; - if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && - qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) - faddr = ha->flt_region_vpd_sec << 2; + if (IS_QLA28XX(ha)) { + qla28xx_get_aux_images(vha, &active_regions); + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_vpd_sec << 2; + + ql_dbg(ql_dbg_init, vha, 0x7070, + "Loading %s nvram image.\n", + active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? + "primary" : "secondary"); + } mutex_lock(&ha->optrom_mutex); if (qla2x00_chip_is_down(vha)) { @@ -528,6 +548,8 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); mutex_unlock(&ha->optrom_mutex); + + ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); skip: return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); } diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 5402b8742..95e1c3c23 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -2493,6 +2493,48 @@ static int qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job) return 0; } +#ifndef NEW_LIBFC_API +static int qla2x00_get_flash_image_status(struct fc_bsg_job *bsg_job) +#else +static int qla2x00_get_flash_image_status(struct bsg_job *bsg_job) +#endif +{ + scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + struct qla_hw_data *ha = vha->hw; + struct qla_active_regions regions = { }; + struct active_regions active_regions = { }; + + qla28xx_get_aux_images(vha, &active_regions); + regions.global_image = active_regions.global; + + if (IS_QLA28XX(ha)) { + qla27xx_get_active_image(vha, &active_regions); + regions.board_config = active_regions.aux.board_config; + regions.vpd_nvram = active_regions.aux.vpd_nvram; + regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1; + regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3; + } + + ql_dbg(ql_dbg_user, vha, 0x70e1, + "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n", + __func__, vha->host_no, regions.global_image, + regions.board_config, regions.vpd_nvram, + regions.npiv_config_0_1, regions.npiv_config_2_3); + + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, ®ions, sizeof(regions)); + + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + bsg_reply->reply_payload_rcv_len = sizeof(regions); + bsg_reply->result = DID_OK << 16; + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + + return 0; +} + #ifndef NEW_LIBFC_API static int qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) #else @@ -2569,6 +2611,9 @@ static int qla2x00_process_vendor_specific(struct bsg_job *bsg_job) case QL_VND_DPORT_DIAGNOSTICS: return qla2x00_do_dport_diagnostics(bsg_job); + case QL_VND_SS_GET_FLASH_IMAGE_STATUS: + return qla2x00_get_flash_image_status(bsg_job); + default: return -ENOSYS; } diff --git a/qla2x00t-32gbit/qla_bsg.h b/qla2x00t-32gbit/qla_bsg.h index d97dfd521..7594fad7b 100644 --- a/qla2x00t-32gbit/qla_bsg.h +++ b/qla2x00t-32gbit/qla_bsg.h @@ -31,6 +31,7 @@ #define QL_VND_GET_PRIV_STATS 0x18 #define QL_VND_DPORT_DIAGNOSTICS 0x19 #define QL_VND_GET_PRIV_STATS_EX 0x1A +#define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E /* BSG Vendor specific subcode returns */ #define EXT_STATUS_OK 0 @@ -279,4 +280,14 @@ struct qla_dport_diag { #define QLA_DPORT_RESULT 0x0 #define QLA_DPORT_START 0x2 +/* active images in flash */ +struct qla_active_regions { + uint8_t global_image; + uint8_t board_config; + uint8_t vpd_nvram; + uint8_t npiv_config_0_1; + uint8_t npiv_config_2_3; + uint8_t reserved[32]; +} __packed; + #endif diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 66a6ca8c0..ca14ab7da 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1222,6 +1222,9 @@ struct mbx_cmd_32 { #define QLA27XX_IMG_STATUS_VER_MINOR 0x00 #define QLA27XX_IMG_STATUS_SIGN 0xFACEFADE #define QLA28XX_IMG_STATUS_SIGN 0xFACEFADF +#define QLA28XX_IMG_STATUS_SIGN 0xFACEFADF +#define QLA28XX_AUX_IMG_STATUS_SIGN 0xFACEFAED +#define QLA27XX_DEFAULT_IMAGE 0 #define QLA27XX_PRIMARY_IMAGE 1 #define QLA27XX_SECONDARY_IMAGE 2 @@ -4135,22 +4138,28 @@ struct qla_hw_data { uint32_t fdt_protect_sec_cmd; uint32_t fdt_wrt_sts_reg_cmd; - uint32_t flt_region_flt; - uint32_t flt_region_fdt; - uint32_t flt_region_boot; - uint32_t flt_region_boot_sec; - uint32_t flt_region_fw; - uint32_t flt_region_fw_sec; - uint32_t flt_region_vpd_nvram; - uint32_t flt_region_vpd; - uint32_t flt_region_vpd_sec; - uint32_t flt_region_nvram; - uint32_t flt_region_npiv_conf; - uint32_t flt_region_gold_fw; - uint32_t flt_region_fcp_prio; - uint32_t flt_region_bootload; - uint32_t flt_region_img_status_pri; - uint32_t flt_region_img_status_sec; + struct { + uint32_t flt_region_flt; + uint32_t flt_region_fdt; + uint32_t flt_region_boot; + uint32_t flt_region_boot_sec; + uint32_t flt_region_fw; + uint32_t flt_region_fw_sec; + uint32_t flt_region_vpd_nvram; + uint32_t flt_region_vpd_nvram_sec; + uint32_t flt_region_vpd; + uint32_t flt_region_vpd_sec; + uint32_t flt_region_nvram; + uint32_t flt_region_nvram_sec; + uint32_t flt_region_npiv_conf; + uint32_t flt_region_gold_fw; + uint32_t flt_region_fcp_prio; + uint32_t flt_region_bootload; + uint32_t flt_region_img_status_pri; + uint32_t flt_region_img_status_sec; + uint32_t flt_region_aux_img_status_pri; + uint32_t flt_region_aux_img_status_sec; + }; uint8_t active_image; /* Needed for BEACON */ @@ -4271,9 +4280,20 @@ struct qla_hw_data { atomic_t zio_threshold; uint16_t last_zio_threshold; + #define DEFAULT_ZIO_THRESHOLD 5 }; +struct active_regions { + uint8_t global; + struct { + uint8_t board_config; + uint8_t vpd_nvram; + uint8_t npiv_config_0_1; + uint8_t npiv_config_2_3; + } aux; +}; + #define FW_ABILITY_MAX_SPEED_MASK 0xFUL #define FW_ABILITY_MAX_SPEED_16G 0x0 #define FW_ABILITY_MAX_SPEED_32G 0x1 @@ -4488,13 +4508,20 @@ typedef struct scsi_qla_host { struct qla27xx_image_status { uint8_t image_status_mask; uint16_t generation; - uint8_t reserved[3]; - uint8_t ver_minor; uint8_t ver_major; + uint8_t ver_minor; + uint8_t bitmap; /* 28xx only */ + uint8_t reserved[2]; uint32_t checksum; uint32_t signature; } __packed; +/* 28xx aux image status bimap values */ +#define QLA28XX_AUX_IMG_BOARD_CONFIG BIT_0 +#define QLA28XX_AUX_IMG_VPD_NVRAM BIT_1 +#define QLA28XX_AUX_IMG_NPIV_CONFIG_0_1 BIT_2 +#define QLA28XX_AUX_IMG_NPIV_CONFIG_2_3 BIT_3 + #define SET_VP_IDX 1 #define SET_AL_PA 2 #define RESET_VP_IDX 3 diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index 0b2419187..aac9c252c 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -1526,6 +1526,18 @@ struct qla_flt_header { #define FLT_REG_VPD_SEC_27XX_2 0xD8 #define FLT_REG_VPD_SEC_27XX_3 0xDA +/* 28xx */ +#define FLT_REG_AUX_IMG_PRI_28XX 0x125 +#define FLT_REG_AUX_IMG_SEC_28XX 0x126 +#define FLT_REG_VPD_SEC_28XX_0 0x10C +#define FLT_REG_VPD_SEC_28XX_1 0x10E +#define FLT_REG_VPD_SEC_28XX_2 0x110 +#define FLT_REG_VPD_SEC_28XX_3 0x112 +#define FLT_REG_NVRAM_SEC_28XX_0 0x10D +#define FLT_REG_NVRAM_SEC_28XX_1 0x10F +#define FLT_REG_NVRAM_SEC_28XX_2 0x111 +#define FLT_REG_NVRAM_SEC_28XX_3 0x113 + struct qla_flt_region { uint16_t code; uint8_t attribute; diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index cd4281f51..bcf22f05a 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -93,7 +93,6 @@ extern int qla2xxx_mctp_dump(scsi_qla_host_t *); extern int qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *); extern int qla2x00_init_rings(scsi_qla_host_t *); -extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *); extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *, int, int, bool); extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *); @@ -108,6 +107,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); int qla24xx_detect_sfp(scsi_qla_host_t *vha); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); +extern void qla28xx_get_aux_images(struct scsi_qla_host *, + struct active_regions *); +extern void qla27xx_get_active_image(struct scsi_qla_host *, + struct active_regions *); + void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *, diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index ac8485804..5ff6c1f9f 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -7242,95 +7242,281 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) return (rval); } -uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) +static void +qla27xx_print_image(struct scsi_qla_host *vha, char *name, + struct qla27xx_image_status *image_status) +{ + ql_dbg(ql_dbg_init, vha, 0x018b, + "%s %s: mask=%#02x gen=%#04x ver=%u.%u map=%#01x sum=%#08x sig=%#08x\n", + name, "status", + image_status->image_status_mask, + le16_to_cpu(image_status->generation), + image_status->ver_major, + image_status->ver_minor, + image_status->bitmap, + le32_to_cpu(image_status->checksum), + le32_to_cpu(image_status->signature)); +} + +static bool +qla28xx_check_aux_image_status_signature( + struct qla27xx_image_status *image_status) +{ + ulong signature = le32_to_cpu(image_status->signature); + + return signature != QLA28XX_AUX_IMG_STATUS_SIGN; +} + +static bool +qla27xx_check_image_status_signature(struct qla27xx_image_status *image_status) +{ + ulong signature = le32_to_cpu(image_status->signature); + + return + signature != QLA27XX_IMG_STATUS_SIGN && + signature != QLA28XX_IMG_STATUS_SIGN; +} + +static ulong +qla27xx_image_status_checksum(struct qla27xx_image_status *image_status) +{ + uint32_t *p = (void *)image_status; + uint n = sizeof(*image_status) / sizeof(*p); + uint32_t sum = 0; + + for ( ; n--; p++) + sum += le32_to_cpup(p); + + return sum; +} + +static inline uint +qla28xx_component_bitmask(struct qla27xx_image_status *aux, uint bitmask) +{ + return aux->bitmap & bitmask ? + QLA27XX_SECONDARY_IMAGE : QLA27XX_PRIMARY_IMAGE; +} + +static void +qla28xx_component_status( + struct active_regions *active_regions, struct qla27xx_image_status *aux) +{ + active_regions->aux.board_config = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_BOARD_CONFIG); + + active_regions->aux.vpd_nvram = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_VPD_NVRAM); + + active_regions->aux.npiv_config_0_1 = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_0_1); + + active_regions->aux.npiv_config_2_3 = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_2_3); +} + +static int +qla27xx_compare_image_generation( + struct qla27xx_image_status *pri_image_status, + struct qla27xx_image_status *sec_image_status) +{ + /* calculate generation delta as uint16 (this accounts for wrap) */ + int16_t delta = + le16_to_cpu(pri_image_status->generation) - + le16_to_cpu(sec_image_status->generation); + + ql_dbg(ql_dbg_init, NULL, 0x0180, "generation delta = %d\n", delta); + + return delta; +} + +void +qla28xx_get_aux_images( + struct scsi_qla_host *vha, struct active_regions *active_regions) { - struct qla27xx_image_status pri_image_status, sec_image_status; - bool valid_pri_image = true, valid_sec_image = true; - uint32_t *wptr; - uint chksum, cnt, size = sizeof(pri_image_status) / sizeof(*wptr); struct qla_hw_data *ha = vha->hw; - uint32_t signature; + struct qla27xx_image_status pri_aux_image_status, sec_aux_image_status; + bool valid_pri_image = false, valid_sec_image = false; + bool active_pri_image = false, active_sec_image = false; - ha->active_image = 0; - - if (!ha->flt_region_img_status_pri) { - valid_pri_image = false; + if (!ha->flt_region_aux_img_status_pri) { + ql_dbg(ql_dbg_init, vha, 0x018a, "Primary aux image not addressed\n"); goto check_sec_image; } - qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status), - ha->flt_region_img_status_pri, size); + qla24xx_read_flash_data(vha, (void *)&pri_aux_image_status, + ha->flt_region_aux_img_status_pri, + sizeof(pri_aux_image_status) >> 2); + qla27xx_print_image(vha, "Primary aux image", &pri_aux_image_status); - signature = le32_to_cpu(pri_image_status.signature); - if (signature != QLA27XX_IMG_STATUS_SIGN && - signature != QLA28XX_IMG_STATUS_SIGN) { + if (qla28xx_check_aux_image_status_signature(&pri_aux_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018b, + "Primary aux image signature (%#x) not valid\n", + le32_to_cpu(pri_aux_image_status.signature)); + goto check_sec_image; + } + + if (qla27xx_image_status_checksum(&pri_aux_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018c, + "Primary aux image checksum failed\n"); + goto check_sec_image; + } + + valid_pri_image = true; + + if (pri_aux_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Primary aux image is active\n"); + active_pri_image = true; + } + +check_sec_image: + if (!ha->flt_region_aux_img_status_sec) { + ql_dbg(ql_dbg_init, vha, 0x018a, + "Secondary aux image not addressed\n"); + goto check_valid_image; + } + + qla24xx_read_flash_data(vha, (void *)&sec_aux_image_status, + ha->flt_region_aux_img_status_sec, + sizeof(sec_aux_image_status) >> 2); + qla27xx_print_image(vha, "Secondary aux image", &sec_aux_image_status); + + if (qla28xx_check_aux_image_status_signature(&sec_aux_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018b, + "Secondary aux image signature (%#x) not valid\n", + le32_to_cpu(sec_aux_image_status.signature)); + goto check_valid_image; + } + + if (qla27xx_image_status_checksum(&sec_aux_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018c, + "Secondary aux image checksum failed\n"); + goto check_valid_image; + } + + valid_sec_image = true; + + if (sec_aux_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Secondary aux image is active\n"); + active_sec_image = true; + } + +check_valid_image: + if (valid_pri_image && active_pri_image && + valid_sec_image && active_sec_image) { + if (qla27xx_compare_image_generation(&pri_aux_image_status, + &sec_aux_image_status) >= 0) { + qla28xx_component_status(active_regions, + &pri_aux_image_status); + } else { + qla28xx_component_status(active_regions, + &sec_aux_image_status); + } + } else if (valid_pri_image && active_pri_image) { + qla28xx_component_status(active_regions, &pri_aux_image_status); + } else if (valid_sec_image && active_sec_image) { + qla28xx_component_status(active_regions, &sec_aux_image_status); + } + + ql_dbg(ql_dbg_init, vha, 0x018f, + "aux images active: BCFG=%u VPD/NVR=%u NPIV0/1=%u NPIV2/3=%u\n", + active_regions->aux.board_config, + active_regions->aux.vpd_nvram, + active_regions->aux.npiv_config_0_1, + active_regions->aux.npiv_config_2_3); +} + +void +qla27xx_get_active_image(struct scsi_qla_host *vha, + struct active_regions *active_regions) +{ + struct qla_hw_data *ha = vha->hw; + struct qla27xx_image_status pri_image_status, sec_image_status; + bool valid_pri_image = false, valid_sec_image = false; + bool active_pri_image = false, active_sec_image = false; + + if (!ha->flt_region_img_status_pri) { + ql_dbg(ql_dbg_init, vha, 0x018a, "Primary image not addressed\n"); + goto check_sec_image; + } + + qla24xx_read_flash_data(vha, (void *)(&pri_image_status), + ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2); + qla27xx_print_image(vha, "Primary image", &pri_image_status); + + if (qla27xx_check_image_status_signature(&pri_image_status)) { ql_dbg(ql_dbg_init, vha, 0x018b, "Primary image signature (%#x) not valid\n", le32_to_cpu(pri_image_status.signature)); - valid_pri_image = false; goto check_sec_image; } - wptr = (uint32_t *)(&pri_image_status); - cnt = size; - - for (chksum = 0; cnt--; wptr++) - chksum += le32_to_cpu(*wptr); - - if (chksum) { + if (qla27xx_image_status_checksum(&pri_image_status)) { ql_dbg(ql_dbg_init, vha, 0x018c, - "Primary image checksum failed (%#x)\n", chksum); - valid_pri_image = false; + "Primary image checksum failed\n"); + goto check_sec_image; + } + + valid_pri_image = true; + + if (pri_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Primary image is active\n"); + active_pri_image = true; } check_sec_image: if (!ha->flt_region_img_status_sec) { - valid_sec_image = false; + ql_dbg(ql_dbg_init, vha, 0x018a, "Secondary image not addressed\n"); goto check_valid_image; } qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status), - ha->flt_region_img_status_sec, size); + ha->flt_region_img_status_sec, sizeof(sec_image_status) >> 2); + qla27xx_print_image(vha, "Secondary image", &sec_image_status); - signature = le32_to_cpu(sec_image_status.signature); - if (signature != QLA27XX_IMG_STATUS_SIGN && - signature != QLA28XX_IMG_STATUS_SIGN) { - ql_dbg(ql_dbg_init, vha, 0x018d, + if (qla27xx_check_image_status_signature(&sec_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018b, "Secondary image signature (%#x) not valid\n", le32_to_cpu(sec_image_status.signature)); - valid_sec_image = false; goto check_valid_image; } - wptr = (uint32_t *)(&sec_image_status); - cnt = size; - for (chksum = 0; cnt--; wptr++) - chksum += le32_to_cpu(*wptr); - if (chksum) { - ql_dbg(ql_dbg_init, vha, 0x018e, - "Secondary image checksum failed (%#x)\n", chksum); - valid_sec_image = false; + if (qla27xx_image_status_checksum(&sec_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018c, + "Secondary image checksum failed\n"); + goto check_valid_image; + } + + valid_sec_image = true; + + if (sec_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Secondary image is active\n"); + active_sec_image = true; } check_valid_image: - if (valid_pri_image && (pri_image_status.image_status_mask & 1)) - ha->active_image = QLA27XX_PRIMARY_IMAGE; + if (valid_pri_image && active_pri_image) + active_regions->global = QLA27XX_PRIMARY_IMAGE; - if (valid_sec_image && (sec_image_status.image_status_mask & 1)) { - if (!ha->active_image || - le16_to_cpu(pri_image_status.generation) < - le16_to_cpu(sec_image_status.generation)) { - ha->active_image = QLA27XX_SECONDARY_IMAGE; + if (valid_sec_image && active_sec_image) { + if (!active_regions->global || + qla27xx_compare_image_generation( + &pri_image_status, &sec_image_status) < 0) { + active_regions->global = QLA27XX_SECONDARY_IMAGE; } } - ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x018f, "%s image\n", - ha->active_image == 0 ? "default bootld and fw" : - ha->active_image == 1 ? "primary" : - ha->active_image == 2 ? "secondary" : - "Invalid"); - - return ha->active_image; + ql_dbg(ql_dbg_init, vha, 0x018f, "active image %s (%u)\n", + active_regions->global == QLA27XX_DEFAULT_IMAGE ? + "default (boot/fw)" : + active_regions->global == QLA27XX_PRIMARY_IMAGE ? + "primary" : + active_regions->global == QLA27XX_SECONDARY_IMAGE ? + "secondary" : "invalid", + active_regions->global); } bool qla24xx_risc_firmware_invalid(uint32_t *dword) @@ -7706,7 +7892,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) dcode = fwdt->template; for (i = 0; i < risc_size; i++) - dcode[i] = le32_to_cpu(fwcode[i]); + dcode[i] = fwcode[i]; if (!qla27xx_fwdt_template_valid(dcode)) { ql_log(ql_log_warn, vha, 0x0175, @@ -7769,6 +7955,7 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) { int rval; struct qla_hw_data *ha = vha->hw; + struct active_regions active_regions = { }; if (ql2xfwloadbin == 2) goto try_blob_fw; @@ -7779,10 +7966,12 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) * 3) Golden-Firmware residing in flash -- (limited operation). */ - if (!IS_QLA27XX(ha) || !IS_QLA28XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto try_primary_fw; - if (qla27xx_find_valid_image(vha) != QLA27XX_SECONDARY_IMAGE) + qla27xx_get_active_image(vha, &active_regions); + + if (active_regions.global != QLA27XX_SECONDARY_IMAGE) goto try_primary_fw; ql_dbg(ql_dbg_init, vha, 0x008b, @@ -7978,6 +8167,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) uint32_t chksum; uint16_t cnt; struct qla_hw_data *ha = vha->hw; + uint32_t faddr; + struct active_regions active_regions = { }; rval = QLA_SUCCESS; icb = (struct init_cb_81xx *)ha->init_cb; @@ -7989,14 +8180,35 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) if (IS_P3P_TYPE(ha) || IS_QLA8031(ha)) ha->vpd_size = FA_VPD_SIZE_82XX; + if (IS_QLA28XX(ha)) + qla28xx_get_aux_images(vha, &active_regions); + /* Get VPD data into cache */ ha->vpd = ha->nvram + VPD_OFFSET; - ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2, - ha->vpd_size); + + faddr = ha->flt_region_vpd; + if (IS_QLA28XX(ha)) { + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_vpd_sec; + ql_dbg(ql_dbg_init, vha, 0x0110, + "Loading %s nvram image.\n", + active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? + "primary" : "secondary"); + } + qla24xx_read_flash_data(vha, ha->vpd, faddr, ha->vpd_size >> 2); /* Get NVRAM data into cache and calculate checksum. */ - ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2, - ha->nvram_size); + faddr = ha->flt_region_nvram; + if (IS_QLA28XX(ha)) { + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_nvram_sec; + } + ql_dbg(ql_dbg_init, vha, 0x0110, + "Loading %s nvram image.\n", + active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? + "primary" : "secondary"); + qla24xx_read_flash_data(vha, ha->nvram, faddr, ha->nvram_size >> 2); + dptr = (uint32_t *)nv; for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++) chksum += le32_to_cpu(*dptr); diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index eb4514a56..08c7dca07 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -862,21 +862,59 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_boot_sec = start; break; + case FLT_REG_AUX_IMG_PRI_28XX: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + ha->flt_region_aux_img_status_pri = start; + break; + case FLT_REG_AUX_IMG_SEC_28XX: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + ha->flt_region_aux_img_status_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_0: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 0) + ha->flt_region_nvram_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_1: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 1) + ha->flt_region_nvram_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_2: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 2) + ha->flt_region_nvram_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_3: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 3) + ha->flt_region_nvram_sec = start; + break; case FLT_REG_VPD_SEC_27XX_0: - if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_0: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->flt_region_vpd_nvram_sec = start; + if (ha->port_no == 0) + ha->flt_region_vpd_sec = start; + } break; case FLT_REG_VPD_SEC_27XX_1: - if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_1: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 1) + ha->flt_region_vpd_sec = start; break; case FLT_REG_VPD_SEC_27XX_2: - if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_2: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 2) + ha->flt_region_vpd_sec = start; break; case FLT_REG_VPD_SEC_27XX_3: - if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_3: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 3) + ha->flt_region_vpd_sec = start; break; } } @@ -3020,6 +3058,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) int i; struct qla_hw_data *ha = vha->hw; uint32_t faddr = 0; + struct active_regions active_regions = { }; if (IS_P3P_TYPE(ha)) return ret; @@ -3033,9 +3072,12 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); pcihdr = ha->flt_region_boot << 2; - if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && - qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) - pcihdr = ha->flt_region_boot_sec << 2; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + qla27xx_get_active_image(vha, &active_regions); + if (active_regions.global == QLA27XX_SECONDARY_IMAGE) { + pcihdr = ha->flt_region_boot_sec << 2; + } + } do { /* Verify PCI expansion ROM header. */ @@ -3108,9 +3150,10 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) /* Read firmware image information. */ memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); faddr = ha->flt_region_fw; - if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && - qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) - faddr = ha->flt_region_fw_sec; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + if (active_regions.global == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_fw_sec; + } qla24xx_read_flash_data(vha, dcode, faddr, 8); if (qla24xx_risc_firmware_invalid(dcode)) { From 3e397c0d71aba15705019db753968b53e8b47a05 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:18:59 +0000 Subject: [PATCH 15/42] qla2xxx: Secure flash update support for ISP28XX This patch adds support for Secure flash update with ISP28xx. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8209 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 31 ++- qla2x00t-32gbit/qla_fw.h | 8 + qla2x00t-32gbit/qla_gbl.h | 22 ++- qla2x00t-32gbit/qla_init.c | 47 ++++- qla2x00t-32gbit/qla_mbx.c | 141 ++++++++++++++ qla2x00t-32gbit/qla_mr.c | 7 +- qla2x00t-32gbit/qla_nx.c | 4 +- qla2x00t-32gbit/qla_os.c | 18 +- qla2x00t-32gbit/qla_sup.c | 387 ++++++++++++++++++++++++++++++++++--- 9 files changed, 616 insertions(+), 49 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index ca14ab7da..c346dfb46 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1051,6 +1051,7 @@ struct mbx_cmd_32 { #define MBC_GET_FIRMWARE_VERSION 8 /* Get firmware revision. */ #define MBC_LOAD_RISC_RAM 9 /* Load RAM command. */ #define MBC_DUMP_RISC_RAM 0xa /* Dump RAM command. */ +#define MBC_SECURE_FLASH_UPDATE 0xa /* Secure Flash Update(28xx) */ #define MBC_LOAD_RISC_RAM_EXTENDED 0xb /* Load RAM extended. */ #define MBC_DUMP_RISC_RAM_EXTENDED 0xc /* Dump RAM extended. */ #define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */ @@ -3154,10 +3155,10 @@ struct rsp_que; struct isp_operations { int (*pci_config) (struct scsi_qla_host *); - void (*reset_chip) (struct scsi_qla_host *); + int (*reset_chip)(struct scsi_qla_host *); int (*chip_diag) (struct scsi_qla_host *); void (*config_rings) (struct scsi_qla_host *); - void (*reset_adapter) (struct scsi_qla_host *); + int (*reset_adapter)(struct scsi_qla_host *); int (*nvram_config) (struct scsi_qla_host *); void (*update_fw_options) (struct scsi_qla_host *); int (*load_risc) (struct scsi_qla_host *, uint32_t *); @@ -3646,6 +3647,8 @@ struct qla_hw_data { uint32_t rida_fmt2:1; uint32_t purge_mbox:1; uint32_t n2n_bigger:1; + uint32_t secure_adapter:1; + uint32_t secure_fw:1; } flags; uint16_t max_exchg; @@ -3934,6 +3937,9 @@ struct qla_hw_data { void *sfp_data; dma_addr_t sfp_data_dma; + void *flt; + dma_addr_t flt_dma; + #define XGMAC_DATA_SIZE 4096 void *xgmac_data; dma_addr_t xgmac_data_dma; @@ -4381,6 +4387,7 @@ typedef struct scsi_qla_host { #define N2N_LOGIN_NEEDED 30 #define IOCB_WORK_ACTIVE 31 #define SET_ZIO_THRESHOLD_NEEDED 32 +#define ISP_ABORT_TO_ROM 33 unsigned long pci_flags; #define PFLG_DISCONNECTED 0 /* PCI device removed */ @@ -4568,6 +4575,24 @@ struct qla2_sgx { } \ } + +#define SFUB_CHECKSUM_SIZE 4 + +struct secure_flash_update_block { + uint32_t block_info; + uint32_t signature_lo; + uint32_t signature_hi; + uint32_t signature_upper[0x3e]; +}; + +struct secure_flash_update_block_pk { + uint32_t block_info; + uint32_t signature_lo; + uint32_t signature_hi; + uint32_t signature_upper[0x3e]; + uint32_t public_key[0x41]; +}; + /* * Macros to help code, maintain, etc. */ @@ -4768,6 +4793,8 @@ struct sff_8247_a0 { IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \ IS_QLA28XX(_vha->hw))) +#define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016 + #define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \ (IS_QLA27XX(_ha) || IS_QLA28XX(_ha) || IS_QLA83XX(_ha))) diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index aac9c252c..3305bac0e 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -1547,6 +1547,10 @@ struct qla_flt_region { uint32_t end; }; +#define FLT_REGION_SIZE 16 +#define FLT_MAX_REGIONS 0xFF +#define FLT_REGIONS_SIZE (FLT_REGION_SIZE * FLT_MAX_REGIONS) + /* Flash NPIV Configuration Table ********************************************/ struct qla_npiv_header { @@ -1736,6 +1740,10 @@ struct access_chip_rsp_84xx { #define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS) #define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000) +/* FAC semaphore defines */ +#define FAC_SEMAPHORE_UNLOCK 0 +#define FAC_SEMAPHORE_LOCK 1 + struct nvram_81xx { /* NVRAM header. */ uint8_t id[4]; diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index bcf22f05a..e9af4a7ef 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -18,14 +18,14 @@ extern int qla2100_pci_config(struct scsi_qla_host *); extern int qla2300_pci_config(struct scsi_qla_host *); extern int qla24xx_pci_config(scsi_qla_host_t *); extern int qla25xx_pci_config(scsi_qla_host_t *); -extern void qla2x00_reset_chip(struct scsi_qla_host *); -extern void qla24xx_reset_chip(struct scsi_qla_host *); +extern int qla2x00_reset_chip(struct scsi_qla_host *); +extern int qla24xx_reset_chip(struct scsi_qla_host *); extern int qla2x00_chip_diag(struct scsi_qla_host *); extern int qla24xx_chip_diag(struct scsi_qla_host *); extern void qla2x00_config_rings(struct scsi_qla_host *); extern void qla24xx_config_rings(struct scsi_qla_host *); -extern void qla2x00_reset_adapter(struct scsi_qla_host *); -extern void qla24xx_reset_adapter(struct scsi_qla_host *); +extern int qla2x00_reset_adapter(struct scsi_qla_host *); +extern int qla24xx_reset_adapter(struct scsi_qla_host *); extern int qla2x00_nvram_config(struct scsi_qla_host *); extern int qla24xx_nvram_config(struct scsi_qla_host *); extern int qla81xx_nvram_config(struct scsi_qla_host *); @@ -473,6 +473,8 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *, int); extern int qla81xx_fac_erase_sector(scsi_qla_host_t *, uint32_t, uint32_t); +extern int qla81xx_fac_semaphore_access(scsi_qla_host_t *, int); + extern int qla2x00_get_xgmac_stats(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t *); @@ -518,6 +520,14 @@ extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *); extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t); int qla24xx_res_count_wait(struct scsi_qla_host *, uint16_t *, int); +extern int qla28xx_secure_flash_update(scsi_qla_host_t *, uint16_t, uint16_t, + uint32_t, dma_addr_t, uint32_t); + +extern int qla2xxx_read_remote_register(scsi_qla_host_t *, uint32_t, + uint32_t *); +extern int qla2xxx_write_remote_register(scsi_qla_host_t *, uint32_t, + uint32_t); + /* * Global Function Prototypes in qla_isr.c source file. */ @@ -723,7 +733,7 @@ extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); /* qlafx00 related functions */ extern int qlafx00_pci_config(struct scsi_qla_host *); extern int qlafx00_initialize_adapter(struct scsi_qla_host *); -extern void qlafx00_soft_reset(scsi_qla_host_t *); +extern int qlafx00_soft_reset(scsi_qla_host_t *); extern int qlafx00_chip_diag(scsi_qla_host_t *); extern void qlafx00_config_rings(struct scsi_qla_host *); extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *); @@ -766,7 +776,7 @@ extern int qla82xx_pci_region_offset(struct pci_dev *, int); extern int qla82xx_iospace_config(struct qla_hw_data *); /* Initialization related functions */ -extern void qla82xx_reset_chip(struct scsi_qla_host *); +extern int qla82xx_reset_chip(struct scsi_qla_host *); extern void qla82xx_config_rings(struct scsi_qla_host *); extern void qla82xx_watchdog(scsi_qla_host_t *); extern int qla82xx_start_firmware(scsi_qla_host_t *); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 5ff6c1f9f..38c1bac49 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2099,6 +2099,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) int rval; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; memset(&vha->qla_stats, 0, sizeof(vha->qla_stats)); memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat)); @@ -2133,6 +2134,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) ha->isp_ops->reset_chip(vha); + /* Check for secure flash support */ + if (IS_QLA28XX(ha)) { + if (RD_REG_DWORD(®->mailbox12) & BIT_0) { + ql_log(ql_log_info, vha, 0xffff, "Adapter is Secure\n"); + ha->flags.secure_adapter = 1; + } + } + + rval = qla2xxx_get_flash_info(vha); if (rval) { ql_log(ql_log_fatal, vha, 0x004f, @@ -2449,7 +2459,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha) * * Returns 0 on success. */ -void +int qla2x00_reset_chip(scsi_qla_host_t *vha) { unsigned long flags = 0; @@ -2457,9 +2467,10 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; uint32_t cnt; uint16_t cmd; + int rval = QLA_FUNCTION_FAILED; if (unlikely(pci_channel_offline(ha->pdev))) - return; + return rval; ha->isp_ops->disable_intrs(ha); @@ -2585,6 +2596,8 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) } spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return QLA_SUCCESS; } /** @@ -2825,14 +2838,15 @@ acquired: * * Returns 0 on success. */ -void +int qla24xx_reset_chip(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + int rval = QLA_FUNCTION_FAILED; if (pci_channel_offline(ha->pdev) && ha->flags.pci_channel_io_perm_failure) { - return; + return rval; } ha->isp_ops->disable_intrs(ha); @@ -2840,7 +2854,9 @@ qla24xx_reset_chip(scsi_qla_host_t *vha) qla25xx_manipulate_risc_semaphore(vha); /* Perform RISC reset. */ - qla24xx_reset_risc(vha); + rval = qla24xx_reset_risc(vha); + + return rval; } /** @@ -6677,6 +6693,14 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) if (vha->flags.online) { qla2x00_abort_isp_cleanup(vha); + if (test_and_clear_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags)) { + ha->flags.chip_reset_done = 1; + vha->flags.online = 1; + status = 0; + clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); + return status; + } + if (IS_QLA8031(ha)) { ql_dbg(ql_dbg_p3p, vha, 0xb05c, "Clearing fcoe driver presence.\n"); @@ -6917,7 +6941,7 @@ qla25xx_init_queues(struct qla_hw_data *ha) * Input: * ha = adapter block pointer. */ -void +int qla2x00_reset_adapter(scsi_qla_host_t *vha) { unsigned long flags = 0; @@ -6933,17 +6957,20 @@ qla2x00_reset_adapter(scsi_qla_host_t *vha) WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); RD_REG_WORD(®->hccr); /* PCI Posting. */ spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return QLA_SUCCESS; } -void +int qla24xx_reset_adapter(scsi_qla_host_t *vha) { unsigned long flags = 0; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + int rval = QLA_SUCCESS; if (IS_P3P_TYPE(ha)) - return; + return rval; vha->flags.online = 0; ha->isp_ops->disable_intrs(ha); @@ -6957,6 +6984,8 @@ qla24xx_reset_adapter(scsi_qla_host_t *vha) if (IS_NOPOLLING_TYPE(ha)) ha->isp_ops->enable_intrs(ha); + + return rval; } /* On sparc systems, obtain port and node WWN from firmware @@ -8180,7 +8209,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) if (IS_P3P_TYPE(ha) || IS_QLA8031(ha)) ha->vpd_size = FA_VPD_SIZE_82XX; - if (IS_QLA28XX(ha)) + if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) qla28xx_get_aux_images(vha, &active_regions); /* Get VPD data into cache */ diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 3b4c9778b..4548fad98 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -1147,6 +1147,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20]; ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22]; ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24]; + if (IS_QLA28XX(ha)) { + if (mcp->mb[16] & BIT_10) { + ql_log(ql_log_info, vha, 0xffff, + "FW support secure flash updates\n"); + ha->flags.secure_fw = 1; + } + } } failed: @@ -4594,6 +4601,42 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) return rval; } +int +qla81xx_fac_semaphore_access(scsi_qla_host_t *vha, int lock) +{ + int rval = QLA_SUCCESS; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return rval; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; + mcp->mb[1] = (lock ? FAC_OPT_CMD_LOCK_SEMAPHORE : + FAC_OPT_CMD_UNLOCK_SEMAPHORE); + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x10e3, + "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", + rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4, + "Done %s.\n", __func__); + } + + return rval; +} + int qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha) { @@ -6534,3 +6577,101 @@ int qla24xx_res_count_wait(struct scsi_qla_host *vha, done: return rval; } + +int qla28xx_secure_flash_update(scsi_qla_host_t *vha, uint16_t opts, + uint16_t region, uint32_t len, dma_addr_t sfub_dma_addr, + uint32_t sfub_len) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + mcp->mb[0] = MBC_SECURE_FLASH_UPDATE; + mcp->mb[1] = opts; + mcp->mb[2] = region; + mcp->mb[3] = MSW(len); + mcp->mb[4] = LSW(len); + mcp->mb[5] = MSW(sfub_dma_addr); + mcp->mb[6] = LSW(sfub_dma_addr); + mcp->mb[7] = MSW(MSD(sfub_dma_addr)); + mcp->mb[8] = LSW(MSD(sfub_dma_addr)); + mcp->mb[9] = sfub_len; + mcp->out_mb = + MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s(%ld): failed rval 0x%x, %x %x %x", + __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1], + mcp->mb[2]); + } + + return rval; +} + +int qla2xxx_write_remote_register(scsi_qla_host_t *vha, uint32_t addr, + uint32_t data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_WRITE_REMOTE_REG; + mcp->mb[1] = LSW(addr); + mcp->mb[2] = MSW(addr); + mcp->mb[3] = LSW(data); + mcp->mb[4] = MSW(data); + mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x10e9, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, + "Done %s.\n", __func__); + } + + return rval; +} + +int qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr, + uint32_t *data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_READ_REMOTE_REG; + mcp->mb[1] = LSW(addr); + mcp->mb[2] = MSW(addr); + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + *data = (uint32_t)((((uint32_t)mcp->mb[4]) << 16) | mcp->mb[3]); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x10e9, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, + "Done %s.\n", __func__); + } + + return rval; +} diff --git a/qla2x00t-32gbit/qla_mr.c b/qla2x00t-32gbit/qla_mr.c index a006c3e94..30b3d9ce2 100644 --- a/qla2x00t-32gbit/qla_mr.c +++ b/qla2x00t-32gbit/qla_mr.c @@ -628,17 +628,20 @@ qlafx00_soc_cpu_reset(scsi_qla_host_t *vha) * * Returns 0 on success. */ -void +int qlafx00_soft_reset(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + int rval = QLA_FUNCTION_FAILED; if (unlikely(pci_channel_offline(ha->pdev) && ha->flags.pci_channel_io_perm_failure)) - return; + return rval; ha->isp_ops->disable_intrs(ha); qlafx00_soc_cpu_reset(vha); + + return QLA_SUCCESS; } /** diff --git a/qla2x00t-32gbit/qla_nx.c b/qla2x00t-32gbit/qla_nx.c index d545d3441..e0b4387fd 100644 --- a/qla2x00t-32gbit/qla_nx.c +++ b/qla2x00t-32gbit/qla_nx.c @@ -1757,11 +1757,13 @@ qla82xx_pci_config(scsi_qla_host_t *vha) * * Returns 0 on success. */ -void +int qla82xx_reset_chip(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; ha->isp_ops->disable_intrs(ha); + + return QLA_SUCCESS; } void qla82xx_config_rings(struct scsi_qla_host *vha) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 44d3db4b5..75a115128 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -55,7 +55,7 @@ static struct kmem_cache *ctx_cachep; /* * error level for logging */ -uint ql_errlev = ql_log_all; +uint ql_errlev = 0x8001; static int ql2xenableclass2; module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR); @@ -4368,8 +4368,20 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, goto fail_sfp_data; } + ha->flt = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE, &ha->flt_dma, + GFP_KERNEL); + if (!ha->flt) { + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, + "Unable to allocate memory for FLT.\n"); + goto fail_flt_buffer; + } + return 0; +fail_flt_buffer: + dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, + ha->sfp_data, ha->sfp_data_dma); fail_sfp_data: kfree(ha->loop_id_map); fail_loop_id_map: @@ -4775,6 +4787,10 @@ qla2x00_mem_free(struct qla_hw_data *ha) dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, ha->sfp_data, ha->sfp_data_dma); + if (ha->flt) + dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, + ha->flt, ha->flt_dma); + if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index 08c7dca07..320c25f3a 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -634,7 +634,7 @@ end: static void qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) { - const char *loc, *locations[] = { "DEF", "FLT" }; + const char *locations[] = { "DEF", "FLT" }, *loc = locations[1]; const uint32_t def_fw[] = { FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR_81 }; const uint32_t def_boot[] = @@ -664,20 +664,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) const uint32_t fcp_prio_cfg1[] = { FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25, 0 }; - uint32_t def; - uint16_t *wptr; - uint16_t cnt, chksum; - uint32_t start; - struct qla_flt_header *flt; - struct qla_flt_region *region; - struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req_q_map[0]; - def = 0; - if (IS_QLA25XX(ha)) - def = 1; - else if (IS_QLA81XX(ha)) - def = 2; + struct qla_hw_data *ha = vha->hw; + uint32_t def = IS_QLA81XX(ha) ? 2 : IS_QLA25XX(ha) ? 1 : 0; + struct qla_flt_header *flt = (void *)ha->flt; + struct qla_flt_region *region = (void *)&flt[1]; + uint16_t *wptr, cnt, chksum; + uint32_t start; /* Assign FCP prio region since older adapters may not have FLT, or FCP prio region in it's FLT. @@ -686,12 +679,11 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) fcp_prio_cfg0[def] : fcp_prio_cfg1[def]; ha->flt_region_flt = flt_addr; - wptr = (uint16_t *)req->ring; - flt = (struct qla_flt_header *)req->ring; - region = (struct qla_flt_region *)&flt[1]; - ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, - flt_addr << 2, OPTROM_BURST_SIZE); - if (*wptr == cpu_to_le16(0xffff)) + wptr = (uint16_t *)ha->flt; + qla24xx_read_flash_data(vha, (void *)flt, flt_addr, + (sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE) >> 2); + + if (le16_to_cpu(*wptr) == 0xffff) goto no_flash_data; if (flt->version != cpu_to_le16(1)) { ql_log(ql_log_warn, vha, 0x0047, @@ -701,7 +693,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) goto no_flash_data; } - cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; + cnt = (sizeof(*flt) + le16_to_cpu(flt->length)) / sizeof(*wptr); for (chksum = 0; cnt--; wptr++) chksum += le16_to_cpu(*wptr); if (chksum) { @@ -712,16 +704,18 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) goto no_flash_data; } - loc = locations[1]; - cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); + cnt = le16_to_cpu(flt->length) / sizeof(*region); for ( ; cnt; cnt--, region++) { /* Store addresses as DWORD offsets. */ start = le32_to_cpu(region->start) >> 2; ql_dbg(ql_dbg_init, vha, 0x0049, "FLT[%#x]: start=%#x end=%#x size=%#x.\n", - le16_to_cpu(region->code), - start, le32_to_cpu(region->end) >> 2, - le32_to_cpu(region->size)); + le16_to_cpu(region->code), start, + le32_to_cpu(region->end) >> 2, + le32_to_cpu(region->size) >> 2); + if (region->attribute) + ql_log(ql_dbg_init, vha, 0xffff, + "Region %x is secure\n", region->code); switch (le16_to_cpu(region->code)) { case FLT_REG_FCOE_FW: @@ -2623,6 +2617,338 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, return buf; } +static int +qla28xx_extract_sfub_and_verify(struct scsi_qla_host *vha, uint32_t *buf, + uint32_t len, uint32_t buf_size_without_sfub, uint8_t *sfub_buf) +{ + uint32_t *p, check_sum = 0; + int i; + + p = buf + buf_size_without_sfub; + + /* Extract SFUB from end of file */ + memcpy(sfub_buf, (uint8_t *)p, + sizeof(struct secure_flash_update_block)); + + for (i = 0; i < (sizeof(struct secure_flash_update_block) >> 2); i++) + check_sum += p[i]; + + check_sum = (~check_sum) + 1; + + if (check_sum != p[i]) { + ql_log(ql_log_warn, vha, 0x7097, + "SFUB checksum failed, 0x%x, 0x%x\n", + check_sum, p[i]); + return QLA_COMMAND_ERROR; + } + + return QLA_SUCCESS; +} + +static int +qla28xx_get_flash_region(struct scsi_qla_host *vha, uint32_t start, + struct qla_flt_region *region) +{ + struct qla_hw_data *ha = vha->hw; + struct qla_flt_header *flt; + struct qla_flt_region *flt_reg; + uint16_t cnt; + int rval = QLA_FUNCTION_FAILED; + + if (!ha->flt) + return QLA_FUNCTION_FAILED; + + flt = (struct qla_flt_header *)ha->flt; + flt_reg = (struct qla_flt_region *)&flt[1]; + cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); + + for (; cnt; cnt--, flt_reg++) { + if (flt_reg->start == start) { + memcpy((uint8_t *)region, flt_reg, + sizeof(struct qla_flt_region)); + rval = QLA_SUCCESS; + break; + } + } + + return rval; +} + +static int +qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, + uint32_t dwords) +{ + struct qla_hw_data *ha = vha->hw; + ulong liter; + ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */ + uint32_t sec_mask, rest_addr, fdata; + void *optrom = NULL; + dma_addr_t optrom_dma; + int rval; + struct secure_flash_update_block *sfub; + dma_addr_t sfub_dma; + uint32_t offset = faddr << 2; + uint32_t buf_size_without_sfub = 0; + struct qla_flt_region region; + bool reset_to_rom = false; + uint32_t risc_size, risc_attr = 0; + uint32_t *fw_array = NULL; + + /* Retrieve region info - must be a start address passed in */ + rval = qla28xx_get_flash_region(vha, offset, ®ion); + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Invalid address %x - not a region start address\n", + offset); + goto done; + } + + /* Allocate dma buffer for burst write */ + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + ql_log(ql_log_warn, vha, 0x7095, + "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE); + rval = QLA_COMMAND_ERROR; + goto done; + } + + /* + * If adapter supports secure flash and region is secure + * extract secure flash update block (SFUB) and verify + */ + if (ha->flags.secure_adapter && region.attribute) { + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Region %x is secure\n", region.code); + + if (region.code == FLT_REG_FW || + region.code == FLT_REG_FW_SEC_27XX) { + fw_array = dwptr; + + /* 1st fw array */ + risc_size = be32_to_cpu(fw_array[3]); + risc_attr = be32_to_cpu(fw_array[9]); + + buf_size_without_sfub = risc_size; + fw_array += risc_size; + + /* 2nd fw array */ + risc_size = be32_to_cpu(fw_array[3]); + + buf_size_without_sfub += risc_size; + fw_array += risc_size; + + /* 1st dump template */ + risc_size = be32_to_cpu(fw_array[2]); + + /* skip header and ignore checksum */ + buf_size_without_sfub += risc_size; + fw_array += risc_size; + + if (risc_attr & BIT_9) { + /* 2nd dump template */ + risc_size = be32_to_cpu(fw_array[2]); + + /* skip header and ignore checksum */ + buf_size_without_sfub += risc_size; + fw_array += risc_size; + } + } else { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Secure region %x not supported\n", + region.code); + rval = QLA_COMMAND_ERROR; + goto done; + } + + sfub = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct secure_flash_update_block), &sfub_dma, + GFP_KERNEL); + if (!sfub) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to allocate memory for SFUB\n"); + rval = QLA_COMMAND_ERROR; + goto done; + } + + rval = qla28xx_extract_sfub_and_verify(vha, dwptr, dwords, + buf_size_without_sfub, (uint8_t *)sfub); + + if (rval != QLA_SUCCESS) + goto done; + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "SFUB extract and verify successful\n"); + } + + rest_addr = (ha->fdt_block_size >> 2) - 1; + sec_mask = ~rest_addr; + + /* Lock semaphore */ + rval = qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_LOCK); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to lock flash semaphore."); + goto done; + } + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Unprotect flash...\n"); + rval = qla24xx_unprotect_flash(vha); + if (rval) { + qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); + ql_log(ql_log_warn, vha, 0x7096, "Failed unprotect flash\n"); + goto done; + } + + for (liter = 0; liter < dwords; liter++, faddr++) { + fdata = (faddr & sec_mask) << 2; + + /* If start of sector */ + if (!(faddr & rest_addr)) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Erase sector %#x...\n", faddr); + rval = qla24xx_erase_sector(vha, fdata); + if (rval) { + ql_dbg(ql_dbg_user, vha, 0x7007, + "Failed erase sector %#x\n", faddr); + goto write_protect; + } + } + } + + if (ha->flags.secure_adapter) { + /* + * If adapter supports secure flash but FW doesn't, + * disable write protect, release semaphore and reset + * chip to execute ROM code in order to update region securely + */ + if (!ha->flags.secure_fw) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Disable Write and Release Semaphore."); + rval = qla24xx_protect_flash(vha); + if (rval != QLA_SUCCESS) { + qla81xx_fac_semaphore_access(vha, + FAC_SEMAPHORE_UNLOCK); + ql_log(ql_log_warn, vha, 0xffff, + "Unable to protect flash."); + goto done; + } + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Reset chip to ROM."); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + set_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + rval = qla2x00_wait_for_chip_reset(vha); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to reset to ROM code."); + goto done; + } + reset_to_rom = true; + ha->flags.fac_supported = 0; + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Lock Semaphore"); + rval = qla2xxx_write_remote_register(vha, + FLASH_SEMAPHORE_REGISTER_ADDR, 0x00020002); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to lock flash semaphore."); + goto done; + } + + /* Unprotect flash */ + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Enable Write."); + rval = qla2x00_write_ram_word(vha, 0x7ffd0101, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x7096, + "Failed unprotect flash\n"); + goto done; + } + } + + /* If region is secure, send Secure Flash MB Cmd */ + if (region.attribute && buf_size_without_sfub) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Sending Secure Flash MB Cmd\n"); + rval = qla28xx_secure_flash_update(vha, 0, region.code, + buf_size_without_sfub, sfub_dma, + sizeof(struct secure_flash_update_block)); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Secure Flash MB Cmd failed %x.", rval); + goto write_protect; + } + } + + } + + /* re-init flash offset */ + faddr = offset >> 2; + + for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { + fdata = (faddr & sec_mask) << 2; + + /* If smaller than a burst remaining */ + if (dwords - liter < dburst) + dburst = dwords - liter; + + /* Copy to dma buffer */ + memcpy(optrom, dwptr, dburst << 2); + + /* Burst write */ + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Write burst (%#lx dwords)...\n", dburst); + rval = qla2x00_load_ram(vha, optrom_dma, + flash_data_addr(ha, faddr), dburst); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x7097, + "Failed burst write at %x (%p/%#llx)...\n", + flash_data_addr(ha, faddr), optrom, + (u64)optrom_dma); + break; + } + + liter += dburst - 1; + faddr += dburst - 1; + dwptr += dburst - 1; + continue; + } + +write_protect: + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Protect flash...\n"); + rval = qla24xx_protect_flash(vha); + if (rval) { + qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); + ql_log(ql_log_warn, vha, 0x7099, + "Failed protect flash\n"); + } + + if (reset_to_rom == true) { + /* Schedule DPC to restart the RISC */ + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + + rval = qla2x00_wait_for_hba_online(vha); + if (rval != QLA_SUCCESS) + ql_log(ql_log_warn, vha, 0xffff, + "Adapter did not come out of reset\n"); + } + +done: + if (optrom) + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + + return rval; +} + int qla24xx_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) @@ -2635,8 +2961,12 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, void *buf, set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with write. */ - rval = qla24xx_write_flash_data(vha, buf, offset >> 2, - length >> 2); + if (IS_QLA28XX(ha)) + rval = qla28xx_write_flash_data(vha, (uint32_t *)buf, + offset >> 2, length >> 2); + else + rval = qla24xx_write_flash_data(vha, (uint32_t *)buf, + offset >> 2, length >> 2); clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); scsi_unblock_requests(vha->host); @@ -3151,6 +3481,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); faddr = ha->flt_region_fw; if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + qla27xx_get_active_image(vha, &active_regions); if (active_regions.global == QLA27XX_SECONDARY_IMAGE) faddr = ha->flt_region_fw_sec; } From de350a3ca4bf3cfb0c6321f0df547dc28238a40f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:19:21 +0000 Subject: [PATCH 16/42] qla2xxx: Update driver version to 10.01.00.15-k This version includes support for ISP28XX. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8210 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_version.h b/qla2x00t-32gbit/qla_version.h index 0690dac24..0f8cca27c 100644 --- a/qla2x00t-32gbit/qla_version.h +++ b/qla2x00t-32gbit/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.00.00.14-k" +#define QLA2XXX_VERSION "10.01.00.15-k" #define QLA_DRIVER_MAJOR_VER 10 -#define QLA_DRIVER_MINOR_VER 0 +#define QLA_DRIVER_MINOR_VER 1 #define QLA_DRIVER_PATCH_VER 0 #define QLA_DRIVER_BETA_VER 0 From 176993a76606cbae24e25237531b88135b130731 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:19:48 +0000 Subject: [PATCH 17/42] qla2xxx: Fix comment alignment in qla_bsg.c Fix a minor formatting issue with comment section in qla_bsg.c. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8211 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_bsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 95e1c3c23..286e7890a 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -1,4 +1,4 @@ - /* +/* * QLogic Fibre Channel HBA Driver * Copyright (c) 2003-2014 QLogic Corporation * From c93f1c41abefe425fe0aa32d18229adc83abcdd6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:20:10 +0000 Subject: [PATCH 18/42] qla2xxx: Fix a small typo in qla_bsg.c Fixed a typo for 'iiDMA' cmd in qla_bsg.c. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8212 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_bsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 286e7890a..8709f814f 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -1406,7 +1406,7 @@ static int qla24xx_iidma(struct bsg_job *bsg_job) if (rval) { ql_log(ql_log_warn, vha, 0x704c, - "iIDMA cmd failed for %8phN -- " + "iiDMA cmd failed for %8phN -- " "%04x %x %04x %04x.\n", fcport->port_name, rval, fcport->fp_speed, mb[0], mb[1]); rval = (DID_ERROR << 16); From 6093c63ba1abc3c583e842076111d4867b3882c3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:20:36 +0000 Subject: [PATCH 19/42] qla2xxx: Simplify conditional check again Clang warns when it sees a logical not on the left side of a conditional statement because it thinks the logical not should be applied to the whole statement, not just the left side: drivers/scsi/qla2xxx/qla_nx.c:3703:7: warning: logical not is only applied to the left hand side of this comparison [-Wlogical-not-parentheses] This particular instance was already fixed by commit 0bfe7d3cae58 ("scsi: qla2xxx: Simplify conditional check") upstream but it was reintroduced by commit 3695310e37b4 ("scsi: qla2xxx: Update flash read/write routine") in the 5.2/scsi-queue. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8213 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_nx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_nx.c b/qla2x00t-32gbit/qla_nx.c index e0b4387fd..359ebb634 100644 --- a/qla2x00t-32gbit/qla_nx.c +++ b/qla2x00t-32gbit/qla_nx.c @@ -3700,8 +3700,8 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Wait for pending cmds (physical and virtual) to complete */ - if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0, - WAIT_HOST) == QLA_SUCCESS) { + if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, + WAIT_HOST)) { ql_dbg(ql_dbg_init, vha, 0x00b3, "Done wait for " "pending commands.\n"); From eb4388978ebf1b9a8abb53bcdfebacd5bab5383b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:21:01 +0000 Subject: [PATCH 20/42] qla2xxx: Set the SCSI command result before calling the command done This patch tries to address race condition between abort handler and completion handler. When scsi command result is set by both abort and completion handler, scsi_done() is only called after refcount on SRB structure goes to zero. The abort handler sets this result prematurely even when the refcount is non-zero value. Fix this by setting SCSI cmd->result before scsi_done() is called. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8214 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 75a115128..8211f4670 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -805,8 +805,6 @@ qla2x00_sp_compl(void *ptr, int res) srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - cmd->result = res; - if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; @@ -814,6 +812,7 @@ qla2x00_sp_compl(void *ptr, int res) return; sp->free(sp); + cmd->result = res; cmd->scsi_done(cmd); } From 03427baae1570fa4011a2a21fdccd9f8ca26eda8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:21:34 +0000 Subject: [PATCH 21/42] qla2xxx: Set the qpair in SRB to NULL when SRB is released This patch sets QPair pointer to NULL to prevent abort command racing ahead of normal command completion handling during scsi_done call. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8215 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_inline.h | 1 + 1 file changed, 1 insertion(+) diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index d383ac44d..0bdf090ba 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -261,6 +261,7 @@ done: static inline void qla2xxx_rel_qpair_sp(struct qla_qpair *qpair, srb_t *sp) { + sp->qpair = NULL; mempool_free(sp, qpair->srb_mempool); QLA_QPAIR_MARK_NOT_BUSY(qpair); } From 32324e46de6d9aa30a003f118320a34f0bb784e6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:22:14 +0000 Subject: [PATCH 22/42] qla2xxx: Reset the FCF_ASYNC_{SENT|ACTIVE} flags Driver maintains state machine for processing and completing switch commands. This patch resets FCF_ASYNC_{SENT|ACTIVE} flag to indicate if the previous command is active or sent, in order for next GPSC command to advance the state machine. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8216 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_gs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index 824651ecd..b9541876a 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -3032,6 +3032,8 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res) ql_dbg(ql_dbg_disc, vha, 0x2053, "Async done-%s res %x, WWPN %s \n", sp->name, res, wwn_to_str(fcport->port_name)); + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); + if (res == QLA_FUNCTION_TIMEOUT) return; @@ -4359,6 +4361,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport) done_free_sp: sp->free(sp); + fcport->flags &= ~FCF_ASYNC_SENT; done: return rval; } From e1ae68953157594187e6ebfcd8bd82929135f928 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:23:00 +0000 Subject: [PATCH 23/42] qla2xxx: Increase max_sgl_segments to 1024 This patch increases max_sgl_segments from 128 to the maximum supported which is 1024. Increasing max_sgl_segments allows the driver to support larger I/O sizes. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8217 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 21af641b0..796640877 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -579,7 +579,7 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = { .fcp_io = qla_nvme_post_cmd, .fcp_abort = qla_nvme_fcp_abort, .max_hw_queues = 8, - .max_sgl_segments = 128, + .max_sgl_segments = 1024, .max_dif_sgl_segments = 64, .dma_boundary = 0xFFFFFFFF, .local_priv_sz = 8, From a686180c77ce5e84f39fa7aa896bfa3bfecd4606 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:23:33 +0000 Subject: [PATCH 24/42] qla2xxx: Disable T10-DIF feature with FC-NVMe during probe With FC-NVMe enabled, driver does not support T10 DIF/DIX. This patch disables T10-PI information when ql2xnvmeenable is set. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8218 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 8211f4670..fa6345bc4 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -2955,6 +2955,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* This may fail but that's ok */ pci_enable_pcie_error_reporting(pdev); + /* Turn off T10-DIF when FC-NVMe is enabled */ + if (ql2xnvmeenable) + ql2xenabledif = 0; + ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, From 10505579af8d8c326d8b010561f71665e882008a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:23:55 +0000 Subject: [PATCH 25/42] qla2xxx: Fix incorrect region-size setting in optrom SYSFS routines Commit e6f77540c067 ("scsi: qla2xxx: Fix an integer overflow in sysfs code") incorrectly set 'optrom_region_size' to 'start+size', which can overflow option-rom boundaries when 'start' is non-zero. Continue setting optrom_region_size to the proper adjusted value of 'size'. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8219 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 868709019..93058379d 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -376,7 +376,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, } ha->optrom_region_start = start; - ha->optrom_region_size = start + size; + ha->optrom_region_size = size; ha->optrom_state = QLA_SREADING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); @@ -449,7 +449,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, } ha->optrom_region_start = start; - ha->optrom_region_size = start + size; + ha->optrom_region_size = size; ha->optrom_state = QLA_SWRITING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); From b93f3b4b8c09d856d02d6cf5cf6990cbeb0327d2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:24:17 +0000 Subject: [PATCH 26/42] qla2xxx: Further limit FLASH region write access from SysFS Recent ISPs have larger and more complex flash-write semantics (secure-access and signing). The BSG interfaces support these semantics for all ISPs and is exclusively used by QLogic user-space tools. Limit flash-write operations to ISPs <= 25xx. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8220 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 93058379d..b2520e499 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -430,6 +430,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, * 0x000000 -> 0x07ffff -- Boot code. * 0x080000 -> 0x0fffff -- Firmware. * 0x120000 -> 0x12ffff -- VPD and HBA parameters. + * + * > ISP25xx type boards: + * + * None -- should go through BSG. */ valid = 0; if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) @@ -437,9 +441,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; - else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) - || IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) - || IS_QLA27XX(ha) || IS_QLA28XX(ha)) + else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) valid = 1; if (!valid) { ql_log(ql_log_warn, vha, 0x7065, From 81a25cb3e040285a51fcfee92bb0720d24165e27 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:24:43 +0000 Subject: [PATCH 27/42] qla2xxx: Fix fw dump corruption If fw dump buffer size changes and there is an existing fw dump, then save the old dump in the newly allocated buffer. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8221 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 1 + qla2x00t-32gbit/qla_init.c | 72 ++++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index c346dfb46..78a57ec98 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4065,6 +4065,7 @@ struct qla_hw_data { } fwdt[2]; struct qla2xxx_fw_dump *fw_dump; uint32_t fw_dump_len; + u32 fw_dump_alloc_len; bool fw_dumped; bool fw_dump_mpi; unsigned long fw_dump_cap_flags; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 38c1bac49..acc5a7058 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3138,12 +3138,12 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) !IS_QLA28XX(ha)) mq_size = sizeof(struct qla2xxx_mq_chain); /* - * Allocate maximum buffer size for all queues. + * Allocate maximum buffer size for all queues - Q0. * Resizing must be done at end-of-dump processing. */ - mq_size += ha->max_req_queues * + mq_size += (ha->max_req_queues - 1) * (req->length * sizeof(request_t)); - mq_size += ha->max_rsp_queues * + mq_size += (ha->max_rsp_queues - 1) * (rsp->length * sizeof(response_t)); } if (ha->tgt.atio_ring) @@ -3218,42 +3218,62 @@ try_eft: ha->exlogin_size; allocate: - if (!ha->fw_dump_len || dump_size != ha->fw_dump_len) { + if (!ha->fw_dump_len || dump_size > ha->fw_dump_alloc_len) { + + ql_dbg(ql_dbg_init, vha, 0x00c5, + "%s dump_size %d fw_dump_len %d fw_dump_alloc_len %d\n", + __func__, dump_size, ha->fw_dump_len, + ha->fw_dump_alloc_len); + fw_dump = vmalloc(dump_size); if (!fw_dump) { ql_log(ql_log_warn, vha, 0x00c4, "Unable to allocate (%d KB) for firmware dump.\n", dump_size / 1024); } else { - if (ha->fw_dump) + if (ha->fw_dumped) { + memcpy(fw_dump, ha->fw_dump, ha->fw_dump_len); vfree(ha->fw_dump); - ha->fw_dump = fw_dump; + ha->fw_dump = fw_dump; + ha->fw_dump_alloc_len = dump_size; + ql_dbg(ql_dbg_init, vha, 0x00c5, + "Re-Allocated (%d KB) and save firmware dump.\n", + dump_size / 1024); + } else { + if (ha->fw_dump) + vfree(ha->fw_dump); + ha->fw_dump = fw_dump; - ha->fw_dump_len = dump_size; - ql_dbg(ql_dbg_init, vha, 0x00c5, - "Allocated (%d KB) for firmware dump.\n", - dump_size / 1024); + ha->fw_dump_len = ha->fw_dump_alloc_len = + dump_size; + ql_dbg(ql_dbg_init, vha, 0x00c5, + "Allocated (%d KB) for firmware dump.\n", + dump_size / 1024); - if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) - return; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + return; - ha->fw_dump->signature[0] = 'Q'; - ha->fw_dump->signature[1] = 'L'; - ha->fw_dump->signature[2] = 'G'; - ha->fw_dump->signature[3] = 'C'; - ha->fw_dump->version = htonl(1); + ha->fw_dump->signature[0] = 'Q'; + ha->fw_dump->signature[1] = 'L'; + ha->fw_dump->signature[2] = 'G'; + ha->fw_dump->signature[3] = 'C'; + ha->fw_dump->version = htonl(1); - ha->fw_dump->fixed_size = htonl(fixed_size); - ha->fw_dump->mem_size = htonl(mem_size); - ha->fw_dump->req_q_size = htonl(req_q_size); - ha->fw_dump->rsp_q_size = htonl(rsp_q_size); + ha->fw_dump->fixed_size = htonl(fixed_size); + ha->fw_dump->mem_size = htonl(mem_size); + ha->fw_dump->req_q_size = htonl(req_q_size); + ha->fw_dump->rsp_q_size = htonl(rsp_q_size); - ha->fw_dump->eft_size = htonl(eft_size); - ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma)); - ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma)); + ha->fw_dump->eft_size = htonl(eft_size); + ha->fw_dump->eft_addr_l = + htonl(LSD(ha->eft_dma)); + ha->fw_dump->eft_addr_h = + htonl(MSD(ha->eft_dma)); - ha->fw_dump->header_size = - htonl(offsetof(struct qla2xxx_fw_dump, isp)); + ha->fw_dump->header_size = + htonl(offsetof + (struct qla2xxx_fw_dump, isp)); + } } } } From a32be9e6d2f8e761286914a9144ebd06c75a3cc4 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:25:24 +0000 Subject: [PATCH 28/42] qla2xxx: Protect qla2x00_sysfs_read_fw_dump() with a mutex Add mutex protection to prevent driver from freeing the FW dump buffer while the extraction is in progress. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8222 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 25 ++++++++++++++----------- qla2x00t-32gbit/qla_init.c | 6 +++++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index b2520e499..da64fe54f 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -29,24 +29,27 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, if (!(ha->fw_dump_reading || ha->mctp_dump_reading)) return 0; + mutex_lock(&ha->optrom_mutex); if (IS_P3P_TYPE(ha)) { if (off < ha->md_template_size) { rval = memory_read_from_buffer(buf, count, &off, ha->md_tmplt_hdr, ha->md_template_size); - return rval; + } else { + off -= ha->md_template_size; + rval = memory_read_from_buffer(buf, count, + &off, ha->md_dump, ha->md_dump_size); } - off -= ha->md_template_size; - rval = memory_read_from_buffer(buf, count, - &off, ha->md_dump, ha->md_dump_size); - return rval; - } else if (ha->mctp_dumped && ha->mctp_dump_reading) - return memory_read_from_buffer(buf, count, &off, ha->mctp_dump, + } else if (ha->mctp_dumped && ha->mctp_dump_reading) { + rval = memory_read_from_buffer(buf, count, &off, ha->mctp_dump, MCTP_DUMP_SIZE); - else if (ha->fw_dump_reading) - return memory_read_from_buffer(buf, count, &off, ha->fw_dump, + } else if (ha->fw_dump_reading) { + rval = memory_read_from_buffer(buf, count, &off, ha->fw_dump, ha->fw_dump_len); - else - return 0; + } else { + rval = 0; + } + mutex_unlock(&ha->optrom_mutex); + return rval; } static ssize_t diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index acc5a7058..229bd6322 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3231,6 +3231,7 @@ allocate: "Unable to allocate (%d KB) for firmware dump.\n", dump_size / 1024); } else { + mutex_lock(&ha->optrom_mutex); if (ha->fw_dumped) { memcpy(fw_dump, ha->fw_dump, ha->fw_dump_len); vfree(ha->fw_dump); @@ -3250,8 +3251,10 @@ allocate: "Allocated (%d KB) for firmware dump.\n", dump_size / 1024); - if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + mutex_unlock(&ha->optrom_mutex); return; + } ha->fw_dump->signature[0] = 'Q'; ha->fw_dump->signature[1] = 'L'; @@ -3274,6 +3277,7 @@ allocate: htonl(offsetof (struct qla2xxx_fw_dump, isp)); } + mutex_unlock(&ha->optrom_mutex); } } } From c4e0fbce6f35da5d935a0566208468bdc3f45e77 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:25:48 +0000 Subject: [PATCH 29/42] qla2xxx: Cleanup fcport memory to prevent leak Clean up fcport list and loopid in one place and iterate through for loop. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8223 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_init.c | 2 ++ qla2x00t-32gbit/qla_os.c | 7 ++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 229bd6322..1aef32e17 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -4820,6 +4820,8 @@ qla2x00_free_fcport(fc_port_t *fcport) fcport->ct_desc.ct_sns = NULL; } + list_del(&fcport->list); + qla2x00_clear_loop_id(fcport); kfree(fcport); } diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index fa6345bc4..aec2cf33e 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3965,11 +3965,8 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha) { fc_port_t *fcport, *tfcport; - list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) { - list_del(&fcport->list); - qla2x00_clear_loop_id(fcport); - kfree(fcport); - } + list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) + qla2x00_free_fcport(fcport); } static inline void From 1e7c4b0d9b4de6fbef41cb874fa633a4e132895d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:26:12 +0000 Subject: [PATCH 30/42] qla2xxx: Remove redundant qla2x00_abort_all_cmds during unload This patch removes redundant qla2x00_abort_all_cmds() during driver unload. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8224 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index aec2cf33e..a6bc4e711 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3875,8 +3875,6 @@ qla2x00_remove_one(struct pci_dev *pdev) qla2x00_delete_all_vps(ha, base_vha); - qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); - qla2x00_dfs_remove(base_vha); qla84xx_put_chip(base_vha); From 16f7d633dda5c6e6415d942f67ebfabb64d261a8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:26:34 +0000 Subject: [PATCH 31/42] qla2xxx: Fix driver unload when FC-NVMe LUNs are connected This patch allows driver to unload using "modprobe -r" when FC-NVMe LUNs are connected. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8225 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_nvme.c | 29 +++++++++++++++++++++++------ qla2x00t-32gbit/qla_os.c | 6 ++++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 796640877..c8f6245a4 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -172,12 +172,13 @@ static void qla_nvme_sp_done(void *ptr, int res) if (!atomic_dec_and_test(&sp->ref_count)) return; - if (res == QLA_SUCCESS) - fd->status = 0; - else - fd->status = NVME_SC_INTERNAL; - - fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; + if (res == QLA_SUCCESS) { + fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; + } else { + fd->rcv_rsplen = 0; + fd->transferred_length = 0; + } + fd->status = 0; fd->done(fd); qla2xxx_rel_qpair_sp(sp->qpair, sp); @@ -201,6 +202,22 @@ static void qla_nvme_abort_work(struct work_struct *work) if (!ha->flags.fw_started && (fcport && fcport->deleted)) return; + if (ha->flags.host_shutting_down) { + ql_log(ql_log_info, sp->fcport->vha, 0xffff, + "%s Calling done on sp: %p, type: 0x%x, sp->ref_count: 0x%x\n", + __func__, sp, sp->type, atomic_read(&sp->ref_count)); + sp->done(sp, 0); + return; + } + + if (atomic_read(&sp->ref_count) == 0) { + WARN_ON(1); + ql_log(ql_log_info, fcport->vha, 0xffff, + "%s: command alredy aborted on sp: %p\n", + __func__, sp); + return; + } + rval = ha->isp_ops->abort_command(sp); ql_dbg(ql_dbg_io, fcport->vha, 0x212b, diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index a6bc4e711..df51d06cf 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -6808,8 +6808,10 @@ qla2x00_timer(struct timer_list *t) * FC-NVME * see if the active AEN count has changed from what was last reported. */ - if (!vha->vp_idx && (atomic_read(&ha->nvme_active_aen_cnt) != - ha->nvme_last_rptd_aen) && ha->zio_mode == QLA_ZIO_MODE_6) { + if (!vha->vp_idx && + (atomic_read(&ha->nvme_active_aen_cnt) != ha->nvme_last_rptd_aen) && + ha->zio_mode == QLA_ZIO_MODE_6 && + !ha->flags.host_shutting_down) { ql_log(ql_log_info, vha, 0x3002, "nvme: Sched: Set ZIO exchange threshold to %d.\n", ha->nvme_last_rptd_aen); From 371c5d00e385902c50caa5c51d2cae9cb7dde1fc Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:26:57 +0000 Subject: [PATCH 32/42] qla2xxx: Change abort wait_loop from msleep to wait_event_timeout This patch converts driver wait time from using msleep to wair_event_timeout to prevent race condition. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8226 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 2 +- qla2x00t-32gbit/qla_os.c | 83 +++++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 78a57ec98..037674116 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -560,6 +560,7 @@ typedef struct srb { int rc; int retry_count; struct completion comp; + wait_queue_head_t *cwaitq; union { struct srb_iocb iocb_cmd; #ifndef NEW_LIBFC_API @@ -4813,5 +4814,4 @@ struct sff_8247_a0 { #include "qla_gbl.h" #include "qla_dbg.h" #include "qla_inline.h" - #endif diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index df51d06cf..93006e0dc 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -766,7 +766,7 @@ qla2x00_sp_free_dma(void *ptr) } if (!ctx) - goto end; + return; if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ @@ -791,12 +791,6 @@ qla2x00_sp_free_dma(void *ptr) ha->gbl_dsd_avail += ctx1->dsd_use_cnt; mempool_free(ctx1, ha->ctx_mempool); } - -end: - if (sp->type != SRB_NVME_CMD && sp->type != SRB_NVME_LS) { - CMD_SP(cmd) = NULL; - qla2x00_rel_sp(sp); - } } void @@ -804,6 +798,7 @@ qla2x00_sp_compl(void *ptr, int res) { srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); + wait_queue_head_t *cwaitq = sp->cwaitq; if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; @@ -813,7 +808,11 @@ qla2x00_sp_compl(void *ptr, int res) sp->free(sp); cmd->result = res; + CMD_SP(cmd) = NULL; cmd->scsi_done(cmd); + if (cwaitq) + wake_up(cwaitq); + qla2x00_rel_sp(sp); } void @@ -836,7 +835,7 @@ qla2xxx_qpair_sp_free_dma(void *ptr) } if (!ctx) - goto end; + return; if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ @@ -896,10 +895,6 @@ qla2xxx_qpair_sp_free_dma(void *ptr) } sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID; } - -end: - CMD_SP(cmd) = NULL; - qla2xxx_rel_qpair_sp(sp->qpair, sp); } void @@ -907,8 +902,7 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) { srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - - cmd->result = res; + wait_queue_head_t *cwaitq = sp->cwaitq; if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; @@ -917,7 +911,12 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) return; sp->free(sp); + cmd->result = res; + CMD_SP(cmd) = NULL; cmd->scsi_done(cmd); + if (cwaitq) + wake_up(cwaitq); + qla2xxx_rel_qpair_sp(sp->qpair, sp); } #if defined(RHEL_MAJOR) && RHEL_MAJOR -0 == 6 && RHEL_MINOR -0 >= 2 @@ -1429,7 +1428,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) vha->host_no, id, lun, sp, cmd, sp->handle); /* Get a reference to the sp and drop the lock.*/ - rval = ha->isp_ops->abort_command(sp); if (rval) { if (rval == QLA_FUNCTION_PARAMETER_ERROR) @@ -1446,37 +1444,46 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } spin_lock_irqsave(qpair->qp_lock_ptr, flags); - /* - * Clear the slot in the oustanding_cmds array if we can't find the - * command to reclaim the resources. - */ - if (rval == QLA_FUNCTION_PARAMETER_ERROR) - vha->req->outstanding_cmds[sp->handle] = NULL; /* - * sp->done will do ref_count-- - * sp_get() took an extra count above + * Releasing of the SRB and associated command resources + * is managed through ref_count. + * Whether we need to wait for the abort completion or complete + * the abort handler should be based on the ref_count. */ - sp->done(sp, DID_RESET << 16); + if (atomic_read(&sp->ref_count) > 1) { + /* + * The command is not yet completed. We need to wait for either + * command completion or abort completion. + */ + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(eh_waitq); + uint32_t ratov = ha->r_a_tov/10; - /* Did the command return during mailbox execution? */ - if (ret == FAILED && !CMD_SP(cmd)) - ret = SUCCESS; + /* Go ahead and release the extra ref_count obtained earlier */ + sp->done(sp, DID_RESET << 16); + sp->cwaitq = &eh_waitq; - if (!CMD_SP(cmd)) - wait = 0; - - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - - /* Wait for the command to be returned. */ - if (wait) { - if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x8006, - "Abort handler timed out cmd=%p.\n", cmd); + if (!wait_event_lock_irq_timeout(eh_waitq, + CMD_SP(cmd) == NULL, *qpair->qp_lock_ptr, + msecs_to_jiffies(4 * ratov * 1000))) { + /* + * The abort got dropped, LOGO will be sent and the + * original command will be completed with CS_TIMEOUT + * completion + */ + ql_dbg(ql_dbg_taskm, vha, 0xffff, + "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n", + __func__, ha->r_a_tov); + sp->cwaitq = NULL; ret = FAILED; + goto end; } + } else { + /* Command completed while processing the abort */ + sp->done(sp, DID_RESET << 16); } - +end: + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); ql_log(ql_log_info, vha, 0x801c, "Abort command issued nexus=%ld:%d:%llu -- %d %x.\n", vha->host_no, id, lun, wait, ret); From 3548f0998a4334b3ff03c48e0593ef670f15cea6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:27:20 +0000 Subject: [PATCH 33/42] qla2xxx: Update driver version to 10.01.00.16-k git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8227 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_version.h b/qla2x00t-32gbit/qla_version.h index 0f8cca27c..cd6bdf71e 100644 --- a/qla2x00t-32gbit/qla_version.h +++ b/qla2x00t-32gbit/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.01.00.15-k" +#define QLA2XXX_VERSION "10.01.00.16-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1 From 5892ed7ed17985dfc18a8a640d1bb50aded0183c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:28:05 +0000 Subject: [PATCH 34/42] qla2xxx: Remove useless memset() The memory return by kzalloc() has already be set to zero, so remove useless memset(0). git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8228 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_init.c | 1 - 1 file changed, 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 1aef32e17..6143b1ad9 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -8863,7 +8863,6 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, "Failed to allocate memory for queue pair.\n"); return NULL; } - memset(qpair, 0, sizeof(struct qla_qpair)); qpair->hw = vha->hw; qpair->vha = vha; From 22af9c7653aa5af1bb488d7c2ca3917baee9cfd8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:28:40 +0000 Subject: [PATCH 35/42] qla2xxx: Fix spelling mistake "alredy" -> "already" There is a spelling mistake in a ql_log message. Fix it. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8229 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index c8f6245a4..a01edf708 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -213,7 +213,7 @@ static void qla_nvme_abort_work(struct work_struct *work) if (atomic_read(&sp->ref_count) == 0) { WARN_ON(1); ql_log(ql_log_info, fcport->vha, 0xffff, - "%s: command alredy aborted on sp: %p\n", + "%s: command already aborted on sp: %p\n", __func__, sp); return; } From 674a38d0062aef67cf1a32b6cbe101f349a32578 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:29:07 +0000 Subject: [PATCH 36/42] qla2xxx: Change a stack variable into a static const variable Make qla2x00_get_host_fabric_name() slightly faster by changing a stack array into a static array. Declare that array const now that the wwn_to_u64() argument pointer has been declared const. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8230 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index da64fe54f..b8706ed3a 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -2723,8 +2723,9 @@ static void qla2x00_get_host_fabric_name(struct Scsi_Host *shost) { scsi_qla_host_t *vha = shost_priv(shost); - uint8_t node_name[WWN_SIZE] = { 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF}; + static const uint8_t node_name[WWN_SIZE] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; u64 fabric_name = wwn_to_u64(node_name); if (vha->device_flags & SWITCH_FOUND) From 9696dfb235945225da2942dd684ad7eba40eb28c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:29:34 +0000 Subject: [PATCH 37/42] qla2xxx: Use ARRAY_SIZE() in the definition of QLA_LAST_SPEED Make the code easier to read by avoiding to use a hard-coded constant. This patch does not change any functionality. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8231 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index feea37414..b58f3cfe5 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -378,7 +378,7 @@ qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed) static const char *const link_speeds[] = { "1", "2", "?", "4", "8", "16", "32", "10" }; -#define QLA_LAST_SPEED 7 +#define QLA_LAST_SPEED (ARRAY_SIZE(link_speeds) - 1) if (IS_QLA2100(ha) || IS_QLA2200(ha)) return link_speeds[0]; From 8eb2cd510411da4afea3b9df4c29adbecbde6712 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:29:58 +0000 Subject: [PATCH 38/42] qla2xxx: Declare local symbols static This patch avoids that sparse complains that a declaration is missing. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8232 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 93006e0dc..7afad4463 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -303,14 +303,14 @@ MODULE_PARM_DESC(qla2xuseresexchforels, "Reserve 1/2 of emergency exchanges for ELS.\n" " 0 (default): disabled"); -int ql2xprotmask; +static int ql2xprotmask; module_param(ql2xprotmask, int, 0644); MODULE_PARM_DESC(ql2xprotmask, "Override DIF/DIX protection capabilities mask\n" "Default is 0 which sets protection mask based on " "capabilities reported by HBA firmware.\n"); -int ql2xprotguard; +static int ql2xprotguard; module_param(ql2xprotguard, int, 0644); MODULE_PARM_DESC(ql2xprotguard, "Override choice of DIX checksum\n" " 0 -- Let HBA firmware decide\n" From 5da65c0be7c93045e3167399b8f7edce01cce5d6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:30:27 +0000 Subject: [PATCH 39/42] qla2xxx: Make qla2x00_process_response_queue() easier to read Make qla2x00_process_response_queue() easier to read by splitting this function. This patch does not change any functionality. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8233 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_isr.c | 85 ++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index b58f3cfe5..d876f4b24 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -1992,6 +1992,52 @@ static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req, sp->done(sp, rval); } +/* Process a single response queue entry. */ +static void qla2x00_process_response_entry(struct scsi_qla_host *vha, + struct rsp_que *rsp, + sts_entry_t *pkt) +{ + sts21_entry_t *sts21_entry; + sts22_entry_t *sts22_entry; + uint16_t handle_cnt; + uint16_t cnt; + + switch (pkt->entry_type) { + case STATUS_TYPE: + qla2x00_status_entry(vha, rsp, pkt); + break; + case STATUS_TYPE_21: + sts21_entry = (sts21_entry_t *)pkt; + handle_cnt = sts21_entry->handle_count; + for (cnt = 0; cnt < handle_cnt; cnt++) + qla2x00_process_completed_request(vha, rsp->req, + sts21_entry->handle[cnt]); + break; + case STATUS_TYPE_22: + sts22_entry = (sts22_entry_t *)pkt; + handle_cnt = sts22_entry->handle_count; + for (cnt = 0; cnt < handle_cnt; cnt++) + qla2x00_process_completed_request(vha, rsp->req, + sts22_entry->handle[cnt]); + break; + case STATUS_CONT_TYPE: + qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); + break; + case MBX_IOCB_TYPE: + qla2x00_mbx_iocb_entry(vha, rsp->req, (struct mbx_entry *)pkt); + break; + case CT_IOCB_TYPE: + qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); + break; + default: + /* Type Not Supported. */ + ql_log(ql_log_warn, vha, 0x504a, + "Received unknown response pkt type %x entry status=%x.\n", + pkt->entry_type, pkt->entry_status); + break; + } +} + /** * qla2x00_process_response_queue() - Process response queue entries. * @rsp: response queue @@ -2003,8 +2049,6 @@ qla2x00_process_response_queue(struct rsp_que *rsp) struct qla_hw_data *ha = rsp->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; sts_entry_t *pkt; - uint16_t handle_cnt; - uint16_t cnt; vha = pci_get_drvdata(ha->pdev); @@ -2029,42 +2073,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp) continue; } - switch (pkt->entry_type) { - case STATUS_TYPE: - qla2x00_status_entry(vha, rsp, pkt); - break; - case STATUS_TYPE_21: - handle_cnt = ((sts21_entry_t *)pkt)->handle_count; - for (cnt = 0; cnt < handle_cnt; cnt++) { - qla2x00_process_completed_request(vha, rsp->req, - ((sts21_entry_t *)pkt)->handle[cnt]); - } - break; - case STATUS_TYPE_22: - handle_cnt = ((sts22_entry_t *)pkt)->handle_count; - for (cnt = 0; cnt < handle_cnt; cnt++) { - qla2x00_process_completed_request(vha, rsp->req, - ((sts22_entry_t *)pkt)->handle[cnt]); - } - break; - case STATUS_CONT_TYPE: - qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); - break; - case MBX_IOCB_TYPE: - qla2x00_mbx_iocb_entry(vha, rsp->req, - (struct mbx_entry *)pkt); - break; - case CT_IOCB_TYPE: - qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); - break; - default: - /* Type Not Supported. */ - ql_log(ql_log_warn, vha, 0x504a, - "Received unknown response pkt type %x " - "entry status=%x.\n", - pkt->entry_type, pkt->entry_status); - break; - } + qla2x00_process_response_entry(vha, rsp, pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); } From 0f7639a9a23b2fecadb7e51b9784daaac3ca7c0c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:34:26 +0000 Subject: [PATCH 40/42] qla2xxx: Use get/put_unaligned where appropriate This patch makes the code easier to read but does not change any functionality. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8234 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_bsg.c | 2 +- qla2x00t-32gbit/qla_iocb.c | 21 +++++++++------------ qla2x00t-32gbit/qla_nvme.c | 4 ++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 8709f814f..2757ac957 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -1090,7 +1090,7 @@ static int qla84xx_updatefw(struct bsg_job *bsg_job) } flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; - fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2))); + fw_ver = get_unaligned_le32((uint32_t *)fw_buf + 2); mn->entry_type = VERIFY_CHIP_IOCB_TYPE; mn->entry_count = 1; diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 86de44202..aba94fc9a 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -107,7 +107,7 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha) cont_pkt = (cont_entry_t *)req->ring_ptr; /* Load packet defaults. */ - *((uint32_t *)(&cont_pkt->entry_type)) = cpu_to_le32(CONTINUE_TYPE); + put_unaligned_le32(CONTINUE_TYPE, &cont_pkt->entry_type); return (cont_pkt); } @@ -136,9 +136,8 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req) cont_pkt = (cont_a64_entry_t *)req->ring_ptr; /* Load packet defaults. */ - *((uint32_t *)(&cont_pkt->entry_type)) = IS_QLAFX00(vha->hw) ? - cpu_to_le32(CONTINUE_A64_TYPE_FX00) : - cpu_to_le32(CONTINUE_A64_TYPE); + put_unaligned_le32(IS_QLAFX00(vha->hw) ? CONTINUE_A64_TYPE_FX00 : + CONTINUE_A64_TYPE, &cont_pkt->entry_type); return (cont_pkt); } @@ -202,8 +201,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 2 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - cpu_to_le32(COMMAND_TYPE); + put_unaligned_le32(COMMAND_TYPE, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -260,7 +258,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_A64_TYPE); + put_unaligned_le32(COMMAND_A64_TYPE, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -596,7 +594,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_6); + put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -711,7 +709,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_7); + put_unaligned_le32(COMMAND_TYPE_7, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -1430,7 +1428,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type CRC_2 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_CRC_2); + put_unaligned_le32(COMMAND_TYPE_CRC_2, &cmd_pkt->entry_type); vha = sp->vha; ha = vha->hw; @@ -3770,8 +3768,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, #endif /*Update entry type to indicate bidir command */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - cpu_to_le32(COMMAND_BIDIRECTIONAL); + put_unaligned_le32(COMMAND_BIDIRECTIONAL, &cmd_pkt->entry_type); /* Set the transfer direction, in this set both flags * Also set the BD_WRAP_BACK flag, firmware will take care diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index a01edf708..4dba38916 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -457,8 +457,8 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) req->ring_ptr++; } cont_pkt = (cont_a64_entry_t *)req->ring_ptr; - *((uint32_t *)(&cont_pkt->entry_type)) = - cpu_to_le32(CONTINUE_A64_TYPE); + put_unaligned_le32(CONTINUE_A64_TYPE, + &cont_pkt->entry_type); cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; avail_dsds = 5; From bfefaa01801c94d2f150af99012003a912e66f85 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:34:50 +0000 Subject: [PATCH 41/42] qla2xxx: Unregister chrdev if module initialization fails If module initialization fails after the character device has been registered, unregister the character device. Additionally, avoid duplicating error path code. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8235 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 7afad4463..48c0ede90 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -7462,8 +7462,7 @@ qla2x00_module_init(void) /* Initialize target kmem_cache and mem_pools */ ret = qlt_init(); if (ret < 0) { - kmem_cache_destroy(srb_cachep); - return ret; + goto destroy_cache; } else if (ret > 0) { /* * If initiator mode is explictly disabled by qlt_init(), @@ -7487,11 +7486,10 @@ qla2x00_module_init(void) qla2xxx_transport_template = fc_attach_transport(&qla2xxx_transport_functions); if (!qla2xxx_transport_template) { - kmem_cache_destroy(srb_cachep); ql_log(ql_log_fatal, NULL, 0x0002, "fc_attach_transport failed...Failing load!.\n"); - qlt_exit(); - return -ENODEV; + ret = -ENODEV; + goto qlt_exit; } apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops); @@ -7503,27 +7501,37 @@ qla2x00_module_init(void) qla2xxx_transport_vport_template = fc_attach_transport(&qla2xxx_transport_vport_functions); if (!qla2xxx_transport_vport_template) { - kmem_cache_destroy(srb_cachep); - qlt_exit(); - fc_release_transport(qla2xxx_transport_template); ql_log(ql_log_fatal, NULL, 0x0004, "fc_attach_transport vport failed...Failing load!.\n"); - return -ENODEV; + ret = -ENODEV; + goto unreg_chrdev; } ql_log(ql_log_info, NULL, 0x0005, "QLogic Fibre Channel HBA Driver: %s.\n", qla2x00_version_str); ret = pci_register_driver(&qla2xxx_pci_driver); if (ret) { - kmem_cache_destroy(srb_cachep); - qlt_exit(); - fc_release_transport(qla2xxx_transport_template); - fc_release_transport(qla2xxx_transport_vport_template); ql_log(ql_log_fatal, NULL, 0x0006, "pci_register_driver failed...ret=%d Failing load!.\n", ret); + goto release_vport_transport; } return ret; + +release_vport_transport: + fc_release_transport(qla2xxx_transport_vport_template); + +unreg_chrdev: + if (apidev_major >= 0) + unregister_chrdev(apidev_major, QLA2XXX_APIDEV); + fc_release_transport(qla2xxx_transport_template); + +qlt_exit: + qlt_exit(); + +destroy_cache: + kmem_cache_destroy(srb_cachep); + return ret; } /** From 338d9d761138febd48d6b72ed56c0cc14df6c5be Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 14 Apr 2019 01:35:43 +0000 Subject: [PATCH 42/42] qla2xxx: Unregister resources in the opposite order of the registration order Make sure that resources are only unregistered after the users of these resources have been unregistered. Only unregister the character device if registration of it succeeded. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8236 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 48c0ede90..3bb68d59c 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -7540,14 +7540,15 @@ destroy_cache: static void __exit qla2x00_module_exit(void) { - unregister_chrdev(apidev_major, QLA2XXX_APIDEV); pci_unregister_driver(&qla2xxx_pci_driver); qla2x00_release_firmware(); - kmem_cache_destroy(srb_cachep); - qlt_exit(); kmem_cache_destroy(ctx_cachep); - fc_release_transport(qla2xxx_transport_template); fc_release_transport(qla2xxx_transport_vport_template); + if (apidev_major >= 0) + unregister_chrdev(apidev_major, QLA2XXX_APIDEV); + fc_release_transport(qla2xxx_transport_template); + qlt_exit(); + kmem_cache_destroy(srb_cachep); } module_init(qla2x00_module_init);