From 98a11ac4cd6db08b1451d1233d7b637a25938833 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:06:52 +0000 Subject: [PATCH 01/49] qla2x00t-32gbit: Fix unbound NVME response length On certain cases when response length is less than 32, NVME response data is supplied inline in IOCB. This is indicated by some combination of state flags. There was an instance when a high, and incorrect, response length was indicated causing driver to overrun buffers. Fix this by checking and limiting the response payload length. Fixes: 7401bc18d1ee3 ("scsi: qla2xxx: Add FC-NVMe command handling") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200124045014.23554-1-hmadhani@marvell.com Signed-off-by: Arun Easi Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen [ commit 00fe717ee1ea3c2979db4f94b1533c57aed8dea9 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8784 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_dbg.c | 6 ------ qla2x00t-32gbit/qla_dbg.h | 6 ++++++ qla2x00t-32gbit/qla_isr.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/qla2x00t-32gbit/qla_dbg.c b/qla2x00t-32gbit/qla_dbg.c index e5500bba0..88a56e848 100644 --- a/qla2x00t-32gbit/qla_dbg.c +++ b/qla2x00t-32gbit/qla_dbg.c @@ -2519,12 +2519,6 @@ qla83xx_fw_dump_failed: /* Driver Debug Functions. */ /****************************************************************************/ -static inline int -ql_mask_match(uint level) -{ - return (level & ql2xextended_error_logging) == level; -} - /* * This function is for formatting and logging debug information. * It is to be used when vha is available. It formats the message diff --git a/qla2x00t-32gbit/qla_dbg.h b/qla2x00t-32gbit/qla_dbg.h index bb01b680c..433e95502 100644 --- a/qla2x00t-32gbit/qla_dbg.h +++ b/qla2x00t-32gbit/qla_dbg.h @@ -374,3 +374,9 @@ extern int qla24xx_dump_ram(struct qla_hw_data *, uint32_t, uint32_t *, extern void qla24xx_pause_risc(struct device_reg_24xx __iomem *, struct qla_hw_data *); extern int qla24xx_soft_reset(struct qla_hw_data *); + +static inline int +ql_mask_match(uint level) +{ + return (level & ql2xextended_error_logging) == level; +} diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 9bede48c8..cabeb5703 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -1959,6 +1959,18 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, inbuf = (uint32_t *)&sts->nvme_ersp_data; outbuf = (uint32_t *)fd->rspaddr; iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); + if (unlikely(iocb->u.nvme.rsp_pyld_len > + sizeof(struct nvme_fc_ersp_iu))) { + if (ql_mask_match(ql_dbg_io)) { + WARN_ONCE(1, "Unexpected response payload length %u.\n", + iocb->u.nvme.rsp_pyld_len); + ql_log(ql_log_warn, fcport->vha, 0x5100, + "Unexpected response payload length %u.\n", + iocb->u.nvme.rsp_pyld_len); + } + iocb->u.nvme.rsp_pyld_len = + sizeof(struct nvme_fc_ersp_iu); + } iter = iocb->u.nvme.rsp_pyld_len >> 2; for (; iter; iter--) *outbuf++ = swab32(*inbuf++); From 590c45cf3227e4668fedd0a32c123b0b2c847ad4 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:08:16 +0000 Subject: [PATCH 02/49] qla2x00t-32gbit: Check locking assumptions at runtime in qla2x00_abort_srb() Document the locking assumptions this function relies on and also verify these locking assumptions at runtime. Cc: Quinn Tran Cc: Daniel Wagner Link: https://lore.kernel.org/r/20200123042345.23886-2-bvanassche@acm.org Acked-by: Himanshu Madhani Reviewed-by: Martin Wilck Reviewed-by: Roman Bolshakov Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen [ commit 2494c2868d6e0eaaefd42f4fd2d260a8c35d240d upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8785 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 3b65ef45f..d184eac01 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -1737,6 +1737,8 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, bool ret_cmd; uint32_t ratov_j; + lockdep_assert_held(qp->qp_lock_ptr); + if (qla2x00_chip_is_down(vha)) { sp->done(sp, res); return; From 3b661a286d1e7dbe21209c6876ca9cc0da4cafcd Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:09:38 +0000 Subject: [PATCH 03/49] qla2x00t-32gbit: Add beacon LED config sysfs interface This patch provides an interface to do the following (using MBC 0x3B): - Displays (in hex) the LED config words for all three LEDs. - Programs the config words for one LED or for all three LEDs. The sysfs node defined is named beacon_config. First, to allow driver to gain LED control, do this: # echo 1 > /sys/class/scsi_host/host#/beacon Then, to display config words for all three LEDs do this: # cat /sys/class/scsi_host/host#/beacon_config To set config words for all three LEDs do this: # echo 3 xxxx yyyy zzzz > /sys/class/scsi_host/host#/beacon_config Or, to set config word for a specific single LED n do this: # echo n xxxx > /sys/class/scsi_host/host#/beacon_config where n is the LED number (0, 1, 2) Finally, to restore LED control back to firmware, do this: # echo 0 > /sys/class/scsi_host/host#/beacon Link: https://lore.kernel.org/r/20200212214436.25532-2-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 07553b1e83b46414caa693ba10d1a16487409b61 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8786 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 76 ++++++++++++++++++++++++++++++++++++++ qla2x00t-32gbit/qla_def.h | 1 + qla2x00t-32gbit/qla_gbl.h | 1 + qla2x00t-32gbit/qla_mbx.c | 57 ++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index d7e7043f9..d6a59c92c 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -1323,6 +1323,79 @@ qla2x00_beacon_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t +qla2x00_beacon_config_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; + uint16_t led[3] = { 0 }; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + if (ql26xx_led_config(vha, 0, led)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%#04hx %#04hx %#04hx\n", + led[0], led[1], led[2]); +} + +static ssize_t +qla2x00_beacon_config_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + uint16_t options = BIT_0; + uint16_t led[3] = { 0 }; + uint16_t word[4]; + int n; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + n = sscanf(buf, "%hx %hx %hx %hx", word+0, word+1, word+2, word+3); + if (n == 4) { + if (word[0] == 3) { + options |= BIT_3|BIT_2|BIT_1; + led[0] = word[1]; + led[1] = word[2]; + led[2] = word[3]; + goto write; + } + return -EINVAL; + } + + if (n == 2) { + /* check led index */ + if (word[0] == 0) { + options |= BIT_2; + led[0] = word[1]; + goto write; + } + if (word[0] == 1) { + options |= BIT_3; + led[1] = word[1]; + goto write; + } + if (word[0] == 2) { + options |= BIT_1; + led[2] = word[1]; + goto write; + } + return -EINVAL; + } + + return -EINVAL; + +write: + if (ql26xx_led_config(vha, options, led)) + return -EFAULT; + + return count; +} + static ssize_t qla2x00_optrom_bios_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2264,6 +2337,8 @@ static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, qla2x00_zio_timer_store); static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, qla2x00_beacon_store); +static DEVICE_ATTR(beacon_config, 0644, qla2x00_beacon_config_show, + qla2x00_beacon_config_store); static DEVICE_ATTR(optrom_bios_version, S_IRUGO, qla2x00_optrom_bios_version_show, NULL); static DEVICE_ATTR(optrom_efi_version, S_IRUGO, @@ -2327,6 +2402,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_zio, &dev_attr_zio_timer, &dev_attr_beacon, + &dev_attr_beacon_config, &dev_attr_optrom_bios_version, &dev_attr_optrom_efi_version, &dev_attr_optrom_fcode_version, diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index e336f03a9..efa3adc2b 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1160,6 +1160,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBC_GET_FIRMWARE_OPTION 0x28 /* Get Firmware Options. */ #define MBC_GET_MEM_OFFLOAD_CNTRL_STAT 0x34 /* Memory Offload ctrl/Stat*/ #define MBC_SET_FIRMWARE_OPTION 0x38 /* Set Firmware Options. */ +#define MBC_SET_GET_FC_LED_CONFIG 0x3b /* Set/Get FC LED config */ #define MBC_LOOP_PORT_BYPASS 0x40 /* Loop Port Bypass. */ #define MBC_LOOP_PORT_ENABLE 0x41 /* Loop Port Enable. */ #define MBC_GET_RESOURCE_COUNTS 0x42 /* Get Resource Counts. */ diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 83b03e037..d0c8307f8 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -848,6 +848,7 @@ extern void qla82xx_clear_pending_mbx(scsi_qla_host_t *); extern int qla82xx_read_temperature(scsi_qla_host_t *); extern int qla8044_read_temperature(scsi_qla_host_t *); extern int qla2x00_read_sfp_dev(struct scsi_qla_host *, char *, int); +extern int ql26xx_led_config(scsi_qla_host_t *, uint16_t, uint16_t *); /* BSG related functions */ #ifndef NEW_LIBFC_API diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 9e09964f5..e1916bec5 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -6688,3 +6688,60 @@ int qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr, return rval; } + +int +ql26xx_led_config(scsi_qla_host_t *vha, uint16_t options, uint16_t *led) +{ + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + int rval; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx, vha, 0x7070, "Entered %s (options=%x).\n", + __func__, options); + + mcp->mb[0] = MBC_SET_GET_FC_LED_CONFIG; + mcp->mb[1] = options; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + if (options & BIT_0) { + if (options & BIT_1) { + mcp->mb[2] = led[2]; + mcp->out_mb |= MBX_2; + } + if (options & BIT_2) { + mcp->mb[3] = led[0]; + mcp->out_mb |= MBX_3; + } + if (options & BIT_3) { + mcp->mb[4] = led[1]; + mcp->out_mb |= MBX_4; + } + } else { + mcp->in_mb |= MBX_4|MBX_3|MBX_2; + } + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval) { + ql_dbg(ql_dbg_mbx, vha, 0x7071, "Failed %s %x (mb=%x,%x)\n", + __func__, rval, mcp->mb[0], mcp->mb[1]); + return rval; + } + + if (options & BIT_0) { + ha->beacon_blink_led = 0; + ql_dbg(ql_dbg_mbx, vha, 0x7072, "Done %s\n", __func__); + } else { + led[2] = mcp->mb[2]; + led[0] = mcp->mb[3]; + led[1] = mcp->mb[4]; + ql_dbg(ql_dbg_mbx, vha, 0x7073, "Done %s (led=%x,%x,%x)\n", + __func__, led[0], led[1], led[2]); + } + + return rval; +} From bdb841a7130d08e69d1a5925c1807aeb10508eb5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:10:16 +0000 Subject: [PATCH 04/49] qla2x00t-32gbit: Move free of fcport out of interrupt context This patch moves freeing of fcport out of interrupt context. Link: https://lore.kernel.org/r/20200212214436.25532-3-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 054f4382417098b4d0028f8145fa214d448792d7 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8787 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_bsg.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 14b3df646..a070c717f 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -32,6 +32,14 @@ static inline void bsg_job_done_backport(struct fc_bsg_job *job, int result, #define bsg_job_done bsg_job_done_backport #endif +static void qla2xxx_free_fcport_work(struct work_struct *work) +{ + struct fc_port *fcport = container_of(work, typeof(*fcport), + free_work); + + qla2x00_free_fcport(fcport); +} + /* BSG support for ELS/CT pass through */ void qla2x00_bsg_job_done(srb_t *sp, int res) { @@ -82,8 +90,10 @@ void qla2x00_bsg_sp_free(srb_t *sp) if (sp->type == SRB_CT_CMD || sp->type == SRB_FXIOCB_BCMD || - sp->type == SRB_ELS_CMD_HST) - qla2x00_free_fcport(sp->fcport); + sp->type == SRB_ELS_CMD_HST) { + INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work); + queue_work(ha->wq, &sp->fcport->free_work); + } qla2x00_rel_sp(sp); } From 75f9dada7a41d5272b6f07318359ddd5c89e0a60 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:10:56 +0000 Subject: [PATCH 05/49] qla2x00t-32gbit: Add sysfs node for D-Port Diagnostics AEN data This patch adds sysfs node to show D-Port diag data. Link: https://lore.kernel.org/r/20200212214436.25532-4-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit e6ad2b79b82f41a51f90c95686c39cd8be4a35f3 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8788 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 21 +++++++++++++++++++++ qla2x00t-32gbit/qla_def.h | 1 + qla2x00t-32gbit/qla_isr.c | 1 + 3 files changed, 23 insertions(+) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index d6a59c92c..401b5ee1f 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -2323,6 +2323,26 @@ qla2x00_port_no_show(struct device *dev, struct device_attribute *attr, return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no); } +static ssize_t +qla2x00_dport_diagnostics_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + if (!*vha->dport_data) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", + vha->dport_data[0], vha->dport_data[1], + vha->dport_data[2], vha->dport_data[3]); +} +static DEVICE_ATTR(dport_diagnostics, 0444, + qla2x00_dport_diagnostics_show, NULL); + 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); @@ -2431,6 +2451,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_port_speed, &dev_attr_port_no, &dev_attr_fw_attr, + &dev_attr_dport_diagnostics, NULL, /* reserve for qlini_mode */ NULL, /* reserve for ql2xiniexchg */ NULL, /* reserve for ql2xexchoffld */ diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index efa3adc2b..68cc6ee8b 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4568,6 +4568,7 @@ typedef struct scsi_qla_host { uint8_t n2n_node_name[WWN_SIZE]; uint8_t n2n_port_name[WWN_SIZE]; uint16_t n2n_id; + __le16 dport_data[4]; struct list_head gpnid_list; struct fab_scan scan; diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index cabeb5703..7d27ac4df 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -1266,6 +1266,7 @@ global_port_update: ql_dbg(ql_dbg_async, vha, 0x5052, "D-Port Diagnostics: %04x %04x %04x %04x\n", mb[0], mb[1], mb[2], mb[3]); + memcpy(vha->dport_data, mb, sizeof(vha->dport_data)); if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { static char *results[] = { "start", "done(pass)", "done(error)", "undefined" }; From 3fe1f170503dd5b1a0c470a787f16482f2ec54b9 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:11:28 +0000 Subject: [PATCH 06/49] qla2x00t-32gbit: Add endianizer macro calls to fc host stats This patch fixes endian warning for fc_host_stats. Link: https://lore.kernel.org/r/20200212214436.25532-6-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 974c086045446a7cdad5de26ff691d9ac82a24a6 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8789 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_attr.c | 36 +++++++++++--------- qla2x00t-32gbit/qla_def.h | 69 ++++++++++++++++++-------------------- 2 files changed, 54 insertions(+), 51 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 401b5ee1f..97cabd7e0 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -2745,22 +2745,28 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) if (rval != QLA_SUCCESS) goto done_free; - p->link_failure_count = stats->link_fail_cnt; - p->loss_of_sync_count = stats->loss_sync_cnt; - p->loss_of_signal_count = stats->loss_sig_cnt; - p->prim_seq_protocol_err_count = stats->prim_seq_err_cnt; - p->invalid_tx_word_count = stats->inval_xmit_word_cnt; - p->invalid_crc_count = stats->inval_crc_cnt; + p->link_failure_count = le32_to_cpu(stats->link_fail_cnt); + p->loss_of_sync_count = le32_to_cpu(stats->loss_sync_cnt); + p->loss_of_signal_count = le32_to_cpu(stats->loss_sig_cnt); + p->prim_seq_protocol_err_count = le32_to_cpu(stats->prim_seq_err_cnt); + p->invalid_tx_word_count = le32_to_cpu(stats->inval_xmit_word_cnt); + p->invalid_crc_count = le32_to_cpu(stats->inval_crc_cnt); if (IS_FWI2_CAPABLE(ha)) { - p->lip_count = stats->lip_cnt; - p->tx_frames = stats->tx_frames; - p->rx_frames = stats->rx_frames; - p->dumped_frames = stats->discarded_frames; - p->nos_count = stats->nos_rcvd; + p->lip_count = le32_to_cpu(stats->lip_cnt); + p->tx_frames = le32_to_cpu(stats->tx_frames); + p->rx_frames = le32_to_cpu(stats->rx_frames); + p->dumped_frames = le32_to_cpu(stats->discarded_frames); + p->nos_count = le32_to_cpu(stats->nos_rcvd); p->error_frames = - stats->dropped_frames + stats->discarded_frames; - p->rx_words = vha->qla_stats.input_bytes; - p->tx_words = vha->qla_stats.output_bytes; + le32_to_cpu(stats->dropped_frames) + + le32_to_cpu(stats->discarded_frames); + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + p->rx_words = le64_to_cpu(stats->fpm_recv_word_cnt); + p->tx_words = le64_to_cpu(stats->fpm_xmit_word_cnt); + } else { + p->rx_words = vha->qla_stats.input_bytes; + p->tx_words = vha->qla_stats.output_bytes; + } } p->fcp_control_requests = vha->qla_stats.control_requests; p->fcp_input_requests = vha->qla_stats.input_requests; @@ -2768,7 +2774,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) p->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20; p->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20; p->seconds_since_last_reset = - get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; + get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; do_div(p->seconds_since_last_reset, HZ); done_free: diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 68cc6ee8b..4be8b0778 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1501,47 +1501,44 @@ typedef struct { #define GLSO_USE_DID BIT_3 struct link_statistics { - uint32_t link_fail_cnt; - uint32_t loss_sync_cnt; - uint32_t loss_sig_cnt; - uint32_t prim_seq_err_cnt; - uint32_t inval_xmit_word_cnt; - uint32_t inval_crc_cnt; - uint32_t lip_cnt; - uint32_t link_up_cnt; - uint32_t link_down_loop_init_tmo; - uint32_t link_down_los; - uint32_t link_down_loss_rcv_clk; + __le32 link_fail_cnt; + __le32 loss_sync_cnt; + __le32 loss_sig_cnt; + __le32 prim_seq_err_cnt; + __le32 inval_xmit_word_cnt; + __le32 inval_crc_cnt; + __le32 lip_cnt; + __le32 link_up_cnt; + __le32 link_down_loop_init_tmo; + __le32 link_down_los; + __le32 link_down_loss_rcv_clk; uint32_t reserved0[5]; - uint32_t port_cfg_chg; + __le32 port_cfg_chg; uint32_t reserved1[11]; - uint32_t rsp_q_full; - uint32_t atio_q_full; - uint32_t drop_ae; - uint32_t els_proto_err; - uint32_t reserved2; - uint32_t tx_frames; - uint32_t rx_frames; - uint32_t discarded_frames; - uint32_t dropped_frames; + __le32 rsp_q_full; + __le32 atio_q_full; + __le32 drop_ae; + __le32 els_proto_err; + __le32 reserved2; + __le32 tx_frames; + __le32 rx_frames; + __le32 discarded_frames; + __le32 dropped_frames; uint32_t reserved3; - uint32_t nos_rcvd; + __le32 nos_rcvd; uint32_t reserved4[4]; - uint32_t tx_prjt; - uint32_t rcv_exfail; - uint32_t rcv_abts; - uint32_t seq_frm_miss; - uint32_t corr_err; - uint32_t mb_rqst; - uint32_t nport_full; - uint32_t eofa; + __le32 tx_prjt; + __le32 rcv_exfail; + __le32 rcv_abts; + __le32 seq_frm_miss; + __le32 corr_err; + __le32 mb_rqst; + __le32 nport_full; + __le32 eofa; uint32_t reserved5; - uint32_t fpm_recv_word_cnt_lo; - uint32_t fpm_recv_word_cnt_hi; - uint32_t fpm_disc_word_cnt_lo; - uint32_t fpm_disc_word_cnt_hi; - uint32_t fpm_xmit_word_cnt_lo; - uint32_t fpm_xmit_word_cnt_hi; + __le64 fpm_recv_word_cnt; + __le64 fpm_disc_word_cnt; + __le64 fpm_xmit_word_cnt; uint32_t reserved6[70]; }; From 91211187637933f3f8bbc15f1f4a39ce28df1e5f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:12:12 +0000 Subject: [PATCH 07/49] qla2x00t-32gbit: Add changes in preparation for vendor extended FDMI/RDP This patch prepares code for implementing Vendor specific extended FDMI/RDP commands. It also addes support for MBC_GET_PORT_DATABASE and MBC_GET_RNID_PARAMS commands. Link: https://lore.kernel.org/r/20200212214436.25532-7-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 818c7f87a177781bc155a2bfa39066c89c5a6cdc upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8790 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 3 + qla2x00t-32gbit/qla_fw.h | 4 ++ qla2x00t-32gbit/qla_gbl.h | 12 +++- qla2x00t-32gbit/qla_gs.c | 15 +++-- qla2x00t-32gbit/qla_init.c | 28 ++++++--- qla2x00t-32gbit/qla_mbx.c | 121 ++++++++++++++++++++++++++++++++----- qla2x00t-32gbit/qla_mid.c | 3 + qla2x00t-32gbit/qla_os.c | 4 +- 8 files changed, 155 insertions(+), 35 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 4be8b0778..654261be8 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1287,7 +1287,9 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBX_1 BIT_1 #define MBX_0 BIT_0 +#define RNID_TYPE_ELS_CMD 0x5 #define RNID_TYPE_PORT_LOGIN 0x7 +#define RNID_BUFFER_CREDITS 0x8 #define RNID_TYPE_SET_VERSION 0x9 #define RNID_TYPE_ASIC_TEMP 0xC @@ -4486,6 +4488,7 @@ typedef struct scsi_qla_host { uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; uint8_t fabric_node_name[WWN_SIZE]; + uint8_t fabric_port_name[WWN_SIZE]; struct nvme_fc_local_port *nvme_local_port; struct completion nvme_del_done; diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index b4cc6de58..f63afde32 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -43,6 +43,9 @@ #define PDO_FORCE_ADISC BIT_1 #define PDO_FORCE_PLOGI BIT_0 +struct buffer_credit_24xx { + u32 parameter[28]; +}; #define PORT_DATABASE_24XX_SIZE 64 struct port_database_24xx { @@ -1894,6 +1897,7 @@ struct nvram_81xx { * BIT 6-15 = Unused */ uint16_t enhanced_features; + uint16_t reserved_24[4]; /* Offset 416. */ diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index d0c8307f8..f6d1b4525 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -32,6 +32,8 @@ extern int qla81xx_nvram_config(struct scsi_qla_host *); extern void qla2x00_update_fw_options(struct scsi_qla_host *); extern void qla24xx_update_fw_options(scsi_qla_host_t *); extern void qla81xx_update_fw_options(scsi_qla_host_t *); +extern void qla83xx_update_fw_options(scsi_qla_host_t *); + extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *); @@ -142,6 +144,7 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; +extern int ql2xsmartsan; extern int ql2xallocfwdump; extern int ql2xextended_error_logging; extern int ql2xiidmaenable; @@ -357,6 +360,9 @@ qla2x00_init_firmware(scsi_qla_host_t *, uint16_t); extern int qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t); +extern int +qla24xx_get_port_database(scsi_qla_host_t *, u16, struct port_database_24xx *); + extern int qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *); @@ -455,6 +461,10 @@ qla82xx_set_driver_version(scsi_qla_host_t *, char *); extern int qla25xx_set_driver_version(scsi_qla_host_t *, char *); +extern int +qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, + dma_addr_t); + extern int qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *, uint16_t, uint16_t, uint16_t, uint16_t); @@ -660,7 +670,7 @@ extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern int qla2x00_fdmi_register(scsi_qla_host_t *); extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *); extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *); -extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); +extern size_t qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *, struct ct_sns_rsp *, const char *); extern void qla2x00_async_iocb_timeout(void *data); diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index aaa4a5bbf..c01eb87c7 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -844,19 +844,18 @@ done: return rval; } -void +size_t qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size) { struct qla_hw_data *ha = vha->hw; if (IS_QLAFX00(ha)) - snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number, - ha->mr.fw_version, qla2x00_version_str); - else - snprintf(snn, size, - "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number, - ha->fw_major_version, ha->fw_minor_version, - ha->fw_subminor_version, qla2x00_version_str); + return scnprintf(snn, size, "%s FW:v%s DVR:v%s", + ha->model_number, ha->mr.fw_version, qla2x00_version_str); + + return scnprintf(snn, size, "%s FW:v%d.%02d.%02d DVR:v%s", + ha->model_number, ha->fw_major_version, ha->fw_minor_version, + ha->fw_subminor_version, qla2x00_version_str); } /** diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index a5076f43e..6b88db898 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -5542,24 +5542,22 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) } vha->device_flags |= SWITCH_FOUND; + rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_port_name, 0); + if (rval != QLA_SUCCESS) + ql_dbg(ql_dbg_disc, vha, 0x20ff, + "Failed to get Fabric Port Name\n"); if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) { rval = qla2x00_send_change_request(vha, 0x3, 0); if (rval != QLA_SUCCESS) ql_log(ql_log_warn, vha, 0x121, - "Failed to enable receiving of RSCN requests: 0x%x.\n", - rval); + "Failed to enable receiving of RSCN requests: 0x%x.\n", + rval); } - do { qla2x00_mgmt_svr_login(vha); - /* FDMI support. */ - if (ql2xfdmienable && - test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) - qla2x00_fdmi_register(vha); - /* Ensure we are logged into the SNS. */ loop_id = NPH_SNS_LID(ha); rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff, @@ -5571,6 +5569,12 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); return rval; } + + /* FDMI support. */ + if (ql2xfdmienable && + test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) + qla2x00_fdmi_register(vha); + if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) { if (qla2x00_rft_id(vha)) { /* EMPTY */ @@ -8664,6 +8668,14 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) return status; } +void +qla83xx_update_fw_options(scsi_qla_host_t *vha) +{ + struct qla_hw_data *ha = vha->hw; + + qla2x00_set_fw_options(vha, ha->fw_options); +} + void qla81xx_update_fw_options(scsi_qla_host_t *vha) { diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index e1916bec5..f1c2a9ea5 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -643,7 +643,6 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, return rval; } -#define EXTENDED_BB_CREDITS BIT_0 #define NVME_ENABLE_FLAG BIT_3 static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) { @@ -1410,12 +1409,12 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mcp->mb[0] = MBC_IOCB_COMMAND_A64; mcp->mb[1] = 0; - mcp->mb[2] = MSW(phys_addr); - mcp->mb[3] = LSW(phys_addr); + mcp->mb[2] = MSW(LSD(phys_addr)); + mcp->mb[3] = LSW(LSD(phys_addr)); mcp->mb[6] = MSW(MSD(phys_addr)); mcp->mb[7] = LSW(MSD(phys_addr)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_2|MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = tov; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -1424,13 +1423,14 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval); } else { - sts_entry_t *sts_entry = (sts_entry_t *) buffer; + sts_entry_t *sts_entry = buffer; /* Mask reserved bits. */ sts_entry->entry_status &= IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a, - "Done %s.\n", __func__); + "Done %s (status=%x).\n", __func__, + sts_entry->entry_status); } return rval; @@ -2045,6 +2045,57 @@ gpd_error_out: return rval; } +int +qla24xx_get_port_database(scsi_qla_host_t *vha, u16 nport_handle, + struct port_database_24xx *pdb) +{ + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + dma_addr_t pdb_dma; + int rval; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1115, + "Entered %s.\n", __func__); + + memset(pdb, 0, sizeof(*pdb)); + + pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb, + sizeof(*pdb), DMA_FROM_DEVICE); + if (!pdb_dma) { + ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n"); + return QLA_MEMORY_ALLOC_FAILED; + } + + mcp->mb[0] = MBC_GET_PORT_DATABASE; + mcp->mb[1] = nport_handle; + mcp->mb[2] = MSW(LSD(pdb_dma)); + mcp->mb[3] = LSW(LSD(pdb_dma)); + mcp->mb[6] = MSW(MSD(pdb_dma)); + mcp->mb[7] = LSW(MSD(pdb_dma)); + mcp->mb[9] = 0; + mcp->mb[10] = 0; + mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = sizeof(*pdb); + mcp->flags = MBX_DMA_IN; + mcp->tov = vha->hw->login_timeout * 2; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x111a, + "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, 0x111b, + "Done %s.\n", __func__); + } + + dma_unmap_single(&vha->hw->pdev->dev, pdb_dma, + sizeof(*pdb), DMA_FROM_DEVICE); + + return rval; +} + /* * qla2x00_get_firmware_state * Get adapter firmware state. @@ -3060,18 +3111,19 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - uint32_t *iter, dwords; + uint32_t *iter = (void *)stats; + ushort dwords = sizeof(*stats)/sizeof(*iter); ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, "Entered %s.\n", __func__); memset(&mc, 0, sizeof(mc)); mc.mb[0] = MBC_GET_LINK_PRIV_STATS; - mc.mb[2] = MSW(stats_dma); - mc.mb[3] = LSW(stats_dma); + mc.mb[2] = MSW(LSD(stats_dma)); + mc.mb[3] = LSW(LSD(stats_dma)); mc.mb[6] = MSW(MSD(stats_dma)); mc.mb[7] = LSW(MSD(stats_dma)); - mc.mb[8] = sizeof(struct link_statistics) / 4; + mc.mb[8] = dwords; mc.mb[9] = cpu_to_le16(vha->vp_idx); mc.mb[10] = cpu_to_le16(options); @@ -3086,8 +3138,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a, "Done %s.\n", __func__); /* Re-endianize - firmware data is le32. */ - dwords = sizeof(struct link_statistics) / 4; - iter = &stats->link_fail_cnt; for ( ; dwords--; iter++) le32_to_cpus(iter); } @@ -4827,6 +4877,45 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, return rval; } +int +qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, + dma_addr_t bbc_dma) +{ + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + int rval; + + if (!IS_FWI2_CAPABLE(vha->hw)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118e, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_GET_RNID_PARAMS; + mcp->mb[1] = RNID_BUFFER_CREDITS << 8; + mcp->mb[2] = MSW(LSD(bbc_dma)); + mcp->mb[3] = LSW(LSD(bbc_dma)); + mcp->mb[6] = MSW(MSD(bbc_dma)); + mcp->mb[7] = LSW(MSD(bbc_dma)); + mcp->mb[8] = sizeof(*bbc) / sizeof(*bbc->parameter); + mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = sizeof(*bbc); + mcp->flags = MBX_DMA_IN; + mcp->tov = MBX_TOV_SECONDS; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x118f, + "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1190, + "Done %s.\n", __func__); + } + + return rval; +} + static int qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) { @@ -4880,8 +4969,8 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mcp->mb[0] = MBC_READ_SFP; mcp->mb[1] = dev; - mcp->mb[2] = MSW(sfp_dma); - mcp->mb[3] = LSW(sfp_dma); + mcp->mb[2] = MSW(LSD(sfp_dma)); + mcp->mb[3] = LSW(LSD(sfp_dma)); mcp->mb[6] = MSW(MSD(sfp_dma)); mcp->mb[7] = LSW(MSD(sfp_dma)); mcp->mb[8] = len; @@ -4934,8 +5023,8 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mcp->mb[0] = MBC_WRITE_SFP; mcp->mb[1] = dev; - mcp->mb[2] = MSW(sfp_dma); - mcp->mb[3] = LSW(sfp_dma); + mcp->mb[2] = MSW(LSD(sfp_dma)); + mcp->mb[3] = LSW(LSD(sfp_dma)); mcp->mb[6] = MSW(MSD(sfp_dma)); mcp->mb[7] = LSW(MSD(sfp_dma)); mcp->mb[8] = len; diff --git a/qla2x00t-32gbit/qla_mid.c b/qla2x00t-32gbit/qla_mid.c index 8ae639d08..d211f803c 100644 --- a/qla2x00t-32gbit/qla_mid.c +++ b/qla2x00t-32gbit/qla_mid.c @@ -509,6 +509,9 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) vha->mgmt_svr_loop_id = qla2x00_reserve_mgmt_server_loop_id(vha); vha->dpc_flags = 0L; + ha->dpc_active = 0; + set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); + set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); /* * To fix the issue of processing a parent's RSCN for the vport before diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index d184eac01..bbf860f13 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -2328,7 +2328,7 @@ static struct isp_operations qla81xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla83xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, @@ -2445,7 +2445,7 @@ static struct isp_operations qla83xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla83xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, From b88921cc3cf36e16572a439f07546c301531614a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:12:42 +0000 Subject: [PATCH 08/49] qla2x00t-32gbit: Add vendor extended RDP additions and amendments This patch adds RDP command support in the driver. With the help of new ql2xsmartsan parameter, driver will use PUREX IOCB mode to send RDP command to switch and will be able to receive various diagnostic data. Link: https://lore.kernel.org/r/20200212214436.25532-8-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit d83a80ee57f0cb38baccc75e96bc56ac47d300b3 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8791 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 135 +++++++++ qla2x00t-32gbit/qla_fw.h | 44 +++ qla2x00t-32gbit/qla_gbl.h | 3 + qla2x00t-32gbit/qla_init.c | 15 +- qla2x00t-32gbit/qla_isr.c | 10 + qla2x00t-32gbit/qla_mbx.c | 58 ++++ qla2x00t-32gbit/qla_os.c | 546 ++++++++++++++++++++++++++++++++++++- 7 files changed, 807 insertions(+), 4 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 654261be8..bf12ab26b 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1293,6 +1293,9 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define RNID_TYPE_SET_VERSION 0x9 #define RNID_TYPE_ASIC_TEMP 0xC +#define ELS_CMD_MAP_SIZE 32 +#define ELS_COMMAND_RDP 0x18 + /* * Firmware state codes from get firmware state mailbox command */ @@ -3589,6 +3592,133 @@ struct qlfc_fw { uint32_t len; }; +struct rdp_req_payload { + uint32_t els_request; + uint32_t desc_list_len; + + /* NPIV descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t reserved; + uint8_t nport_id[3]; + } npiv_desc; +}; + +struct rdp_rsp_payload { + struct { + uint32_t cmd; + uint32_t len; + } hdr; + + /* LS Request Info descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t req_payload_word_0; + } ls_req_info_desc; + + /* LS Request Info descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t req_payload_word_0; + } ls_req_info_desc2; + + /* SFP diagnostic param descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t temperature; + uint16_t vcc; + uint16_t tx_bias; + uint16_t tx_power; + uint16_t rx_power; + uint16_t sfp_flags; + } sfp_diag_desc; + + /* Port Speed Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t speed_capab; + uint16_t operating_speed; + } port_speed_desc; + + /* Link Error Status Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t link_fail_cnt; + uint32_t loss_sync_cnt; + uint32_t loss_sig_cnt; + uint32_t prim_seq_err_cnt; + uint32_t inval_xmit_word_cnt; + uint32_t inval_crc_cnt; + uint8_t pn_port_phy_type; + uint8_t reserved[3]; + } ls_err_desc; + + /* Port name description with diag param */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t WWNN[WWN_SIZE]; + uint8_t WWPN[WWN_SIZE]; + } port_name_diag_desc; + + /* Port Name desc for Direct attached Fx_Port or Nx_Port */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t WWNN[WWN_SIZE]; + uint8_t WWPN[WWN_SIZE]; + } port_name_direct_desc; + + /* Buffer Credit descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t fcport_b2b; + uint32_t attached_fcport_b2b; + uint32_t fcport_rtt; + } buffer_credit_desc; + + /* Optical Element Data Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t high_alarm; + uint16_t low_alarm; + uint16_t high_warn; + uint16_t low_warn; + uint32_t element_flags; + } optical_elmt_desc[5]; + + /* Optical Product Data Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t vendor_name[16]; + uint8_t part_number[16]; + uint8_t serial_number[16]; + uint8_t revision[4]; + uint8_t date[8]; + } optical_prod_desc; +}; + +#define RDP_DESC_LEN(obj) \ + (sizeof(obj) - sizeof((obj).desc_tag) - sizeof((obj).desc_len)) + +#define RDP_PORT_SPEED_1GB BIT_15 +#define RDP_PORT_SPEED_2GB BIT_14 +#define RDP_PORT_SPEED_4GB BIT_13 +#define RDP_PORT_SPEED_10GB BIT_12 +#define RDP_PORT_SPEED_8GB BIT_11 +#define RDP_PORT_SPEED_16GB BIT_10 +#define RDP_PORT_SPEED_32GB BIT_9 +#define RDP_PORT_SPEED_UNKNOWN BIT_0 + struct scsi_qlt_host { void *target_lport_ptr; struct mutex tgt_mutex; @@ -3992,6 +4122,8 @@ struct qla_hw_data { #define SFP_DEV_SIZE 512 #define SFP_BLOCK_SIZE 64 +#define SFP_RTDI_LEN SFP_BLOCK_SIZE + void *sfp_data; dma_addr_t sfp_data_dma; @@ -4451,6 +4583,8 @@ typedef struct scsi_qla_host { #define ISP_ABORT_TO_ROM 33 #define VPORT_DELETE 34 +#define PROCESS_PUREX_IOCB 63 + unsigned long pci_flags; #define PFLG_DISCONNECTED 0 /* PCI device removed */ #define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */ @@ -4559,6 +4693,7 @@ typedef struct scsi_qla_host { uint16_t ql2xexchoffld; uint16_t ql2xiniexchg; + void *purex_data; struct name_list_extended gnl; /* Count of active session/fcport */ int fcport_count; diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index f63afde32..056040f19 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -735,6 +735,50 @@ struct ct_entry_24xx { struct dsd64 dsd[2]; }; +/* + * ISP queue - PUREX IOCB entry structure definition + */ +#define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */ +typedef struct purex_entry_24xx { + uint8_t entry_type; /* Entry type. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + + uint16_t reserved1; + uint8_t vp_idx; + uint8_t reserved2; + + uint16_t status_flags; + uint16_t nport_handle; + + uint16_t frame_size; + uint16_t trunc_frame_size; + + uint32_t rx_xchg_addr; + + uint8_t d_id[3]; + uint8_t r_ctl; + + uint8_t s_id[3]; + uint8_t cs_ctl; + + uint8_t f_ctl[3]; + uint8_t type; + + uint16_t seq_cnt; + uint8_t df_ctl; + uint8_t seq_id; + + uint16_t rx_id; + uint16_t ox_id; + uint32_t param; + + uint8_t els_frame_payload[20]; +} purex_entry_24xx_t; + +#define PUREX_ENTRY_SIZE (sizeof(purex_entry_24xx_t)) + /* * ISP queue - ELS Pass-Through entry structure definition. */ diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index f6d1b4525..5be12df32 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -461,6 +461,9 @@ qla82xx_set_driver_version(scsi_qla_host_t *, char *); extern int qla25xx_set_driver_version(scsi_qla_host_t *, char *); +extern int +qla25xx_set_els_cmds_supported(scsi_qla_host_t *); + extern int qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, dma_addr_t); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 6b88db898..2063f2876 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3708,6 +3708,10 @@ enable_82xx_npiv: "ISP Firmware failed checksum.\n"); goto failed; } + + /* Enable PUREX PASSTHRU */ + if (ql2xsmartsan) + qla25xx_set_els_cmds_supported(vha); } else goto failed; @@ -3929,7 +3933,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) /* Update Serial Link options. */ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) - return; + goto enable_purex; rval = qla2x00_set_serdes_params(vha, le16_to_cpu(ha->fw_seriallink_options24[1]), @@ -3939,6 +3943,12 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ql_log(ql_log_warn, vha, 0x0104, "Unable to update Serial Link options (%x).\n", rval); } + +enable_purex: + if (ql2xsmartsan) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + + qla2x00_set_fw_options(vha, ha->fw_options); } void @@ -8673,6 +8683,9 @@ qla83xx_update_fw_options(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + if (ql2xsmartsan) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + qla2x00_set_fw_options(vha, ha->fw_options); } diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 7d27ac4df..f87853fa8 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -43,6 +43,13 @@ const char *const port_state_str[] = { "ONLINE" }; +static void qla24xx_purex_iocb(scsi_qla_host_t *vha, struct req_que *req, + struct sts_entry_24xx *pkt) +{ + memcpy(vha->purex_data, pkt, PUREX_ENTRY_SIZE); + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); +} + /** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: interrupt number @@ -3152,6 +3159,9 @@ process_err: qla_ctrlvp_completed(vha, rsp->req, (struct vp_ctrl_entry_24xx *)pkt); break; + case PUREX_IOCB_TYPE: + qla24xx_purex_iocb(vha, rsp->req, pkt); + break; default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index f1c2a9ea5..2d029616e 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -4877,6 +4877,64 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, return rval; } +int +qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint8_t *els_cmd_map; + dma_addr_t els_cmd_map_dma; + uint cmd_opcode = ELS_COMMAND_RDP; + uint index = cmd_opcode / 8; + uint bit = cmd_opcode % 8; + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha)) + return QLA_SUCCESS; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197, + "Entered %s.\n", __func__); + + els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE, + &els_cmd_map_dma, GFP_KERNEL); + if (!els_cmd_map) { + ql_log(ql_log_warn, vha, 0x7101, + "Failed to allocate RDP els command param.\n"); + return QLA_MEMORY_ALLOC_FAILED; + } + + memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE); + + els_cmd_map[index] |= 1 << bit; + + mcp->mb[0] = MBC_SET_RNID_PARAMS; + mcp->mb[1] = RNID_TYPE_ELS_CMD << 8; + mcp->mb[2] = MSW(LSD(els_cmd_map_dma)); + mcp->mb[3] = LSW(LSD(els_cmd_map_dma)); + mcp->mb[6] = MSW(MSD(els_cmd_map_dma)); + mcp->mb[7] = LSW(MSD(els_cmd_map_dma)); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = MBX_DMA_OUT; + mcp->buf_size = ELS_CMD_MAP_SIZE; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x118d, + "Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c, + "Done %s.\n", __func__); + } + + dma_free_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + els_cmd_map, els_cmd_map_dma); + + return rval; +} + int qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, dma_addr_t bbc_dma) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index bbf860f13..3923e3a56 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -324,6 +324,15 @@ MODULE_PARM_DESC(ql2xdifbundlinginternalbuffers, "0 (Default). Based on check.\n" "1 Force using internal buffers\n"); +int ql2xsmartsan; +module_param(ql2xsmartsan, int, 0444); +module_param_named(smartsan, ql2xsmartsan, int, 0444); +MODULE_PARM_DESC(ql2xsmartsan, + "Send SmartSAN Management Attributes for FDMI Registration." + " Default is 0 - No SmartSAN registration," + " 1 - Register SmartSAN Management Attributes."); + + static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) @@ -3312,6 +3321,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto probe_failed; } + base_vha->purex_data = kzalloc(PUREX_ENTRY_SIZE, GFP_KERNEL); + if (!base_vha->purex_data) + ql_log(ql_log_warn, base_vha, 0x7118, + "Failed to allocate memory for PUREX data\n"); + if (IS_QLAFX00(ha)) host->can_queue = QLAFX00_MAX_CANQUEUE; else @@ -3494,6 +3508,7 @@ skip_dpc: return 0; probe_failed: + kfree(base_vha->purex_data); if (base_vha->gnl.l) { dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); @@ -3810,6 +3825,8 @@ qla2x00_remove_one(struct pci_dev *pdev) qla84xx_put_chip(base_vha); + kfree(base_vha->purex_data); + /* Disable timer */ if (base_vha->timer_active) qla2x00_stop_timer(base_vha); @@ -5780,6 +5797,518 @@ retry_lock: return; } +static uint +qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) +{ + if (IS_CNA_CAPABLE(ha)) + return RDP_PORT_SPEED_10GB; + + if (IS_QLA27XX(ha)) { + if (FW_ABILITY_MAX_SPEED(ha) == FW_ABILITY_MAX_SPEED_32G) + return RDP_PORT_SPEED_32GB|RDP_PORT_SPEED_16GB| + RDP_PORT_SPEED_8GB; + + return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| + RDP_PORT_SPEED_4GB; + } + + if (IS_QLA2031(ha)) + return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| + RDP_PORT_SPEED_4GB; + + if (IS_QLA25XX(ha)) + return RDP_PORT_SPEED_8GB|RDP_PORT_SPEED_4GB| + RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; + + if (IS_QLA24XX_TYPE(ha)) + return RDP_PORT_SPEED_4GB|RDP_PORT_SPEED_2GB| + RDP_PORT_SPEED_1GB; + + if (IS_QLA23XX(ha)) + return RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; + + return RDP_PORT_SPEED_1GB; +} + +static uint +qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) +{ + switch (ha->link_data_rate) { + case PORT_SPEED_1GB: + return RDP_PORT_SPEED_1GB; + + case PORT_SPEED_2GB: + return RDP_PORT_SPEED_2GB; + + case PORT_SPEED_4GB: + return RDP_PORT_SPEED_4GB; + + case PORT_SPEED_8GB: + return RDP_PORT_SPEED_8GB; + + case PORT_SPEED_10GB: + return RDP_PORT_SPEED_10GB; + + case PORT_SPEED_16GB: + return RDP_PORT_SPEED_16GB; + + case PORT_SPEED_32GB: + return RDP_PORT_SPEED_32GB; + + default: + return RDP_PORT_SPEED_UNKNOWN; + } +} + +/* + * Function Name: qla24xx_process_purex_iocb + * + * Description: + * Prepare a RDP response and send to Fabric switch + * + * PARAMETERS: + * vha: SCSI qla host + * purex: RDP request received by HBA + */ +static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) +{ + struct qla_hw_data *ha = vha->hw; + struct purex_entry_24xx *purex = pkt; + struct port_database_24xx *pdb = NULL; + dma_addr_t rsp_els_dma; + dma_addr_t rsp_payload_dma; + dma_addr_t stat_dma; + dma_addr_t bbc_dma; + dma_addr_t sfp_dma; + struct els_entry_24xx *rsp_els = NULL; + struct rdp_rsp_payload *rsp_payload = NULL; + struct link_statistics *stat = NULL; + struct buffer_credit_24xx *bbc = NULL; + uint8_t *sfp = NULL; + uint16_t sfp_flags = 0; + int rval = -ENOMEM; + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, + "%s: Enter\n", __func__); + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0181, + "-------- ELS REQ -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, + (void *)purex, sizeof(*purex)); + + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), + &rsp_els_dma, GFP_KERNEL); + if (!rsp_els) + goto dealloc; + + rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), + &rsp_payload_dma, GFP_KERNEL); + if (!rsp_payload) + goto dealloc; + + sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, + &sfp_dma, GFP_KERNEL); + + stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat), + &stat_dma, GFP_KERNEL); + + bbc = dma_alloc_coherent(&ha->pdev->dev, sizeof(*bbc), + &bbc_dma, GFP_KERNEL); + + /* Prepare Response IOCB */ + memset(rsp_els, 0, sizeof(*rsp_els)); + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; + rsp_els->sys_define = 0; + rsp_els->entry_status = 0; + rsp_els->handle = 0; + rsp_els->nport_handle = purex->nport_handle; + rsp_els->tx_dsd_count = 1; + rsp_els->vp_index = purex->vp_idx; + rsp_els->sof_type = EST_SOFI3; + rsp_els->rx_xchg_address = purex->rx_xchg_addr; + rsp_els->rx_dsd_count = 0; + rsp_els->opcode = purex->els_frame_payload[0]; + + rsp_els->port_id[0] = purex->s_id[0]; + rsp_els->port_id[1] = purex->s_id[1]; + rsp_els->port_id[2] = purex->s_id[2]; + + rsp_els->control_flags = EPD_ELS_ACC; + rsp_els->rx_byte_count = 0; + rsp_els->tx_byte_count = cpu_to_le32(sizeof(*rsp_payload)); + + put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); + rsp_els->tx_len = rsp_els->tx_byte_count; + + rsp_els->rx_address = 0; + rsp_els->rx_len = 0; + + if (sizeof(*rsp_payload) <= 0x100) + goto accept; + + pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); + if (!pdb) + goto reduce; + + rval = qla24xx_get_port_database(vha, purex->nport_handle, pdb); + if (rval) + goto reduce; + + if (pdb->port_id[0] != purex->s_id[2] || + pdb->port_id[1] != purex->s_id[1] || + pdb->port_id[2] != purex->s_id[0]) + goto reduce; + + if (pdb->current_login_state == PDS_PLOGI_COMPLETE || + pdb->current_login_state == PDS_PRLI_COMPLETE) + goto accept; + +reduce: + ql_dbg(ql_dbg_init, vha, 0x016e, "Requesting port is not logged in.\n"); + rsp_els->tx_byte_count = rsp_els->tx_len = + offsetof(struct rdp_rsp_payload, buffer_credit_desc); + ql_dbg(ql_dbg_init, vha, 0x016f, "Reduced response payload size %u.\n", + rsp_els->tx_byte_count); + +accept: + /* Prepare Response Payload */ + rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ + rsp_payload->hdr.len = cpu_to_be32( + rsp_els->tx_byte_count - sizeof(rsp_payload->hdr)); + + /* Link service Request Info Descriptor */ + rsp_payload->ls_req_info_desc.desc_tag = cpu_to_be32(0x1); + rsp_payload->ls_req_info_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc)); + rsp_payload->ls_req_info_desc.req_payload_word_0 = + cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + /* Link service Request Info Descriptor 2 */ + rsp_payload->ls_req_info_desc2.desc_tag = cpu_to_be32(0x1); + rsp_payload->ls_req_info_desc2.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc2)); + rsp_payload->ls_req_info_desc2.req_payload_word_0 = + cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + if (sfp) { + /* SFP Flags */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x7, 2, 0); + if (!rval) { + /* SFP Flags bits 3-0: Port Tx Laser Type */ + if (sfp[0] & BIT_2 || sfp[1] & (BIT_6|BIT_5)) + sfp_flags |= BIT_0; /* short wave */ + else if (sfp[0] & BIT_1) + sfp_flags |= BIT_1; /* long wave 1310nm */ + else if (sfp[1] & BIT_4) + sfp_flags |= BIT_1|BIT_0; /* long wave 1550nm */ + } + + /* SFP Type */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x0, 1, 0); + if (!rval) { + sfp_flags |= BIT_4; /* optical */ + if (sfp[0] == 0x3) + sfp_flags |= BIT_6; /* sfp+ */ + } + + /* SFP Diagnostics */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); + if (!rval && sfp_flags) { + uint16_t *trx = (void *)sfp; /* already be16 */ + + rsp_payload->sfp_diag_desc.desc_tag = + cpu_to_be32(0x10000); + rsp_payload->sfp_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); + rsp_payload->sfp_diag_desc.temperature = trx[0]; + rsp_payload->sfp_diag_desc.vcc = trx[1]; + rsp_payload->sfp_diag_desc.tx_bias = trx[2]; + rsp_payload->sfp_diag_desc.tx_power = trx[3]; + rsp_payload->sfp_diag_desc.rx_power = trx[4]; + rsp_payload->sfp_diag_desc.sfp_flags = + cpu_to_be16(sfp_flags); + } + } + + /* Port Speed Descriptor */ + rsp_payload->port_speed_desc.desc_tag = cpu_to_be32(0x10001); + rsp_payload->port_speed_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_speed_desc)); + rsp_payload->port_speed_desc.speed_capab = cpu_to_be16( + qla25xx_rdp_port_speed_capability(ha)); + rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( + qla25xx_rdp_port_speed_currently(ha)); + + if (stat) { + rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); + if (!rval) { + /* Link Error Status Descriptor */ + rsp_payload->ls_err_desc.desc_tag = + cpu_to_be32(0x10002); + rsp_payload->ls_err_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); + rsp_payload->ls_err_desc.link_fail_cnt = + cpu_to_be32(stat->link_fail_cnt); + rsp_payload->ls_err_desc.loss_sync_cnt = + cpu_to_be32(stat->loss_sync_cnt); + rsp_payload->ls_err_desc.loss_sig_cnt = + cpu_to_be32(stat->loss_sig_cnt); + rsp_payload->ls_err_desc.prim_seq_err_cnt = + cpu_to_be32(stat->prim_seq_err_cnt); + rsp_payload->ls_err_desc.inval_xmit_word_cnt = + cpu_to_be32(stat->inval_xmit_word_cnt); + rsp_payload->ls_err_desc.inval_crc_cnt = + cpu_to_be32(stat->inval_crc_cnt); + rsp_payload->ls_err_desc.pn_port_phy_type |= BIT_6; + } + } + + /* Portname Descriptor */ + rsp_payload->port_name_diag_desc.desc_tag = cpu_to_be32(0x10003); + rsp_payload->port_name_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_diag_desc)); + memcpy(rsp_payload->port_name_diag_desc.WWNN, + vha->node_name, + sizeof(rsp_payload->port_name_diag_desc.WWNN)); + memcpy(rsp_payload->port_name_diag_desc.WWPN, + vha->port_name, + sizeof(rsp_payload->port_name_diag_desc.WWPN)); + + /* F-Port Portname Descriptor */ + rsp_payload->port_name_direct_desc.desc_tag = cpu_to_be32(0x10003); + rsp_payload->port_name_direct_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_direct_desc)); + memcpy(rsp_payload->port_name_direct_desc.WWNN, + vha->fabric_node_name, + sizeof(rsp_payload->port_name_direct_desc.WWNN)); + memcpy(rsp_payload->port_name_direct_desc.WWPN, + vha->fabric_port_name, + sizeof(rsp_payload->port_name_direct_desc.WWPN)); + + if (rsp_els->tx_byte_count < sizeof(*rsp_payload)) + goto send; + + if (bbc) { + memset(bbc, 0, sizeof(*bbc)); + rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); + if (!rval) { + /* Bufer Credit Descriptor */ + rsp_payload->buffer_credit_desc.desc_tag = + cpu_to_be32(0x10006); + rsp_payload->buffer_credit_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN( + rsp_payload->buffer_credit_desc)); + rsp_payload->buffer_credit_desc.fcport_b2b = + cpu_to_be32(LSW(bbc->parameter[0])); + rsp_payload->buffer_credit_desc.attached_fcport_b2b = + cpu_to_be32(0); + rsp_payload->buffer_credit_desc.fcport_rtt = + cpu_to_be32(0); + } + } + + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); + if (!rval) { + uint16_t *trx = (void *)sfp; /* already be16 */ + + /* Optical Element Descriptor, Temperature */ + rsp_payload->optical_elmt_desc[0].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[0].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; + rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; + rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; + rsp_payload->optical_elmt_desc[0].low_warn = trx[3]; + rsp_payload->optical_elmt_desc[0].element_flags = + cpu_to_be32(1 << 28); + + /* Optical Element Descriptor, Voltage */ + rsp_payload->optical_elmt_desc[1].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[1].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; + rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; + rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; + rsp_payload->optical_elmt_desc[1].low_warn = trx[7]; + rsp_payload->optical_elmt_desc[1].element_flags = + cpu_to_be32(2 << 28); + + /* Optical Element Descriptor, Tx Bias Current */ + rsp_payload->optical_elmt_desc[2].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[2].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; + rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; + rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; + rsp_payload->optical_elmt_desc[2].low_warn = trx[11]; + rsp_payload->optical_elmt_desc[2].element_flags = + cpu_to_be32(3 << 28); + + /* Optical Element Descriptor, Tx Power */ + rsp_payload->optical_elmt_desc[3].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[3].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; + rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; + rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; + rsp_payload->optical_elmt_desc[3].low_warn = trx[15]; + rsp_payload->optical_elmt_desc[3].element_flags = + cpu_to_be32(4 << 28); + + /* Optical Element Descriptor, Rx Power */ + rsp_payload->optical_elmt_desc[4].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[4].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; + rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; + rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; + rsp_payload->optical_elmt_desc[4].low_warn = trx[19]; + rsp_payload->optical_elmt_desc[4].element_flags = + cpu_to_be32(5 << 28); + } + + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 112, 64, 0); + if (!rval) { + /* Temperature high/low alarm/warning */ + rsp_payload->optical_elmt_desc[0].element_flags |= + cpu_to_be32( + (sfp[0] >> 7 & 1) << 3 | + (sfp[0] >> 6 & 1) << 2 | + (sfp[4] >> 7 & 1) << 1 | + (sfp[4] >> 6 & 1) << 0); + + /* Voltage high/low alarm/warning */ + rsp_payload->optical_elmt_desc[1].element_flags |= + cpu_to_be32( + (sfp[0] >> 5 & 1) << 3 | + (sfp[0] >> 4 & 1) << 2 | + (sfp[4] >> 5 & 1) << 1 | + (sfp[4] >> 4 & 1) << 0); + + /* Tx Bias Current high/low alarm/warning */ + rsp_payload->optical_elmt_desc[2].element_flags |= + cpu_to_be32( + (sfp[0] >> 3 & 1) << 3 | + (sfp[0] >> 2 & 1) << 2 | + (sfp[4] >> 3 & 1) << 1 | + (sfp[4] >> 2 & 1) << 0); + + /* Tx Power high/low alarm/warning */ + rsp_payload->optical_elmt_desc[3].element_flags |= + cpu_to_be32( + (sfp[0] >> 1 & 1) << 3 | + (sfp[0] >> 0 & 1) << 2 | + (sfp[4] >> 1 & 1) << 1 | + (sfp[4] >> 0 & 1) << 0); + + /* Rx Power high/low alarm/warning */ + rsp_payload->optical_elmt_desc[4].element_flags |= + cpu_to_be32( + (sfp[1] >> 7 & 1) << 3 | + (sfp[1] >> 6 & 1) << 2 | + (sfp[5] >> 7 & 1) << 1 | + (sfp[5] >> 6 & 1) << 0); + } + } + + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); + if (!rval) { + /* Optical Product Data Descriptor */ + rsp_payload->optical_prod_desc.desc_tag = + cpu_to_be32(0x10008); + rsp_payload->optical_prod_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN( + rsp_payload->optical_prod_desc)); + memcpy(rsp_payload->optical_prod_desc.vendor_name, + sfp + 0, + sizeof(rsp_payload->optical_prod_desc.vendor_name)); + memcpy(rsp_payload->optical_prod_desc.part_number, + sfp + 20, + sizeof(rsp_payload->optical_prod_desc.part_number)); + memcpy(rsp_payload->optical_prod_desc.revision, + sfp + 36, + sizeof(rsp_payload->optical_prod_desc.revision)); + memcpy(rsp_payload->optical_prod_desc.serial_number, + sfp + 48, + sizeof(rsp_payload->optical_prod_desc.serial_number)); + } + + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 84, 8, 0); + if (!rval) { + memcpy(rsp_payload->optical_prod_desc.date, + sfp + 0, + sizeof(rsp_payload->optical_prod_desc.date)); + } + } + +send: + ql_dbg(ql_dbg_init, vha, 0x0183, + "Sending ELS Response to RDP Request...\n"); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0184, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0185, + (void *)rsp_els, sizeof(*rsp_els)); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, + "-------- ELS RSP PAYLOAD -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, + (void *)rsp_payload, rsp_els->tx_byte_count); + + rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x0188, + "%s: failed to issue IOCB (%x).\n", __func__, rval); + } else if (rsp_els->entry_status != 0) { + ql_log(ql_log_warn, vha, 0x0189, + "%s: failed to complete IOCB -- error status (%x).\n", + __func__, rsp_els->entry_status); + rval = QLA_FUNCTION_FAILED; + } else { + ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); + } + +dealloc: + kfree(pdb); + + if (bbc) + dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), + bbc, bbc_dma); + if (stat) + dma_free_coherent(&ha->pdev->dev, sizeof(*stat), + stat, stat_dma); + if (sfp) + dma_free_coherent(&ha->pdev->dev, SFP_RTDI_LEN, + sfp, sfp_dma); + if (rsp_payload) + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_payload), + rsp_payload, rsp_payload_dma); + if (rsp_els) + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), + rsp_els, rsp_els_dma); + + return rval; +} + void qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) { @@ -6127,6 +6656,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) base_vha->flags.online = 0; + kfree(base_vha->purex_data); + qla2x00_destroy_deferred_work(ha); /* @@ -6350,6 +6881,13 @@ qla2x00_do_dpc(void *data) } } + if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags) && + (atomic_read(&base_vha->loop_state) == LOOP_READY)) { + qla24xx_process_purex_iocb(base_vha, + base_vha->purex_data); + clear_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags); + } + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { qla2x00_update_fcports(base_vha); @@ -6741,7 +7279,8 @@ qla2x00_timer(struct timer_list *t) test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || - test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) { + test_bit(RELOGIN_NEEDED, &vha->dpc_flags) || + test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags))) { ql_dbg(ql_dbg_timer, vha, 0x600b, "isp_abort_needed=%d loop_resync_needed=%d " "fcport_update_needed=%d start_dpc=%d " @@ -6754,12 +7293,13 @@ qla2x00_timer(struct timer_list *t) ql_dbg(ql_dbg_timer, vha, 0x600c, "beacon_blink_needed=%d isp_unrecoverable=%d " "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d " - "relogin_needed=%d.\n", + "relogin_needed=%d, Process_purex_iocb=%d.\n", test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags), test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags), test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags), test_bit(VP_DPC_NEEDED, &vha->dpc_flags), - test_bit(RELOGIN_NEEDED, &vha->dpc_flags)); + test_bit(RELOGIN_NEEDED, &vha->dpc_flags), + test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)); qla2xxx_wake_dpc(vha); } From 0519dae5de55e82e172c8b045750a8a423202229 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:14:49 +0000 Subject: [PATCH 09/49] qla2x00t-32gbit: Add ql2xrdpenable module parameter for RDP This patch provides separate module parameter ql2xrdpenable to turn on/off RDP capability in the driver. However, if ql2xsmartsan parameter is enabled, it will also turn on ql2xfdmienable parameter since it is required for RDP to work. Link: https://lore.kernel.org/r/20200212214436.25532-9-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit bd7de0b1c3947e176effb5f5b4a47eab79db771e upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8792 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_gbl.h | 1 + qla2x00t-32gbit/qla_init.c | 12 +++++++++--- qla2x00t-32gbit/qla_os.c | 10 +++++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 5be12df32..4e9913f0c 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -144,6 +144,7 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; +extern int ql2xrdpenable; extern int ql2xsmartsan; extern int ql2xallocfwdump; extern int ql2xextended_error_logging; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 2063f2876..0cd1d1648 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2270,6 +2270,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init, vha, 0x0078, "Verifying loaded RISC code...\n"); + /* If smartsan enabled then require fdmi and rdp enabled */ + if (ql2xsmartsan) { + ql2xfdmienable = 1; + ql2xrdpenable = 1; + } + if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) { rval = ha->isp_ops->chip_diag(vha); if (rval) @@ -3710,7 +3716,7 @@ enable_82xx_npiv: } /* Enable PUREX PASSTHRU */ - if (ql2xsmartsan) + if (ql2xrdpenable) qla25xx_set_els_cmds_supported(vha); } else goto failed; @@ -3945,7 +3951,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) } enable_purex: - if (ql2xsmartsan) + if (ql2xrdpenable) ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; qla2x00_set_fw_options(vha, ha->fw_options); @@ -8683,7 +8689,7 @@ qla83xx_update_fw_options(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - if (ql2xsmartsan) + if (ql2xrdpenable) ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; qla2x00_set_fw_options(vha, ha->fw_options); diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 3923e3a56..53b12c916 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -126,7 +126,8 @@ module_param(ql2xfdmienable, int, S_IRUGO|S_IWUSR); module_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registrations. " - "0 - no FDMI. Default is 1 - perform FDMI."); + "0 - no FDMI registrations. " + "1 - provide FDMI registrations (default)."); #define MAX_Q_DEPTH 64 static int ql2xmaxqdepth = MAX_Q_DEPTH; @@ -332,6 +333,13 @@ MODULE_PARM_DESC(ql2xsmartsan, " Default is 0 - No SmartSAN registration," " 1 - Register SmartSAN Management Attributes."); +int ql2xrdpenable; +module_param(ql2xrdpenable, int, 0444); +module_param_named(rdpenable, ql2xrdpenable, int, 0444); +MODULE_PARM_DESC(ql2xrdpenable, + "Enables RDP responses. " + "0 - no RDP responses (default). " + "1 - provide RDP responses."); static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); From 28a97cee1b13bd637ecaa70e67f1ea2560a3d5b0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:15:33 +0000 Subject: [PATCH 10/49] qla2x00t-32gbit: Add vendor extended FDMI commands This patch adds support for extended FDMI commands and cleans up code to reduce duplication. Link: https://lore.kernel.org/r/20200212214436.25532-10-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 52bfb089d9d384a1ac0f6d94da7636eb9373a8f9 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8793 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 158 ++-- qla2x00t-32gbit/qla_gs.c | 1743 +++++++++++++++++-------------------- 2 files changed, 870 insertions(+), 1031 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index bf12ab26b..c8ad95c95 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -2654,10 +2654,11 @@ static const char * const port_dstate_str[] = { #define GFF_ID_RSP_SIZE (16 + 128) /* - * HBA attribute types. + * FDMI HBA attribute types. */ -#define FDMI_HBA_ATTR_COUNT 9 -#define FDMIV2_HBA_ATTR_COUNT 17 +#define FDMI1_HBA_ATTR_COUNT 9 +#define FDMI2_HBA_ATTR_COUNT 17 + #define FDMI_HBA_NODE_NAME 0x1 #define FDMI_HBA_MANUFACTURER 0x2 #define FDMI_HBA_SERIAL_NUMBER 0x3 @@ -2669,12 +2670,13 @@ static const char * const port_dstate_str[] = { #define FDMI_HBA_FIRMWARE_VERSION 0x9 #define FDMI_HBA_OS_NAME_AND_VERSION 0xa #define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb + #define FDMI_HBA_NODE_SYMBOLIC_NAME 0xc -#define FDMI_HBA_VENDOR_ID 0xd +#define FDMI_HBA_VENDOR_SPECIFIC_INFO 0xd #define FDMI_HBA_NUM_PORTS 0xe #define FDMI_HBA_FABRIC_NAME 0xf #define FDMI_HBA_BOOT_BIOS_NAME 0x10 -#define FDMI_HBA_TYPE_VENDOR_IDENTIFIER 0xe0 +#define FDMI_HBA_VENDOR_IDENTIFIER 0xe0 struct ct_fdmi_hba_attr { uint16_t type; @@ -2691,31 +2693,9 @@ struct ct_fdmi_hba_attr { uint8_t fw_version[32]; uint8_t os_version[128]; uint32_t max_ct_len; - } a; -}; -struct ct_fdmi_hba_attributes { - uint32_t count; - struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT]; -}; - -struct ct_fdmiv2_hba_attr { - uint16_t type; - uint16_t len; - union { - uint8_t node_name[WWN_SIZE]; - uint8_t manufacturer[64]; - uint8_t serial_num[32]; - uint8_t model[16+1]; - uint8_t model_desc[80]; - uint8_t hw_version[16]; - uint8_t driver_version[32]; - uint8_t orom_version[16]; - uint8_t fw_version[32]; - uint8_t os_version[128]; - uint32_t max_ct_len; uint8_t sym_name[256]; - uint32_t vendor_id; + uint32_t vendor_specific_info; uint32_t num_ports; uint8_t fabric_name[WWN_SIZE]; uint8_t bios_name[32]; @@ -2723,22 +2703,30 @@ struct ct_fdmiv2_hba_attr { } a; }; -struct ct_fdmiv2_hba_attributes { +struct ct_fdmi1_hba_attributes { uint32_t count; - struct ct_fdmiv2_hba_attr entry[FDMIV2_HBA_ATTR_COUNT]; + struct ct_fdmi_hba_attr entry[FDMI1_HBA_ATTR_COUNT]; +}; + +struct ct_fdmi2_hba_attributes { + uint32_t count; + struct ct_fdmi_hba_attr entry[FDMI2_HBA_ATTR_COUNT]; }; /* - * Port attribute types. + * FDMI Port attribute types. */ -#define FDMI_PORT_ATTR_COUNT 6 -#define FDMIV2_PORT_ATTR_COUNT 16 +#define FDMI1_PORT_ATTR_COUNT 6 +#define FDMI2_PORT_ATTR_COUNT 16 +#define FDMI2_SMARTSAN_PORT_ATTR_COUNT 23 + #define FDMI_PORT_FC4_TYPES 0x1 #define FDMI_PORT_SUPPORT_SPEED 0x2 #define FDMI_PORT_CURRENT_SPEED 0x3 #define FDMI_PORT_MAX_FRAME_SIZE 0x4 #define FDMI_PORT_OS_DEVICE_NAME 0x5 #define FDMI_PORT_HOST_NAME 0x6 + #define FDMI_PORT_NODE_NAME 0x7 #define FDMI_PORT_NAME 0x8 #define FDMI_PORT_SYM_NAME 0x9 @@ -2748,7 +2736,15 @@ struct ct_fdmiv2_hba_attributes { #define FDMI_PORT_FC4_TYPE 0xd #define FDMI_PORT_STATE 0x101 #define FDMI_PORT_COUNT 0x102 -#define FDMI_PORT_ID 0x103 +#define FDMI_PORT_IDENTIFIER 0x103 + +#define FDMI_SMARTSAN_SERVICE 0xF100 +#define FDMI_SMARTSAN_GUID 0xF101 +#define FDMI_SMARTSAN_VERSION 0xF102 +#define FDMI_SMARTSAN_PROD_NAME 0xF103 +#define FDMI_SMARTSAN_PORT_INFO 0xF104 +#define FDMI_SMARTSAN_QOS_SUPPORT 0xF105 +#define FDMI_SMARTSAN_SECURITY_SUPPORT 0xF106 #define FDMI_PORT_SPEED_1GB 0x1 #define FDMI_PORT_SPEED_2GB 0x2 @@ -2764,37 +2760,6 @@ struct ct_fdmiv2_hba_attributes { #define FC_CLASS_3 0x08 #define FC_CLASS_2_3 0x0C -struct ct_fdmiv2_port_attr { - uint16_t type; - uint16_t len; - union { - uint8_t fc4_types[32]; - uint32_t sup_speed; - uint32_t cur_speed; - uint32_t max_frame_size; - uint8_t os_dev_name[32]; - uint8_t host_name[256]; - uint8_t node_name[WWN_SIZE]; - uint8_t port_name[WWN_SIZE]; - uint8_t port_sym_name[128]; - uint32_t port_type; - uint32_t port_supported_cos; - uint8_t fabric_name[WWN_SIZE]; - uint8_t port_fc4_type[32]; - uint32_t port_state; - uint32_t num_ports; - uint32_t port_id; - } a; -}; - -/* - * Port Attribute Block. - */ -struct ct_fdmiv2_port_attributes { - uint32_t count; - struct ct_fdmiv2_port_attr entry[FDMIV2_PORT_ATTR_COUNT]; -}; - struct ct_fdmi_port_attr { uint16_t type; uint16_t len; @@ -2805,14 +2770,49 @@ struct ct_fdmi_port_attr { uint32_t max_frame_size; uint8_t os_dev_name[32]; uint8_t host_name[256]; + + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + uint8_t port_sym_name[128]; + uint32_t port_type; + uint32_t port_supported_cos; + uint8_t fabric_name[WWN_SIZE]; + uint8_t port_fc4_type[32]; + uint32_t port_state; + uint32_t num_ports; + uint32_t port_id; + + uint8_t smartsan_service[24]; + uint8_t smartsan_guid[16]; + uint8_t smartsan_version[24]; + uint8_t smartsan_prod_name[16]; + uint32_t smartsan_port_info; + uint32_t smartsan_qos_support; + uint32_t smartsan_security_support; } a; }; -struct ct_fdmi_port_attributes { +struct ct_fdmi1_port_attributes { uint32_t count; - struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT]; + struct ct_fdmi_port_attr entry[FDMI1_PORT_ATTR_COUNT]; }; +struct ct_fdmi2_port_attributes { + uint32_t count; + struct ct_fdmi_port_attr entry[FDMI2_PORT_ATTR_COUNT]; +}; + +#define FDMI_ATTR_TYPELEN(obj) \ + (sizeof((obj)->type) + sizeof((obj)->len)) + +#define FDMI_ATTR_ALIGNMENT(len) \ + (4 - ((len) & 3)) + +/* FDMI register call options */ +#define CALLOPT_FDMI1 0 +#define CALLOPT_FDMI2 1 +#define CALLOPT_FDMI2_SMARTSAN 2 + /* FDMI definitions. */ #define GRHL_CMD 0x100 #define GHAT_CMD 0x101 @@ -2823,10 +2823,13 @@ struct ct_fdmi_port_attributes { #define RHBA_RSP_SIZE 16 #define RHAT_CMD 0x201 + #define RPRT_CMD 0x210 +#define RPRT_RSP_SIZE 24 #define RPA_CMD 0x211 #define RPA_RSP_SIZE 16 +#define SMARTSAN_RPA_RSP_SIZE 24 #define DHBA_CMD 0x300 #define DHBA_REQ_SIZE (16 + 8) @@ -2909,30 +2912,24 @@ struct ct_sns_req { uint8_t hba_identifier[8]; uint32_t entry_count; uint8_t port_name[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi2_hba_attributes attrs; } rhba; struct { uint8_t hba_identifier[8]; - uint32_t entry_count; - uint8_t port_name[8]; - struct ct_fdmiv2_hba_attributes attrs; - } rhba2; - - struct { - uint8_t hba_identifier[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi1_hba_attributes attrs; } rhat; struct { uint8_t port_name[8]; - struct ct_fdmi_port_attributes attrs; + struct ct_fdmi2_port_attributes attrs; } rpa; struct { + uint8_t hba_identifier[8]; uint8_t port_name[8]; - struct ct_fdmiv2_port_attributes attrs; - } rpa2; + struct ct_fdmi2_port_attributes attrs; + } rprt; struct { uint8_t port_name[8]; @@ -3046,7 +3043,7 @@ struct ct_sns_rsp { struct { uint32_t entry_count; uint8_t port_name[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi1_hba_attributes attrs; } ghat; struct { @@ -3717,6 +3714,7 @@ struct rdp_rsp_payload { #define RDP_PORT_SPEED_8GB BIT_11 #define RDP_PORT_SPEED_16GB BIT_10 #define RDP_PORT_SPEED_32GB BIT_9 +#define RDP_PORT_SPEED_64GB BIT_8 #define RDP_PORT_SPEED_UNKNOWN BIT_0 struct scsi_qlt_host { diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index c01eb87c7..e67105aca 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -19,6 +19,8 @@ static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8); static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*); static int qla_async_rsnn_nn(scsi_qla_host_t *); + + /** * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query. * @vha: HA context @@ -1500,747 +1502,732 @@ qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd, return &p->p.req; } -/** - * qla2x00_fdmi_rhba() - perform RHBA FDMI registration - * @vha: HA context - * - * Returns 0 on success. - */ -static int -qla2x00_fdmi_rhba(scsi_qla_host_t *vha) +static uint +qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha) { - int rval, alen; - uint32_t size, sn; - - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmi_hba_attr *eiter; - struct qla_hw_data *ha = vha->hw; - - /* Issue RHBA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE); - ct_req->req.rhba.entry_count = cpu_to_be32(1); - memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE); - size = 2 * WWN_SIZE + 4 + 4; - - /* Attributes */ - ct_req->req.rhba.attrs.count = - cpu_to_be32(FDMI_HBA_ATTR_COUNT); - entries = &ct_req->req; - - /* Nodename. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x2025, - "NodeName = %8phN.\n", eiter->a.node_name); - - /* Manufacturer. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); - alen = strlen(QLA2XXX_MANUFACTURER); - snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), - "%s", "QLogic Corporation"); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2026, - "Manufacturer = %s.\n", eiter->a.manufacturer); - - /* Serial number. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); - if (IS_FWI2_CAPABLE(ha)) - qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, - sizeof(eiter->a.serial_num)); - else { - sn = ((ha->serial0 & 0x1f) << 16) | - (ha->serial2 << 8) | ha->serial1; - snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), - "%c%05d", 'A' + sn / 100000, sn % 100000); - } - alen = strlen(eiter->a.serial_num); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2027, - "Serial no. = %s.\n", eiter->a.serial_num); - - /* Model name. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MODEL); - snprintf(eiter->a.model, sizeof(eiter->a.model), - "%s", ha->model_number); - alen = strlen(eiter->a.model); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2028, - "Model Name = %s.\n", eiter->a.model); - - /* Model description. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), - "%s", ha->model_desc); - alen = strlen(eiter->a.model_desc); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2029, - "Model Desc = %s.\n", eiter->a.model_desc); - - /* Hardware version. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); - if (!IS_FWI2_CAPABLE(ha)) { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } - alen = strlen(eiter->a.hw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202a, - "Hardware ver = %s.\n", eiter->a.hw_version); - - /* Driver version. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); - snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), - "%s", qla2x00_version_str); - alen = strlen(eiter->a.driver_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202b, - "Driver ver = %s.\n", eiter->a.driver_version); - - /* Option ROM version. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); - snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), - "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.orom_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha , 0x202c, - "Optrom vers = %s.\n", eiter->a.orom_version); - - /* Firmware version */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); - ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, - sizeof(eiter->a.fw_version)); - alen = strlen(eiter->a.fw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202d, - "Firmware vers = %s.\n", eiter->a.fw_version); - - /* Update MS request size. */ - qla2x00_update_ms_fdmi_iocb(vha, size + 16); - - ql_dbg(ql_dbg_disc, vha, 0x202e, - "RHBA identifier = %8phN size=%d.\n", - ct_req->req.rhba.hba_identifier, size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076, - entries, size); - - /* Execute MS IOCB */ - rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x2030, - "RHBA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; - if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && - ct_rsp->header.explanation_code == - CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x2034, - "HBA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x20ad, - "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); - } - } else { - ql_dbg(ql_dbg_disc, vha, 0x2035, - "RHBA exiting normally.\n"); - } - - return rval; -} - -/** - * qla2x00_fdmi_rpa() - perform RPA registration - * @vha: HA context - * - * Returns 0 on success. - */ -static int -qla2x00_fdmi_rpa(scsi_qla_host_t *vha) -{ - int rval, alen; - uint32_t size; - struct qla_hw_data *ha = vha->hw; - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmi_port_attr *eiter; - struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; - struct new_utsname *p_sysid = NULL; - - /* Issue RPA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, - RPA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE); - size = WWN_SIZE + 4; - - /* Attributes */ - ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT); - entries = &ct_req->req; - - /* FC4 types. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); - eiter->len = cpu_to_be16(4 + 32); - eiter->a.fc4_types[2] = 0x01; - size += 4 + 32; - - ql_dbg(ql_dbg_disc, vha, 0x2039, - "FC4_TYPES=%02x %02x.\n", - eiter->a.fc4_types[2], - eiter->a.fc4_types[1]); - - /* Supported speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); - eiter->len = cpu_to_be16(4 + 4); if (IS_CNA_CAPABLE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_32GB| - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB); - else if (IS_QLA2031(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB); - else if (IS_QLA25XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA24XX_TYPE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA23XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_1GB); - size += 4 + 4; + return FDMI_PORT_SPEED_10GB; + if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { + uint speeds = 0; - ql_dbg(ql_dbg_disc, vha, 0x203a, - "Supported_Speed=%x.\n", eiter->a.sup_speed); - - /* Current speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); - eiter->len = cpu_to_be16(4 + 4); + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= FDMI_PORT_SPEED_64GB; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= FDMI_PORT_SPEED_32GB; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= FDMI_PORT_SPEED_16GB; + } + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= FDMI_PORT_SPEED_8GB; + } + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= FDMI_PORT_SPEED_4GB; + } + return speeds; + } + if (IS_QLA2031(ha)) + return FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB| + FDMI_PORT_SPEED_4GB; + if (IS_QLA25XX(ha)) + return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB| + FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + if (IS_QLA24XX_TYPE(ha)) + return FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_2GB| + FDMI_PORT_SPEED_1GB; + if (IS_QLA23XX(ha)) + return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + return FDMI_PORT_SPEED_1GB; +} +static uint +qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha) +{ switch (ha->link_data_rate) { case PORT_SPEED_1GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_1GB); - break; + return FDMI_PORT_SPEED_1GB; case PORT_SPEED_2GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_2GB); - break; + return FDMI_PORT_SPEED_2GB; case PORT_SPEED_4GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_4GB); - break; + return FDMI_PORT_SPEED_4GB; case PORT_SPEED_8GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_8GB); - break; + return FDMI_PORT_SPEED_8GB; case PORT_SPEED_10GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_10GB); - break; + return FDMI_PORT_SPEED_10GB; case PORT_SPEED_16GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_16GB); - break; + return FDMI_PORT_SPEED_16GB; case PORT_SPEED_32GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_32GB); - break; + return FDMI_PORT_SPEED_32GB; + case PORT_SPEED_64GB: + return FDMI_PORT_SPEED_64GB; default: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); - break; + return FDMI_PORT_SPEED_UNKNOWN; } - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x203b, - "Current_Speed=%x.\n", eiter->a.cur_speed); - - /* Max frame size. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); - eiter->len = cpu_to_be16(4 + 4); - eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? - le16_to_cpu(icb24->frame_payload_size) : - le16_to_cpu(ha->init_cb->frame_payload_size); - eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x203c, - "Max_Frame_Size=%x.\n", eiter->a.max_frame_size); - - /* OS device name. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), - "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); - alen = strlen(eiter->a.os_dev_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x204b, - "OS_Device_Name=%s.\n", eiter->a.os_dev_name); - - /* Hostname. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); - p_sysid = utsname(); - if (p_sysid) { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", p_sysid->nodename); - } else { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", fc_host_system_hostname(vha->host)); - } - alen = strlen(eiter->a.host_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name); - - /* Update MS request size. */ - qla2x00_update_ms_fdmi_iocb(vha, size + 16); - - ql_dbg(ql_dbg_disc, vha, 0x203e, - "RPA portname %016llx, size = %d.\n", - wwn_to_u64(ct_req->req.rpa.port_name), size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079, - entries, size); - - /* Execute MS IOCB */ - rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x2040, - "RPA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; - if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && - ct_rsp->header.explanation_code == - CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20cd, - "RPA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } - - } else { - ql_dbg(ql_dbg_disc, vha, 0x2041, - "RPA exiting normally.\n"); - } - - return rval; } /** - * qla2x00_fdmiv2_rhba() - perform RHBA FDMI v2 registration + * qla2x00_hba_attributes() perform HBA attributes registration * @vha: HA context + * @entries: number of entries to use + * @callopt: Option to issue extended or standard FDMI + * command parameter * * Returns 0 on success. */ -static int -qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha) +static unsigned long +qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) { - int rval, alen; - uint32_t size, sn; - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmiv2_hba_attr *eiter; struct qla_hw_data *ha = vha->hw; - struct new_utsname *p_sysid = NULL; - - /* Issue RHBA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, - RHBA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE); - ct_req->req.rhba2.entry_count = cpu_to_be32(1); - memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE); - size = 2 * WWN_SIZE + 4 + 4; - - /* Attributes */ - ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT); - entries = &ct_req->req; + struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + struct ct_fdmi_hba_attr *eiter; + uint16_t alen; + unsigned long size = 0; /* Nodename. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x207d, - "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name)); - + memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); + alen = sizeof(eiter->a.node_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a0, + "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); /* Manufacturer. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); - snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), - "%s", "QLogic Corporation"); - eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0'; - alen = strlen(eiter->a.manufacturer); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a5, - "Manufacturer = %s.\n", eiter->a.manufacturer); - + alen = scnprintf( + eiter->a.manufacturer, sizeof(eiter->a.manufacturer), + "%s", "QLogic Corporation"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a1, + "MANUFACTURER = %s.\n", eiter->a.manufacturer); /* Serial number. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); - if (IS_FWI2_CAPABLE(ha)) - qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, - sizeof(eiter->a.serial_num)); - else { - sn = ((ha->serial0 & 0x1f) << 16) | - (ha->serial2 << 8) | ha->serial1; - snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), - "%c%05d", 'A' + sn / 100000, sn % 100000); + alen = 0; + if (IS_FWI2_CAPABLE(ha)) { + alen = qla2xxx_get_vpd_field(vha, "SN", + eiter->a.serial_num, sizeof(eiter->a.serial_num)); } - alen = strlen(eiter->a.serial_num); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a6, - "Serial no. = %s.\n", eiter->a.serial_num); - + if (!alen) { + uint32_t sn = ((ha->serial0 & 0x1f) << 16) | + (ha->serial2 << 8) | ha->serial1; + alen = scnprintf( + eiter->a.serial_num, sizeof(eiter->a.serial_num), + "%c%05d", 'A' + sn / 100000, sn % 100000); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a2, + "SERIAL NUMBER = %s.\n", eiter->a.serial_num); /* Model name. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MODEL); - snprintf(eiter->a.model, sizeof(eiter->a.model), - "%s", ha->model_number); - alen = strlen(eiter->a.model); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a7, - "Model Name = %s.\n", eiter->a.model); - + alen = scnprintf( + eiter->a.model, sizeof(eiter->a.model), + "%s", ha->model_number); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a3, + "MODEL NAME = %s.\n", eiter->a.model); /* Model description. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), - "%s", ha->model_desc); - alen = strlen(eiter->a.model_desc); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a8, - "Model Desc = %s.\n", eiter->a.model_desc); - + alen = scnprintf( + eiter->a.model_desc, sizeof(eiter->a.model_desc), + "%s", ha->model_desc); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a4, + "MODEL DESCRIPTION = %s.\n", eiter->a.model_desc); /* Hardware version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); - if (!IS_FWI2_CAPABLE(ha)) { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); + alen = 0; + if (IS_FWI2_CAPABLE(ha)) { + if (!alen) { + alen = qla2xxx_get_vpd_field(vha, "MN", + eiter->a.hw_version, sizeof(eiter->a.hw_version)); + } + if (!alen) { + alen = qla2xxx_get_vpd_field(vha, "EC", + eiter->a.hw_version, sizeof(eiter->a.hw_version)); + } } - alen = strlen(eiter->a.hw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a9, - "Hardware ver = %s.\n", eiter->a.hw_version); - + if (!alen) { + alen = scnprintf( + eiter->a.hw_version, sizeof(eiter->a.hw_version), + "HW:%s", ha->adapter_id); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a5, + "HARDWARE VERSION = %s.\n", eiter->a.hw_version); /* Driver version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); - snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), - "%s", qla2x00_version_str); - alen = strlen(eiter->a.driver_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20aa, - "Driver ver = %s.\n", eiter->a.driver_version); - + alen = scnprintf( + eiter->a.driver_version, sizeof(eiter->a.driver_version), + "%s", qla2x00_version_str); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a6, + "DRIVER VERSION = %s.\n", eiter->a.driver_version); /* Option ROM version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); - snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), - "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.orom_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha , 0x20ab, - "Optrom version = %d.%02d.\n", eiter->a.orom_version[1], - eiter->a.orom_version[0]); + alen = scnprintf( + eiter->a.orom_version, sizeof(eiter->a.orom_version), + "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a7, + "OPTROM VERSION = %d.%02d.\n", + eiter->a.orom_version[1], eiter->a.orom_version[0]); /* Firmware version */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, sizeof(eiter->a.fw_version)); - alen = strlen(eiter->a.fw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20ac, - "Firmware vers = %s.\n", eiter->a.fw_version); - + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a8, + "FIRMWARE VERSION = %s.\n", eiter->a.fw_version); + if (callopt == CALLOPT_FDMI1) + goto done; /* OS Name and Version */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION); - p_sysid = utsname(); + alen = 0; if (p_sysid) { - snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), - "%s %s %s", - p_sysid->sysname, p_sysid->release, p_sysid->version); - } else { - snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), - "%s %s", "Linux", fc_host_system_hostname(vha->host)); + alen = scnprintf( + eiter->a.os_version, sizeof(eiter->a.os_version), + "%s %s %s", + p_sysid->sysname, p_sysid->release, p_sysid->machine); } - alen = strlen(eiter->a.os_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20ae, - "OS Name and Version = %s.\n", eiter->a.os_version); - + if (!alen) { + alen = scnprintf( + eiter->a.os_version, sizeof(eiter->a.os_version), + "%s %s", + "Linux", fc_host_system_hostname(vha->host)); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a9, + "OS VERSION = %s.\n", eiter->a.os_version); /* MAX CT Payload Length */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH); - eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size); - eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20af, - "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len); - + eiter->a.max_ct_len = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? + icb24->frame_payload_size : ha->init_cb->frame_payload_size)); + alen = sizeof(eiter->a.max_ct_len); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20aa, + "CT PAYLOAD LENGTH = 0x%x.\n", be32_to_cpu(eiter->a.max_ct_len)); /* Node Sybolic Name */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME); - qla2x00_get_sym_node_name(vha, eiter->a.sym_name, + alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name, sizeof(eiter->a.sym_name)); - alen = strlen(eiter->a.sym_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20b0, - "Symbolic Name = %s.\n", eiter->a.sym_name); - - /* Vendor Id */ + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ab, + "SYMBOLIC NAME = %s.\n", eiter->a.sym_name); + /* Vendor Specific information */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID); - eiter->a.vendor_id = cpu_to_be32(0x1077); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20b1, - "Vendor Id = %x.\n", eiter->a.vendor_id); - + eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_SPECIFIC_INFO); + eiter->a.vendor_specific_info = cpu_to_be32(PCI_VENDOR_ID_QLOGIC); + alen = sizeof(eiter->a.vendor_specific_info); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ac, + "VENDOR SPECIFIC INFO = 0x%x.\n", + be32_to_cpu(eiter->a.vendor_specific_info)); /* Num Ports */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS); eiter->a.num_ports = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20b2, - "Port Num = %x.\n", eiter->a.num_ports); - + alen = sizeof(eiter->a.num_ports); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ad, + "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); /* Fabric Name */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME); - memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20b3, - "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); - + memcpy(eiter->a.fabric_name, vha->fabric_node_name, + sizeof(eiter->a.fabric_name)); + alen = sizeof(eiter->a.fabric_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ae, + "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); /* BIOS Version */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME); - snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name), - "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.bios_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20b4, - "BIOS Name = %s\n", eiter->a.bios_name); - + alen = scnprintf( + eiter->a.bios_name, sizeof(eiter->a.bios_name), + "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20af, + "BIOS NAME = %s\n", eiter->a.bios_name); /* Vendor Identifier */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER); - snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), - "%s", "QLGC"); - alen = strlen(eiter->a.vendor_identifier); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; + eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_IDENTIFIER); + alen = scnprintf( + eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), + "%s", "QLGC"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20b0, + "VENDOR IDENTIFIER = %s.\n", eiter->a.vendor_identifier); +done: + return size; +} - ql_dbg(ql_dbg_disc, vha, 0x201b, - "Vendor Identifier = %s.\n", eiter->a.vendor_identifier); +/** + * qla2x00_port_attributes() perform Port attributes registration + * @vha: HA context + * @entries: number of entries to use + * @callopt: Option to issue extended or standard FDMI + * command parameter + * + * Returns 0 on success. + */ +static unsigned long +qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) +{ + struct qla_hw_data *ha = vha->hw; + struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + char *hostname = p_sysid ? + p_sysid->nodename : fc_host_system_hostname(vha->host); + struct ct_fdmi_port_attr *eiter; + uint16_t alen; + unsigned long size = 0; + + /* FC4 types. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); + eiter->a.fc4_types[0] = 0x00; + eiter->a.fc4_types[1] = 0x00; + eiter->a.fc4_types[2] = 0x01; + eiter->a.fc4_types[3] = 0x00; + alen = sizeof(eiter->a.fc4_types); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c0, + "FC4 TYPES = %016llx.\n", *(uint64_t *)eiter->a.fc4_types); + if (vha->flags.nvme_enabled) { + eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ + ql_dbg(ql_dbg_disc, vha, 0x211f, + "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", + eiter->a.fc4_types[6]); + } + /* Supported speed. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); + eiter->a.sup_speed = cpu_to_be32( + qla25xx_fdmi_port_speed_capability(ha)); + alen = sizeof(eiter->a.sup_speed); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c1, + "SUPPORTED SPEED = %x.\n", be32_to_cpu(eiter->a.sup_speed)); + /* Current speed. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); + eiter->a.cur_speed = cpu_to_be32( + qla25xx_fdmi_port_speed_currently(ha)); + alen = sizeof(eiter->a.cur_speed); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c2, + "CURRENT SPEED = %x.\n", be32_to_cpu(eiter->a.cur_speed)); + /* Max frame size. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); + eiter->a.max_frame_size = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? + icb24->frame_payload_size : ha->init_cb->frame_payload_size)); + alen = sizeof(eiter->a.max_frame_size); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c3, + "MAX FRAME SIZE = %x.\n", be32_to_cpu(eiter->a.max_frame_size)); + /* OS device name. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); + alen = scnprintf( + eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), + "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c4, + "OS DEVICE NAME = %s.\n", eiter->a.os_dev_name); + /* Hostname. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); + if (!*hostname || !strncmp(hostname, "(none)", 6)) + hostname = "Linux-default"; + alen = scnprintf( + eiter->a.host_name, sizeof(eiter->a.host_name), + "%s", hostname); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c5, + "HOSTNAME = %s.\n", eiter->a.host_name); + + if (callopt == CALLOPT_FDMI1) + goto done; + + /* Node Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); + memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); + alen = sizeof(eiter->a.node_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c6, + "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); + + /* Port Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_NAME); + memcpy(eiter->a.port_name, vha->port_name, sizeof(eiter->a.port_name)); + alen = sizeof(eiter->a.port_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c7, + "PORTNAME = %016llx.\n", wwn_to_u64(eiter->a.port_name)); + + /* Port Symbolic Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); + alen = qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, + sizeof(eiter->a.port_sym_name)); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c8, + "PORT SYMBOLIC NAME = %s\n", eiter->a.port_sym_name); + + /* Port Type */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_TYPE); + eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); + alen = sizeof(eiter->a.port_type); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c9, + "PORT TYPE = %x.\n", be32_to_cpu(eiter->a.port_type)); + + /* Supported Class of Service */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); + eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); + alen = sizeof(eiter->a.port_supported_cos); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ca, + "SUPPORTED COS = %08x\n", be32_to_cpu(eiter->a.port_supported_cos)); + + /* Port Fabric Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); + memcpy(eiter->a.fabric_name, vha->fabric_node_name, + sizeof(eiter->a.fabric_name)); + alen = sizeof(eiter->a.fabric_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cb, + "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); + + /* FC4_type */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); + eiter->a.port_fc4_type[0] = 0x00; + eiter->a.port_fc4_type[1] = 0x00; + eiter->a.port_fc4_type[2] = 0x01; + eiter->a.port_fc4_type[3] = 0x00; + alen = sizeof(eiter->a.port_fc4_type); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cc, + "PORT ACTIVE FC4 TYPE = %016llx.\n", + *(uint64_t *)eiter->a.port_fc4_type); + + /* Port State */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_STATE); + eiter->a.port_state = cpu_to_be32(2); + alen = sizeof(eiter->a.port_state); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cd, + "PORT_STATE = %x.\n", be32_to_cpu(eiter->a.port_state)); + + /* Number of Ports */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_COUNT); + eiter->a.num_ports = cpu_to_be32(1); + alen = sizeof(eiter->a.num_ports); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ce, + "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); + + /* Port Identifier */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_IDENTIFIER); + eiter->a.port_id = cpu_to_be32(vha->d_id.b24); + alen = sizeof(eiter->a.port_id); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cf, + "PORT ID = %x.\n", be32_to_cpu(eiter->a.port_id)); + + if (callopt == CALLOPT_FDMI2 || !ql2xsmartsan) + goto done; + + /* Smart SAN Service Category (Populate Smart SAN Initiator)*/ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_SERVICE); + alen = scnprintf( + eiter->a.smartsan_service, sizeof(eiter->a.smartsan_service), + "%s", "Smart SAN Initiator"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d0, + "SMARTSAN SERVICE CATEGORY = %s.\n", eiter->a.smartsan_service); + + /* Smart SAN GUID (NWWN+PWWN) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_GUID); + memcpy(eiter->a.smartsan_guid, vha->node_name, WWN_SIZE); + memcpy(eiter->a.smartsan_guid + WWN_SIZE, vha->port_name, WWN_SIZE); + alen = sizeof(eiter->a.smartsan_guid); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d1, + "Smart SAN GUID = %016llx-%016llx\n", + wwn_to_u64(eiter->a.smartsan_guid), + wwn_to_u64(eiter->a.smartsan_guid + WWN_SIZE)); + + /* Smart SAN Version (populate "Smart SAN Version 1.0") */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_VERSION); + alen = scnprintf( + eiter->a.smartsan_version, sizeof(eiter->a.smartsan_version), + "%s", "Smart SAN Version 2.0"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d2, + "SMARTSAN VERSION = %s\n", eiter->a.smartsan_version); + + /* Smart SAN Product Name (Specify Adapter Model No) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_PROD_NAME); + alen = scnprintf(eiter->a.smartsan_prod_name, + sizeof(eiter->a.smartsan_prod_name), + "ISP%04x", ha->pdev->device); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d3, + "SMARTSAN PRODUCT NAME = %s\n", eiter->a.smartsan_prod_name); + + /* Smart SAN Port Info (specify: 1=Physical, 2=NPIV, 3=SRIOV) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_PORT_INFO); + eiter->a.smartsan_port_info = cpu_to_be32(vha->vp_idx ? 2 : 1); + alen = sizeof(eiter->a.smartsan_port_info); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d4, + "SMARTSAN PORT INFO = %x\n", eiter->a.smartsan_port_info); + + /* Smart SAN Security Support */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_SECURITY_SUPPORT); + eiter->a.smartsan_security_support = cpu_to_be32(1); + alen = sizeof(eiter->a.smartsan_security_support); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d6, + "SMARTSAN SECURITY SUPPORT = %d\n", + be32_to_cpu(eiter->a.smartsan_security_support)); + +done: + return size; +} + +/** + * qla2x00_fdmi_rhba() - perform RHBA FDMI registration + * @vha: HA context + * @callopt: Option to issue FDMI registration + * + * Returns 0 on success. + */ +static int +qla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt) +{ + struct qla_hw_data *ha = vha->hw; + unsigned long size = 0; + unsigned int rval, count; + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + void *entries; + + count = callopt != CALLOPT_FDMI1 ? + FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT; + + size = RHBA_RSP_SIZE; + + ql_dbg(ql_dbg_disc, vha, 0x20e0, + "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size); + + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); + + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size); + ct_rsp = &ha->ct_sns->p.rsp; + + /* Prepare FDMI command entries */ + memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, + sizeof(ct_req->req.rhba.hba_identifier)); + size += sizeof(ct_req->req.rhba.hba_identifier); + + ct_req->req.rhba.entry_count = cpu_to_be32(1); + size += sizeof(ct_req->req.rhba.entry_count); + + memcpy(ct_req->req.rhba.port_name, vha->port_name, + sizeof(ct_req->req.rhba.port_name)); + size += sizeof(ct_req->req.rhba.port_name); + + /* Attribute count */ + ct_req->req.rhba.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rhba.attrs.count); + + /* Attribute block */ + entries = &ct_req->req.rhba.attrs.entry; + + size += qla2x00_hba_attributes(vha, entries, callopt); /* Update MS request size. */ qla2x00_update_ms_fdmi_iocb(vha, size + 16); - ql_dbg(ql_dbg_disc, vha, 0x20b5, - "RHBA identifier = %016llx.\n", - wwn_to_u64(ct_req->req.rhba2.hba_identifier)); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6, + ql_dbg(ql_dbg_disc, vha, 0x20e1, + "RHBA %016llx %016llx.\n", + wwn_to_u64(ct_req->req.rhba.hba_identifier), + wwn_to_u64(ct_req->req.rhba.port_name)); + + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20e2, entries, size); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x20b7, - "RHBA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20e3, + "RHBA iocb failed (%d).\n", rval); + return rval; + } + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA"); + if (rval) { if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && ct_rsp->header.explanation_code == CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20b8, - "HBA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x2016, - "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); + ql_dbg(ql_dbg_disc, vha, 0x20e4, + "RHBA already registered.\n"); + return QLA_ALREADY_REGISTERED; } - } else { - ql_dbg(ql_dbg_disc, vha, 0x20b9, - "RHBA FDMI V2 exiting normally.\n"); + + ql_dbg(ql_dbg_disc, vha, 0x20e5, + "RHBA failed, CT Reason %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; } + ql_dbg(ql_dbg_disc, vha, 0x20e6, "RHBA exiting normally.\n"); return rval; } -/** - * qla2x00_fdmi_dhba() - - * @vha: HA context - * - * Returns 0 on success. - */ + static int qla2x00_fdmi_dhba(scsi_qla_host_t *vha) { @@ -2249,22 +2236,17 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) ms_iocb_entry_t *ms_pkt; struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; - /* Issue RPA */ /* Prepare common MS IOCB */ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE, DHBA_RSP_SIZE); - /* Prepare CT request */ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; - /* Prepare FDMI command arguments -- portname. */ memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE); - ql_dbg(ql_dbg_disc, vha, 0x2036, "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name); - /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, sizeof(ms_iocb_entry_t)); @@ -2279,337 +2261,178 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) ql_dbg(ql_dbg_disc, vha, 0x2038, "DHBA exiting normally.\n"); } - return rval; } /** - * qla2x00_fdmiv2_rpa() - + * qla2x00_fdmi_rprt() perform RPRT registration * @vha: HA context + * @callopt: Option to issue extended or standard FDMI + * command parameter * * Returns 0 on success. */ static int -qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) +qla2x00_fdmi_rprt(scsi_qla_host_t *vha, int callopt) { - int rval, alen; - uint32_t size; + struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); struct qla_hw_data *ha = vha->hw; + ulong size = 0; + uint rval, count; ms_iocb_entry_t *ms_pkt; struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; void *entries; - struct ct_fdmiv2_port_attr *eiter; - struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; - struct new_utsname *p_sysid = NULL; + count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? + FDMI2_SMARTSAN_PORT_ATTR_COUNT : + callopt != CALLOPT_FDMI1 ? + FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; - /* Issue RPA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); + size = RPRT_RSP_SIZE; + ql_dbg(ql_dbg_disc, vha, 0x20e8, + "RPRT (callopt=%x count=%u size=%lu).\n", callopt, count, size); + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_CMD, size); + ct_rsp = &ha->ct_sns->p.rsp; + /* Prepare FDMI command entries */ + memcpy(ct_req->req.rprt.hba_identifier, base_vha->port_name, + sizeof(ct_req->req.rprt.hba_identifier)); + size += sizeof(ct_req->req.rprt.hba_identifier); + memcpy(ct_req->req.rprt.port_name, vha->port_name, + sizeof(ct_req->req.rprt.port_name)); + size += sizeof(ct_req->req.rprt.port_name); + /* Attribute count */ + ct_req->req.rprt.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rprt.attrs.count); + /* Attribute block */ + entries = ct_req->req.rprt.attrs.entry; + size += qla2x00_port_attributes(vha, entries, callopt); + /* Update MS request size. */ + qla2x00_update_ms_fdmi_iocb(vha, size + 16); + ql_dbg(ql_dbg_disc, vha, 0x20e9, + "RPRT %016llx %016llx.\n", + wwn_to_u64(ct_req->req.rprt.port_name), + wwn_to_u64(ct_req->req.rprt.port_name)); + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ea, + entries, size); + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20eb, + "RPRT iocb failed (%d).\n", rval); + return rval; + } + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPRT"); + if (rval) { + if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && + ct_rsp->header.explanation_code == + CT_EXPL_ALREADY_REGISTERED) { + ql_dbg(ql_dbg_disc, vha, 0x20ec, + "RPRT already registered.\n"); + return QLA_ALREADY_REGISTERED; + } + + ql_dbg(ql_dbg_disc, vha, 0x20ed, + "RPRT failed, CT Reason code: %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; + } + ql_dbg(ql_dbg_disc, vha, 0x20ee, "RPRT exiting normally.\n"); + return rval; +} + +/** + * qla2x00_fdmi_rpa() - perform RPA registration + * @vha: HA context + * @callopt: Option to issue FDMI registration + * + * Returns 0 on success. + */ +static int +qla2x00_fdmi_rpa(scsi_qla_host_t *vha, uint callopt) +{ + struct qla_hw_data *ha = vha->hw; + ulong size = 0; + uint rval, count; + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + void *entries; + + count = + callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? + FDMI2_SMARTSAN_PORT_ATTR_COUNT : + callopt != CALLOPT_FDMI1 ? + FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; + + size = + callopt != CALLOPT_FDMI1 ? + SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE; + + ql_dbg(ql_dbg_disc, vha, 0x20f0, + "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size); + + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE); + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size); ct_rsp = &ha->ct_sns->p.rsp; - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE); - size = WWN_SIZE + 4; + /* Prepare FDMI command entries. */ + memcpy(ct_req->req.rpa.port_name, vha->port_name, + sizeof(ct_req->req.rpa.port_name)); + size += sizeof(ct_req->req.rpa.port_name); - /* Attributes */ - ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT); - entries = &ct_req->req; + /* Attribute count */ + ct_req->req.rpa.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rpa.attrs.count); - /* FC4 types. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); - eiter->len = cpu_to_be16(4 + 32); - eiter->a.fc4_types[2] = 0x01; - size += 4 + 32; + /* Attribute block */ + entries = ct_req->req.rpa.attrs.entry; - ql_dbg(ql_dbg_disc, vha, 0x20ba, - "FC4_TYPES=%02x %02x.\n", - eiter->a.fc4_types[2], - eiter->a.fc4_types[1]); - - if (vha->flags.nvme_enabled) { - eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ - ql_dbg(ql_dbg_disc, vha, 0x211f, - "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", - eiter->a.fc4_types[6]); - } - - /* Supported speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - if (IS_CNA_CAPABLE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_32GB| - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB); - else if (IS_QLA2031(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB); - else if (IS_QLA25XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA24XX_TYPE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA23XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_1GB); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20bb, - "Supported Port Speed = %x.\n", eiter->a.sup_speed); - - /* Current speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - switch (ha->link_data_rate) { - case PORT_SPEED_1GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB); - break; - case PORT_SPEED_2GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB); - break; - case PORT_SPEED_4GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB); - break; - case PORT_SPEED_8GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB); - break; - case PORT_SPEED_10GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB); - break; - case PORT_SPEED_16GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB); - break; - case PORT_SPEED_32GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB); - break; - default: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); - break; - } - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x2017, - "Current_Speed = %x.\n", eiter->a.cur_speed); - - /* Max frame size. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); - eiter->len = cpu_to_be16(4 + 4); - eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? - le16_to_cpu(icb24->frame_payload_size) : - le16_to_cpu(ha->init_cb->frame_payload_size); - eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20bc, - "Max_Frame_Size = %x.\n", eiter->a.max_frame_size); - - /* OS device name. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - alen = strlen(QLA2XXX_DRIVER_NAME); - snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), - "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20be, - "OS_Device_Name = %s.\n", eiter->a.os_dev_name); - - /* Hostname. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); - p_sysid = utsname(); - if (p_sysid) { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", p_sysid->nodename); - } else { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", fc_host_system_hostname(vha->host)); - } - alen = strlen(eiter->a.host_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x201a, - "HostName=%s.\n", eiter->a.host_name); - - /* Node Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c0, - "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name)); - - /* Port Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_NAME); - memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c1, - "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name)); - - /* Port Symbolic Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); - qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, - sizeof(eiter->a.port_sym_name)); - alen = strlen(eiter->a.port_sym_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20c2, - "port symbolic name = %s\n", eiter->a.port_sym_name); - - /* Port Type */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_TYPE); - eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c3, - "Port Type = %x.\n", eiter->a.port_type); - - /* Class of Service */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); - eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c4, - "Supported COS = %08x\n", eiter->a.port_supported_cos); - - /* Port Fabric Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); - memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c5, - "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); - - /* FC4_type */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); - eiter->a.port_fc4_type[0] = 0; - eiter->a.port_fc4_type[1] = 0; - eiter->a.port_fc4_type[2] = 1; - eiter->a.port_fc4_type[3] = 0; - eiter->len = cpu_to_be16(4 + 32); - size += 4 + 32; - - ql_dbg(ql_dbg_disc, vha, 0x20c6, - "Port Active FC4 Type = %02x %02x.\n", - eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]); - - if (vha->flags.nvme_enabled) { - eiter->a.port_fc4_type[4] = 0; - eiter->a.port_fc4_type[5] = 0; - eiter->a.port_fc4_type[6] = 1; /* NVMe type 28h */ - ql_dbg(ql_dbg_disc, vha, 0x2120, - "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", - eiter->a.port_fc4_type[6]); - } - - /* Port State */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_STATE); - eiter->a.port_state = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c7, - "Port State = %x.\n", eiter->a.port_state); - - /* Number of Ports */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_COUNT); - eiter->a.num_ports = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c8, - "Number of ports = %x.\n", eiter->a.num_ports); - - /* Port Id */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_ID); - eiter->a.port_id = cpu_to_be32(vha->d_id.b24); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x201c, - "Port Id = %x.\n", eiter->a.port_id); + size += qla2x00_port_attributes(vha, entries, callopt); /* Update MS request size. */ qla2x00_update_ms_fdmi_iocb(vha, size + 16); - ql_dbg(ql_dbg_disc, vha, 0x2018, - "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca, + ql_dbg(ql_dbg_disc, vha, 0x20f1, + "RPA %016llx.\n", wwn_to_u64(ct_req->req.rpa.port_name)); + + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20f2, entries, size); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x20cb, - "RPA FDMI v2 issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20f3, + "RPA iocb failed (%d).\n", rval); + return rval; + } + + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA"); + if (rval) { if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && ct_rsp->header.explanation_code == CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20ce, - "RPA FDMI v2 already registered\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x2020, - "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); + ql_dbg(ql_dbg_disc, vha, 0x20f4, + "RPA already registered.\n"); + return QLA_ALREADY_REGISTERED; } - } else { - ql_dbg(ql_dbg_disc, vha, 0x20cc, - "RPA FDMI V2 exiting normally.\n"); + + ql_dbg(ql_dbg_disc, vha, 0x20f5, + "RPA failed, CT Reason code: %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; } + ql_dbg(ql_dbg_disc, vha, 0x20f6, "RPA exiting normally.\n"); return rval; } @@ -2622,18 +2445,31 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) int qla2x00_fdmi_register(scsi_qla_host_t *vha) { - int rval = QLA_FUNCTION_FAILED; + int rval = QLA_SUCCESS; struct qla_hw_data *ha = vha->hw; if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLAFX00(ha)) - return QLA_FUNCTION_FAILED; + return rval; rval = qla2x00_mgmt_svr_login(vha); if (rval) return rval; - rval = qla2x00_fdmiv2_rhba(vha); + /* For npiv/vport send rprt only */ + if (vha->vp_idx) { + if (ql2xsmartsan) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2_SMARTSAN); + if (rval || !ql2xsmartsan) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2); + if (rval) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI1); + + return rval; + } + + /* Try fdmi2 first, if fails then try fdmi1 */ + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); if (rval) { if (rval != QLA_ALREADY_REGISTERED) goto try_fdmi; @@ -2642,18 +2478,22 @@ qla2x00_fdmi_register(scsi_qla_host_t *vha) if (rval) goto try_fdmi; - rval = qla2x00_fdmiv2_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); if (rval) goto try_fdmi; } - rval = qla2x00_fdmiv2_rpa(vha); + + if (ql2xsmartsan) + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2_SMARTSAN); + if (rval || !ql2xsmartsan) + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2); if (rval) goto try_fdmi; - goto out; + return rval; try_fdmi: - rval = qla2x00_fdmi_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); if (rval) { if (rval != QLA_ALREADY_REGISTERED) return rval; @@ -2662,12 +2502,13 @@ try_fdmi: if (rval) return rval; - rval = qla2x00_fdmi_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); if (rval) return rval; } - rval = qla2x00_fdmi_rpa(vha); -out: + + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI1); + return rval; } From 57b38d03971984d108538599d2a1ed189e7b226a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:16:11 +0000 Subject: [PATCH 11/49] qla2x00t-32gbit: Display message for FCE enabled During Link up phase and Data rate MBX command response, print message indicating FCE is enabled. Link: https://lore.kernel.org/r/20200212214436.25532-11-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 75666f4a8c4103fb120717140c26cdbf6b1bf053 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8794 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_isr.c | 6 ++++++ qla2x00t-32gbit/qla_mbx.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index f87853fa8..9b5f69845 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -832,6 +832,12 @@ skip_rio: "LOOP UP detected (%s Gbps).\n", qla2x00_get_link_speed_str(ha, ha->link_data_rate)); + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + if (mb[2] & BIT_0) + ql_log(ql_log_info, vha, 0x11a0, + "FEC=enabled (link up).\n"); + } + vha->flags.management_server_logged_in = 0; qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 2d029616e..c1698bf74 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -5554,6 +5554,15 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x1107, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { + if (mcp->mb[1] != 0x7) + ha->link_data_rate = mcp->mb[1]; + + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + if (mcp->mb[4] & BIT_0) + ql_log(ql_log_info, vha, 0x11a2, + "FEC=enabled (data rate).\n"); + } + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, "Done %s.\n", __func__); if (mcp->mb[1] != 0x7) From e57446e99ff31ecc31a407cb408ac753784c8b19 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:16:41 +0000 Subject: [PATCH 12/49] qla2x00t-32gbit: Show correct port speed capabilities for RDP command This patch correctly displays port speed capability and current speed for RDP command. Link: https://lore.kernel.org/r/20200212214436.25532-12-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 8b01e4db834db611555cc4ec5d8d9550024361af upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8795 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 41 ++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 53b12c916..8df722626 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -5811,13 +5811,39 @@ qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) if (IS_CNA_CAPABLE(ha)) return RDP_PORT_SPEED_10GB; - if (IS_QLA27XX(ha)) { - if (FW_ABILITY_MAX_SPEED(ha) == FW_ABILITY_MAX_SPEED_32G) - return RDP_PORT_SPEED_32GB|RDP_PORT_SPEED_16GB| - RDP_PORT_SPEED_8GB; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + unsigned int speeds = 0; - return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| - RDP_PORT_SPEED_4GB; + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= RDP_PORT_SPEED_64GB; + } + + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= RDP_PORT_SPEED_32GB; + } + + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= RDP_PORT_SPEED_16GB; + } + + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= RDP_PORT_SPEED_8GB; + } + + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= RDP_PORT_SPEED_4GB; + } + + return speeds; } if (IS_QLA2031(ha)) @@ -5863,6 +5889,9 @@ qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) case PORT_SPEED_32GB: return RDP_PORT_SPEED_32GB; + case PORT_SPEED_64GB: + return RDP_PORT_SPEED_64GB; + default: return RDP_PORT_SPEED_UNKNOWN; } From 04176824aa5feea8962631bbd02cdd12ecb3c379 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:17:40 +0000 Subject: [PATCH 13/49] qla2x00t-32gbit: Cleanup ELS/PUREX iocb fields This patch does the following to improve RDP processing: - Rename field port_id to d_id in ELS and PUREX iocb structs to match FW spec. - Remove redundant comments from ELS and PUREX iocb structs. - Refactor fields in ELS iocb struct for error subcode common access. - Properly use error subcode fields in rdp processing routine. - Add print logs for alloc failure in purex rdp processing routine. Link: https://lore.kernel.org/r/20200212214436.25532-13-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 09e382bc3dd946cfee74044d18d1886567874300 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8796 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_fw.h | 39 ++++++++++++++++++++++++-------------- qla2x00t-32gbit/qla_iocb.c | 12 ++++++------ qla2x00t-32gbit/qla_os.c | 28 ++++++++++++++++----------- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index 056040f19..5594d6c83 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -791,9 +791,8 @@ struct els_entry_24xx { uint32_t handle; /* System handle. */ - uint16_t reserved_1; - - uint16_t nport_handle; /* N_PORT handle. */ + uint16_t comp_status; /* response only */ + uint16_t nport_handle; uint16_t tx_dsd_count; @@ -808,7 +807,7 @@ struct els_entry_24xx { uint8_t opcode; uint8_t reserved_2; - uint8_t port_id[3]; + uint8_t d_id[3]; uint8_t s_id[3]; uint16_t control_flags; /* Control flags. */ @@ -820,13 +819,24 @@ struct els_entry_24xx { #define ECF_CLR_PASSTHRU_PEND BIT_12 #define ECF_INCL_FRAME_HDR BIT_11 - __le32 rx_byte_count; - __le32 tx_byte_count; + union { + struct { + __le32 rx_byte_count; + __le32 tx_byte_count; - __le64 tx_address __packed; /* Data segment 0 address. */ - __le32 tx_len; /* Data segment 0 length. */ - __le64 rx_address __packed; /* Data segment 1 address. */ - __le32 rx_len; /* Data segment 1 length. */ + __le64 tx_address __packed; /* DSD 0 address. */ + __le32 tx_len; /* DSD 0 length. */ + + __le64 rx_address __packed; /* DSD 1 address. */ + __le32 rx_len; /* DSD 1 length. */ + }; + struct { + uint32_t total_byte_count; + uint32_t error_subcode_1; + uint32_t error_subcode_2; + uint32_t error_subcode_3; + }; + }; }; struct els_sts_entry_24xx { @@ -852,15 +862,16 @@ struct els_sts_entry_24xx { uint8_t opcode; uint8_t reserved_3; - uint8_t port_id[3]; - uint8_t reserved_4; - - uint16_t reserved_5; + uint8_t d_id[3]; + uint8_t s_id[3]; uint16_t control_flags; /* Control flags. */ uint32_t total_byte_count; uint32_t error_subcode_1; uint32_t error_subcode_2; + uint32_t error_subcode_3; + + uint32_t reserved_4[4]; }; /* * ISP queue - Mailbox Command entry structure definition. diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 92aebc721..c1cd70cc1 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -2690,9 +2690,9 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->rx_dsd_count = 0; els_iocb->opcode = elsio->u.els_logo.els_cmd; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; /* For SID the byte order is different than DID */ els_iocb->s_id[1] = vha->d_id.b.al_pa; els_iocb->s_id[2] = vha->d_id.b.area; @@ -3040,9 +3040,9 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) sp->type == SRB_ELS_CMD_RPT ? bsg_request->rqst_data.r_els.els_code : bsg_request->rqst_data.h_els.command_code; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; els_iocb->control_flags = 0; els_iocb->rx_byte_count = cpu_to_le32(bsg_job->reply_payload.payload_len); diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 8df722626..b31626edf 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -5935,13 +5935,19 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &rsp_els_dma, GFP_KERNEL); - if (!rsp_els) + if (!rsp_els) { + ql_log(ql_log_warn, vha, 0x0183, + "Failed allocate dma buffer ELS RSP.\n"); goto dealloc; + } rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), &rsp_payload_dma, GFP_KERNEL); - if (!rsp_payload) + if (!rsp_payload) { + ql_log(ql_log_warn, vha, 0x0184, + "Failed allocate dma buffer ELS RSP payload.\n"); goto dealloc; + } sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, &sfp_dma, GFP_KERNEL); @@ -5967,9 +5973,9 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) rsp_els->rx_dsd_count = 0; rsp_els->opcode = purex->els_frame_payload[0]; - rsp_els->port_id[0] = purex->s_id[0]; - rsp_els->port_id[1] = purex->s_id[1]; - rsp_els->port_id[2] = purex->s_id[2]; + rsp_els->d_id[0] = purex->s_id[0]; + rsp_els->d_id[1] = purex->s_id[1]; + rsp_els->d_id[2] = purex->s_id[2]; rsp_els->control_flags = EPD_ELS_ACC; rsp_els->rx_byte_count = 0; @@ -6312,14 +6318,14 @@ send: rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); - if (rval != QLA_SUCCESS) { + if (rval) { ql_log(ql_log_warn, vha, 0x0188, - "%s: failed to issue IOCB (%x).\n", __func__, rval); - } else if (rsp_els->entry_status != 0) { + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (rsp_els->comp_status) { ql_log(ql_log_warn, vha, 0x0189, - "%s: failed to complete IOCB -- error status (%x).\n", - __func__, rsp_els->entry_status); - rval = QLA_FUNCTION_FAILED; + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, rsp_els->comp_status, + rsp_els->error_subcode_1, rsp_els->error_subcode_2); } else { ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); } From f2c5c66f397bfab7ad72a8518465954f4d56f9a8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:18:23 +0000 Subject: [PATCH 14/49] qla2x00t-32gbit: Add deferred queue for processing ABTS and RDP This patch adds deferred queue for processing aborts and RDP in the driver. Link: https://lore.kernel.org/r/20200212214436.25532-14-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 576bfde80b28232a1dfcf0466986ed2934146d0a upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8797 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 15 +++- qla2x00t-32gbit/qla_fw.h | 91 +++++++++++++++++++++- qla2x00t-32gbit/qla_gbl.h | 2 + qla2x00t-32gbit/qla_isr.c | 154 +++++++++++++++++++++++++++++++++++++- qla2x00t-32gbit/qla_mid.c | 7 ++ qla2x00t-32gbit/qla_os.c | 62 ++++++++++----- 6 files changed, 304 insertions(+), 27 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index c8ad95c95..329208f62 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4501,6 +4501,15 @@ struct active_regions { #define QLA_SET_DATA_RATE_NOLR 1 #define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */ +struct purex_item { + struct list_head list; + struct scsi_qla_host *vha; + void (*process_item)(struct scsi_qla_host *vha, void *pkt); + struct { + uint8_t iocb[64]; + } iocb; +}; + /* * Qlogic scsi host structure */ @@ -4691,7 +4700,11 @@ typedef struct scsi_qla_host { uint16_t ql2xexchoffld; uint16_t ql2xiniexchg; - void *purex_data; + struct purex_list { + struct list_head head; + spinlock_t lock; + } purex_list; + struct name_list_extended gnl; /* Count of active session/fcport */ int fcport_count; diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index 5594d6c83..a5e28be74 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -739,7 +739,7 @@ struct ct_entry_24xx { * ISP queue - PUREX IOCB entry structure definition */ #define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */ -typedef struct purex_entry_24xx { +struct purex_entry_24xx { uint8_t entry_type; /* Entry type. */ uint8_t entry_count; /* Entry count. */ uint8_t sys_define; /* System defined. */ @@ -775,9 +775,7 @@ typedef struct purex_entry_24xx { uint32_t param; uint8_t els_frame_payload[20]; -} purex_entry_24xx_t; - -#define PUREX_ENTRY_SIZE (sizeof(purex_entry_24xx_t)) +}; /* * ISP queue - ELS Pass-Through entry structure definition. @@ -1012,6 +1010,91 @@ struct abort_entry_24xx { uint8_t reserved_2[12]; }; +#define ABTS_RCV_TYPE 0x54 +#define ABTS_RSP_TYPE 0x55 +struct abts_entry_24xx { + uint8_t entry_type; + uint8_t entry_count; + uint8_t handle_count; + uint8_t entry_status; + + uint32_t handle; /* type 0x55 only */ + + uint16_t comp_status; /* type 0x55 only */ + uint16_t nport_handle; /* type 0x54 only */ + + uint16_t control_flags; /* type 0x55 only */ + uint8_t vp_idx; + uint8_t sof_type; /* sof_type is upper nibble */ + + uint32_t rx_xch_addr; + + uint8_t d_id[3]; + uint8_t r_ctl; + + uint8_t s_id[3]; + uint8_t cs_ctl; + + uint8_t f_ctl[3]; + uint8_t type; + + uint16_t seq_cnt; + uint8_t df_ctl; + uint8_t seq_id; + + uint16_t rx_id; + uint16_t ox_id; + + uint32_t param; + + union { + struct { + uint32_t subcode3; + uint32_t rsvd; + uint32_t subcode1; + uint32_t subcode2; + } error; + struct { + uint16_t rsrvd1; + uint8_t last_seq_id; + uint8_t seq_id_valid; + uint16_t aborted_rx_id; + uint16_t aborted_ox_id; + uint16_t high_seq_cnt; + uint16_t low_seq_cnt; + } ba_acc; + struct { + uint8_t vendor_unique; + uint8_t explanation; + uint8_t reason; + } ba_rjt; + } payload; + + uint32_t rx_xch_addr_to_abort; +} __packed; + +/* ABTS payload explanation values */ +#define BA_RJT_EXP_NO_ADDITIONAL 0 +#define BA_RJT_EXP_INV_OX_RX_ID 3 +#define BA_RJT_EXP_SEQ_ABORTED 5 + +/* ABTS payload reason values */ +#define BA_RJT_RSN_INV_CMD_CODE 1 +#define BA_RJT_RSN_LOGICAL_ERROR 3 +#define BA_RJT_RSN_LOGICAL_BUSY 5 +#define BA_RJT_RSN_PROTOCOL_ERROR 7 +#define BA_RJT_RSN_UNABLE_TO_PERFORM 9 +#define BA_RJT_RSN_VENDOR_SPECIFIC 0xff + +/* FC_F values */ +#define FC_TYPE_BLD 0x000 /* Basic link data */ +#define FC_F_CTL_RSP_CNTXT 0x800000 /* Responder of exchange */ +#define FC_F_CTL_LAST_SEQ 0x100000 /* Last sequence */ +#define FC_F_CTL_END_SEQ 0x80000 /* Last sequence */ +#define FC_F_CTL_SEQ_INIT 0x010000 /* Sequence initiative */ +#define FC_ROUTING_BLD 0x80 /* Basic link data frame */ +#define FC_R_CTL_BLD_BA_ACC 0x04 /* BA_ACC (basic accept) */ + /* * ISP I/O Register Set structure definitions. */ diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 4e9913f0c..6eba62ef7 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -234,6 +234,7 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_post_relogin_work(struct scsi_qla_host *vha); void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *); +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt); /* * Global Functions in qla_mid.c source file. @@ -937,6 +938,7 @@ void qlt_remove_target_resources(struct qla_hw_data *); void qlt_clr_qp_table(struct scsi_qla_host *vha); void qlt_set_mode(struct scsi_qla_host *); int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode); +extern void qla24xx_process_purex_list(struct purex_list *); /* nvme.c */ void qla_nvme_unregister_remote_port(struct fc_port *fcport); diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 9b5f69845..854464665 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -43,13 +43,144 @@ const char *const port_state_str[] = { "ONLINE" }; -static void qla24xx_purex_iocb(scsi_qla_host_t *vha, struct req_que *req, - struct sts_entry_24xx *pkt) +static void qla24xx_purex_iocb(scsi_qla_host_t *vha, void *pkt, + void (*process_item)(struct scsi_qla_host *vha, void *pkt)) { - memcpy(vha->purex_data, pkt, PUREX_ENTRY_SIZE); + struct purex_list *list = &vha->purex_list; + struct purex_item *item; + ulong flags; + + item = kzalloc(sizeof(*item), GFP_KERNEL); + if (!item) { + ql_log(ql_log_warn, vha, 0x5092, + ">> Failed allocate purex list item.\n"); + return; + } + + item->vha = vha; + item->process_item = process_item; + memcpy(&item->iocb, pkt, sizeof(item->iocb)); + + spin_lock_irqsave(&list->lock, flags); + list_add_tail(&item->list, &list->head); + spin_unlock_irqrestore(&list->lock, flags); + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); } +static void +qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt) +{ + struct abts_entry_24xx *abts = pkt; + struct qla_hw_data *ha = vha->hw; + struct els_entry_24xx *rsp_els; + struct abts_entry_24xx *abts_rsp; + dma_addr_t dma; + uint32_t fctl; + int rval; + + ql_dbg(ql_dbg_init, vha, 0x0286, "%s: entered.\n", __func__); + + ql_log(ql_log_warn, vha, 0x0287, + "Processing ABTS xchg=%#x oxid=%#x rxid=%#x seqid=%#x seqcnt=%#x\n", + abts->rx_xch_addr_to_abort, abts->ox_id, abts->rx_id, + abts->seq_id, abts->seq_cnt); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, + "-------- ABTS RCV -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, + (uint8_t *)abts, sizeof(*abts)); + + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &dma, + GFP_KERNEL); + if (!rsp_els) { + ql_log(ql_log_warn, vha, 0x0287, + "Failed allocate dma buffer ABTS/ELS RSP.\n"); + return; + } + + /* terminate exchange */ + memset(rsp_els, 0, sizeof(*rsp_els)); + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; + rsp_els->nport_handle = ~0; + rsp_els->rx_xchg_address = abts->rx_xch_addr_to_abort; + rsp_els->control_flags = EPD_RX_XCHG; + ql_dbg(ql_dbg_init, vha, 0x0283, + "Sending ELS Response to terminate exchange %#x...\n", + abts->rx_xch_addr_to_abort); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, + (uint8_t *)rsp_els, sizeof(*rsp_els)); + rval = qla2x00_issue_iocb(vha, rsp_els, dma, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x0288, + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (rsp_els->comp_status) { + ql_log(ql_log_warn, vha, 0x0289, + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, rsp_els->comp_status, + rsp_els->error_subcode_1, rsp_els->error_subcode_2); + } else { + ql_dbg(ql_dbg_init, vha, 0x028a, + "%s: abort exchange done.\n", __func__); + } + + /* send ABTS response */ + abts_rsp = (void *)rsp_els; + memset(abts_rsp, 0, sizeof(*abts_rsp)); + abts_rsp->entry_type = ABTS_RSP_TYPE; + abts_rsp->entry_count = 1; + abts_rsp->nport_handle = abts->nport_handle; + abts_rsp->vp_idx = abts->vp_idx; + abts_rsp->sof_type = abts->sof_type & 0xf0; + abts_rsp->rx_xch_addr = abts->rx_xch_addr; + abts_rsp->d_id[0] = abts->s_id[0]; + abts_rsp->d_id[1] = abts->s_id[1]; + abts_rsp->d_id[2] = abts->s_id[2]; + abts_rsp->r_ctl = FC_ROUTING_BLD | FC_R_CTL_BLD_BA_ACC; + abts_rsp->s_id[0] = abts->d_id[0]; + abts_rsp->s_id[1] = abts->d_id[1]; + abts_rsp->s_id[2] = abts->d_id[2]; + abts_rsp->cs_ctl = abts->cs_ctl; + /* include flipping bit23 in fctl */ + fctl = ~(abts->f_ctl[2] | 0x7F) << 16 | + FC_F_CTL_LAST_SEQ | FC_F_CTL_END_SEQ | FC_F_CTL_SEQ_INIT; + abts_rsp->f_ctl[0] = fctl >> 0 & 0xff; + abts_rsp->f_ctl[1] = fctl >> 8 & 0xff; + abts_rsp->f_ctl[2] = fctl >> 16 & 0xff; + abts_rsp->type = FC_TYPE_BLD; + abts_rsp->rx_id = abts->rx_id; + abts_rsp->ox_id = abts->ox_id; + abts_rsp->payload.ba_acc.aborted_rx_id = abts->rx_id; + abts_rsp->payload.ba_acc.aborted_ox_id = abts->ox_id; + abts_rsp->payload.ba_acc.high_seq_cnt = ~0; + abts_rsp->rx_xch_addr_to_abort = abts->rx_xch_addr_to_abort; + ql_dbg(ql_dbg_init, vha, 0x028b, + "Sending BA ACC response to ABTS %#x...\n", + abts->rx_xch_addr_to_abort); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, + (uint8_t *)abts_rsp, sizeof(*abts_rsp)); + rval = qla2x00_issue_iocb(vha, abts_rsp, dma, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x028c, + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (abts_rsp->comp_status) { + ql_log(ql_log_warn, vha, 0x028d, + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, abts_rsp->comp_status, + abts_rsp->payload.error.subcode1, + abts_rsp->payload.error.subcode2); + } else { + ql_dbg(ql_dbg_init, vha, 0x028ea, + "%s: done.\n", __func__); + } + + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma); +} + /** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: interrupt number @@ -3121,6 +3252,11 @@ process_err: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; case ABTS_RECV_24XX: + if (qla_ini_mode_enabled(vha)) { + qla24xx_purex_iocb(vha, pkt, + qla24xx_process_abts); + break; + } if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { /* ensure that the ATIO queue is empty */ @@ -3166,8 +3302,18 @@ process_err: (struct vp_ctrl_entry_24xx *)pkt); break; case PUREX_IOCB_TYPE: - qla24xx_purex_iocb(vha, rsp->req, pkt); + { + struct purex_entry_24xx *purex = (void *)pkt; + + if (purex->els_frame_payload[3] != ELS_COMMAND_RDP) { + ql_dbg(ql_dbg_init, vha, 0x5091, + "Discarding ELS Request opcode %#x...\n", + purex->els_frame_payload[3]); + break; + } + qla24xx_purex_iocb(vha, pkt, qla24xx_process_purex_rdp); break; + } default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, diff --git a/qla2x00t-32gbit/qla_mid.c b/qla2x00t-32gbit/qla_mid.c index d211f803c..e86c94f78 100644 --- a/qla2x00t-32gbit/qla_mid.c +++ b/qla2x00t-32gbit/qla_mid.c @@ -361,6 +361,13 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) } } + if (test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)) { + if (atomic_read(&vha->loop_state) == LOOP_READY) { + qla24xx_process_purex_list(&vha->purex_list); + clear_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); + } + } + if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) { ql_dbg(ql_dbg_dpc, vha, 0x4016, "FCPort update scheduled.\n"); diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index b31626edf..2ea6c81f7 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3329,11 +3329,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto probe_failed; } - base_vha->purex_data = kzalloc(PUREX_ENTRY_SIZE, GFP_KERNEL); - if (!base_vha->purex_data) - ql_log(ql_log_warn, base_vha, 0x7118, - "Failed to allocate memory for PUREX data\n"); - if (IS_QLAFX00(ha)) host->can_queue = QLAFX00_MAX_CANQUEUE; else @@ -3516,7 +3511,6 @@ skip_dpc: return 0; probe_failed: - kfree(base_vha->purex_data); if (base_vha->gnl.l) { dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); @@ -3833,8 +3827,6 @@ qla2x00_remove_one(struct pci_dev *pdev) qla84xx_put_chip(base_vha); - kfree(base_vha->purex_data); - /* Disable timer */ if (base_vha->timer_active) qla2x00_stop_timer(base_vha); @@ -3876,6 +3868,20 @@ qla2x00_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } +static inline void +qla24xx_free_purex_list(struct purex_list *list) +{ + struct list_head *item, *next; + ulong flags; + + spin_lock_irqsave(&list->lock, flags); + list_for_each_safe(item, next, &list->head) { + list_del(item); + kfree(list_entry(item, struct purex_item, list)); + } + spin_unlock_irqrestore(&list->lock, flags); +} + static void qla2x00_free_device(scsi_qla_host_t *vha) { @@ -3908,6 +3914,8 @@ qla2x00_free_device(scsi_qla_host_t *vha) } + qla24xx_free_purex_list(&vha->purex_list); + qla2x00_mem_free(ha); qla82xx_md_free(vha); @@ -4881,6 +4889,9 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, INIT_LIST_HEAD(&vha->gpnid_list); INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn); + INIT_LIST_HEAD(&vha->purex_list.head); + spin_lock_init(&vha->purex_list.lock); + spin_lock_init(&vha->work_lock); spin_lock_init(&vha->cmd_list_lock); init_waitqueue_head(&vha->fcport_waitQ); @@ -5907,7 +5918,7 @@ qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) * vha: SCSI qla host * purex: RDP request received by HBA */ -static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) { struct qla_hw_data *ha = vha->hw; struct purex_entry_24xx *purex = pkt; @@ -5923,7 +5934,7 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) struct buffer_credit_24xx *bbc = NULL; uint8_t *sfp = NULL; uint16_t sfp_flags = 0; - int rval = -ENOMEM; + int rval; ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, "%s: Enter\n", __func__); @@ -6348,8 +6359,23 @@ dealloc: if (rsp_els) dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, rsp_els_dma); +} - return rval; +void qla24xx_process_purex_list(struct purex_list *list) +{ + struct list_head head = LIST_HEAD_INIT(head); + struct purex_item *item, *next; + ulong flags; + + spin_lock_irqsave(&list->lock, flags); + list_splice_init(&list->head, &head); + spin_unlock_irqrestore(&list->lock, flags); + + list_for_each_entry_safe(item, next, &head, list) { + list_del(&item->list); + item->process_item(item->vha, &item->iocb); + kfree(item); + } } void @@ -6699,8 +6725,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) base_vha->flags.online = 0; - kfree(base_vha->purex_data); - qla2x00_destroy_deferred_work(ha); /* @@ -6924,11 +6948,13 @@ qla2x00_do_dpc(void *data) } } - if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags) && - (atomic_read(&base_vha->loop_state) == LOOP_READY)) { - qla24xx_process_purex_iocb(base_vha, - base_vha->purex_data); - clear_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags); + if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags)) { + if (atomic_read(&base_vha->loop_state) == LOOP_READY) { + qla24xx_process_purex_list + (&base_vha->purex_list); + clear_bit(PROCESS_PUREX_IOCB, + &base_vha->dpc_flags); + } } if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, From 9350f88176b1fa16f000f4fb1667dfd3711b5847 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:18:56 +0000 Subject: [PATCH 15/49] qla2x00t-32gbit: Handle cases for limiting RDP response payload length This patch reduces RDP response payload length, if requesting port is a domain controller (sid 0xfffc01) and fw is earlier than 8.09.00 and fw is not 8.05.65 then limit the RDP response payload length to maximum of 256 bytes by terminating the response just before the optical element descriptor. Link: https://lore.kernel.org/r/20200212214436.25532-15-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Joe Carnuccio Signed-off-by: Martin K. Petersen [ commit 4879237cd28eebb9350a7e6d970677997abe2b9d upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8798 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 42 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 2ea6c81f7..15e506a66 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -5816,6 +5816,32 @@ retry_lock: return; } +static bool +qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, + struct purex_entry_24xx *purex) +{ + char fwstr[16]; + u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; + + /* Domain Controller is always logged-out. */ + /* if RDP request is not from Domain Controller: */ + if (sid != 0xfffc01) + return false; + + ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); + + vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); + fwstr[strcspn(fwstr, " ")] = 0; + /* if FW version allows RDP response length upto 2048 bytes: */ + if (strcmp(fwstr, "8.09.00") > 0 || strcmp(fwstr, "8.05.65") == 0) + return false; + + ql_dbg(ql_dbg_init, vha, 0x0181, "%s: fw=%s\n", __func__, fwstr); + + /* RDP response length is to be reduced to maximum 256 bytes */ + return true; +} + static uint qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) { @@ -5934,6 +5960,7 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) struct buffer_credit_24xx *bbc = NULL; uint8_t *sfp = NULL; uint16_t sfp_flags = 0; + uint rsp_payload_length = sizeof(*rsp_payload); int rval; ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, @@ -5944,6 +5971,14 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, (void *)purex, sizeof(*purex)); + if (qla25xx_rdp_rsp_reduce_size(vha, purex)) { + rsp_payload_length = + offsetof(typeof(*rsp_payload), optical_elmt_desc); + ql_dbg(ql_dbg_init, vha, 0x0181, + "Reducing RSP payload length to %u bytes...\n", + rsp_payload_length); + } + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &rsp_els_dma, GFP_KERNEL); if (!rsp_els) { @@ -5990,7 +6025,7 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_els->control_flags = EPD_ELS_ACC; rsp_els->rx_byte_count = 0; - rsp_els->tx_byte_count = cpu_to_le32(sizeof(*rsp_payload)); + rsp_els->tx_byte_count = cpu_to_le32(rsp_payload_length); put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); rsp_els->tx_len = rsp_els->tx_byte_count; @@ -6165,6 +6200,9 @@ accept: } } + if (rsp_payload_length < sizeof(*rsp_payload)) + goto send; + if (sfp) { memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); @@ -6325,7 +6363,7 @@ send: ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, "-------- ELS RSP PAYLOAD -------\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, - (void *)rsp_payload, rsp_els->tx_byte_count); + (void *)rsp_payload, rsp_payload_length); rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); From d2d888e9d8729672de3f855eb1ae78e2c77948b5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:19:26 +0000 Subject: [PATCH 16/49] qla2x00t-32gbit: Fix RDP response size This patch fixes RDP length in case when driver needs to reduce length of RDP response Link: https://lore.kernel.org/r/20200212214436.25532-16-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 84f7d2e7b1f5203050b47cfa65e284182d32f203 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8799 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 53 ++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 15e506a66..74e58ecdb 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -5822,6 +5822,7 @@ qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, { char fwstr[16]; u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; + struct port_database_24xx *pdb; /* Domain Controller is always logged-out. */ /* if RDP request is not from Domain Controller: */ @@ -5830,6 +5831,24 @@ qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); + pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); + if (!pdb) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Failed allocate pdb\n", __func__); + } else if (qla24xx_get_port_database(vha, purex->nport_handle, pdb)) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Failed get pdb sid=%x\n", __func__, sid); + } else if (pdb->current_login_state != PDS_PLOGI_COMPLETE && + pdb->current_login_state != PDS_PRLI_COMPLETE) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Port not logged in sid=%#x\n", __func__, sid); + } else { + /* RDP request is from logged in port */ + kfree(pdb); + return false; + } + kfree(pdb); + vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); fwstr[strcspn(fwstr, " ")] = 0; /* if FW version allows RDP response length upto 2048 bytes: */ @@ -5948,7 +5967,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) { struct qla_hw_data *ha = vha->hw; struct purex_entry_24xx *purex = pkt; - struct port_database_24xx *pdb = NULL; dma_addr_t rsp_els_dma; dma_addr_t rsp_payload_dma; dma_addr_t stat_dma; @@ -6033,34 +6051,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_els->rx_address = 0; rsp_els->rx_len = 0; - if (sizeof(*rsp_payload) <= 0x100) - goto accept; - - pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); - if (!pdb) - goto reduce; - - rval = qla24xx_get_port_database(vha, purex->nport_handle, pdb); - if (rval) - goto reduce; - - if (pdb->port_id[0] != purex->s_id[2] || - pdb->port_id[1] != purex->s_id[1] || - pdb->port_id[2] != purex->s_id[0]) - goto reduce; - - if (pdb->current_login_state == PDS_PLOGI_COMPLETE || - pdb->current_login_state == PDS_PRLI_COMPLETE) - goto accept; - -reduce: - ql_dbg(ql_dbg_init, vha, 0x016e, "Requesting port is not logged in.\n"); - rsp_els->tx_byte_count = rsp_els->tx_len = - offsetof(struct rdp_rsp_payload, buffer_credit_desc); - ql_dbg(ql_dbg_init, vha, 0x016f, "Reduced response payload size %u.\n", - rsp_els->tx_byte_count); - -accept: /* Prepare Response Payload */ rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ rsp_payload->hdr.len = cpu_to_be32( @@ -6178,9 +6168,6 @@ accept: vha->fabric_port_name, sizeof(rsp_payload->port_name_direct_desc.WWPN)); - if (rsp_els->tx_byte_count < sizeof(*rsp_payload)) - goto send; - if (bbc) { memset(bbc, 0, sizeof(*bbc)); rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); @@ -6380,8 +6367,6 @@ send: } dealloc: - kfree(pdb); - if (bbc) dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), bbc, bbc_dma); From b06d019fd8c9b80641b17639cd7182086ff8db69 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:20:03 +0000 Subject: [PATCH 17/49] qla2x00t-32gbit: Use endian macros to assign static fields in fwdump header This takes care of big endian architectures. Link: https://lore.kernel.org/r/20200212214436.25532-17-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit a31056ddc6651b457d72d8d71d32143764df86d2 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8800 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_tmpl.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/qla2x00t-32gbit/qla_tmpl.c b/qla2x00t-32gbit/qla_tmpl.c index 5b0c057de..6aeb1c3fb 100644 --- a/qla2x00t-32gbit/qla_tmpl.c +++ b/qla2x00t-32gbit/qla_tmpl.c @@ -870,7 +870,7 @@ bailout: static void qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp) { - tmp->capture_timestamp = jiffies; + tmp->capture_timestamp = cpu_to_le32(jiffies); } static void @@ -882,9 +882,10 @@ qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", v+0, v+1, v+2, v+3, v+4, v+5) != 6); - tmp->driver_info[0] = v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]; - tmp->driver_info[1] = v[5] << 8 | v[4]; - tmp->driver_info[2] = 0x12345678; + tmp->driver_info[0] = cpu_to_le32( + v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); + tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]); + tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678); } static void @@ -894,10 +895,10 @@ qla27xx_firmware_info(struct scsi_qla_host *vha, tmp->firmware_version[0] = vha->hw->fw_major_version; tmp->firmware_version[1] = vha->hw->fw_minor_version; tmp->firmware_version[2] = vha->hw->fw_subminor_version; - tmp->firmware_version[3] = - vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes; - tmp->firmware_version[4] = - vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]; + tmp->firmware_version[3] = cpu_to_le32( + vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes); + tmp->firmware_version[4] = cpu_to_le32( + vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]); } static void From 369e73fb5ad59b94b02b41618e4b2b7495ce4e13 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:20:40 +0000 Subject: [PATCH 18/49] qla2x00t-32gbit: Correction to selection of loopback/echo test This fixes loopback and echo test options. Link: https://lore.kernel.org/r/20200212214436.25532-18-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 64d21b314173c46d5c88a55cf559b0677e39d884 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8801 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 a070c717f..37d0db295 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -777,7 +777,7 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) uint16_t response[MAILBOX_REGISTER_COUNT]; uint16_t config[4], new_config[4]; uint8_t *fw_sts_ptr; - uint8_t *req_data = NULL; + void *req_data = NULL; dma_addr_t req_data_dma; uint32_t req_data_len; uint8_t *rsp_data = NULL; From 67f2033af85a74ed14af5db5ba51ad6bcbd85f8f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:21:17 +0000 Subject: [PATCH 19/49] qla2x00t-32gbit: Fix qla2x00_echo_test() based on ISP type Ths patch fixes MBX in-direction for setting right bits for qla2x00_echo_test() Link: https://lore.kernel.org/r/20200212214436.25532-19-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 83cfd3dc002fc730387a1ec5fa0d4097cc31ee9f upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8802 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_mbx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index c1698bf74..cd4f441f7 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -5317,10 +5317,11 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mcp->out_mb |= MBX_2; mcp->in_mb = MBX_0; - if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || - IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) + if (IS_CNA_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || + IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_1; - if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) + if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) mcp->in_mb |= MBX_3; mcp->tov = MBX_TOV_SECONDS; From be964cdb42826d6ee2862558da311a39a5e6af9c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:21:46 +0000 Subject: [PATCH 20/49] qla2x00t-32gbit: Print portname for logging in qla24xx_logio_entry() Add port name in the messages file to help debugging of Login/Logout IOCBs Link: https://lore.kernel.org/r/20200212214436.25532-20-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit cbe729a63d5a2c5909c6ae7e54665059496e43b9 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8803 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_isr.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 854464665..1136d900f 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -1919,11 +1919,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, } if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { - ql_dbg(ql_dbg_async, fcport->vha, 0x5036, - "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x " - "iop0=%x.\n", type, fcport->port_name, sp->handle, - fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, + ql_dbg(ql_dbg_async, sp->vha, 0x5036, + "Async-%s complete: handle=%x pid=%06x wwpn=%8phC iop0=%x\n", + type, sp->handle, fcport->d_id.b24, fcport->port_name, le32_to_cpu(logio->io_parameter[0])); vha->hw->exch_starvation = 0; @@ -2002,11 +2000,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, break; } - ql_dbg(ql_dbg_async, fcport->vha, 0x5037, - "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x " - "iop0=%x iop1=%x.\n", type, fcport->port_name, - sp->handle, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, + ql_dbg(ql_dbg_async, sp->vha, 0x5037, + "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n", + type, sp->handle, fcport->d_id.b24, fcport->port_name, le16_to_cpu(logio->comp_status), le32_to_cpu(logio->io_parameter[0]), le32_to_cpu(logio->io_parameter[1])); From 62a6e7be90eabd6ae4948a612505d808350f138e Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:22:15 +0000 Subject: [PATCH 21/49] qla2x00t-32gbit: Use correct ISP28xx active FW region For ISP28xx, use 28xx call to retrieve active FW region. Link: https://lore.kernel.org/r/20200212214436.25532-21-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit 8d4926d13076a89c1f750fe5af4c082d8ea15008 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8804 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 37d0db295..52555a643 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -2574,7 +2574,7 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job) regions.global_image = active_regions.global; if (IS_QLA28XX(ha)) { - qla27xx_get_active_image(vha, &active_regions); + qla28xx_get_aux_images(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; From a14a1505f293fae40d5bca01cee083d4aa50f6a0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:22:51 +0000 Subject: [PATCH 22/49] qla2x00t-32gbit: Save rscn_gen for new fcport Add missing rscn_gen when creating new fcport. Link: https://lore.kernel.org/r/20200212214436.25532-22-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit d26a8982c9bd92ce3596eb4f86e922cdaf6751e5 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8805 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_gs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index e67105aca..5af49a7dd 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -3487,6 +3487,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE)) continue; fcport->scan_state = QLA_FCPORT_FOUND; + fcport->last_rscn_gen = fcport->rscn_gen; found = true; /* * If device was not a fabric device before. From 7c96145fa568c3f24cac56d8df4cc39a29514d55 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:23:24 +0000 Subject: [PATCH 23/49] qla2x00t-32gbit: Fix control flags for login/logout IOCB This patch fixes control flag options for login/logout IOCB. Link: https://lore.kernel.org/r/20200212214436.25532-23-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 419ae5fe73e50084fa794934fb62fab34f564b7c upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8806 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_iocb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index c1cd70cc1..fd1906dd8 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -2368,6 +2368,8 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) struct srb_iocb *lio = &sp->u.iocb_cmd; logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; + logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); + if (lio->u.logio.flags & SRB_LOGIN_PRLI_ONLY) { logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI); } else { @@ -2945,7 +2947,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, sp->fcport = fcport; elsio->timeout = qla2x00_els_dcmd2_iocb_timeout; - init_completion(&elsio->u.els_plogi.comp); if (wait) sp->flags = SRB_WAKEUP_ON_COMP; @@ -2955,7 +2956,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE; ptr = elsio->u.els_plogi.els_plogi_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.tx_size, &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_plogi_pyld) { @@ -2964,7 +2965,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, } resp_ptr = elsio->u.els_plogi.els_resp_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.rx_size, &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_resp_pyld) { @@ -2988,6 +2989,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, sizeof(*elsio->u.els_plogi.els_plogi_pyld)); + init_completion(&elsio->u.els_plogi.comp); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { rval = QLA_FUNCTION_FAILED; From b72c9a33d29913bae5c20aaffab7551468096e1b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:23:58 +0000 Subject: [PATCH 24/49] qla2x00t-32gbit: Add fixes for mailbox command This patch fixes: - qla2x00_issue_iocb_timeout will now return if chip is down - only check for sp->qpair in abort handling Link: https://lore.kernel.org/r/20200212214436.25532-24-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 345f574dac85276d1471492c6e90c57e3f90a4f3 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8807 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_mbx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index cd4f441f7..3bb6ab6f2 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -1404,6 +1404,9 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + if (qla2x00_chip_is_down(vha)) + return QLA_INVALID_COMMAND; + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, "Entered %s.\n", __func__); @@ -1475,7 +1478,7 @@ qla2x00_abort_command(srb_t *sp) ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b, "Entered %s.\n", __func__); - if (vha->flags.qpairs_available && sp->qpair) + if (sp->qpair) req = sp->qpair->req; else req = vha->req; From 9959382e107ef503d3af5e97fb794c601c2a5486 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:24:47 +0000 Subject: [PATCH 25/49] qla2x00t-32gbit: Use QLA_FW_STOPPED macro to propagate flag This patch uses QLA_FW_STOPPED macro so that flag is propogated to all the QPairs. Link: https://lore.kernel.org/r/20200212214436.25532-25-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 0fc5b7e62322e1aa8384013ee1caff3f87d30207 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8808 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 0cd1d1648..a0d5cabea 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -6677,7 +6677,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) ha->flags.n2n_ae = 0; ha->flags.lip_ae = 0; ha->current_topology = 0; - ha->flags.fw_started = 0; + QLA_FW_STOPPED(ha); ha->flags.fw_init_done = 0; ha->chip_reset++; ha->base_qpair->chip_reset = ha->chip_reset; From f46232802babcc7df863c243a2abdf1dfd3e6fff Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:25:31 +0000 Subject: [PATCH 26/49] qla2x00t-32gbit: Update driver version to 10.01.00.24-k Link: https://lore.kernel.org/r/20200212214436.25532-26-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 1939295a8dfa7be1cea478d6d7d283c091b780d4 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8809 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 bb03c022e..6b4ca3ed8 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.22-k" +#define QLA2XXX_VERSION "10.01.00.24-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1 From 0f6172d6acfb642d6baa0c235e5f3d319100df66 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:26:34 +0000 Subject: [PATCH 27/49] qla2x00t-32gbit: Fix sparse warning reported by kbuild bot this patch fixes following sparse warnings >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: sparse: incorrect type in assignment (different base types) >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: expected unsigned int [usertype] capture_timestamp >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: got restricted __le32 [usertype] drivers/scsi/qla2xxx/qla_tmpl.c:885:29: sparse: sparse: incorrect type in assignment (different base types) >> drivers/scsi/qla2xxx/qla_tmpl.c:885:29: sparse: expected unsigned int vim +873 drivers/scsi/qla2xxx/qla_tmpl.c 869 870 static void 871 qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp) 872 { > 873 tmp->capture_timestamp = cpu_to_le32(jiffies); 874 } 875 876 static void 877 qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) 878 { 879 uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; 880 881 WARN_ON_ONCE(sscanf(qla2x00_version_str, 882 "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", 883 v+0, v+1, v+2, v+3, v+4, v+5) != 6); 884 > 885 tmp->driver_info[0] = cpu_to_le32( 886 v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); 887 tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]); 888 tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678); 889 } 890 Link: https://lore.kernel.org/r/20200227201148.13973-1-hmadhani@marvell.com Fixes: a31056ddc665 ("scsi: qla2xxx: Use endian macros to assign static fields in fwdump header") Reported-by: kbuild test robot Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 0a36fd6cef5e3a11a273300e777a26cb26274547 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8810 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_tmpl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_tmpl.h b/qla2x00t-32gbit/qla_tmpl.h index d2a0014e8..bba8dc90a 100644 --- a/qla2x00t-32gbit/qla_tmpl.h +++ b/qla2x00t-32gbit/qla_tmpl.h @@ -18,11 +18,11 @@ struct __packed qla27xx_fwdt_template { __le32 entry_count; uint32_t template_version; - uint32_t capture_timestamp; + __le32 capture_timestamp; uint32_t template_checksum; uint32_t reserved_2; - uint32_t driver_info[3]; + __le32 driver_info[3]; uint32_t saved_state[16]; From 75581dea86530320f212138e37908decea9bd411 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:27:19 +0000 Subject: [PATCH 28/49] qla2x00t-32gbit: Simplify the code for aborting SCSI commands Since the SCSI core does not reuse the tag of the SCSI command that is being aborted by .eh_abort() before .eh_abort() has finished it is not necessary to check from inside that callback whether or not the SCSI command has already completed. Instead, rely on the firmware to return an error code when attempting to abort a command that has already completed. Additionally, rely on the firmware to return an error code when attempting to abort an already aborted command. In qla2x00_abort_srb(), use blk_mq_request_started() instead of sp->completed and sp->aborted. Link: https://lore.kernel.org/r/20200220043441.20504-2-bvanassche@acm.org Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Acked-by: Himanshu Madhani Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen c81ef0ed4477c637d1f1dd96ecd8e8fbe18b7283 git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8811 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 3 --- qla2x00t-32gbit/qla_isr.c | 5 ----- qla2x00t-32gbit/qla_os.c | 27 ++++++++++++++------------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 329208f62..e5a7b28f6 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -619,9 +619,6 @@ typedef struct srb { struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; - unsigned int abort:1; - unsigned int aborted:1; - unsigned int completed:1; uint32_t handle; uint16_t flags; diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 1136d900f..db103d73f 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -2681,11 +2681,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) return; } - if (sp->abort) - sp->aborted = 1; - else - sp->completed = 1; - if (sp->cmd_type != TYPE_SRB) { req->outstanding_cmds[handle] = NULL; ql_dbg(ql_dbg_io, vha, 0x3015, diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 74e58ecdb..98043e811 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -1307,17 +1307,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return SUCCESS; spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (sp->completed) { - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return SUCCESS; - } - - if (sp->abort || sp->aborted) { - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return FAILED; - } - - sp->abort = 1; sp->comp = ∁ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); @@ -1742,6 +1731,10 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) return QLA_SUCCESS; } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, unsigned long *flags) __releases(qp->qp_lock_ptr) @@ -1750,6 +1743,7 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, DECLARE_COMPLETION_ONSTACK(comp); scsi_qla_host_t *vha = qp->vha; struct qla_hw_data *ha = vha->hw; + struct scsi_cmnd *cmd = GET_CMD_SP(sp); int rval; bool ret_cmd; uint32_t ratov_j; @@ -1771,7 +1765,6 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, } sp->comp = ∁ - sp->abort = 1; spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); rval = ha->isp_ops->abort_command(sp); @@ -1795,13 +1788,17 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, } spin_lock_irqsave(qp->qp_lock_ptr, *flags); - if (ret_cmd && (!sp->completed || !sp->aborted)) + if (ret_cmd && blk_mq_request_started(cmd->request)) sp->done(sp, res); } else { sp->done(sp, res); } } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ static void __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) { @@ -1848,6 +1845,10 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) spin_unlock_irqrestore(qp->qp_lock_ptr, flags); } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ void qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) { From 69315453ffcc3e3305fe833279e747e8ab795b95 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:27:57 +0000 Subject: [PATCH 29/49] qla2x00t-32gbit: Suppress endianness complaints in qla2x00_configure_local_loop() Instead of changing endianness in-place, write the data in CPU endian format in another buffer and copy that buffer back. This patch does not change any functionality but silences some sparse endianness warnings. Link: https://lore.kernel.org/r/20200220043441.20504-3-bvanassche@acm.org Cc: Roman Bolshakov Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen [ commit 1ee5ac365c2a554b59b0e7445455d93a0577662b upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8812 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 2 +- qla2x00t-32gbit/qla_init.c | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index e5a7b28f6..05558b848 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -436,7 +436,7 @@ struct els_logo_payload { struct els_plogi_payload { uint8_t opcode; uint8_t rsvd[3]; - uint8_t data[112]; + __be32 data[112 / 4]; }; struct ct_arg { diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index a0d5cabea..59311d9da 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -5076,7 +5076,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) if (N2N_TOPO(ha)) { if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { /* borrowing */ - u32 *bp, i, sz; + u32 *bp, sz; memset(ha->init_cb, 0, ha->init_cb_size); sz = min_t(int, sizeof(struct els_plogi_payload), @@ -5084,13 +5084,12 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, (void *)ha->init_cb, sz); if (rval == QLA_SUCCESS) { - bp = (uint32_t *)ha->init_cb; - for (i = 0; i < sz/4 ; i++, bp++) - *bp = cpu_to_be32(*bp); + __be32 *q = &ha->plogi_els_payld.data[0]; - memcpy(&ha->plogi_els_payld.data, - (void *)ha->init_cb, - sizeof(ha->plogi_els_payld.data)); + bp = (uint32_t *)ha->init_cb; + cpu_to_be32_array(q, bp, sz / 4); + + memcpy(bp, q, sizeof(ha->plogi_els_payld.data)); } else { ql_dbg(ql_dbg_init, vha, 0x00d1, "PLOGI ELS param read fail.\n"); From 37b9c874791a9b8c40fd196337b7ad68d0b714f8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:28:39 +0000 Subject: [PATCH 30/49] qla2x00t-32gbit: Fix sparse warnings triggered by the PCI state checking code This patch fixes the following sparse warnings: drivers/scsi/qla2xxx/qla_mbx.c:120:21: warning: restricted pci_channel_state_t degrades to integer drivers/scsi/qla2xxx/qla_mbx.c:120:37: warning: restricted pci_channel_state_t degrades to integer >From include/linux/pci.h: enum pci_channel_state { /* I/O channel is in normal state */ pci_channel_io_normal = (__force pci_channel_state_t) 1, /* I/O to channel is blocked */ pci_channel_io_frozen = (__force pci_channel_state_t) 2, /* PCI card is dead */ pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, }; Link: https://lore.kernel.org/r/20200220043441.20504-4-bvanassche@acm.org Cc: Roman Bolshakov Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Acked-by: Himanshu Madhani Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen [ commit 471298cab82d255e358901ea5baff24abe1a53b8 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8813 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_mbx.c | 5 ++--- qla2x00t-32gbit/qla_mr.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 3bb6ab6f2..85e5a1b6a 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -117,10 +117,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); - if (ha->pdev->error_state > pci_channel_io_frozen) { + if (ha->pdev->error_state == pci_channel_io_perm_failure) { ql_log(ql_log_warn, vha, 0x1001, - "error_state is greater than pci_channel_io_frozen, " - "exiting.\n"); + "PCI channel failed permanently, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } diff --git a/qla2x00t-32gbit/qla_mr.c b/qla2x00t-32gbit/qla_mr.c index 5e61f20d4..719a6ee68 100644 --- a/qla2x00t-32gbit/qla_mr.c +++ b/qla2x00t-32gbit/qla_mr.c @@ -53,10 +53,9 @@ qlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp) struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); - if (ha->pdev->error_state > pci_channel_io_frozen) { + if (ha->pdev->error_state == pci_channel_io_perm_failure) { ql_log(ql_log_warn, vha, 0x115c, - "error_state is greater than pci_channel_io_frozen, " - "exiting.\n"); + "PCI channel failed permanently, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } From c9e7188d200ec0d67890714024115d52ea97f499 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:29:20 +0000 Subject: [PATCH 31/49] qla2x00t-32gbit: Convert MAKE_HANDLE() from a define into an inline function This patch allows sparse to verify the endianness of the arguments passed to make_handle(). Link: https://lore.kernel.org/r/20200220043441.20504-5-bvanassche@acm.org Cc: Roman Bolshakov Cc: Daniel Wagner Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Acked-by: Himanshu Madhani Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen [ commit c25eb70a10243c1ad24e74375aceb65ab8951e93 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8814 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 5 ++++- qla2x00t-32gbit/qla_iocb.c | 22 +++++++++++----------- qla2x00t-32gbit/qla_mbx.c | 10 +++++----- qla2x00t-32gbit/qla_mr.c | 8 ++++---- qla2x00t-32gbit/qla_nvme.c | 2 +- qla2x00t-32gbit/qla_target.c | 6 +++--- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 05558b848..b91444745 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -141,7 +141,10 @@ typedef struct { #define LSD(x) ((uint32_t)((uint64_t)(x))) #define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) -#define MAKE_HANDLE(x, y) ((uint32_t)((((uint32_t)(x)) << 16) | (uint32_t)(y))) +static inline uint32_t make_handle(uint16_t x, uint16_t y) +{ + return ((uint32_t)x << 16) | y; +} /* * I/O register diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index fd1906dd8..10f795b96 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -530,7 +530,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle); + mrk24->handle = make_handle(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16((uint16_t)lun); @@ -1661,7 +1661,7 @@ qla24xx_start_scsi(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -1849,7 +1849,7 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -1981,7 +1981,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -2184,7 +2184,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -2497,7 +2497,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->entry_type = TSK_MGMT_IOCB_TYPE; tsk->entry_count = 1; - tsk->handle = MAKE_HANDLE(req->id, tsk->handle); + tsk->handle = make_handle(req->id, tsk->handle); tsk->nport_handle = cpu_to_le16(fcport->loop_id); tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); tsk->control_flags = cpu_to_le32(flags); @@ -3378,7 +3378,7 @@ sufficient_dsds: } cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -3449,7 +3449,7 @@ sufficient_dsds: goto queuing_error; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ @@ -3554,7 +3554,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) memset(abt_iocb, 0, sizeof(struct abort_entry_24xx)); abt_iocb->entry_type = ABORT_IOCB_TYPE; abt_iocb->entry_count = 1; - abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + abt_iocb->handle = cpu_to_le32(make_handle(req->id, sp->handle)); if (sp->fcport) { abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; @@ -3562,7 +3562,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) abt_iocb->port_id[2] = sp->fcport->d_id.b.domain; } abt_iocb->handle_to_abort = - cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no, + cpu_to_le32(make_handle(aio->u.abt.req_que_no, aio->u.abt.cmd_hndl)); abt_iocb->vp_index = vha->vp_idx; abt_iocb->req_que_no = cpu_to_le16(aio->u.abt.req_que_no); @@ -3929,7 +3929,7 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) } cmd_pkt = (struct cmd_bidir *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 85e5a1b6a..0f0af3c2c 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -2437,7 +2437,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; - lg->handle = MAKE_HANDLE(req->id, lg->handle); + lg->handle = make_handle(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); if (opt & BIT_0) @@ -2707,7 +2707,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, req = vha->req; lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; - lg->handle = MAKE_HANDLE(req->id, lg->handle); + lg->handle = make_handle(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO| @@ -3197,9 +3197,9 @@ qla24xx_abort_command(srb_t *sp) abt->entry_type = ABORT_IOCB_TYPE; abt->entry_count = 1; - abt->handle = MAKE_HANDLE(req->id, abt->handle); + abt->handle = make_handle(req->id, abt->handle); abt->nport_handle = cpu_to_le16(fcport->loop_id); - abt->handle_to_abort = MAKE_HANDLE(req->id, handle); + abt->handle_to_abort = make_handle(req->id, handle); abt->port_id[0] = fcport->d_id.b.al_pa; abt->port_id[1] = fcport->d_id.b.area; abt->port_id[2] = fcport->d_id.b.domain; @@ -3276,7 +3276,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; tsk->p.tsk.entry_count = 1; - tsk->p.tsk.handle = MAKE_HANDLE(req->id, tsk->p.tsk.handle); + tsk->p.tsk.handle = make_handle(req->id, tsk->p.tsk.handle); tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); tsk->p.tsk.control_flags = cpu_to_le32(type); diff --git a/qla2x00t-32gbit/qla_mr.c b/qla2x00t-32gbit/qla_mr.c index 719a6ee68..01e5e1db5 100644 --- a/qla2x00t-32gbit/qla_mr.c +++ b/qla2x00t-32gbit/qla_mr.c @@ -3148,7 +3148,7 @@ qlafx00_start_scsi(srb_t *sp) memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE); - lcmd_pkt.handle = MAKE_HANDLE(req->id, sp->handle); + lcmd_pkt.handle = make_handle(req->id, sp->handle); lcmd_pkt.reserved_0 = 0; lcmd_pkt.port_path_ctrl = 0; lcmd_pkt.reserved_1 = 0; @@ -3218,7 +3218,7 @@ qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb) memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00)); tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00; tm_iocb.entry_count = 1; - tm_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + tm_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); tm_iocb.reserved_0 = 0; tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id); tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags); @@ -3244,9 +3244,9 @@ qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb) memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00)); abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00; abt_iocb.entry_count = 1; - abt_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + abt_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); abt_iocb.abort_handle = - cpu_to_le32(MAKE_HANDLE(req->id, fxio->u.abt.cmd_hndl)); + cpu_to_le32(make_handle(req->id, fxio->u.abt.cmd_hndl)); abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id); abt_iocb.req_que_no = cpu_to_le16(req->id); diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 5b7f4abdc..7bd8ccb37 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -424,7 +424,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_nvme *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ clr_ptr = (uint32_t *)cmd_pkt + 2; diff --git a/qla2x00t-32gbit/qla_target.c b/qla2x00t-32gbit/qla_target.c index 72761eb53..4b1126cb4 100644 --- a/qla2x00t-32gbit/qla_target.c +++ b/qla2x00t-32gbit/qla_target.c @@ -1773,7 +1773,7 @@ static int qlt_build_abts_resp_iocb(struct qla_tgt_mgmt_cmd *mcmd) qpair->req->outstanding_cmds[h] = (srb_t *)mcmd; } - resp->handle = MAKE_HANDLE(qpair->req->id, h); + resp->handle = make_handle(qpair->req->id, h); resp->entry_type = ABTS_RESP_24XX; resp->entry_count = 1; resp->nport_handle = abts->nport_handle; @@ -2610,7 +2610,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair, } else qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle = make_handle(qpair->req->id, h); pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); @@ -3124,7 +3124,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) } else qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle = make_handle(qpair->req->id, h); pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); From 4000dcb0fa9c67ceb4d77d4b46d16515747c9793 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:30:03 +0000 Subject: [PATCH 32/49] qla2x00t-32gbit: Add 16.0GT for PCI String This patch adds 16.0GT for readable display string. Link: https://lore.kernel.org/r/20200226224022.24518-2-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit efd39a2ad6ff6d1187caac8491d710f41b6a93ab upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8815 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 98043e811..2d8c41294 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -620,6 +620,9 @@ qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) case 3: speed_str = "8.0GT/s"; break; + case 4: + speed_str = "16.0GT/s"; + break; default: speed_str = ""; break; From ab031229cef5d582d4f8390e94eb6f933554a7ac Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:30:37 +0000 Subject: [PATCH 33/49] qla2x00t-32gbit: Avoid setting firmware options twice in 24xx_update_fw_options. This patch moves ql2xrdpenable check earlier to avoids setting fw_option once again before exiting qla24xx_update_fw_options. Link: https://lore.kernel.org/r/20200226224022.24518-3-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: Martin K. Petersen [ commit 9ef4847a80d317e4033c2ecf0e73e54c5fd4771d upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8816 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_init.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 59311d9da..57a9656b1 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3929,6 +3929,9 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] &= ~BIT_8; } + if (ql2xrdpenable) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + ql_dbg(ql_dbg_init, vha, 0x00e8, "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", __func__, ha->fw_options[1], ha->fw_options[2], @@ -3939,7 +3942,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) /* Update Serial Link options. */ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) - goto enable_purex; + return; rval = qla2x00_set_serdes_params(vha, le16_to_cpu(ha->fw_seriallink_options24[1]), @@ -3949,12 +3952,6 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ql_log(ql_log_warn, vha, 0x0104, "Unable to update Serial Link options (%x).\n", rval); } - -enable_purex: - if (ql2xrdpenable) - ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; - - qla2x00_set_fw_options(vha, ha->fw_options); } void From 545a43ff56f00a8e592174c67016d4e9a4898a22 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:31:12 +0000 Subject: [PATCH 34/49] qla2x00t-32gbit: Use FC generic update firmware options routine for ISP27xx This patch uses generic firmware update options for FCoE based adapters as well to reduce code duplication. Link: https://lore.kernel.org/r/20200226224022.24518-4-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: Martin K. Petersen [ commit 37efd51f75f30b48c2d19ee94eeccfd4325c3cb4 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8817 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_gbl.h | 2 -- qla2x00t-32gbit/qla_init.c | 66 -------------------------------------- qla2x00t-32gbit/qla_os.c | 4 +-- 3 files changed, 2 insertions(+), 70 deletions(-) diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 6eba62ef7..359601bea 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -31,8 +31,6 @@ extern int qla24xx_nvram_config(struct scsi_qla_host *); extern int qla81xx_nvram_config(struct scsi_qla_host *); extern void qla2x00_update_fw_options(struct scsi_qla_host *); extern void qla24xx_update_fw_options(scsi_qla_host_t *); -extern void qla81xx_update_fw_options(scsi_qla_host_t *); -extern void qla83xx_update_fw_options(scsi_qla_host_t *); extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 57a9656b1..5d0886ff5 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -8680,72 +8680,6 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) return status; } -void -qla83xx_update_fw_options(scsi_qla_host_t *vha) -{ - struct qla_hw_data *ha = vha->hw; - - if (ql2xrdpenable) - ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; - - qla2x00_set_fw_options(vha, ha->fw_options); -} - -void -qla81xx_update_fw_options(scsi_qla_host_t *vha) -{ - struct qla_hw_data *ha = vha->hw; - - /* Hold status IOCBs until ABTS response received. */ - if (ql2xfwholdabts) - ha->fw_options[3] |= BIT_12; - - /* Set Retry FLOGI in case of P2P connection */ - if (ha->operating_mode == P2P) { - ha->fw_options[2] |= BIT_3; - ql_dbg(ql_dbg_disc, vha, 0x2103, - "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n", - __func__, ha->fw_options[2]); - } - - /* Move PUREX, ABTS RX & RIDA to ATIOQ */ - if (ql2xmvasynctoatio) { - if (qla_tgt_mode_enabled(vha) || - qla_dual_mode_enabled(vha)) - ha->fw_options[2] |= BIT_11; - else - ha->fw_options[2] &= ~BIT_11; - } - - if (qla_tgt_mode_enabled(vha) || - qla_dual_mode_enabled(vha)) { - /* FW auto send SCSI status during */ - ha->fw_options[1] |= BIT_8; - ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8; - - /* FW perform Exchange validation */ - ha->fw_options[2] |= BIT_4; - } else { - ha->fw_options[1] &= ~BIT_8; - ha->fw_options[10] &= 0x00ff; - - ha->fw_options[2] &= ~BIT_4; - } - - if (ql2xetsenable) { - /* Enable ETS Burst. */ - memset(ha->fw_options, 0, sizeof(ha->fw_options)); - ha->fw_options[2] |= BIT_9; - } - - ql_dbg(ql_dbg_init, vha, 0x00e9, - "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", - __func__, ha->fw_options[1], ha->fw_options[2], - ha->fw_options[3], vha->host->active_mode); - - qla2x00_set_fw_options(vha, ha->fw_options); -} - /* * qla24xx_get_fcp_prio * Gets the fcp cmd priority value for the logged in port. diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 2d8c41294..5fedb84d8 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -2349,7 +2349,7 @@ static struct isp_operations qla81xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla83xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, @@ -2466,7 +2466,7 @@ static struct isp_operations qla83xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla83xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, From f0e0dcd90344997f33ba1ec81b5b02d377dc48ea Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:31:52 +0000 Subject: [PATCH 35/49] qla2x00t-32gbit: Fix FCP-SCSI FC4 flag passing error This patch fixes issue where incorrect flag was used for sending switch commands. Link: https://lore.kernel.org/r/20200226224022.24518-5-hmadhani@marvell.com Fixes: e8c72ba51a15 ("[SCSI] qla2xxx: Use GFF_ID to check FCP-SCSI FC4 type before logging into Nx_Ports") Fixes: a4239945b8ad ("scsi: qla2xxx: Add switch command to simplify fabric discovery") Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit 8e0e063af0d1be30245a08fab0515a3cccfcd513 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8818 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_gs.c | 4 ++-- qla2x00t-32gbit/qla_init.c | 4 ++-- qla2x00t-32gbit/qla_target.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index 5af49a7dd..42c3ad27f 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -2733,7 +2733,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list) for (i = 0; i < ha->max_fibre_devices; i++) { /* Set default FC4 Type as UNKNOWN so the default is to * Process this port */ - list[i].fc4_type = FC4_TYPE_UNKNOWN; + list[i].fc4_type = 0; /* Do not attempt GFF_ID if we are not FWI_2 capable */ if (!IS_FWI2_CAPABLE(ha)) @@ -3083,7 +3083,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) "%s %d %8phC post new sess\n", __func__, __LINE__, ea->port_name); qla24xx_post_newsess_work(vha, &ea->id, - ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN); + ea->port_name, NULL, NULL, 0); } } } diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 5d0886ff5..21092f30b 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -1043,7 +1043,7 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) __func__, __LINE__, (u8 *)&wwn, id.b24); wwnn = wwn_to_u64(e->node_name); qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn, - (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN); + (u8 *)&wwnn, NULL, 0); } } @@ -5829,7 +5829,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha) /* Bypass ports whose FCP-4 type is not FCP_SCSI */ if (ql2xgffidenable && (!(new_fcport->fc4_type & FS_FC4TYPE_FCP) && - new_fcport->fc4_type != FC4_TYPE_UNKNOWN)) + new_fcport->fc4_type != 0)) continue; spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); diff --git a/qla2x00t-32gbit/qla_target.c b/qla2x00t-32gbit/qla_target.c index 4b1126cb4..371835aaa 100644 --- a/qla2x00t-32gbit/qla_target.c +++ b/qla2x00t-32gbit/qla_target.c @@ -4807,11 +4807,11 @@ static int qlt_handle_login(struct scsi_qla_host *vha, qla24xx_post_newsess_work(vha, &port_id, iocb->u.isp24.port_name, iocb->u.isp24.u.plogi.node_name, - pla, FC4_TYPE_UNKNOWN); + pla, 0); else qla24xx_post_newsess_work(vha, &port_id, iocb->u.isp24.port_name, NULL, - pla, FC4_TYPE_UNKNOWN); + pla, 0); goto out; } From f3061aef5ff2f3461781164c71721477c9f27c03 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:32:39 +0000 Subject: [PATCH 36/49] qla2x00t-32gbit: Improved secure flash support messages This patch improved message for Secure Flash support. No functionality has been changed. Link: https://lore.kernel.org/r/20200226224022.24518-6-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Michael Hernandez Signed-off-by: Martin K. Petersen [ commit 4ba836f686284ef1eab0cf7a8f3402e24e6dc4cd upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8819 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_init.c | 6 +++--- qla2x00t-32gbit/qla_mbx.c | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 21092f30b..6187494aa 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2219,10 +2219,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *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"); + if (RD_REG_DWORD(®->mailbox12) & BIT_0) ha->flags.secure_adapter = 1; - } + ql_log(ql_log_info, vha, 0xffff, "Secure Adapter: %s\n", + (ha->flags.secure_adapter) ? "Yes" : "No"); } diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 0f0af3c2c..938b4e419 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -1135,11 +1135,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) 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"); + if (mcp->mb[16] & BIT_10) ha->flags.secure_fw = 1; - } + + ql_log(ql_log_info, vha, 0xffff, + "Secure Flash Update in FW: %s\n", + (ha->flags.secure_fw) ? "Supported" : + "Not Supported"); } } From c04763810c49dbb29bd7e147026665b7a8064af9 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:33:31 +0000 Subject: [PATCH 37/49] qla2x00t-32gbit: Return appropriate failure through BSG Interface This patch ensures flash updates API calls return possible failure status through BSG interface to the application. Link: https://lore.kernel.org/r/20200226224022.24518-7-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Michael Hernandez Signed-off-by: Martin K. Petersen [ commit 1b81e7f3019d632a707e07927e946ffbbc102910 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8820 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_bsg.c | 9 +++++++-- qla2x00t-32gbit/qla_sup.c | 13 ++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 52555a643..a5ebcd08b 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -1601,10 +1601,15 @@ qla2x00_update_optrom(struct bsg_job *bsg_job) bsg_job->request_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); - ha->isp_ops->write_optrom(vha, ha->optrom_buffer, + rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); - bsg_reply->result = DID_OK; + if (rval) { + bsg_reply->result = -EINVAL; + rval = -EINVAL; + } else { + bsg_reply->result = DID_OK; + } vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index bbe90354f..07f0d8669 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -2686,7 +2686,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t sec_mask, rest_addr, fdata; void *optrom = NULL; dma_addr_t optrom_dma; - int rval; + int rval, ret; struct secure_flash_update_block *sfub; dma_addr_t sfub_dma; uint32_t offset = faddr << 2; @@ -2942,11 +2942,12 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, write_protect: ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, "Protect flash...\n"); - rval = qla24xx_protect_flash(vha); - if (rval) { + ret = qla24xx_protect_flash(vha); + if (ret) { qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); ql_log(ql_log_warn, vha, 0x7099, "Failed protect flash\n"); + rval = QLA_COMMAND_ERROR; } if (reset_to_rom == true) { @@ -2954,10 +2955,12 @@ write_protect: set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); - rval = qla2x00_wait_for_hba_online(vha); - if (rval != QLA_SUCCESS) + ret = qla2x00_wait_for_hba_online(vha); + if (ret != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0xffff, "Adapter did not come out of reset\n"); + rval = QLA_COMMAND_ERROR; + } } done: From 99aaaf0a06c8c9aad991e06c4ec2bc36bbbf241d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:34:25 +0000 Subject: [PATCH 38/49] qla2x00t-32gbit: Use a dedicated interrupt handler for 'handshake-required' ISPs There's no point checking flags.disable_msix_handshake in the interrupt handler hot-path. Instead perform the check during queue-pair instantiation and use the proper interrupt handler. Link: https://lore.kernel.org/r/20200226224022.24518-8-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Andrew Vasquez Signed-off-by: Martin K. Petersen [ commit 7b2a73963c91cf6bad6b8f58636560cd1f3cf319 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8821 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 1 + qla2x00t-32gbit/qla_gbl.h | 2 ++ qla2x00t-32gbit/qla_isr.c | 31 ++++++++++++++++++++++++------- qla2x00t-32gbit/qla_mid.c | 3 ++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index b91444745..6fa6be8f8 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3277,6 +3277,7 @@ struct isp_operations { #define QLA_MSIX_RSP_Q 0x01 #define QLA_ATIO_VECTOR 0x02 #define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03 +#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04 #define QLA_MIDX_DEFAULT 0 #define QLA_MIDX_RSP_Q 1 diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 359601bea..05773bc82 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -569,6 +569,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *, uint32_t); extern irqreturn_t qla2xxx_msix_rsp_q(int irq, void *dev_id); +extern irqreturn_t +qla2xxx_msix_rsp_q_hs(int irq, void *dev_id); fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t); fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8); fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index db103d73f..efc02b2d5 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -3617,6 +3617,25 @@ qla24xx_msix_default(int irq, void *dev_id) irqreturn_t qla2xxx_msix_rsp_q(int irq, void *dev_id) +{ + struct qla_hw_data *ha; + struct qla_qpair *qpair; + + qpair = dev_id; + if (!qpair) { + ql_log(ql_log_info, NULL, 0x505b, + "%s: NULL response queue pointer.\n", __func__); + return IRQ_NONE; + } + ha = qpair->hw; + + queue_work(ha->wq, &qpair->q_work); + + return IRQ_HANDLED; +} + +irqreturn_t +qla2xxx_msix_rsp_q_hs(int irq, void *dev_id) { struct qla_hw_data *ha; struct qla_qpair *qpair; @@ -3631,13 +3650,10 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id) } ha = qpair->hw; - /* Clear the interrupt, if enabled, for this response queue */ - if (unlikely(!ha->flags.disable_msix_handshake)) { - reg = &ha->iobase->isp24; - spin_lock_irqsave(&ha->hardware_lock, flags); - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - } + reg = &ha->iobase->isp24; + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); queue_work(ha->wq, &qpair->q_work); @@ -3669,6 +3685,7 @@ static const struct qla_init_msix_entry msix_entries[] = { { "rsp_q", qla24xx_msix_rsp_q }, { "atio_q", qla83xx_msix_atio_q }, { "qpair_multiq", qla2xxx_msix_rsp_q }, + { "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs }, }; static const struct qla_init_msix_entry qla82xx_msix_entries[] = { diff --git a/qla2x00t-32gbit/qla_mid.c b/qla2x00t-32gbit/qla_mid.c index e86c94f78..d82e92da5 100644 --- a/qla2x00t-32gbit/qla_mid.c +++ b/qla2x00t-32gbit/qla_mid.c @@ -896,7 +896,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, rsp->rsp_q_out); ret = qla25xx_request_irq(ha, qpair, qpair->msix, - QLA_MSIX_QPAIR_MULTIQ_RSP_Q); + ha->flags.disable_msix_handshake ? + QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS); if (ret) goto que_failed; From 98844e345608fb1ddd6eac993acc7cd728e33edf Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:35:00 +0000 Subject: [PATCH 39/49] qla2x00t-32gbit: fix FW resource count values This patch fixes issue where current and original exchanges count were swapped for intiator and targets. Also fix IOCB count for current and original which were swapped. Link: https://lore.kernel.org/r/20200226224022.24518-9-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit ce1ee122e0f048fc67c1259489f0802a28049bfd upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8822 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_dfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/qla2x00t-32gbit/qla_dfs.c b/qla2x00t-32gbit/qla_dfs.c index 0a6fb359f..e62b21152 100644 --- a/qla2x00t-32gbit/qla_dfs.c +++ b/qla2x00t-32gbit/qla_dfs.c @@ -134,11 +134,11 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) } else { seq_puts(s, "FW Resource count\n\n"); seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]); - seq_printf(s, "current TGT exchg count[%d]\n", mb[2]); - seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]); - seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]); - seq_printf(s, "Original IOCB count[%d]\n", mb[7]); - seq_printf(s, "Current IOCB count[%d]\n", mb[10]); + seq_printf(s, "Current TGT exchg count[%d]\n", mb[2]); + seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[3]); + seq_printf(s, "Original Initiator Exchange count[%d]\n", mb[6]); + seq_printf(s, "Current IOCB count[%d]\n", mb[7]); + seq_printf(s, "Original IOCB count[%d]\n", mb[10]); seq_printf(s, "MAX VP count[%d]\n", mb[11]); seq_printf(s, "MAX FCF count[%d]\n", mb[12]); seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n", @@ -149,7 +149,6 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) mb[22]); seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n", mb[23]); - } return 0; From 44b99951e2660e72faede7c083eb446dbeb77b16 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:35:34 +0000 Subject: [PATCH 40/49] qla2x00t-32gbit: Update BPM enablement semantics. commit e4e3a2ce9556 ("scsi: qla2xxx: Add ability to autodetect SFP type") takes a heavy handed approach to BPM (Buffer Plus Management) enablement: 1) During hardware initialization, if an LR-capable transceiver is recognized, the driver schedules a disruptive post-initialization chip-reset (ISP-ABORT) to allow the BPM settings to be sent to the firmware. This chip-reset will result in (short-term) path-loss to all fc-rports and their attached SCSI devices. 2) LR-detection is triggered during any link-up event, resulting in a refresh and potential chip-reset Based on firmware-team guidance, upon LR-capable transceiver recognition, the driver's hardware initialization code will now re-execute firmware with the new BPM settings, then continue on with driver initialization. To address the second issue, the driver performs LR-capable detection upon the driver receiving a transceiver-insertion asynchronous event from firmware. No short-term path loss is needed with this new semantic. Link: https://lore.kernel.org/r/20200226224022.24518-10-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Andrew Vasquez Signed-off-by: Martin K. Petersen [ commit b0f18eee6fc1ee21c07abb55e9ccabc9ed9c09f0 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8823 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_def.h | 20 +++++---- qla2x00t-32gbit/qla_fw.h | 3 +- qla2x00t-32gbit/qla_gbl.h | 2 +- qla2x00t-32gbit/qla_init.c | 88 +++++++++++++++++++++++++++----------- qla2x00t-32gbit/qla_isr.c | 9 ++-- qla2x00t-32gbit/qla_mbx.c | 48 +++------------------ qla2x00t-32gbit/qla_os.c | 22 ++++------ 7 files changed, 97 insertions(+), 95 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 6fa6be8f8..8cc106a1a 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -1075,6 +1075,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBA_TEMPERATURE_ALERT 0x8070 /* Temperature Alert */ #define MBA_DPORT_DIAGNOSTICS 0x8080 /* D-port Diagnostics */ #define MBA_TRANS_INSERT 0x8130 /* Transceiver Insertion */ +#define MBA_TRANS_REMOVE 0x8131 /* Transceiver Removal */ #define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */ #define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change Notification */ @@ -3829,8 +3830,8 @@ struct qla_hw_data { uint32_t fw_started:1; uint32_t fw_init_done:1; - uint32_t detected_lr_sfp:1; - uint32_t using_lr_setting:1; + uint32_t lr_detected:1; + uint32_t rida_fmt2:1; uint32_t purge_mbox:1; uint32_t n2n_bigger:1; @@ -3839,7 +3840,7 @@ struct qla_hw_data { } flags; uint16_t max_exchg; - uint16_t long_range_distance; /* 32G & above */ + uint16_t lr_distance; /* 32G & above */ #define LR_DISTANCE_5K 1 #define LR_DISTANCE_10K 0 @@ -4998,11 +4999,14 @@ struct sff_8247_a0 { u8 resv2[128]; }; -#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_QLA28XX(_vha->hw))) +/* BPM -- Buffer Plus Management support. */ +#define IS_BPM_CAPABLE(ha) \ + (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ + IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BPM_RANGE_CAPABLE(ha) \ + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BPM_ENABLED(vha) \ + (ql2xautodetectsfp && !vha->vp_idx && IS_BPM_CAPABLE(vha->hw)) #define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016 diff --git a/qla2x00t-32gbit/qla_fw.h b/qla2x00t-32gbit/qla_fw.h index a5e28be74..ec87f1424 100644 --- a/qla2x00t-32gbit/qla_fw.h +++ b/qla2x00t-32gbit/qla_fw.h @@ -1878,9 +1878,8 @@ struct access_chip_rsp_84xx { /* LR Distance bit positions */ #define LR_DIST_NV_POS 2 +#define LR_DIST_NV_MASK 0xf #define LR_DIST_FW_POS 12 -#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 diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 05773bc82..4b44e569b 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -109,7 +109,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *, int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*, void *, u8); int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); -int qla24xx_detect_sfp(scsi_qla_host_t *vha); +int qla24xx_detect_sfp(scsi_qla_host_t *); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); extern void qla28xx_get_aux_images(struct scsi_qla_host *, diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 6187494aa..a47c07566 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3550,53 +3550,77 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha) } -/* - * Return Code: - * QLA_SUCCESS: no action - * QLA_INTERFACE_ERROR: SFP is not there. - * QLA_FUNCTION_FAILED: detected New SFP +/** + * qla24xx_detect_sfp() + * + * @vha: adapter state pointer. + * + * @return + * 0 -- Configure firmware to use short-range settings -- normal + * buffer-to-buffer credits. + * + * 1 -- Configure firmware to use long-range settings -- extra + * buffer-to-buffer credits should be allocated with + * ha->lr_distance containing distance settings from NVRAM or SFP + * (if supported). */ int qla24xx_detect_sfp(scsi_qla_host_t *vha) { - int rc = QLA_SUCCESS; + int rc, used_nvram; struct sff_8247_a0 *a; struct qla_hw_data *ha = vha->hw; + struct nvram_81xx *nv = ha->nvram; +#define LR_DISTANCE_UNKNOWN 2 + static const char * const types[] = { "Short", "Long" }; + static const char * const lengths[] = { "(10km)", "(5km)", "" }; + u8 ll = 0; - if (!AUTO_DETECT_SFP_SUPPORT(vha)) + /* Seed with NVRAM settings. */ + used_nvram = 0; + ha->flags.lr_detected = 0; + if (IS_BPM_RANGE_CAPABLE(ha) && + (nv->enhanced_features & NEF_LR_DIST_ENABLE)) { + used_nvram = 1; + ha->flags.lr_detected = 1; + ha->lr_distance = + (nv->enhanced_features >> LR_DIST_NV_POS) + & LR_DIST_NV_MASK; + } + + if (!IS_BPM_ENABLED(vha)) goto out; - + /* Determine SR/LR capabilities of SFP/Transceiver. */ rc = qla2x00_read_sfp_dev(vha, NULL, 0); if (rc) goto out; + used_nvram = 0; a = (struct sff_8247_a0 *)vha->hw->sfp_data; qla2xxx_print_sfp_info(vha); - if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) { - /* long range */ - ha->flags.detected_lr_sfp = 1; + ha->flags.lr_detected = 0; + ll = a->fc_ll_cc7; + if (ll & FC_LL_VL || ll & FC_LL_L) { + /* Long range, track length. */ + ha->flags.lr_detected = 1; if (a->length_km > 5 || a->length_100m > 50) - ha->long_range_distance = LR_DISTANCE_10K; + ha->lr_distance = LR_DISTANCE_10K; else - ha->long_range_distance = LR_DISTANCE_5K; - - if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting) - ql_dbg(ql_dbg_async, vha, 0x507b, - "Detected Long Range SFP.\n"); - } else { - /* short range */ - ha->flags.detected_lr_sfp = 0; - if (ha->flags.using_lr_setting) - ql_dbg(ql_dbg_async, vha, 0x5084, - "Detected Short Range SFP.\n"); + ha->lr_distance = LR_DISTANCE_5K; } if (!vha->flags.init_done) rc = QLA_SUCCESS; out: - return rc; + ql_dbg(ql_dbg_async, vha, 0x507b, + "SFP detect: %s-Range SFP %s (nvr=%x ll=%x lr=%x lrd=%x).\n", + types[ha->flags.lr_detected], + ha->flags.lr_detected ? lengths[ha->lr_distance] : + lengths[LR_DISTANCE_UNKNOWN], + used_nvram, ll, ha->flags.lr_detected, ha->lr_distance); + return ha->flags.lr_detected; } /** @@ -3614,6 +3638,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; unsigned long flags; uint16_t fw_major_version; + int done_once = 0; if (IS_P3P_TYPE(ha)) { rval = ha->isp_ops->load_risc(vha, &srisc_address); @@ -3634,6 +3659,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) qla81xx_mpi_sync(vha); +execute_fw_with_lr: /* Load firmware sequences */ rval = ha->isp_ops->load_risc(vha, &srisc_address); if (rval == QLA_SUCCESS) { @@ -3655,7 +3681,15 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) rval = qla2x00_execute_fw(vha, srisc_address); /* Retrieve firmware information. */ if (rval == QLA_SUCCESS) { - qla24xx_detect_sfp(vha); + /* Enable BPM support? */ + if (!done_once++ && qla24xx_detect_sfp(vha)) { + ql_dbg(ql_dbg_init, vha, 0x00ca, + "Re-starting firmware -- BPM.\n"); + /* Best-effort - re-init. */ + ha->isp_ops->reset_chip(vha); + ha->isp_ops->chip_diag(vha); + goto execute_fw_with_lr; + } if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) && @@ -3932,6 +3966,10 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) if (ql2xrdpenable) ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + /* Enable Async 8130/8131 events -- transceiver insertion/removal */ + if (IS_BPM_RANGE_CAPABLE(ha)) + ha->fw_options[3] |= BIT_10; + ql_dbg(ql_dbg_init, vha, 0x00e8, "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", __func__, ha->fw_options[1], ha->fw_options[2], diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index efc02b2d5..f4380a22b 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -972,10 +972,6 @@ skip_rio: vha->flags.management_server_logged_in = 0; qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); - if (AUTO_DETECT_SFP_SUPPORT(vha)) { - set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); - } break; case MBA_LOOP_DOWN: /* Loop Down Event */ @@ -1448,6 +1444,11 @@ global_port_update: case MBA_TRANS_INSERT: ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Insertion: %04x\n", mb[1]); + set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); + break; + + case MBA_TRANS_REMOVE: + ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Removal\n"); break; default: diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 938b4e419..11a60fb1b 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -643,28 +643,6 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, } #define NVME_ENABLE_FLAG BIT_3 -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) || IS_QLA28XX(ha)) - mb4 |= ha->long_range_distance << LR_DIST_FW_POS; - - return mb4; -} - -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) || IS_QLA28XX(ha)) { - struct nvram_81xx *nv = ha->nvram; - - mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features); - } - - return mb4; -} /* * qla2x00_execute_fw @@ -701,25 +679,13 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[3] = 0; mcp->mb[4] = 0; mcp->mb[11] = 0; - ha->flags.using_lr_setting = 0; - if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - if (ql2xautodetectsfp) { - if (ha->flags.detected_lr_sfp) { - mcp->mb[4] |= - qla25xx_set_sfp_lr_dist(ha); - ha->flags.using_lr_setting = 1; - } - } else { - struct nvram_81xx *nv = ha->nvram; - /* set LR distance if specified in nvram */ - if (nv->enhanced_features & - NEF_LR_DIST_ENABLE) { - mcp->mb[4] |= - qla25xx_set_nvr_lr_dist(ha); - ha->flags.using_lr_setting = 1; - } - } + + /* Enable BPM? */ + if (ha->flags.lr_detected) { + mcp->mb[4] = BIT_0; + if (IS_BPM_RANGE_CAPABLE(ha)) + mcp->mb[4] |= + ha->lr_distance << LR_DIST_FW_POS; } if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha))) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 5fedb84d8..a7108a4fb 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3505,13 +3505,6 @@ skip_dpc: if (test_bit(UNLOADING, &base_vha->dpc_flags)) return -ENODEV; - if (ha->flags.detected_lr_sfp) { - ql_log(ql_log_info, base_vha, 0xffff, - "Reset chip to pick up LR SFP setting\n"); - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); - qla2xxx_wake_dpc(base_vha); - } - return 0; probe_failed: @@ -6928,13 +6921,14 @@ qla2x00_do_dpc(void *data) } if (test_and_clear_bit(DETECT_SFP_CHANGE, - &base_vha->dpc_flags) && - !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) { - qla24xx_detect_sfp(base_vha); - - if (ha->flags.detected_lr_sfp != - ha->flags.using_lr_setting) - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); + &base_vha->dpc_flags)) { + /* Semantic: + * - NO-OP -- await next ISP-ABORT. Preferred method + * to minimize disruptions that will occur + * when a forced chip-reset occurs. + * - Force -- ISP-ABORT scheduled. + */ + /* set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); */ } if (test_and_clear_bit From 8b1ff82c9943c6a0b6310bad7b525692f6c1e77b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:36:04 +0000 Subject: [PATCH 41/49] qla2x00t-32gbit: add more FW debug information Per FW request, MB 1-7 should be logged for 8002 error. Link: https://lore.kernel.org/r/20200226224022.24518-11-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit a82c307e69c465e4d80cc15fde3c00f5b95832d6 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8824 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_isr.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index f4380a22b..99bc1d7fe 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -866,12 +866,24 @@ skip_rio: break; case MBA_SYSTEM_ERR: /* System Error */ - 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 " - "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); + mbx = 0; + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || + IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + u16 m[4]; + + m[0] = RD_REG_WORD(®24->mailbox4); + m[1] = RD_REG_WORD(®24->mailbox5); + m[2] = RD_REG_WORD(®24->mailbox6); + mbx = m[3] = RD_REG_WORD(®24->mailbox7); + + ql_log(ql_log_warn, vha, 0x5003, + "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh mbx4=%xh mbx5=%xh mbx6=%xh mbx7=%xh.\n", + mb[1], mb[2], mb[3], m[0], m[1], m[2], m[3]); + } else + ql_log(ql_log_warn, vha, 0x5003, + "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n ", + mb[1], mb[2], mb[3]); + ha->fw_dump_mpi = (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && RD_REG_WORD(®24->mailbox7) & BIT_8; From 44ab6ef708dcb6578ebfd6e01d0550feb4488498 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:36:34 +0000 Subject: [PATCH 42/49] qla2x00t-32gbit: Force semaphore on flash validation failure For single port 28XX adapter, the second core can still run in the background. The flash semaphore can be held by the non-active core. This patch tell MPI FW to check for this case and clear the semaphore from the non-active core. Link: https://lore.kernel.org/r/20200226224022.24518-12-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit cad9c2d28ec69f1d0370b2ba5abe309b0b709be4 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8825 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_mbx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 11a60fb1b..2c01deb5c 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -666,10 +666,14 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) struct qla_hw_data *ha = vha->hw; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + u8 semaphore = 0; +#define EXE_FW_FORCE_SEMAPHORE BIT_7 + u8 retry = 3; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025, "Entered %s.\n", __func__); +again: mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; @@ -711,6 +715,9 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) if (ha->flags.exchoffld_enabled) mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD; + if (semaphore) + mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE; + mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11; mcp->in_mb |= MBX_3 | MBX_2 | MBX_1; } else { @@ -727,6 +734,15 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { + if (IS_QLA28XX(ha) && rval == QLA_COMMAND_ERROR && + mcp->mb[1] == 0x27 && retry) { + semaphore = 1; + retry--; + ql_dbg(ql_dbg_async, vha, 0x1026, + "Exe FW: force semaphore.\n"); + goto again; + } + ql_dbg(ql_dbg_mbx, vha, 0x1026, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); return rval; From cacab3adea2529ddd0c19545d0657d739f09c289 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:37:02 +0000 Subject: [PATCH 43/49] qla2x00t-32gbit: Fix RDP respond data format RPD information failed to display by switch cli command. This is caused by driver failure to properly format RDP response data with data descriptor to allow switch to parse it correctly. Link: https://lore.kernel.org/r/20200226224022.24518-13-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit 770538c3012ac8ff92d5e4ae18850588c188c5fa upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8826 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 102 ++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index a7108a4fb..2ae5a5c1e 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -6020,7 +6020,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) &bbc_dma, GFP_KERNEL); /* Prepare Response IOCB */ - memset(rsp_els, 0, sizeof(*rsp_els)); rsp_els->entry_type = ELS_IOCB_TYPE; rsp_els->entry_count = 1; rsp_els->sys_define = 0; @@ -6067,6 +6066,11 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_payload->ls_req_info_desc2.req_payload_word_0 = cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + rsp_payload->sfp_diag_desc.desc_tag = cpu_to_be32(0x10000); + rsp_payload->sfp_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); + if (sfp) { /* SFP Flags */ memset(sfp, 0, SFP_RTDI_LEN); @@ -6090,23 +6094,18 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) sfp_flags |= BIT_6; /* sfp+ */ } + rsp_payload->sfp_diag_desc.sfp_flags = cpu_to_be16(sfp_flags); + /* SFP Diagnostics */ memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); - if (!rval && sfp_flags) { + if (!rval) { uint16_t *trx = (void *)sfp; /* already be16 */ - - rsp_payload->sfp_diag_desc.desc_tag = - cpu_to_be32(0x10000); - rsp_payload->sfp_diag_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); rsp_payload->sfp_diag_desc.temperature = trx[0]; rsp_payload->sfp_diag_desc.vcc = trx[1]; rsp_payload->sfp_diag_desc.tx_bias = trx[2]; rsp_payload->sfp_diag_desc.tx_power = trx[3]; rsp_payload->sfp_diag_desc.rx_power = trx[4]; - rsp_payload->sfp_diag_desc.sfp_flags = - cpu_to_be16(sfp_flags); } } @@ -6119,14 +6118,14 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( qla25xx_rdp_port_speed_currently(ha)); + /* Link Error Status Descriptor */ + rsp_payload->ls_err_desc.desc_tag = cpu_to_be32(0x10002); + rsp_payload->ls_err_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); + if (stat) { rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); if (!rval) { - /* Link Error Status Descriptor */ - rsp_payload->ls_err_desc.desc_tag = - cpu_to_be32(0x10002); - rsp_payload->ls_err_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); rsp_payload->ls_err_desc.link_fail_cnt = cpu_to_be32(stat->link_fail_cnt); rsp_payload->ls_err_desc.loss_sync_cnt = @@ -6165,28 +6164,47 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) vha->fabric_port_name, sizeof(rsp_payload->port_name_direct_desc.WWPN)); + /* Bufer Credit Descriptor */ + rsp_payload->buffer_credit_desc.desc_tag = cpu_to_be32(0x10006); + rsp_payload->buffer_credit_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->buffer_credit_desc)); + rsp_payload->buffer_credit_desc.fcport_b2b = 0; + rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0); + rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0); + if (bbc) { memset(bbc, 0, sizeof(*bbc)); rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); if (!rval) { - /* Bufer Credit Descriptor */ - rsp_payload->buffer_credit_desc.desc_tag = - cpu_to_be32(0x10006); - rsp_payload->buffer_credit_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN( - rsp_payload->buffer_credit_desc)); rsp_payload->buffer_credit_desc.fcport_b2b = cpu_to_be32(LSW(bbc->parameter[0])); - rsp_payload->buffer_credit_desc.attached_fcport_b2b = - cpu_to_be32(0); - rsp_payload->buffer_credit_desc.fcport_rtt = - cpu_to_be32(0); } } if (rsp_payload_length < sizeof(*rsp_payload)) goto send; + /* Optical Element Descriptor, Temperature */ + rsp_payload->optical_elmt_desc[0].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[0].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Voltage */ + rsp_payload->optical_elmt_desc[1].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[1].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Tx Bias Current */ + rsp_payload->optical_elmt_desc[2].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[2].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Tx Power */ + rsp_payload->optical_elmt_desc[3].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[3].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Rx Power */ + rsp_payload->optical_elmt_desc[4].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[4].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + if (sfp) { memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); @@ -6194,11 +6212,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) uint16_t *trx = (void *)sfp; /* already be16 */ /* Optical Element Descriptor, Temperature */ - rsp_payload->optical_elmt_desc[0].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[0].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; @@ -6207,11 +6220,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(1 << 28); /* Optical Element Descriptor, Voltage */ - rsp_payload->optical_elmt_desc[1].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[1].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; @@ -6220,11 +6228,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(2 << 28); /* Optical Element Descriptor, Tx Bias Current */ - rsp_payload->optical_elmt_desc[2].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[2].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; @@ -6233,11 +6236,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(3 << 28); /* Optical Element Descriptor, Tx Power */ - rsp_payload->optical_elmt_desc[3].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[3].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; @@ -6246,11 +6244,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(4 << 28); /* Optical Element Descriptor, Rx Power */ - rsp_payload->optical_elmt_desc[4].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[4].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; @@ -6304,16 +6297,15 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) } } + /* Optical Product Data Descriptor */ + rsp_payload->optical_prod_desc.desc_tag = cpu_to_be32(0x10008); + rsp_payload->optical_prod_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->optical_prod_desc)); + if (sfp) { memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); if (!rval) { - /* Optical Product Data Descriptor */ - rsp_payload->optical_prod_desc.desc_tag = - cpu_to_be32(0x10008); - rsp_payload->optical_prod_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN( - rsp_payload->optical_prod_desc)); memcpy(rsp_payload->optical_prod_desc.vendor_name, sfp + 0, sizeof(rsp_payload->optical_prod_desc.vendor_name)); From 231611a1869adf36a2dfb6b15433f6b7fdae5195 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:37:32 +0000 Subject: [PATCH 44/49] qla2x00t-32gbit: Fix NPIV instantiation after FW dump NPIV re-enable code was blocked after FW had been initialized. The blocking check was too broad. Reduce the check to make sure if FW is initialized or not. Link: https://lore.kernel.org/r/20200226224022.24518-14-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit ab391abdc191c2a2874098df86d1fe4b9762ef60 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8827 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_mbx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 2c01deb5c..dee7edc1a 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -1387,7 +1387,7 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (qla2x00_chip_is_down(vha)) + if (!vha->hw->flags.fw_started) return QLA_INVALID_COMMAND; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, From 7924ccd89c29dbfa0241021a820a0c9b4e1cca63 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:38:18 +0000 Subject: [PATCH 45/49] qla2x00t-32gbit: Serialize fc_port alloc in N2N For N2N, fc_port struct is created during report id acquisition. At later time, the loop resync (fabric, n2n, loop) would trigger the rest of the login using the created fc_port struct. The loop resync logic can trigger another fc_port allocation if the 1st allocation was not able to execute. This patch prevents the 2nd allocation trigger. Link: https://lore.kernel.org/r/20200226224022.24518-15-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit 11efe8755d73efd153d6459240866b6d52448f19 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8828 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_init.c | 1 + qla2x00t-32gbit/qla_os.c | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index a47c07566..5e278c44c 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -5147,6 +5147,7 @@ skip_login: set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); } + return QLA_FUNCTION_FAILED; } found_devs = 0; diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 2ae5a5c1e..872bf8cf0 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -5250,9 +5250,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) fcport->n2n_flag = 1; } fcport->fw_login_state = 0; - /* - * wait link init done before sending login - */ + + schedule_delayed_work(&vha->scan.scan_work, 5); } else { qla24xx_fcport_handle_login(vha, fcport); } From b4a2b8a6475b144fa3564f6f91a5cd1df807f0fa Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:38:56 +0000 Subject: [PATCH 46/49] qla2x00t-32gbit: Remove restriction of FC T10-PI and FC-NVMe T10-PI and FC-NVMe are not mutually exclusive. This patch removes restrictions where if FC-NVMe is enabled T10-PI defaults to disabled. Link: https://lore.kernel.org/r/20200226224022.24518-16-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit 3e4615a292b47632d409f0d53a23da85e039b031 upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8829 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_os.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 872bf8cf0..d2ead0e0f 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -136,11 +136,7 @@ MODULE_PARM_DESC(ql2xmaxqdepth, "Maximum queue depth to set for each LUN. " "Default is 64."); -#if (IS_ENABLED(CONFIG_NVME_FC)) -int ql2xenabledif; -#else int ql2xenabledif = 2; -#endif module_param(ql2xenabledif, int, S_IRUGO); MODULE_PARM_DESC(ql2xenabledif, " Enable T10-CRC-DIF:\n" From 9d6877b38d9cc274fea482fa3af38b4af2c54480 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:39:29 +0000 Subject: [PATCH 47/49] qla2x00t-32gbit: Handle NVME status iocb correctly Certain state flags bit combinations are not checked and not handled correctly. Plus, do not log a normal underrun situation where there is no frame drop. Link: https://lore.kernel.org/r/20200226224022.24518-17-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Arun Easi Signed-off-by: Martin K. Petersen [ commit 3d582b34992ba2fe4065f01019f0c08d12916faa upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8830 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_isr.c | 47 ++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 99bc1d7fe..2128bd188 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -2084,6 +2084,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, struct nvmefc_fcp_req *fd; uint16_t ret = QLA_SUCCESS; uint16_t comp_status = le16_to_cpu(sts->comp_status); + int logit = 0; iocb = &sp->u.iocb_cmd; fcport = sp->fcport; @@ -2094,6 +2095,12 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, if (unlikely(iocb->u.nvme.aen_op)) atomic_dec(&sp->vha->hw->nvme_active_aen_cnt); + if (unlikely(comp_status != CS_COMPLETE)) + logit = 1; + + fd->transferred_length = fd->payload_length - + le32_to_cpu(sts->residual_len); + /* * State flags: Bit 6 and 0. * If 0 is set, we don't care about 6. @@ -2104,8 +2111,20 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, */ if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) { iocb->u.nvme.rsp_pyld_len = 0; - } else if ((state_flags & SF_FCP_RSP_DMA)) { + } else if ((state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP)) == + (SF_FCP_RSP_DMA | SF_NVME_ERSP)) { + /* Response already DMA'd to fd->rspaddr. */ iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); + } else if ((state_flags & SF_FCP_RSP_DMA)) { + /* + * Non-zero value in first 12 bytes of NVMe_RSP IU, treat this + * as an error. + */ + iocb->u.nvme.rsp_pyld_len = 0; + fd->transferred_length = 0; + ql_dbg(ql_dbg_io, fcport->vha, 0x307a, + "Unexpected values in NVMe_RSP IU.\n"); + logit = 1; } else if (state_flags & SF_NVME_ERSP) { uint32_t *inbuf, *outbuf; uint16_t iter; @@ -2128,16 +2147,28 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, iter = iocb->u.nvme.rsp_pyld_len >> 2; for (; iter; iter--) *outbuf++ = swab32(*inbuf++); - } else { /* unhandled case */ - ql_log(ql_log_warn, fcport->vha, 0x503a, - "NVME-%s error. Unhandled state_flags of %x\n", - sp->name, state_flags); } - fd->transferred_length = fd->payload_length - - le32_to_cpu(sts->residual_len); + if (state_flags & SF_NVME_ERSP) { + struct nvme_fc_ersp_iu *rsp_iu = fd->rspaddr; + u32 tgt_xfer_len; - if (unlikely(comp_status != CS_COMPLETE)) + tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len); + if (fd->transferred_length != tgt_xfer_len) { + ql_dbg(ql_dbg_io, fcport->vha, 0x3079, + "Dropped frame(s) detected (sent/rcvd=%u/%u).\n", + tgt_xfer_len, fd->transferred_length); + logit = 1; + } else if (comp_status == CS_DATA_UNDERRUN) { + /* + * Do not log if this is just an underflow and there + * is no data loss. + */ + logit = 0; + } + } + + if (unlikely(logit)) ql_log(ql_log_warn, fcport->vha, 0x5060, "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", sp->name, sp->handle, comp_status, From 37e6d53d116b31523979c482a6d743726fab854d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:40:06 +0000 Subject: [PATCH 48/49] qla2x00t-32gbit: Set Nport ID for N2N When transitioning from loop to N2N, stale NPort ID is not re-assigned. Stale ID can collide with remote device. This patch will re-assign NPort ID on N2N is detected. Link: https://lore.kernel.org/r/20200226224022.24518-18-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen [ commit ad8a260aa80d4dfa9588fd5d23b71ec922f61c8b upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8831 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t-32gbit/qla_mbx.c | 42 +++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index dee7edc1a..9fd83d1bf 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -3924,11 +3924,29 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, fcport->scan_state = QLA_FCPORT_SCAN; fcport->n2n_flag = 0; } + id.b24 = 0; + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(rptid_entry->u.f1.port_name)) { + vha->d_id.b24 = 0; + vha->d_id.b.al_pa = 1; + ha->flags.n2n_bigger = 1; + + id.b.al_pa = 2; + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: assign local id %x remote id %x\n", + vha->d_id.b24, id.b24); + } else { + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: Remote login - Waiting for WWPN %8phC.\n", + rptid_entry->u.f1.port_name); + ha->flags.n2n_bigger = 0; + } fcport = qla2x00_find_fcport_by_wwpn(vha, rptid_entry->u.f1.port_name, 1); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + if (fcport) { fcport->plogi_nack_done_deadline = jiffies + HZ; fcport->dm_login_expire = jiffies + 2*HZ; @@ -3939,6 +3957,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (vha->flags.nvme_enabled) fcport->fc4_type |= FS_FC4TYPE_NVME; + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(fcport->port_name)) { + fcport->d_id = id; + } + switch (fcport->disc_state) { case DSC_DELETED: set_bit(RELOGIN_NEEDED, @@ -3951,25 +3974,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, break; } } else { - id.b24 = 0; - if (wwn_to_u64(vha->port_name) > - wwn_to_u64(rptid_entry->u.f1.port_name)) { - vha->d_id.b24 = 0; - vha->d_id.b.al_pa = 1; - ha->flags.n2n_bigger = 1; - ha->flags.n2n_ae = 0; - - id.b.al_pa = 2; - ql_dbg(ql_dbg_async, vha, 0x5075, - "Format 1: assign local id %x remote id %x\n", - vha->d_id.b24, id.b24); - } else { - ql_dbg(ql_dbg_async, vha, 0x5075, - "Format 1: Remote login - Waiting for WWPN %8phC.\n", - rptid_entry->u.f1.port_name); - ha->flags.n2n_bigger = 0; - ha->flags.n2n_ae = 1; - } qla24xx_post_newsess_work(vha, &id, rptid_entry->u.f1.port_name, rptid_entry->u.f1.node_name, From eea7b684730866fd088c8feaf438fb3cdd4bc83d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 7 Mar 2020 21:40:33 +0000 Subject: [PATCH 49/49] qla2x00t-32gbit: Update driver version to 10.01.00.25-k Link: https://lore.kernel.org/r/20200226224022.24518-19-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 4cbca7ea9edaab268f344c2bcd22afcb7370569f upstream ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8832 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 6b4ca3ed8..8ccd9ba1d 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.24-k" +#define QLA2XXX_VERSION "10.01.00.25-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1