All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/25] qla2xxx: Updates for the driver
@ 2020-02-12 21:44 Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 01/25] qla2xxx: Add beacon LED config sysfs interface Himanshu Madhani
                   ` (25 more replies)
  0 siblings, 26 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

Hi Martin, 

This series addes enhancements to the driver in the area of FDMI
commands and adding support for RDP command. This series also
adds support for Beacon LED/D-Port SysFS nodes. 

There are few other patches which are cleanup to improve readability
as well as consolidates code.  

Please apply this series to 5.7.0/scsi-misc at your earliest convenience.

Thanks,
Himanshu

Anil Gurumurthy (1):
  qla2xxx: Remove all DIX-0 references

Himanshu Madhani (8):
  qla2xxx: Display message for FCE enabled
  qla2xxx: Show correct port speed capabilities for RDP command
  qla2xxx: Fix RDP response size
  qla2xxx: Save rscn_gen for new fcport
  qla2xxx: Fix control flags for login/logout IOCB
  qla2xxx: Add fixes for mailbox command
  qla2xxx: Use QLA_FW_STOPPED macro to propagate flag
  qla2xxx: Update driver version to 10.01.00.24-k

Joe Carnuccio (15):
  qla2xxx: Add beacon LED config sysfs interface
  qla2xxx: Move free of fcport out of interrupt context
  qla2xxx: Add sysfs node for D-Port Diagnostics AEN data
  qla2xxx: Add endianizer macro calls to fc host stats
  qla2xxx: Add changes in preparation for vendor extended FDMI/RDP
  qla2xxx: Add vendor extended RDP additions and amendments
  qla2xxx: Add ql2xrdpenable module parameter for RDP
  qla2xxx: Add vendor extended FDMI commands
  qla2xxx: Cleanup ELS/PUREX iocb fields
  qla2xxx: Add deferred queue for processing ABTS and RDP
  qla2xxx: Handle cases for limiting RDP response payload length
  qla2xxx: Use endian macros to assign static fields in fwdump header
  qla2xxx: Correction to selection of loopback/echo test
  qla2xxx: Fix qla2x00_echo_test() based on ISP type
  qla2xxx: Print portname for logging in qla24xx_logio_entry()

Quinn Tran (1):
  qla2xxx: Use correct ISP28xx active FW region

 drivers/scsi/qla2xxx/qla_attr.c    |  136 ++-
 drivers/scsi/qla2xxx/qla_bsg.c     |   27 +-
 drivers/scsi/qla2xxx/qla_def.h     |  357 +++++---
 drivers/scsi/qla2xxx/qla_fw.h      |  170 +++-
 drivers/scsi/qla2xxx/qla_gbl.h     |   19 +-
 drivers/scsi/qla2xxx/qla_gs.c      | 1703 ++++++++++++++++--------------------
 drivers/scsi/qla2xxx/qla_init.c    |   51 +-
 drivers/scsi/qla2xxx/qla_iocb.c    |   20 +-
 drivers/scsi/qla2xxx/qla_isr.c     |  179 +++-
 drivers/scsi/qla2xxx/qla_mbx.c     |  257 +++++-
 drivers/scsi/qla2xxx/qla_mid.c     |   10 +
 drivers/scsi/qla2xxx/qla_os.c      |  648 +++++++++++++-
 drivers/scsi/qla2xxx/qla_tmpl.c    |   17 +-
 drivers/scsi/qla2xxx/qla_version.h |    2 +-
 14 files changed, 2453 insertions(+), 1143 deletions(-)

-- 
2.12.0


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 01/25] qla2xxx: Add beacon LED config sysfs interface
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 02/25] qla2xxx: Move free of fcport out of interrupt context Himanshu Madhani
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This patch Provides 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

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_attr.c | 76 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_def.h  |  1 +
 drivers/scsi/qla2xxx/qla_gbl.h  |  1 +
 drivers/scsi/qla2xxx/qla_mbx.c  | 57 +++++++++++++++++++++++++++++++
 4 files changed, 135 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index d7e7043f9eab..927115dc2526 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1324,6 +1324,79 @@ qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
 }
 
 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/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ed32e9715794..b59643883ad1 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1134,6 +1134,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/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2a64729a2bc5..156ad11a15c4 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -844,6 +844,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 */
 extern int qla24xx_bsg_request(struct bsg_job *);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9e09964f5c0e..e1916bec5e36 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/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;
+}
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 02/25] qla2xxx: Move free of fcport out of interrupt context
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 01/25] qla2xxx: Add beacon LED config sysfs interface Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 03/25] qla2xxx: Add sysfs node for D-Port Diagnostics AEN data Himanshu Madhani
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This patch moves freeing of fcport out of interrupt
context

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index d7169e43f5e1..5870d26ab707 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -11,6 +11,14 @@
 #include <linux/delay.h>
 #include <linux/bsg-lib.h>
 
+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)
 {
@@ -53,8 +61,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);
 }
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 03/25] qla2xxx: Add sysfs node for D-Port Diagnostics AEN data
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 01/25] qla2xxx: Add beacon LED config sysfs interface Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 02/25] qla2xxx: Move free of fcport out of interrupt context Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 04/25] qla2xxx: Remove all DIX-0 references Himanshu Madhani
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This patch adds SysFS node to show D-Port diag data.

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_attr.c | 21 +++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_def.h  |  1 +
 drivers/scsi/qla2xxx/qla_isr.c  |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 927115dc2526..de1930cd53fb 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/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/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b59643883ad1..22f859bef778 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -4541,6 +4541,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/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index e40705d38cea..73b6cfd14581 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1254,6 +1254,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		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" };
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 04/25] qla2xxx: Remove all DIX-0 references
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (2 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 03/25] qla2xxx: Add sysfs node for D-Port Diagnostics AEN data Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 05/25] qla2xxx: Add endianizer macro calls to fc host stats Himanshu Madhani
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Anil Gurumurthy <anil.gurumurthy@qlogic.com>

This patch removes DIX-0 refrence from the source
as its not used anymore and should not be allowed
as supported option.

Signed-off-by: Anil Gurumurthy <anil.gurumurthy@qlogic.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_attr.c | 3 +--
 drivers/scsi/qla2xxx/qla_def.h  | 1 -
 drivers/scsi/qla2xxx/qla_os.c   | 4 +---
 3 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index de1930cd53fb..becde75d0fbc 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2942,8 +2942,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
 
 			guard = SHOST_DIX_GUARD_CRC;
 
-			if (IS_PI_IPGUARD_CAPABLE(ha) &&
-			    (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha)))
+			if (IS_PI_IPGUARD_CAPABLE(ha) && ql2xenabledif)
 				guard |= SHOST_DIX_GUARD_IP;
 
 			scsi_host_set_guard(vha->host, guard);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 22f859bef778..063ba73c7372 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3906,7 +3906,6 @@ struct qla_hw_data {
 				((ha)->fw_attributes_ext[0] & BIT_0))
 #define IS_PI_UNINIT_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
 #define IS_PI_IPGUARD_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
-#define IS_PI_DIFB_DIX0_CAPABLE(ha)	(0)
 #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
 					IS_QLA28XX(ha))
 #define IS_PI_SPLIT_DET_CAPABLE(ha)	(IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 79387ac8936f..7f8b5ab0c4c4 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -132,7 +132,6 @@ MODULE_PARM_DESC(ql2xenabledif,
 		" Enable T10-CRC-DIF:\n"
 		" Default is 2.\n"
 		"  0 -- No DIF Support\n"
-		"  1 -- Enable DIF for all types\n"
 		"  2 -- Enable DIF for all types, except Type 0.\n");
 
 #if (IS_ENABLED(CONFIG_NVME_FC))
@@ -3370,8 +3369,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
 			guard = SHOST_DIX_GUARD_CRC;
 
-			if (IS_PI_IPGUARD_CAPABLE(ha) &&
-			    (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha)))
+			if (IS_PI_IPGUARD_CAPABLE(ha) && ql2xenabledif)
 				guard |= SHOST_DIX_GUARD_IP;
 
 			if (ql2xprotguard)
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 05/25] qla2xxx: Add endianizer macro calls to fc host stats
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (3 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 04/25] qla2xxx: Remove all DIX-0 references Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 06/25] qla2xxx: Add changes in preparation for vendor extended FDMI/RDP Himanshu Madhani
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This patch fixes endian warning for fc_host_stats

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_attr.c | 36 ++++++++++++---------
 drivers/scsi/qla2xxx/qla_def.h  | 69 ++++++++++++++++++++---------------------
 2 files changed, 54 insertions(+), 51 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index becde75d0fbc..d9c8ee820d13 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/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/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 063ba73c7372..209491a1d022 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1475,47 +1475,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];
 };
 
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 06/25] qla2xxx: Add changes in preparation for vendor extended FDMI/RDP
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (4 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 05/25] qla2xxx: Add endianizer macro calls to fc host stats Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 07/25] qla2xxx: Add vendor extended RDP additions and amendments Himanshu Madhani
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@qlogic.com>

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.

Signed-off-by: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |   3 +
 drivers/scsi/qla2xxx/qla_fw.h   |   4 ++
 drivers/scsi/qla2xxx/qla_gbl.h  |  12 +++-
 drivers/scsi/qla2xxx/qla_gs.c   |  15 +++--
 drivers/scsi/qla2xxx/qla_init.c |  28 +++++++---
 drivers/scsi/qla2xxx/qla_mbx.c  | 121 ++++++++++++++++++++++++++++++++++------
 drivers/scsi/qla2xxx/qla_mid.c  |   3 +
 drivers/scsi/qla2xxx/qla_os.c   |   4 +-
 8 files changed, 155 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 209491a1d022..917939c5e5be 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1261,7 +1261,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
 
@@ -4458,6 +4460,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/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index d641918cdd46..02c1dbb4abc8 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -31,6 +31,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 {
@@ -1883,6 +1886,7 @@ struct nvram_81xx {
 	 * BIT 6-15 = Unused
 	 */
 	uint16_t enhanced_features;
+
 	uint16_t reserved_24[4];
 
 	/* Offset 416. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 156ad11a15c4..b40a3fb46c00 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/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;
@@ -354,6 +357,9 @@ 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 *);
 
 extern int
@@ -452,6 +458,10 @@ 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);
 
@@ -656,7 +666,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/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index aaa4a5bbf2ff..c01eb87c709f 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -844,19 +844,18 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
 	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/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9e6b56527b25..9887602529a3 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -5541,24 +5541,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,
@@ -5570,6 +5568,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)
 }
 
 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)
 {
 	struct qla_hw_data *ha = vha->hw;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index e1916bec5e36..f295bd73128f 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/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 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
 	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/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 8ae639d089d1..d211f803c699 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/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/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7f8b5ab0c4c4..39d75de84db6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2286,7 +2286,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,
@@ -2403,7 +2403,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,
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 07/25] qla2xxx: Add vendor extended RDP additions and amendments
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (5 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 06/25] qla2xxx: Add changes in preparation for vendor extended FDMI/RDP Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 08/25] qla2xxx: Add ql2xrdpenable module parameter for RDP Himanshu Madhani
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@qlogic.com>

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.

Signed-off-by: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h  | 135 ++++++++++
 drivers/scsi/qla2xxx/qla_fw.h   |  44 ++++
 drivers/scsi/qla2xxx/qla_gbl.h  |   3 +
 drivers/scsi/qla2xxx/qla_init.c |  15 +-
 drivers/scsi/qla2xxx/qla_isr.c  |  10 +
 drivers/scsi/qla2xxx/qla_mbx.c  |  58 +++++
 drivers/scsi/qla2xxx/qla_os.c   | 546 +++++++++++++++++++++++++++++++++++++++-
 7 files changed, 807 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 917939c5e5be..6ea0ef24a2a8 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1267,6 +1267,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
  */
@@ -3562,6 +3565,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;
@@ -3964,6 +4094,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;
 
@@ -4423,6 +4555,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 */
@@ -4531,6 +4665,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/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 02c1dbb4abc8..649bdfd61bc5 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -724,6 +724,50 @@ 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 {
+	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.
  */
 #define ELS_IOCB_TYPE		0x53	/* ELS Pass-Through IOCB entry */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index b40a3fb46c00..7679f8fa1ddc 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -458,6 +458,9 @@ 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/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9887602529a3..2b36a1bdcc5f 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3708,6 +3708,10 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
 			    "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
@@ -8672,6 +8682,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/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 73b6cfd14581..f0a4245f892c 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -31,6 +31,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
@@ -3128,6 +3135,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 			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/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f295bd73128f..2e531e289eb0 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -4878,6 +4878,64 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
 }
 
 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/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 39d75de84db6..96f5577d3679 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -305,6 +305,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 *);
 static int qla2xxx_map_queues(struct Scsi_Host *shost);
@@ -3268,6 +3277,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
@@ -3449,6 +3463,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	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);
@@ -3765,6 +3780,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);
@@ -5731,6 +5748,518 @@ qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id)
 	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)
 {
@@ -6078,6 +6607,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);
 
 	/*
@@ -6301,6 +6832,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);
@@ -6692,7 +7230,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 "
@@ -6705,12 +7244,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);
 	}
 
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 08/25] qla2xxx: Add ql2xrdpenable module parameter for RDP
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (6 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 07/25] qla2xxx: Add vendor extended RDP additions and amendments Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 09/25] qla2xxx: Add vendor extended FDMI commands Himanshu Madhani
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@qlogic.com>

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 its required for RDP to work.

Signed-off-by: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h  |  1 +
 drivers/scsi/qla2xxx/qla_init.c | 12 +++++++++---
 drivers/scsi/qla2xxx/qla_os.c   | 10 +++++++++-
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 7679f8fa1ddc..cdd8d7947fa8 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/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/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 2b36a1bdcc5f..8fee3f5154c7 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/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 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
 		}
 
 		/* 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);
@@ -8682,7 +8688,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/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 96f5577d3679..4be99f13be42 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -113,7 +113,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;
@@ -313,6 +314,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 *);
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 09/25] qla2xxx: Add vendor extended FDMI commands
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (7 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 08/25] qla2xxx: Add ql2xrdpenable module parameter for RDP Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 10/25] qla2xxx: Display message for FCE enabled Himanshu Madhani
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@qlogic.com>

This patch adds support for extended FDMI commands
and cleans up code to reduce duplication.

Signed-off-by: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  134 ++--
 drivers/scsi/qla2xxx/qla_gs.c  | 1687 ++++++++++++++++++----------------------
 2 files changed, 830 insertions(+), 991 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6ea0ef24a2a8..09853b624aff 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2627,10 +2627,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
@@ -2642,12 +2643,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;
@@ -2664,31 +2666,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];
@@ -2696,22 +2676,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
@@ -2721,7 +2709,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
@@ -2737,7 +2733,7 @@ struct ct_fdmiv2_hba_attributes {
 #define FC_CLASS_3	0x08
 #define FC_CLASS_2_3	0x0C
 
-struct ct_fdmiv2_port_attr {
+struct ct_fdmi_port_attr {
 	uint16_t type;
 	uint16_t len;
 	union {
@@ -2747,6 +2743,7 @@ struct ct_fdmiv2_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];
@@ -2757,35 +2754,38 @@ struct ct_fdmiv2_port_attr {
 		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;
 };
 
-/*
- * Port Attribute Block.
- */
-struct ct_fdmiv2_port_attributes {
+struct ct_fdmi1_port_attributes {
 	uint32_t count;
-	struct ct_fdmiv2_port_attr entry[FDMIV2_PORT_ATTR_COUNT];
+	struct ct_fdmi_port_attr entry[FDMI1_PORT_ATTR_COUNT];
 };
 
-struct ct_fdmi_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];
-	} a;
-};
-
-struct ct_fdmi_port_attributes {
+struct ct_fdmi2_port_attributes {
 	uint32_t count;
-	struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_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
@@ -2796,10 +2796,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)
@@ -2882,30 +2885,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];
@@ -3019,7 +3016,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 {
@@ -3690,6 +3687,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/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index c01eb87c709f..f57bfcb9c548 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/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;
 }
 
+static uint
+qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha)
+{
+	if (IS_CNA_CAPABLE(ha))
+		return FDMI_PORT_SPEED_10GB;
+	if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
+		uint speeds = 0;
+
+		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:
+		return FDMI_PORT_SPEED_1GB;
+	case PORT_SPEED_2GB:
+		return FDMI_PORT_SPEED_2GB;
+	case PORT_SPEED_4GB:
+		return FDMI_PORT_SPEED_4GB;
+	case PORT_SPEED_8GB:
+		return FDMI_PORT_SPEED_8GB;
+	case PORT_SPEED_10GB:
+		return FDMI_PORT_SPEED_10GB;
+	case PORT_SPEED_16GB:
+		return FDMI_PORT_SPEED_16GB;
+	case PORT_SPEED_32GB:
+		return FDMI_PORT_SPEED_32GB;
+	case PORT_SPEED_64GB:
+		return FDMI_PORT_SPEED_64GB;
+	default:
+		return FDMI_PORT_SPEED_UNKNOWN;
+	}
+}
+
 /**
- * qla2x00_fdmi_rhba() - perform RHBA FDMI 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_fdmi_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_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;
+	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, 0x2025,
-	    "NodeName = %8phN.\n", 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);
-	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);
-
+	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) |
+	alen = 0;
+	if (IS_FWI2_CAPABLE(ha)) {
+		alen = qla2xxx_get_vpd_field(vha, "SN",
+		    eiter->a.serial_num, sizeof(eiter->a.serial_num));
+	}
+	if (!alen) {
+		uint32_t 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 = scnprintf(
+			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);
-
+	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, 0x2028,
-	    "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, 0x2029,
-	    "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, 0x202a,
-	    "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, 0x202b,
-	    "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 , 0x202c,
-	    "Optrom vers = %s.\n", eiter->a.orom_version);
+	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, 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");
+	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);
+	alen = 0;
+	if (p_sysid) {
+		alen = scnprintf(
+			eiter->a.os_version, sizeof(eiter->a.os_version),
+			"%s %s %s",
+			p_sysid->sysname, p_sysid->release, p_sysid->machine);
 	}
-
-	return rval;
+	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(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);
+	alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
+	    sizeof(eiter->a.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, 0x20ab,
+	    "SYMBOLIC NAME = %s.\n", eiter->a.sym_name);
+	/* Vendor Specific information */
+	eiter = entries + size;
+	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);
+	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,
+	    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);
+	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_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;
 }
 
 /**
- * qla2x00_fdmi_rpa() - perform RPA registration
+ * 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 int
-qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
+static unsigned long
+qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries,
+    unsigned int callopt)
 {
-	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 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;
-	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;
+	uint16_t alen;
+	unsigned long size = 0;
 
 	/* 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[0] = 0x00;
+	eiter->a.fc4_types[1] = 0x00;
 	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]);
-
+	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->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, 0x203a,
-	    "Supported_Speed=%x.\n", eiter->a.sup_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->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, 0x203b,
-	    "Current_Speed=%x.\n", eiter->a.cur_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->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);
-
+	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);
-	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);
-
+	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);
-	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;
+	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);
 
-	ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name);
+	if (callopt == CALLOPT_FDMI1)
+		goto done;
 
-	/* Update MS request size. */
-	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
+	/* 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));
 
-	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);
+	/* 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));
 
-	/* 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;
-		}
+	/* 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);
 
-	} else {
-		ql_dbg(ql_dbg_disc, vha, 0x2041,
-		    "RPA exiting normally.\n");
-	}
+	/* 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));
 
-	return rval;
+	/* 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_fdmiv2_rhba() - perform RHBA FDMI v2 registration
+ * qla2x00_fdmi_rhba() - perform RHBA FDMI registration
  * @vha: HA context
+ * @callopt: Option to issue FDMI registration
  *
  * Returns 0 on success.
  */
 static int
-qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
+qla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt)
 {
-	int rval, alen;
-	uint32_t size, sn;
+	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;
-	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);
+	count = callopt != CALLOPT_FDMI1 ?
+	    FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT;
 
-	/* 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;
-
-	/* 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));
-
-	/* 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);
-
-	/* 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, 0x20a6,
-	    "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, 0x20a7,
-	    "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);
-
-	/* 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, 0x20a9,
-	    "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, 0x20aa,
-	    "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 , 0x20ab,
-	    "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);
-
-	/* OS Name and Version */
-	eiter = entries + size;
-	eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
-	p_sysid = utsname();
-	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 = 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);
-
-	/* 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);
+	size = RHBA_RSP_SIZE;
 
-	/* 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,
-	    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 */
-	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, 0x20e0,
+	    "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size);
 
-	ql_dbg(ql_dbg_disc, vha, 0x20b1,
-	    "Vendor Id = %x.\n", eiter->a.vendor_id);
-
-	/* 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;
+	/*   Request size adjusted after CT preparation */
+	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
 
-	ql_dbg(ql_dbg_disc, vha, 0x20b2,
-	    "Port Num = %x.\n", eiter->a.num_ports);
+	/* Prepare CT request */
+	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size);
+	ct_rsp = &ha->ct_sns->p.rsp;
 
-	/* 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;
+	/* 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);
 
-	ql_dbg(ql_dbg_disc, vha, 0x20b3,
-	    "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
+	ct_req->req.rhba.entry_count = cpu_to_be32(1);
+	size += sizeof(ct_req->req.rhba.entry_count);
 
-	/* 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;
+	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);
 
-	ql_dbg(ql_dbg_disc, vha, 0x20b4,
-	    "BIOS Name = %s\n", eiter->a.bios_name);
+	/* Attribute count */
+	ct_req->req.rhba.attrs.count = cpu_to_be32(count);
+	size += sizeof(ct_req->req.rhba.attrs.count);
 
-	/* 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;
+	/* Attribute block */
+	entries = &ct_req->req.rhba.attrs.entry;
 
-	ql_dbg(ql_dbg_disc, vha, 0x201b,
-	    "Vendor Identifier = %s.\n", eiter->a.vendor_identifier);
+	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;
-
-	/* 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);
-
+	count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?
+		FDMI2_SMARTSAN_PORT_ATTR_COUNT :
+		callopt != CALLOPT_FDMI1 ?
+		FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;
+
+	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, RPA_CMD, RPA_RSP_SIZE);
+	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_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;
-
-	/* Attributes */
-	ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_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, 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;
+	/* 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;
 	}
-	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);
+	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;
+		}
 
-	/* 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));
+		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;
 	}
-	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, 0x20ee, "RPRT exiting normally.\n");
+	return rval;
+}
 
-	ql_dbg(ql_dbg_disc, vha, 0x20c5,
-	    "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
+/**
+ * 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;
 
-	/* 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;
+	count =
+	    callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?
+		FDMI2_SMARTSAN_PORT_ATTR_COUNT :
+	    callopt != CALLOPT_FDMI1 ?
+		FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;
 
-	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]);
+	size =
+	    callopt != CALLOPT_FDMI1 ?
+		SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE;
 
-	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]);
-	}
+	ql_dbg(ql_dbg_disc, vha, 0x20f0,
+	    "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size);
 
-	/* 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;
+	/* Request size adjusted after CT preparation */
+	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
 
-	ql_dbg(ql_dbg_disc, vha, 0x20c7,
-	    "Port State = %x.\n", eiter->a.port_state);
+	/* Prepare CT request */
+	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size);
+	ct_rsp = &ha->ct_sns->p.rsp;
 
-	/* 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;
+	/* 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);
 
-	ql_dbg(ql_dbg_disc, vha, 0x20c8,
-	    "Number of ports = %x.\n", eiter->a.num_ports);
+	/* Attribute count */
+	ct_req->req.rpa.attrs.count = cpu_to_be32(count);
+	size += sizeof(ct_req->req.rpa.attrs.count);
 
-	/* 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;
+	/* Attribute block */
+	entries = ct_req->req.rpa.attrs.entry;
 
-	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 @@ qla2x00_fdmi_register(scsi_qla_host_t *vha)
 		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;
 }
 
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 10/25] qla2xxx: Display message for FCE enabled
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (8 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 09/25] qla2xxx: Add vendor extended FDMI commands Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 11/25] qla2xxx: Show correct port speed capabilities for RDP command Himanshu Madhani
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

During Link up phase and Data rate MBX command response,
print message indicating FCE is enabled.

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_isr.c | 6 ++++++
 drivers/scsi/qla2xxx/qla_mbx.c | 9 +++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f0a4245f892c..a274872ff15d 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -820,6 +820,12 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		    "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/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 2e531e289eb0..9d73ae165a98 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/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)
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 11/25] qla2xxx: Show correct port speed capabilities for RDP command
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (9 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 10/25] qla2xxx: Display message for FCE enabled Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 12/25] qla2xxx: Cleanup ELS/PUREX iocb fields Himanshu Madhani
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

This patch correctly displays Port speed capabiltiy and
current speed for RDP command.

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_os.c | 41 +++++++++++++++++++++++++++++++++++------
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4be99f13be42..dbbe20c7fbaf 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5762,13 +5762,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))
@@ -5814,6 +5840,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;
 	}
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 12/25] qla2xxx: Cleanup ELS/PUREX iocb fields
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (10 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 11/25] qla2xxx: Show correct port speed capabilities for RDP command Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 13/25] qla2xxx: Add deferred queue for processing ABTS and RDP Himanshu Madhani
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This patch does 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.

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_fw.h   | 39 +++++++++++++++++++++++++--------------
 drivers/scsi/qla2xxx/qla_iocb.c | 12 ++++++------
 drivers/scsi/qla2xxx/qla_os.c   | 28 +++++++++++++++++-----------
 3 files changed, 48 insertions(+), 31 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 649bdfd61bc5..f7a40dcda7ce 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -779,9 +779,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;
 
@@ -796,7 +795,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. */
@@ -808,13 +807,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 {
@@ -840,15 +850,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/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 47bf60a9490a..5b73d09da739 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2684,9 +2684,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;
@@ -3030,9 +3030,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/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index dbbe20c7fbaf..295c7fec0918 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5886,13 +5886,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);
@@ -5918,9 +5924,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;
@@ -6263,14 +6269,14 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt)
 
 	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__);
 	}
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 13/25] qla2xxx: Add deferred queue for processing ABTS and RDP
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (11 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 12/25] qla2xxx: Cleanup ELS/PUREX iocb fields Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 14/25] qla2xxx: Handle cases for limiting RDP response payload length Himanshu Madhani
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This patch adds deferred queue for processing aborts and RDP
in the driver.

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  15 +++-
 drivers/scsi/qla2xxx/qla_fw.h  |  91 ++++++++++++++++++++++--
 drivers/scsi/qla2xxx/qla_gbl.h |   2 +
 drivers/scsi/qla2xxx/qla_isr.c | 154 +++++++++++++++++++++++++++++++++++++++--
 drivers/scsi/qla2xxx/qla_mid.c |   7 ++
 drivers/scsi/qla2xxx/qla_os.c  |  62 ++++++++++++-----
 6 files changed, 304 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 09853b624aff..7f25066d1bbf 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -4473,6 +4473,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
  */
@@ -4663,7 +4672,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/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index f7a40dcda7ce..8af5bc4e2cc6 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -727,7 +727,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. */
@@ -763,9 +763,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.
@@ -1000,6 +998,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/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index cdd8d7947fa8..c056df820ab9 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -230,6 +230,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.
@@ -928,6 +929,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/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a274872ff15d..1089db774bd1 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -31,13 +31,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
@@ -3097,6 +3228,11 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 			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 */
@@ -3142,8 +3278,18 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 			    (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/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index d211f803c699..e86c94f78196 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/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/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 295c7fec0918..1aad4b9ce4b6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3285,11 +3285,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
@@ -3471,7 +3466,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	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);
@@ -3788,8 +3782,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);
@@ -3831,6 +3823,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)
 {
@@ -3863,6 +3869,8 @@ qla2x00_free_device(scsi_qla_host_t *vha)
 	}
 
 
+	qla24xx_free_purex_list(&vha->purex_list);
+
 	qla2x00_mem_free(ha);
 
 	qla82xx_md_free(vha);
@@ -4836,6 +4844,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);
@@ -5858,7 +5869,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;
@@ -5874,7 +5885,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__);
@@ -6299,8 +6310,23 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt)
 	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
@@ -6650,8 +6676,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);
 
 	/*
@@ -6875,11 +6899,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,
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 14/25] qla2xxx: Handle cases for limiting RDP response payload length
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (12 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 13/25] qla2xxx: Add deferred queue for processing ABTS and RDP Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 15/25] qla2xxx: Fix RDP response size Himanshu Madhani
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

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.

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_os.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 1aad4b9ce4b6..d06fa318f378 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5767,6 +5767,32 @@ qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id)
 	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)
 {
@@ -5885,6 +5911,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,
@@ -5895,6 +5922,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) {
@@ -5941,7 +5976,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;
@@ -6116,6 +6151,9 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
 		}
 	}
 
+	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);
@@ -6276,7 +6314,7 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
 	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);
 
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 15/25] qla2xxx: Fix RDP response size
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (13 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 14/25] qla2xxx: Handle cases for limiting RDP response payload length Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 16/25] qla2xxx: Use endian macros to assign static fields in fwdump header Himanshu Madhani
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

This patch fixes RDP length in case when driver
needs to reduce length of RDP response

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_os.c | 53 ++++++++++++++++---------------------------
 1 file changed, 19 insertions(+), 34 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d06fa318f378..b24813051766 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5773,6 +5773,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: */
@@ -5781,6 +5782,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: */
@@ -5899,7 +5918,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;
@@ -5984,34 +6002,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(
@@ -6129,9 +6119,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
 	    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);
@@ -6331,8 +6318,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
 	}
 
 dealloc:
-	kfree(pdb);
-
 	if (bbc)
 		dma_free_coherent(&ha->pdev->dev, sizeof(*bbc),
 		    bbc, bbc_dma);
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 16/25] qla2xxx: Use endian macros to assign static fields in fwdump header
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (14 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 15/25] qla2xxx: Fix RDP response size Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 17/25] qla2xxx: Correction to selection of loopback/echo test Himanshu Madhani
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This takes care of big endian architectures.

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_tmpl.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index 5b0c057def2b..6aeb1c3fb7a8 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -870,7 +870,7 @@ qla27xx_walk_template(struct scsi_qla_host *vha,
 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
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 17/25] qla2xxx: Correction to selection of loopback/echo test
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (15 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 16/25] qla2xxx: Use endian macros to assign static fields in fwdump header Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 18/25] qla2xxx: Fix qla2x00_echo_test() based on ISP type Himanshu Madhani
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

This Fixes loopback and echo test options

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 5870d26ab707..34fa200900fc 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -728,7 +728,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;
@@ -806,10 +806,11 @@ qla2x00_process_loopback(struct bsg_job *bsg_job)
 	    bsg_request->rqst_data.h_vendor.vendor_cmd[2];
 
 	if (atomic_read(&vha->loop_state) == LOOP_READY &&
-	    (ha->current_topology == ISP_CFG_F ||
-	    (get_unaligned_le32(req_data) == ELS_OPCODE_BYTE &&
-	     req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
-	    elreq.options == EXTERNAL_LOOPBACK) {
+	    ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) ||
+	    ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) &&
+	    get_unaligned_le32(req_data) == ELS_OPCODE_BYTE &&
+	    req_data_len == MAX_ELS_FRAME_PAYLOAD &&
+	    elreq.options == EXTERNAL_LOOPBACK))) {
 		type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
 		ql_dbg(ql_dbg_user, vha, 0x701e,
 		    "BSG request type: %s.\n", type);
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 18/25] qla2xxx: Fix qla2x00_echo_test() based on ISP type
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (16 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 17/25] qla2xxx: Correction to selection of loopback/echo test Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 19/25] qla2xxx: Print portname for logging in qla24xx_logio_entry() Himanshu Madhani
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

Ths patch fixes MBX in-direction for setting right
bits for qla2x00_echo_test()

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_mbx.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9d73ae165a98..c81081c3d9b8 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/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;
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 19/25] qla2xxx: Print portname for logging in qla24xx_logio_entry()
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (17 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 18/25] qla2xxx: Fix qla2x00_echo_test() based on ISP type Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 20/25] qla2xxx: Use correct ISP28xx active FW region Himanshu Madhani
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Joe Carnuccio <joe.carnuccio@cavium.com>

Add port name in the messages file to help debugging of
Login/Logout IOCBs

Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 1089db774bd1..d03dd16ce1ea 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1899,11 +1899,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;
@@ -1982,11 +1980,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]));
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 20/25] qla2xxx: Use correct ISP28xx active FW region
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (18 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 19/25] qla2xxx: Print portname for logging in qla24xx_logio_entry() Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 21/25] qla2xxx: Save rscn_gen for new fcport Himanshu Madhani
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

From: Quinn Tran <qutran@marvell.com>

For ISP28xx, use 28xx call to retrieve active FW region.

Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 34fa200900fc..714bcf5e6e53 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -2415,7 +2415,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;
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 21/25] qla2xxx: Save rscn_gen for new fcport
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (19 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 20/25] qla2xxx: Use correct ISP28xx active FW region Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 22/25] qla2xxx: Fix control flags for login/logout IOCB Himanshu Madhani
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

Add missing rscn_gen when creating new fcport.

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_gs.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index f57bfcb9c548..551102462737 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/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.
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 22/25] qla2xxx: Fix control flags for login/logout IOCB
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (20 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 21/25] qla2xxx: Save rscn_gen for new fcport Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 23/25] qla2xxx: Add fixes for mailbox command Himanshu Madhani
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

This patch fixes control flag options for login/logout
IOCB.

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_iocb.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 5b73d09da739..4f022955eb94 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2362,6 +2362,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 {
@@ -2939,7 +2941,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;
 
@@ -2949,7 +2950,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) {
@@ -2958,7 +2959,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) {
@@ -2982,6 +2983,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;
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 23/25] qla2xxx: Add fixes for mailbox command
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (21 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 22/25] qla2xxx: Fix control flags for login/logout IOCB Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 24/25] qla2xxx: Use QLA_FW_STOPPED macro to propagate flag Himanshu Madhani
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

This patch aded following fix

- qla2x00_issue_iocb_timeout will now return if chip is down
- only check for sp->qpair in abort handling

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_mbx.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index c81081c3d9b8..7e5c23a1c3b8 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/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;
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 24/25] qla2xxx: Use QLA_FW_STOPPED macro to propagate flag
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (22 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 23/25] qla2xxx: Add fixes for mailbox command Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-12 21:44 ` [PATCH 25/25] qla2xxx: Update driver version to 10.01.00.24-k Himanshu Madhani
  2020-02-21 23:33 ` [PATCH 00/25] qla2xxx: Updates for the driver Martin K. Petersen
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

This patch uses QLA_FW_STOPPED macro, so that flag is propogated
to all the QPairs.

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 8fee3f5154c7..1ec93e28560e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -6676,7 +6676,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;
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 25/25] qla2xxx: Update driver version to 10.01.00.24-k
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (23 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 24/25] qla2xxx: Use QLA_FW_STOPPED macro to propagate flag Himanshu Madhani
@ 2020-02-12 21:44 ` Himanshu Madhani
  2020-02-21 23:33 ` [PATCH 00/25] qla2xxx: Updates for the driver Martin K. Petersen
  25 siblings, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-12 21:44 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: hmadhani, linux-scsi

Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index bb03c022e023..6b4ca3ed8f22 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/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
-- 
2.12.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH 00/25] qla2xxx: Updates for the driver
  2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
                   ` (24 preceding siblings ...)
  2020-02-12 21:44 ` [PATCH 25/25] qla2xxx: Update driver version to 10.01.00.24-k Himanshu Madhani
@ 2020-02-21 23:33 ` Martin K. Petersen
  2020-02-24 16:36   ` Himanshu Madhani
  2020-02-25  4:32   ` Bart Van Assche
  25 siblings, 2 replies; 29+ messages in thread
From: Martin K. Petersen @ 2020-02-21 23:33 UTC (permalink / raw)
  To: Himanshu Madhani; +Cc: James.Bottomley, martin.petersen, linux-scsi


Himanshu,

> This series addes enhancements to the driver in the area of FDMI
> commands and adding support for RDP command. This series also adds
> support for Beacon LED/D-Port SysFS nodes.
>
> There are few other patches which are cleanup to improve readability
> as well as consolidates code.  
>
> Please apply this series to 5.7.0/scsi-misc at your earliest
> convenience.

Applied to 5.7/scsi-queue. This series lit up like a Xmas tree in
checkpatch. Next time, please verify before posting.

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 00/25] qla2xxx: Updates for the driver
  2020-02-21 23:33 ` [PATCH 00/25] qla2xxx: Updates for the driver Martin K. Petersen
@ 2020-02-24 16:36   ` Himanshu Madhani
  2020-02-25  4:32   ` Bart Van Assche
  1 sibling, 0 replies; 29+ messages in thread
From: Himanshu Madhani @ 2020-02-24 16:36 UTC (permalink / raw)
  To: Martin K. Petersen; +Cc: James.Bottomley, linux-scsi



On 2/21/20, 5:33 PM, "linux-scsi-owner@vger.kernel.org on behalf of Martin K. Petersen" <linux-scsi-owner@vger.kernel.org on behalf of martin.petersen@oracle.com> wrote:

    
    Himanshu,
    
    > This series addes enhancements to the driver in the area of FDMI
    > commands and adding support for RDP command. This series also adds
    > support for Beacon LED/D-Port SysFS nodes.
    >
    > There are few other patches which are cleanup to improve readability
    > as well as consolidates code.  
    >
    > Please apply this series to 5.7.0/scsi-misc at your earliest
    > convenience.
    
    Applied to 5.7/scsi-queue. This series lit up like a Xmas tree in
    checkpatch. Next time, please verify before posting.
  
Will do. 

Thanks,
Himanshu
  
    -- 
    Martin K. Petersen	Oracle Linux Engineering
    


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 00/25] qla2xxx: Updates for the driver
  2020-02-21 23:33 ` [PATCH 00/25] qla2xxx: Updates for the driver Martin K. Petersen
  2020-02-24 16:36   ` Himanshu Madhani
@ 2020-02-25  4:32   ` Bart Van Assche
  1 sibling, 0 replies; 29+ messages in thread
From: Bart Van Assche @ 2020-02-25  4:32 UTC (permalink / raw)
  To: Martin K. Petersen, Himanshu Madhani; +Cc: James.Bottomley, linux-scsi

On 2020-02-21 15:33, Martin K. Petersen wrote:
> Applied to 5.7/scsi-queue. This series lit up like a Xmas tree in
> checkpatch. Next time, please verify before posting.

Hi Martin,

Have these changes already been pushed out? It seems like it has been a
few days since your 5.7/scsi-queue branch has been published:

$ git fetch mkp-scsi && git show mkp-scsi/5.7/scsi-queue | head
commit b417107a659e9745f9ff905196ddff70cbe4eaa7
Author: Gustavo A. R. Silva <gustavo@embeddedor.com>
Date:   Wed Feb 12 18:02:11 2020 -0600

    scsi: advansys: Replace zero-length array with flexible-array member

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2020-02-25  4:32 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-12 21:44 [PATCH 00/25] qla2xxx: Updates for the driver Himanshu Madhani
2020-02-12 21:44 ` [PATCH 01/25] qla2xxx: Add beacon LED config sysfs interface Himanshu Madhani
2020-02-12 21:44 ` [PATCH 02/25] qla2xxx: Move free of fcport out of interrupt context Himanshu Madhani
2020-02-12 21:44 ` [PATCH 03/25] qla2xxx: Add sysfs node for D-Port Diagnostics AEN data Himanshu Madhani
2020-02-12 21:44 ` [PATCH 04/25] qla2xxx: Remove all DIX-0 references Himanshu Madhani
2020-02-12 21:44 ` [PATCH 05/25] qla2xxx: Add endianizer macro calls to fc host stats Himanshu Madhani
2020-02-12 21:44 ` [PATCH 06/25] qla2xxx: Add changes in preparation for vendor extended FDMI/RDP Himanshu Madhani
2020-02-12 21:44 ` [PATCH 07/25] qla2xxx: Add vendor extended RDP additions and amendments Himanshu Madhani
2020-02-12 21:44 ` [PATCH 08/25] qla2xxx: Add ql2xrdpenable module parameter for RDP Himanshu Madhani
2020-02-12 21:44 ` [PATCH 09/25] qla2xxx: Add vendor extended FDMI commands Himanshu Madhani
2020-02-12 21:44 ` [PATCH 10/25] qla2xxx: Display message for FCE enabled Himanshu Madhani
2020-02-12 21:44 ` [PATCH 11/25] qla2xxx: Show correct port speed capabilities for RDP command Himanshu Madhani
2020-02-12 21:44 ` [PATCH 12/25] qla2xxx: Cleanup ELS/PUREX iocb fields Himanshu Madhani
2020-02-12 21:44 ` [PATCH 13/25] qla2xxx: Add deferred queue for processing ABTS and RDP Himanshu Madhani
2020-02-12 21:44 ` [PATCH 14/25] qla2xxx: Handle cases for limiting RDP response payload length Himanshu Madhani
2020-02-12 21:44 ` [PATCH 15/25] qla2xxx: Fix RDP response size Himanshu Madhani
2020-02-12 21:44 ` [PATCH 16/25] qla2xxx: Use endian macros to assign static fields in fwdump header Himanshu Madhani
2020-02-12 21:44 ` [PATCH 17/25] qla2xxx: Correction to selection of loopback/echo test Himanshu Madhani
2020-02-12 21:44 ` [PATCH 18/25] qla2xxx: Fix qla2x00_echo_test() based on ISP type Himanshu Madhani
2020-02-12 21:44 ` [PATCH 19/25] qla2xxx: Print portname for logging in qla24xx_logio_entry() Himanshu Madhani
2020-02-12 21:44 ` [PATCH 20/25] qla2xxx: Use correct ISP28xx active FW region Himanshu Madhani
2020-02-12 21:44 ` [PATCH 21/25] qla2xxx: Save rscn_gen for new fcport Himanshu Madhani
2020-02-12 21:44 ` [PATCH 22/25] qla2xxx: Fix control flags for login/logout IOCB Himanshu Madhani
2020-02-12 21:44 ` [PATCH 23/25] qla2xxx: Add fixes for mailbox command Himanshu Madhani
2020-02-12 21:44 ` [PATCH 24/25] qla2xxx: Use QLA_FW_STOPPED macro to propagate flag Himanshu Madhani
2020-02-12 21:44 ` [PATCH 25/25] qla2xxx: Update driver version to 10.01.00.24-k Himanshu Madhani
2020-02-21 23:33 ` [PATCH 00/25] qla2xxx: Updates for the driver Martin K. Petersen
2020-02-24 16:36   ` Himanshu Madhani
2020-02-25  4:32   ` Bart Van Assche

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.