linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] qla2xxx: Patches for scsi-misc
@ 2017-10-13 16:34 Madhani, Madhani
  2017-10-13 16:34 ` [PATCH v2 1/5] qla2xxx: Add module param ql2xenablemsix Madhani, Madhani
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Madhani, Madhani @ 2017-10-13 16:34 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Himanshu Madhani <himanshu.madhani@cavium.com>

Hi Martin,

This series adds support for INTx mode for qla2xxx driver. Also,
adds support for N2N login for FC-NVMe.

Please apply to 4.15/scsi-queue at your earliest convenience.

Changes from v1 -> v2

o Fixed warnings reported by 0-day kernel build.

Thanks,
Himanshu

Duane Grigsby (2):
  qla2xxx: Allow MBC_GET_PORT_DATABASE to query and save the port states
  qla2xxx: Changes to support N2N logins

Himanshu Madhani (3):
  qla2xxx: Add module param ql2xenablemsix
  qla2xxx: Add ATIO-Q processing for INTx mode
  qla2xxx: Update driver version to 10.00.00.02-k

 drivers/scsi/qla2xxx/qla_def.h     |  29 ++++++
 drivers/scsi/qla2xxx/qla_fw.h      |   4 +-
 drivers/scsi/qla2xxx/qla_gbl.h     |   5 +
 drivers/scsi/qla2xxx/qla_init.c    | 135 ++++++++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_iocb.c    | 195 +++++++++++++++++++++++++++++++++++--
 drivers/scsi/qla2xxx/qla_isr.c     |  59 +++++++++--
 drivers/scsi/qla2xxx/qla_mbx.c     | 105 ++++++++++++++++++--
 drivers/scsi/qla2xxx/qla_os.c      |   9 ++
 drivers/scsi/qla2xxx/qla_target.c  |  12 ++-
 drivers/scsi/qla2xxx/qla_version.h |   2 +-
 10 files changed, 518 insertions(+), 37 deletions(-)

-- 
2.12.0

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

* [PATCH v2 1/5] qla2xxx: Add module param ql2xenablemsix
  2017-10-13 16:34 [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Madhani, Madhani
@ 2017-10-13 16:34 ` Madhani, Madhani
  2017-10-13 16:34 ` [PATCH v2 2/5] qla2xxx: Add ATIO-Q processing for INTx mode Madhani, Madhani
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Madhani, Madhani @ 2017-10-13 16:34 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Himanshu Madhani <himanshu.madhani@cavium.com>

Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h | 1 +
 drivers/scsi/qla2xxx/qla_isr.c | 9 ++++++---
 drivers/scsi/qla2xxx/qla_os.c  | 9 +++++++++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index f852ca60c49f..46c7822c20fc 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -145,6 +145,7 @@ extern int ql2xmvasynctoatio;
 extern int ql2xuctrlirq;
 extern int ql2xnvmeenable;
 extern int ql2xautodetectsfp;
+extern int ql2xenablemsix;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 9d9668aac6f6..ef7afd5eefe3 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3486,11 +3486,14 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
 	scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
 	/* If possible, enable MSI-X. */
-	if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
-	    !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLAFX00(ha) &&
-	    !IS_QLA27XX(ha))
+	if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
+	    !IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
+	    !IS_QLAFX00(ha) && !IS_QLA27XX(ha)))
 		goto skip_msi;
 
+	if (ql2xenablemsix == 2)
+		goto skip_msix;
+
 	if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
 		(ha->pdev->subsystem_device == 0x7040 ||
 		ha->pdev->subsystem_device == 0x7041 ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 937209805baf..cb719345aa0d 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -268,6 +268,15 @@ MODULE_PARM_DESC(ql2xautodetectsfp,
 		 "Detect SFP range and set appropriate distance.\n"
 		 "1 (Default): Enable\n");
 
+int ql2xenablemsix = 1;
+module_param(ql2xenablemsix, int, 0444);
+MODULE_PARM_DESC(ql2xenablemsix,
+    "Set to enable MSI or MSI-X interrupt mechanism.\n"
+    " Default is 1, enable MSI-X interrupt mechanism.\n"
+    " 0 -- enable traditional pin-based mechanism.\n"
+    " 1 -- enable MSI-X interrupt mechanism.\n"
+    " 2 -- enable MSI interrupt mechanism.\n");
+
 /*
  * SCSI host template entry points
  */
-- 
2.12.0

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

* [PATCH v2 2/5] qla2xxx: Add ATIO-Q processing for INTx mode
  2017-10-13 16:34 [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Madhani, Madhani
  2017-10-13 16:34 ` [PATCH v2 1/5] qla2xxx: Add module param ql2xenablemsix Madhani, Madhani
@ 2017-10-13 16:34 ` Madhani, Madhani
  2017-10-13 16:34 ` [PATCH v2 3/5] qla2xxx: Allow MBC_GET_PORT_DATABASE to query and save the port states Madhani, Madhani
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Madhani, Madhani @ 2017-10-13 16:34 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Himanshu Madhani <himanshu.madhani@cavium.com>

Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h    |  1 +
 drivers/scsi/qla2xxx/qla_isr.c    |  8 ++++++--
 drivers/scsi/qla2xxx/qla_target.c | 12 +++++++++---
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 486c075998f6..66d239cbbd66 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -922,6 +922,7 @@ struct mbx_cmd_32 {
 #define INTR_RSP_QUE_UPDATE_83XX	0x14
 #define INTR_ATIO_QUE_UPDATE		0x1C
 #define INTR_ATIO_RSP_QUE_UPDATE	0x1D
+#define INTR_ATIO_QUE_UPDATE_27XX	0x1E
 
 /* ISP mailbox loopback echo diagnostic error code */
 #define MBS_LB_RESET	0x17
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ef7afd5eefe3..ab97fb06c239 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3129,6 +3129,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
 		case INTR_RSP_QUE_UPDATE_83XX:
 			qla24xx_process_response_queue(vha, rsp);
 			break;
+		case INTR_ATIO_QUE_UPDATE_27XX:
 		case INTR_ATIO_QUE_UPDATE:{
 			unsigned long flags2;
 			spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
@@ -3259,6 +3260,7 @@ qla24xx_msix_default(int irq, void *dev_id)
 		case INTR_RSP_QUE_UPDATE_83XX:
 			qla24xx_process_response_queue(vha, rsp);
 			break;
+		case INTR_ATIO_QUE_UPDATE_27XX:
 		case INTR_ATIO_QUE_UPDATE:{
 			unsigned long flags2;
 			spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
@@ -3347,7 +3349,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
 		.pre_vectors = QLA_BASE_VECTORS,
 	};
 
-	if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
+	if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) &&
+	    IS_ATIO_MSIX_CAPABLE(ha)) {
 		desc.pre_vectors++;
 		min_vecs++;
 	}
@@ -3432,7 +3435,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
 	 * If target mode is enable, also request the vector for the ATIO
 	 * queue.
 	 */
-	if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
+	if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) &&
+	    IS_ATIO_MSIX_CAPABLE(ha)) {
 		qentry = &ha->msix_entries[QLA_ATIO_VECTOR];
 		rsp->msix = qentry;
 		qentry->handle = rsp;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index f05cfc83c9c8..12976a25f082 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -6546,6 +6546,7 @@ void
 qlt_24xx_config_rings(struct scsi_qla_host *vha)
 {
 	struct qla_hw_data *ha = vha->hw;
+	struct init_cb_24xx *icb;
 	if (!QLA_TGT_MODE_ENABLED())
 		return;
 
@@ -6553,14 +6554,19 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha)
 	WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0);
 	RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
 
-	if (IS_ATIO_MSIX_CAPABLE(ha)) {
+	icb = (struct init_cb_24xx *)ha->init_cb;
+
+	if ((ql2xenablemsix != 0) && IS_ATIO_MSIX_CAPABLE(ha)) {
 		struct qla_msix_entry *msix = &ha->msix_entries[2];
-		struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb;
 
 		icb->msix_atio = cpu_to_le16(msix->entry);
 		ql_dbg(ql_dbg_init, vha, 0xf072,
 		    "Registering ICB vector 0x%x for atio que.\n",
 		    msix->entry);
+	} else if (ql2xenablemsix == 0) {
+		icb->firmware_options_2 |= cpu_to_le32(BIT_26);
+		ql_dbg(ql_dbg_init, vha, 0xf07f,
+		    "Registering INTx vector for ATIO.\n");
 	}
 }
 
@@ -6805,7 +6811,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
 	if (!QLA_TGT_MODE_ENABLED())
 		return;
 
-	if  (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+	if  ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
 		ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
 		ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
 	} else {
-- 
2.12.0

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

* [PATCH v2 3/5] qla2xxx: Allow MBC_GET_PORT_DATABASE to query and save the port states
  2017-10-13 16:34 [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Madhani, Madhani
  2017-10-13 16:34 ` [PATCH v2 1/5] qla2xxx: Add module param ql2xenablemsix Madhani, Madhani
  2017-10-13 16:34 ` [PATCH v2 2/5] qla2xxx: Add ATIO-Q processing for INTx mode Madhani, Madhani
@ 2017-10-13 16:34 ` Madhani, Madhani
  2017-10-13 16:34 ` [PATCH v2 4/5] qla2xxx: Changes to support N2N logins Madhani, Madhani
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Madhani, Madhani @ 2017-10-13 16:34 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Duane Grigsby <duane.grigsby@cavium.com>

The MBC_GET_PORT_DATABASE command normally checks the port state
informationi. This patch allows it to save that info in the fcport
structure and ignore the check if the query flag is set.

Signed-off-by: Duane Grigsby <duane.grigsby@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  4 ++++
 drivers/scsi/qla2xxx/qla_mbx.c | 29 ++++++++++++++++++++++-------
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 66d239cbbd66..f712c0cd46d6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2303,6 +2303,7 @@ typedef struct fc_port {
 	unsigned int send_els_logo:1;
 	unsigned int login_pause:1;
 	unsigned int login_succ:1;
+	unsigned int query:1;
 
 	struct work_struct nvme_del_work;
 	struct completion nvme_del_done;
@@ -2369,6 +2370,8 @@ typedef struct fc_port {
 	struct list_head gnl_entry;
 	struct work_struct del_work;
 	u8 iocb[IOCB_SIZE];
+	u8 current_login_state;
+	u8 last_login_state;
 } fc_port_t;
 
 #define QLA_FCPORT_SCAN		1
@@ -4114,6 +4117,7 @@ typedef struct scsi_qla_host {
 #define QPAIR_ONLINE_CHECK_NEEDED	27
 #define SET_ZIO_THRESHOLD_NEEDED	28
 #define DETECT_SFP_CHANGE	29
+#define N2N_LOGIN_NEEDED	30
 
 	unsigned long	pci_flags;
 #define PFLG_DISCONNECTED	0	/* PCI device removed */
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 7f71fd378c27..71e56877e1eb 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1822,17 +1822,32 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
 
 	if (IS_FWI2_CAPABLE(ha)) {
 		uint64_t zero = 0;
+		u8 current_login_state, last_login_state;
+
 		pd24 = (struct port_database_24xx *) pd;
 
 		/* Check for logged in state. */
-		if (pd24->current_login_state != PDS_PRLI_COMPLETE &&
-		    pd24->last_login_state != PDS_PRLI_COMPLETE) {
-			ql_dbg(ql_dbg_mbx, vha, 0x1051,
-			    "Unable to verify login-state (%x/%x) for "
-			    "loop_id %x.\n", pd24->current_login_state,
-			    pd24->last_login_state, fcport->loop_id);
+		if (fcport->fc4f_nvme) {
+			current_login_state = pd24->current_login_state >> 4;
+			last_login_state = pd24->last_login_state >> 4;
+		} else {
+			current_login_state = pd24->current_login_state & 0xf;
+			last_login_state = pd24->last_login_state & 0xf;
+		}
+		fcport->current_login_state = pd24->current_login_state;
+		fcport->last_login_state = pd24->last_login_state;
+
+		/* Check for logged in state. */
+		if (current_login_state != PDS_PRLI_COMPLETE &&
+		    last_login_state != PDS_PRLI_COMPLETE) {
+			ql_dbg(ql_dbg_mbx, vha, 0x119a,
+			    "Unable to verify login-state (%x/%x) for loop_id %x.\n",
+			    current_login_state, last_login_state,
+			    fcport->loop_id);
 			rval = QLA_FUNCTION_FAILED;
-			goto gpd_error_out;
+
+			if (!fcport->query)
+				goto gpd_error_out;
 		}
 
 		if (fcport->loop_id == FC_NO_LOOP_ID ||
-- 
2.12.0

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

* [PATCH v2 4/5] qla2xxx: Changes to support N2N logins
  2017-10-13 16:34 [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Madhani, Madhani
                   ` (2 preceding siblings ...)
  2017-10-13 16:34 ` [PATCH v2 3/5] qla2xxx: Allow MBC_GET_PORT_DATABASE to query and save the port states Madhani, Madhani
@ 2017-10-13 16:34 ` Madhani, Madhani
  2017-10-13 17:01   ` Ewan D. Milne
  2017-10-13 16:34 ` [PATCH v2 5/5] qla2xxx: Update driver version to 10.00.00.02-k Madhani, Madhani
  2017-10-17  3:08 ` [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Martin K. Petersen
  5 siblings, 1 reply; 9+ messages in thread
From: Madhani, Madhani @ 2017-10-13 16:34 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Duane Grigsby <duane.grigsby@cavium.com>

If we discovered a topology that is N2N then we will issue a login
to the target. If our WWPN is bigger than the target's WWPN then we
will initiate login, otherwise we will just wait for the target
to initiate login.

Signed-off-by: Duane Grigsby <duane.grigsby@cavium.com>
Signed-off-by: Michael Hernandez <michael.hernandez@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |  24 +++++
 drivers/scsi/qla2xxx/qla_fw.h   |   4 +-
 drivers/scsi/qla2xxx/qla_gbl.h  |   4 +
 drivers/scsi/qla2xxx/qla_init.c | 135 +++++++++++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_iocb.c | 195 +++++++++++++++++++++++++++++++++++++---
 drivers/scsi/qla2xxx/qla_isr.c  |  42 ++++++++-
 drivers/scsi/qla2xxx/qla_mbx.c  |  76 ++++++++++++++++
 7 files changed, 459 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index f712c0cd46d6..01a9b8971e88 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -323,6 +323,12 @@ struct els_logo_payload {
 	uint8_t wwpn[WWN_SIZE];
 };
 
+struct els_plogi_payload {
+	uint8_t opcode;
+	uint8_t rsvd[3];
+	uint8_t data[112];
+};
+
 struct ct_arg {
 	void		*iocb;
 	u16		nport_handle;
@@ -358,6 +364,19 @@ struct srb_iocb {
 			dma_addr_t els_logo_pyld_dma;
 		} els_logo;
 		struct {
+#define ELS_DCMD_PLOGI 0x3
+			uint32_t flags;
+			uint32_t els_cmd;
+			struct completion comp;
+			struct els_plogi_payload *els_plogi_pyld;
+			struct els_plogi_payload *els_resp_pyld;
+			dma_addr_t els_plogi_pyld_dma;
+			dma_addr_t els_resp_pyld_dma;
+			uint32_t	fw_status[3];
+			__le16	comp_status;
+			__le16	len;
+		} els_plogi;
+		struct {
 			/*
 			 * Values for flags field below are as
 			 * defined in tsk_mgmt_entry struct
@@ -2349,6 +2368,7 @@ typedef struct fc_port {
 	uint8_t fc4_type;
 	uint8_t	fc4f_nvme;
 	uint8_t scan_state;
+	uint8_t n2n_flag;
 
 	unsigned long last_queue_full;
 	unsigned long last_ramp_up;
@@ -2372,6 +2392,7 @@ typedef struct fc_port {
 	u8 iocb[IOCB_SIZE];
 	u8 current_login_state;
 	u8 last_login_state;
+	struct completion n2n_done;
 } fc_port_t;
 
 #define QLA_FCPORT_SCAN		1
@@ -4228,6 +4249,9 @@ typedef struct scsi_qla_host {
 	wait_queue_head_t fcport_waitQ;
 	wait_queue_head_t vref_waitq;
 	uint8_t min_link_speed_feat;
+	uint8_t n2n_node_name[WWN_SIZE];
+	uint8_t n2n_port_name[WWN_SIZE];
+	uint16_t	n2n_id;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index bec641aae7b3..d5cef0727e72 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -753,9 +753,7 @@ struct els_entry_24xx {
 	uint8_t reserved_2;
 
 	uint8_t port_id[3];
-	uint8_t reserved_3;
-
-	uint16_t reserved_4;
+	uint8_t s_id[3];
 
 	uint16_t control_flags;		/* Control flags. */
 #define ECF_PAYLOAD_DESCR_MASK	(BIT_15|BIT_14|BIT_13)
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 46c7822c20fc..1e35e961683f 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -45,6 +45,8 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
 extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
 
 extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
+extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *,
+    port_id_t);
 
 extern void qla2x00_update_fcports(scsi_qla_host_t *);
 
@@ -487,6 +489,8 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
     uint16_t *);
 int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *,
 	struct port_database_24xx *);
+int qla24xx_get_port_login_templ(scsi_qla_host_t *, dma_addr_t,
+    void *, uint16_t);
 
 extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *);
 extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4c53199db371..b2a391f93775 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1433,6 +1433,14 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 		qla24xx_post_gpdb_work(vha, ea->fcport, 0);
 		break;
 	default:
+		if (ea->fcport->n2n_flag) {
+			ql_dbg(ql_dbg_disc, vha, 0x2118,
+				"%s %d %8phC post fc4 prli\n",
+				__func__, __LINE__, ea->fcport->port_name);
+			ea->fcport->fc4f_nvme = 0;
+			ea->fcport->n2n_flag = 0;
+			qla24xx_post_prli_work(vha, ea->fcport);
+		}
 		ql_dbg(ql_dbg_disc, vha, 0x2119,
 		    "%s %d %8phC unhandle event of %x\n",
 		    __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
@@ -4366,7 +4374,109 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
 	return (rval);
 }
 
+/*
+ * N2N Login
+ *	Updates Fibre Channel Device Database with local loop devices.
+ *
+ * Input:
+ *	ha = adapter block pointer.
+ *
+ * Returns:
+ */
+static int qla24xx_n2n_handle_login(struct scsi_qla_host *vha,
+    fc_port_t *fcport)
+{
+	struct qla_hw_data *ha = vha->hw;
+	int	res = QLA_SUCCESS, rval;
+	int	greater_wwpn = 0;
+	int	logged_in = 0;
+
+	if (ha->current_topology != ISP_CFG_N)
+		return res;
+
+	if (wwn_to_u64(vha->port_name) >
+	    wwn_to_u64(vha->n2n_port_name)) {
+		ql_dbg(ql_dbg_disc, vha, 0x2002,
+		    "HBA WWPN is greater %llx > target %llx\n",
+		    wwn_to_u64(vha->port_name),
+		    wwn_to_u64(vha->n2n_port_name));
+		greater_wwpn = 1;
+		fcport->d_id.b24 = vha->n2n_id;
+	}
+
+	fcport->loop_id = vha->loop_id;
+	fcport->fc4f_nvme = 0;
+	fcport->query = 1;
+
+	ql_dbg(ql_dbg_disc, vha, 0x4001,
+	    "Initiate N2N login handler: HBA port_id=%06x loopid=%d\n",
+	    fcport->d_id.b24, vha->loop_id);
+
+	/* Fill in member data. */
+	if (!greater_wwpn) {
+		rval = qla2x00_get_port_database(vha, fcport, 0);
+		ql_dbg(ql_dbg_disc, vha, 0x1051,
+		    "Remote login-state (%x/%x) port_id=%06x loop_id=%x, rval=%d\n",
+		    fcport->current_login_state, fcport->last_login_state,
+		    fcport->d_id.b24, fcport->loop_id, rval);
+
+		if (((fcport->current_login_state & 0xf) == 0x4) ||
+		    ((fcport->current_login_state & 0xf) == 0x6))
+			logged_in = 1;
+	}
+
+	if (logged_in || greater_wwpn) {
+		if (!vha->nvme_local_port && vha->flags.nvme_enabled)
+			qla_nvme_register_hba(vha);
+
+		/* Set connected N_Port d_id */
+		if (vha->flags.nvme_enabled)
+			fcport->fc4f_nvme = 1;
+
+		fcport->scan_state = QLA_FCPORT_FOUND;
+		fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+		fcport->disc_state = DSC_GNL;
+		fcport->n2n_flag = 1;
+		fcport->flags = 3;
+		vha->hw->flags.gpsc_supported = 0;
+
+		if (greater_wwpn) {
+			ql_dbg(ql_dbg_disc, vha, 0x20e5,
+			    "%s %d PLOGI ELS %8phC\n",
+			    __func__, __LINE__, fcport->port_name);
+
+			res = qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
+			    fcport, fcport->d_id);
+		}
+
+		if (res != QLA_SUCCESS) {
+			ql_log(ql_log_info, vha, 0xd04d,
+			    "PLOGI Failed: portid=%06x - retrying\n",
+			    fcport->d_id.b24);
+			res = QLA_SUCCESS;
+		} else {
+			/* State 0x6 means FCP PRLI complete */
+			if ((fcport->current_login_state & 0xf) == 0x6) {
+				ql_dbg(ql_dbg_disc, vha, 0x2118,
+				    "%s %d %8phC post GPDB work\n",
+				    __func__, __LINE__, fcport->port_name);
+				fcport->chip_reset =
+				    vha->hw->base_qpair->chip_reset;
+				qla24xx_post_gpdb_work(vha, fcport, 0);
+			} else {
+				ql_dbg(ql_dbg_disc, vha, 0x2118,
+				    "%s %d %8phC post NVMe PRLI\n",
+				    __func__, __LINE__, fcport->port_name);
+				qla24xx_post_prli_work(vha, fcport);
+			}
+		}
+	} else {
+		/* Wait for next database change */
+		set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
+	}
 
+	return res;
+}
 
 /*
  * qla2x00_configure_local_loop
@@ -4437,6 +4547,14 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 		}
 	}
 
+	/* Inititae N2N login. */
+	if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
+		rval = qla24xx_n2n_handle_login(vha, new_fcport);
+		if (rval != QLA_SUCCESS)
+			goto cleanup_allocation;
+		return QLA_SUCCESS;
+	}
+
 	/* Add devices to port list. */
 	id_iter = (char *)ha->gid_list;
 	for (index = 0; index < entries; index++) {
@@ -4478,10 +4596,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 			    "Failed to retrieve fcport information "
 			    "-- get_port_database=%x, loop_id=0x%04x.\n",
 			    rval2, new_fcport->loop_id);
-			ql_dbg(ql_dbg_disc, vha, 0x2105,
-			    "Scheduling resync.\n");
-			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
-			continue;
+			/* Skip retry if N2N */
+			if (ha->current_topology != ISP_CFG_N) {
+				ql_dbg(ql_dbg_disc, vha, 0x2105,
+				    "Scheduling resync.\n");
+				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+				continue;
+			}
 		}
 
 		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
@@ -7554,6 +7675,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
 	if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
 		icb->firmware_options_3 |= BIT_0;
 
+	if (IS_QLA27XX(ha)) {
+		icb->firmware_options_3 |= BIT_8;
+		ql_dbg(ql_log_info, vha, 0x0075,
+		    "Enabling direct connection.\n");
+	}
+
 	if (rval) {
 		ql_log(ql_log_warn, vha, 0x0076,
 		    "NVRAM configuration failed.\n");
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 2f94159186d7..0502ed7ee14e 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
 	scsi_qla_host_t *vha = sp->vha;
 	struct srb_iocb *elsio = &sp->u.iocb_cmd;
+	uint32_t	dsd_len = 24;
 
 	els_iocb->entry_type = ELS_IOCB_TYPE;
 	els_iocb->entry_count = 1;
@@ -2534,24 +2535,198 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 	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->s_id[0] = vha->d_id.b.al_pa;
+	els_iocb->s_id[1] = vha->d_id.b.area;
+	els_iocb->s_id[2] = vha->d_id.b.domain;
 	els_iocb->control_flags = 0;
 
-	els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
-	els_iocb->tx_address[0] =
-	    cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
-	els_iocb->tx_address[1] =
-	    cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
-	els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
+	if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) {
+		els_iocb->tx_byte_count = sizeof(struct els_plogi_payload);
+		els_iocb->tx_address[0] =
+			cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma));
+		els_iocb->tx_address[1] =
+			cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma));
+		els_iocb->tx_len = dsd_len;
+
+		els_iocb->rx_dsd_count = 1;
+		els_iocb->rx_byte_count = sizeof(struct els_plogi_payload);
+		els_iocb->rx_address[0] =
+			cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma));
+		els_iocb->rx_address[1] =
+			cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma));
+		els_iocb->rx_len = dsd_len;
+		ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
+		    "PLOGI ELS IOCB:\n");
+		ql_dump_buffer(ql_log_info, vha, 0x0109,
+		    (uint8_t *)els_iocb, 0x70);
+	} else {
+		els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
+		els_iocb->tx_address[0] =
+		    cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
+		els_iocb->tx_address[1] =
+		    cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
+		els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
 
-	els_iocb->rx_byte_count = 0;
-	els_iocb->rx_address[0] = 0;
-	els_iocb->rx_address[1] = 0;
-	els_iocb->rx_len = 0;
+		els_iocb->rx_byte_count = 0;
+		els_iocb->rx_address[0] = 0;
+		els_iocb->rx_address[1] = 0;
+		els_iocb->rx_len = 0;
+	}
 
 	sp->vha->qla_stats.control_requests++;
 }
 
 static void
+qla2x00_els_dcmd2_sp_free(void *data)
+{
+	srb_t *sp = data;
+	struct srb_iocb *elsio = &sp->u.iocb_cmd;
+
+	if (elsio->u.els_plogi.els_plogi_pyld)
+		dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
+		    elsio->u.els_plogi.els_plogi_pyld,
+		    elsio->u.els_plogi.els_plogi_pyld_dma);
+
+	if (elsio->u.els_plogi.els_resp_pyld)
+		dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
+		    elsio->u.els_plogi.els_resp_pyld,
+		    elsio->u.els_plogi.els_resp_pyld_dma);
+
+	del_timer(&elsio->timer);
+	qla2x00_rel_sp(sp);
+}
+
+static void
+qla2x00_els_dcmd2_iocb_timeout(void *data)
+{
+	srb_t *sp = data;
+	fc_port_t *fcport = sp->fcport;
+	struct scsi_qla_host *vha = sp->vha;
+	struct qla_hw_data *ha = vha->hw;
+	struct srb_iocb *lio = &sp->u.iocb_cmd;
+	unsigned long flags = 0;
+	int res;
+
+	ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3069,
+	    "%s hdl=%x ELS Timeout, %8phC portid=%06x\n",
+	    sp->name, sp->handle, fcport->port_name, fcport->d_id.b24);
+
+	/* Abort the exchange */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	res = ha->isp_ops->abort_command(sp);
+	ql_dbg(ql_dbg_io, vha, 0x3070,
+	    "mbx abort_command %s\n",
+	    (res == QLA_SUCCESS) ? "successful" : "failed");
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	complete(&lio->u.els_plogi.comp);
+}
+
+static void
+qla2x00_els_dcmd2_sp_done(void *ptr, int res)
+{
+	srb_t *sp = ptr;
+	fc_port_t *fcport = sp->fcport;
+	struct srb_iocb *lio = &sp->u.iocb_cmd;
+	struct scsi_qla_host *vha = sp->vha;
+
+	ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3072,
+	    "%s ELS hdl=%x, portid=%06x done %8pC\n",
+	    sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
+
+	complete(&lio->u.els_plogi.comp);
+}
+
+int
+qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+    fc_port_t *fcport, port_id_t remote_did)
+{
+	srb_t *sp;
+	struct srb_iocb *elsio = NULL;
+	struct qla_hw_data *ha = vha->hw;
+	int rval = QLA_SUCCESS;
+	void	*ptr, *resp_ptr;
+	dma_addr_t ptr_dma;
+
+	/* Alloc SRB structure */
+	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+	if (!sp) {
+		ql_log(ql_log_info, vha, 0x70e6,
+		 "SRB allocation failed\n");
+		return -ENOMEM;
+	}
+
+	elsio = &sp->u.iocb_cmd;
+	fcport->d_id.b.domain = remote_did.b.domain;
+	fcport->d_id.b.area = remote_did.b.area;
+	fcport->d_id.b.al_pa = remote_did.b.al_pa;
+
+	ql_dbg(ql_dbg_io, vha, 0x3073,
+	    "Enter: PLOGI portid=%06x\n", fcport->d_id.b24);
+
+	sp->type = SRB_ELS_DCMD;
+	sp->name = "ELS_DCMD";
+	sp->fcport = fcport;
+	qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
+	elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
+	sp->done = qla2x00_els_dcmd2_sp_done;
+	sp->free = qla2x00_els_dcmd2_sp_free;
+
+	ptr = elsio->u.els_plogi.els_plogi_pyld =
+	    dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
+		&elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL);
+	ptr_dma = elsio->u.els_plogi.els_plogi_pyld_dma;
+
+	if (!elsio->u.els_plogi.els_plogi_pyld) {
+		rval = QLA_FUNCTION_FAILED;
+		goto out;
+	}
+
+	resp_ptr = elsio->u.els_plogi.els_resp_pyld =
+	    dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
+		&elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL);
+
+	if (!elsio->u.els_plogi.els_resp_pyld) {
+		rval = QLA_FUNCTION_FAILED;
+		goto out;
+	}
+
+	ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr);
+
+	memset(ptr, 0, sizeof(struct els_plogi_payload));
+	memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
+	elsio->u.els_plogi.els_cmd = els_opcode;
+	elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
+	qla24xx_get_port_login_templ(vha, ptr_dma + 4,
+		&elsio->u.els_plogi.els_plogi_pyld->data[0],
+		sizeof(struct els_plogi_payload));
+
+	ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
+	ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109,
+	    (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
+
+	init_completion(&elsio->u.els_plogi.comp);
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS) {
+		rval = QLA_FUNCTION_FAILED;
+		goto out;
+	}
+
+	ql_dbg(ql_dbg_io, vha, 0x3074,
+	    "%s PLOGI sent, hdl=%x, loopid=%x, portid=%06x\n",
+	    sp->name, sp->handle, fcport->loop_id, fcport->d_id.b24);
+
+	wait_for_completion(&elsio->u.els_plogi.comp);
+
+	if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
+		rval = QLA_FUNCTION_FAILED;
+
+out:
+	sp->free(sp);
+	return rval;
+}
+
+static void
 qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
 	struct bsg_job *bsg_job = sp->u.bsg_job;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ab97fb06c239..d06a1a809188 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1041,6 +1041,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		 */
 		atomic_set(&vha->loop_down_timer, 0);
 		if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
+			!ha->flags.n2n_ae  &&
 		    atomic_read(&vha->loop_state) != LOOP_DEAD) {
 			ql_dbg(ql_dbg_async, vha, 0x5011,
 			    "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
@@ -1545,6 +1546,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	uint32_t fw_status[3];
 	uint8_t* fw_sts_ptr;
 	int res;
+	struct 	srb_iocb *els;
 
 	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 	if (!sp)
@@ -1561,10 +1563,14 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 		break;
 	case SRB_ELS_DCMD:
 		type = "Driver ELS logo";
-		ql_dbg(ql_dbg_user, vha, 0x5047,
-		    "Completing %s: (%p) type=%d.\n", type, sp, sp->type);
-		sp->done(sp, 0);
-		return;
+		if (iocb_type != ELS_IOCB_TYPE) {
+			ql_dbg(ql_dbg_user, vha, 0x5047,
+			    "Completing %s: (%p) type=%d.\n",
+			    type, sp, sp->type);
+			sp->done(sp, 0);
+			return;
+		}
+		break;
 	case SRB_CT_PTHRU_CMD:
 		/* borrowing sts_entry_24xx.comp_status.
 		   same location as ct_entry_24xx.comp_status
@@ -1584,6 +1590,33 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1);
 	fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2);
 
+	if (iocb_type == ELS_IOCB_TYPE) {
+		els = &sp->u.iocb_cmd;
+		els->u.els_plogi.fw_status[0] = fw_status[0];
+		els->u.els_plogi.fw_status[1] = fw_status[1];
+		els->u.els_plogi.fw_status[2] = fw_status[2];
+		els->u.els_plogi.comp_status = fw_status[0];
+		if (comp_status == CS_COMPLETE) {
+			res =  DID_OK << 16;
+		} else {
+			if (comp_status == CS_DATA_UNDERRUN) {
+				res =  DID_OK << 16;
+				els->u.els_plogi.len =
+				le16_to_cpu(((struct els_sts_entry_24xx *)
+					pkt)->total_byte_count);
+			} else {
+				els->u.els_plogi.len = 0;
+				res = DID_ERROR << 16;
+			}
+		}
+		ql_log(ql_log_info, vha, 0x503f,
+		    "ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
+		    type, sp->handle, comp_status, fw_status[1], fw_status[2],
+		    le16_to_cpu(((struct els_sts_entry_24xx *)
+			pkt)->total_byte_count));
+		goto els_ct_done;
+	}
+
 	/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
 	 * fc payload  to the caller
 	 */
@@ -1631,6 +1664,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 		bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
 		bsg_job->reply_len = 0;
 	}
+els_ct_done:
 
 	sp->done(sp, res);
 }
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 71e56877e1eb..d44f65fe9434 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1786,6 +1786,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
 	if (pd  == NULL) {
 		ql_log(ql_log_warn, vha, 0x1050,
 		    "Failed to allocate port database structure.\n");
+		fcport->query = 0;
 		return QLA_MEMORY_ALLOC_FAILED;
 	}
 
@@ -1926,6 +1927,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
 
 gpd_error_out:
 	dma_pool_free(ha->s_dma_pool, pd, pd_dma);
+	fcport->query = 0;
 
 	if (rval != QLA_SUCCESS) {
 		ql_dbg(ql_dbg_mbx, vha, 0x1052,
@@ -3762,6 +3764,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 			rptid_entry->vp_status,
 		    rptid_entry->port_id[2], rptid_entry->port_id[1],
 		    rptid_entry->port_id[0]);
+		ql_dbg(ql_dbg_async, vha, 0x5075,
+		   "Format 1: Remote WWPN %8phC.\n",
+		   rptid_entry->u.f1.port_name);
+
+		ql_dbg(ql_dbg_async, vha, 0x5075,
+		   "Format 1: WWPN %8phC.\n",
+		   vha->port_name);
+
+		/* N2N.  direct connect */
+		if (IS_QLA27XX(ha) &&
+		    ((rptid_entry->u.f1.flags>>1) & 0x7) == 2) {
+			/* if our portname is higher then initiate N2N login */
+			if (wwn_to_u64(vha->port_name) >
+			    wwn_to_u64(rptid_entry->u.f1.port_name)) {
+				// ??? qlt_update_host_map(vha, id);
+				vha->n2n_id = 0x1;
+				ql_dbg(ql_dbg_async, vha, 0x5075,
+				    "Format 1: Setting n2n_update_needed for id %d\n",
+				    vha->n2n_id);
+			} else {
+				ql_dbg(ql_dbg_async, vha, 0x5075,
+				    "Format 1: Remote login - Waiting for WWPN %8phC.\n",
+				    rptid_entry->u.f1.port_name);
+			}
+
+			memcpy(vha->n2n_port_name, rptid_entry->u.f1.port_name,
+			    WWN_SIZE);
+			set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
+			set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
+			set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
+			return;
+		}
 
 		/* buffer to buffer credit flag */
 		vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
@@ -4599,6 +4633,48 @@ qla25xx_set_driver_version(scsi_qla_host_t *vha, char *version)
 	return rval;
 }
 
+int
+qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
+    void	*buf, uint16_t bufsiz)
+{
+	int rval, i;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+	uint32_t	*bp;
+
+	if (!IS_FWI2_CAPABLE(vha->hw))
+		return QLA_FUNCTION_FAILED;
+
+	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
+	    "Entered %s.\n", __func__);
+
+	mcp->mb[0] = MBC_GET_RNID_PARAMS;
+	mcp->mb[1] = RNID_TYPE_PORT_LOGIN << 8;
+	mcp->mb[2] = MSW(buf_dma);
+	mcp->mb[3] = LSW(buf_dma);
+	mcp->mb[6] = MSW(MSD(buf_dma));
+	mcp->mb[7] = LSW(MSD(buf_dma));
+	mcp->mb[8] = bufsiz/4;
+	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_1|MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(vha, mcp);
+
+	if (rval != QLA_SUCCESS) {
+		ql_dbg(ql_dbg_mbx, vha, 0x115a,
+		    "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
+	} else {
+		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
+		    "Done %s.\n", __func__);
+		bp = (uint32_t *) buf;
+		for (i = 0; i < (bufsiz-4)/4; i++, bp++)
+			*bp = cpu_to_be32(*bp);
+	}
+
+	return rval;
+}
+
 static int
 qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
 {
-- 
2.12.0

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

* [PATCH v2 5/5] qla2xxx: Update driver version to 10.00.00.02-k
  2017-10-13 16:34 [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Madhani, Madhani
                   ` (3 preceding siblings ...)
  2017-10-13 16:34 ` [PATCH v2 4/5] qla2xxx: Changes to support N2N logins Madhani, Madhani
@ 2017-10-13 16:34 ` Madhani, Madhani
  2017-10-17  3:08 ` [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Martin K. Petersen
  5 siblings, 0 replies; 9+ messages in thread
From: Madhani, Madhani @ 2017-10-13 16:34 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Himanshu Madhani <himanshu.madhani@cavium.com>

Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.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 8c4b505c9f66..b6ec02b96d3d 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.00.00.01-k"
+#define QLA2XXX_VERSION      "10.00.00.02-k"
 
 #define QLA_DRIVER_MAJOR_VER	10
 #define QLA_DRIVER_MINOR_VER	0
-- 
2.12.0

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

* Re: [PATCH v2 4/5] qla2xxx: Changes to support N2N logins
  2017-10-13 16:34 ` [PATCH v2 4/5] qla2xxx: Changes to support N2N logins Madhani, Madhani
@ 2017-10-13 17:01   ` Ewan D. Milne
  0 siblings, 0 replies; 9+ messages in thread
From: Ewan D. Milne @ 2017-10-13 17:01 UTC (permalink / raw)
  To: Madhani, Madhani; +Cc: James.Bottomley, martin.petersen, linux-scsi

On Fri, 2017-10-13 at 09:34 -0700, Madhani, Madhani wrote:
> From: Duane Grigsby <duane.grigsby@cavium.com>
> 
> If we discovered a topology that is N2N then we will issue a login
> to the target. If our WWPN is bigger than the target's WWPN then we
> will initiate login, otherwise we will just wait for the target
> to initiate login.
> 
> Signed-off-by: Duane Grigsby <duane.grigsby@cavium.com>
> Signed-off-by: Michael Hernandez <michael.hernandez@cavium.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
> ---
>  drivers/scsi/qla2xxx/qla_def.h  |  24 +++++
>  drivers/scsi/qla2xxx/qla_fw.h   |   4 +-
>  drivers/scsi/qla2xxx/qla_gbl.h  |   4 +
>  drivers/scsi/qla2xxx/qla_init.c | 135 +++++++++++++++++++++++++++-
>  drivers/scsi/qla2xxx/qla_iocb.c | 195 +++++++++++++++++++++++++++++++++++++---
>  drivers/scsi/qla2xxx/qla_isr.c  |  42 ++++++++-
>  drivers/scsi/qla2xxx/qla_mbx.c  |  76 ++++++++++++++++
>  7 files changed, 459 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index f712c0cd46d6..01a9b8971e88 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -323,6 +323,12 @@ struct els_logo_payload {
>  	uint8_t wwpn[WWN_SIZE];
>  };
>  
> +struct els_plogi_payload {
> +	uint8_t opcode;
> +	uint8_t rsvd[3];
> +	uint8_t data[112];
> +};
> +
>  struct ct_arg {
>  	void		*iocb;
>  	u16		nport_handle;
> @@ -358,6 +364,19 @@ struct srb_iocb {
>  			dma_addr_t els_logo_pyld_dma;
>  		} els_logo;
>  		struct {
> +#define ELS_DCMD_PLOGI 0x3
> +			uint32_t flags;
> +			uint32_t els_cmd;
> +			struct completion comp;
> +			struct els_plogi_payload *els_plogi_pyld;
> +			struct els_plogi_payload *els_resp_pyld;
> +			dma_addr_t els_plogi_pyld_dma;
> +			dma_addr_t els_resp_pyld_dma;
> +			uint32_t	fw_status[3];
> +			__le16	comp_status;
> +			__le16	len;
> +		} els_plogi;
> +		struct {
>  			/*
>  			 * Values for flags field below are as
>  			 * defined in tsk_mgmt_entry struct
> @@ -2349,6 +2368,7 @@ typedef struct fc_port {
>  	uint8_t fc4_type;
>  	uint8_t	fc4f_nvme;
>  	uint8_t scan_state;
> +	uint8_t n2n_flag;
>  
>  	unsigned long last_queue_full;
>  	unsigned long last_ramp_up;
> @@ -2372,6 +2392,7 @@ typedef struct fc_port {
>  	u8 iocb[IOCB_SIZE];
>  	u8 current_login_state;
>  	u8 last_login_state;
> +	struct completion n2n_done;
>  } fc_port_t;
>  
>  #define QLA_FCPORT_SCAN		1
> @@ -4228,6 +4249,9 @@ typedef struct scsi_qla_host {
>  	wait_queue_head_t fcport_waitQ;
>  	wait_queue_head_t vref_waitq;
>  	uint8_t min_link_speed_feat;
> +	uint8_t n2n_node_name[WWN_SIZE];
> +	uint8_t n2n_port_name[WWN_SIZE];
> +	uint16_t	n2n_id;
>  } scsi_qla_host_t;
>  
>  struct qla27xx_image_status {
> diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
> index bec641aae7b3..d5cef0727e72 100644
> --- a/drivers/scsi/qla2xxx/qla_fw.h
> +++ b/drivers/scsi/qla2xxx/qla_fw.h
> @@ -753,9 +753,7 @@ struct els_entry_24xx {
>  	uint8_t reserved_2;
>  
>  	uint8_t port_id[3];
> -	uint8_t reserved_3;
> -
> -	uint16_t reserved_4;
> +	uint8_t s_id[3];
>  
>  	uint16_t control_flags;		/* Control flags. */
>  #define ECF_PAYLOAD_DESCR_MASK	(BIT_15|BIT_14|BIT_13)
> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> index 46c7822c20fc..1e35e961683f 100644
> --- a/drivers/scsi/qla2xxx/qla_gbl.h
> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> @@ -45,6 +45,8 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
>  extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
>  
>  extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
> +extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *,
> +    port_id_t);
>  
>  extern void qla2x00_update_fcports(scsi_qla_host_t *);
>  
> @@ -487,6 +489,8 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
>      uint16_t *);
>  int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *,
>  	struct port_database_24xx *);
> +int qla24xx_get_port_login_templ(scsi_qla_host_t *, dma_addr_t,
> +    void *, uint16_t);
>  
>  extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *);
>  extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t);
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index 4c53199db371..b2a391f93775 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -1433,6 +1433,14 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
>  		qla24xx_post_gpdb_work(vha, ea->fcport, 0);
>  		break;
>  	default:
> +		if (ea->fcport->n2n_flag) {
> +			ql_dbg(ql_dbg_disc, vha, 0x2118,
> +				"%s %d %8phC post fc4 prli\n",
> +				__func__, __LINE__, ea->fcport->port_name);
> +			ea->fcport->fc4f_nvme = 0;
> +			ea->fcport->n2n_flag = 0;
> +			qla24xx_post_prli_work(vha, ea->fcport);
> +		}
>  		ql_dbg(ql_dbg_disc, vha, 0x2119,
>  		    "%s %d %8phC unhandle event of %x\n",
>  		    __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
> @@ -4366,7 +4374,109 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
>  	return (rval);
>  }
>  
> +/*
> + * N2N Login
> + *	Updates Fibre Channel Device Database with local loop devices.
> + *
> + * Input:
> + *	ha = adapter block pointer.
> + *
> + * Returns:
> + */
> +static int qla24xx_n2n_handle_login(struct scsi_qla_host *vha,
> +    fc_port_t *fcport)
> +{
> +	struct qla_hw_data *ha = vha->hw;
> +	int	res = QLA_SUCCESS, rval;
> +	int	greater_wwpn = 0;
> +	int	logged_in = 0;
> +
> +	if (ha->current_topology != ISP_CFG_N)
> +		return res;
> +
> +	if (wwn_to_u64(vha->port_name) >
> +	    wwn_to_u64(vha->n2n_port_name)) {
> +		ql_dbg(ql_dbg_disc, vha, 0x2002,
> +		    "HBA WWPN is greater %llx > target %llx\n",
> +		    wwn_to_u64(vha->port_name),
> +		    wwn_to_u64(vha->n2n_port_name));
> +		greater_wwpn = 1;
> +		fcport->d_id.b24 = vha->n2n_id;
> +	}
> +
> +	fcport->loop_id = vha->loop_id;
> +	fcport->fc4f_nvme = 0;
> +	fcport->query = 1;
> +
> +	ql_dbg(ql_dbg_disc, vha, 0x4001,
> +	    "Initiate N2N login handler: HBA port_id=%06x loopid=%d\n",
> +	    fcport->d_id.b24, vha->loop_id);
> +
> +	/* Fill in member data. */
> +	if (!greater_wwpn) {
> +		rval = qla2x00_get_port_database(vha, fcport, 0);
> +		ql_dbg(ql_dbg_disc, vha, 0x1051,
> +		    "Remote login-state (%x/%x) port_id=%06x loop_id=%x, rval=%d\n",
> +		    fcport->current_login_state, fcport->last_login_state,
> +		    fcport->d_id.b24, fcport->loop_id, rval);
> +
> +		if (((fcport->current_login_state & 0xf) == 0x4) ||
> +		    ((fcport->current_login_state & 0xf) == 0x6))
> +			logged_in = 1;
> +	}
> +
> +	if (logged_in || greater_wwpn) {
> +		if (!vha->nvme_local_port && vha->flags.nvme_enabled)
> +			qla_nvme_register_hba(vha);
> +
> +		/* Set connected N_Port d_id */
> +		if (vha->flags.nvme_enabled)
> +			fcport->fc4f_nvme = 1;
> +
> +		fcport->scan_state = QLA_FCPORT_FOUND;
> +		fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
> +		fcport->disc_state = DSC_GNL;
> +		fcport->n2n_flag = 1;
> +		fcport->flags = 3;
> +		vha->hw->flags.gpsc_supported = 0;
> +
> +		if (greater_wwpn) {
> +			ql_dbg(ql_dbg_disc, vha, 0x20e5,
> +			    "%s %d PLOGI ELS %8phC\n",
> +			    __func__, __LINE__, fcport->port_name);
> +
> +			res = qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
> +			    fcport, fcport->d_id);
> +		}
> +
> +		if (res != QLA_SUCCESS) {
> +			ql_log(ql_log_info, vha, 0xd04d,
> +			    "PLOGI Failed: portid=%06x - retrying\n",
> +			    fcport->d_id.b24);
> +			res = QLA_SUCCESS;
> +		} else {
> +			/* State 0x6 means FCP PRLI complete */
> +			if ((fcport->current_login_state & 0xf) == 0x6) {
> +				ql_dbg(ql_dbg_disc, vha, 0x2118,
> +				    "%s %d %8phC post GPDB work\n",
> +				    __func__, __LINE__, fcport->port_name);
> +				fcport->chip_reset =
> +				    vha->hw->base_qpair->chip_reset;
> +				qla24xx_post_gpdb_work(vha, fcport, 0);
> +			} else {
> +				ql_dbg(ql_dbg_disc, vha, 0x2118,
> +				    "%s %d %8phC post NVMe PRLI\n",
> +				    __func__, __LINE__, fcport->port_name);
> +				qla24xx_post_prli_work(vha, fcport);
> +			}
> +		}
> +	} else {
> +		/* Wait for next database change */
> +		set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
> +	}
>  
> +	return res;
> +}
>  
>  /*
>   * qla2x00_configure_local_loop
> @@ -4437,6 +4547,14 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
>  		}
>  	}
>  
> +	/* Inititae N2N login. */
> +	if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
> +		rval = qla24xx_n2n_handle_login(vha, new_fcport);
> +		if (rval != QLA_SUCCESS)
> +			goto cleanup_allocation;
> +		return QLA_SUCCESS;
> +	}
> +
>  	/* Add devices to port list. */
>  	id_iter = (char *)ha->gid_list;
>  	for (index = 0; index < entries; index++) {
> @@ -4478,10 +4596,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
>  			    "Failed to retrieve fcport information "
>  			    "-- get_port_database=%x, loop_id=0x%04x.\n",
>  			    rval2, new_fcport->loop_id);
> -			ql_dbg(ql_dbg_disc, vha, 0x2105,
> -			    "Scheduling resync.\n");
> -			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
> -			continue;
> +			/* Skip retry if N2N */
> +			if (ha->current_topology != ISP_CFG_N) {
> +				ql_dbg(ql_dbg_disc, vha, 0x2105,
> +				    "Scheduling resync.\n");
> +				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
> +				continue;
> +			}
>  		}
>  
>  		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
> @@ -7554,6 +7675,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
>  	if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
>  		icb->firmware_options_3 |= BIT_0;
>  
> +	if (IS_QLA27XX(ha)) {
> +		icb->firmware_options_3 |= BIT_8;
> +		ql_dbg(ql_log_info, vha, 0x0075,
> +		    "Enabling direct connection.\n");
> +	}
> +
>  	if (rval) {
>  		ql_log(ql_log_warn, vha, 0x0076,
>  		    "NVRAM configuration failed.\n");
> diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> index 2f94159186d7..0502ed7ee14e 100644
> --- a/drivers/scsi/qla2xxx/qla_iocb.c
> +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> @@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
>  {
>  	scsi_qla_host_t *vha = sp->vha;
>  	struct srb_iocb *elsio = &sp->u.iocb_cmd;
> +	uint32_t	dsd_len = 24;
>  
>  	els_iocb->entry_type = ELS_IOCB_TYPE;
>  	els_iocb->entry_count = 1;
> @@ -2534,24 +2535,198 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
>  	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->s_id[0] = vha->d_id.b.al_pa;
> +	els_iocb->s_id[1] = vha->d_id.b.area;
> +	els_iocb->s_id[2] = vha->d_id.b.domain;
>  	els_iocb->control_flags = 0;
>  
> -	els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
> -	els_iocb->tx_address[0] =
> -	    cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
> -	els_iocb->tx_address[1] =
> -	    cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
> -	els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
> +	if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) {
> +		els_iocb->tx_byte_count = sizeof(struct els_plogi_payload);
> +		els_iocb->tx_address[0] =
> +			cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma));
> +		els_iocb->tx_address[1] =
> +			cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma));
> +		els_iocb->tx_len = dsd_len;
> +
> +		els_iocb->rx_dsd_count = 1;
> +		els_iocb->rx_byte_count = sizeof(struct els_plogi_payload);
> +		els_iocb->rx_address[0] =
> +			cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma));
> +		els_iocb->rx_address[1] =
> +			cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma));
> +		els_iocb->rx_len = dsd_len;
> +		ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
> +		    "PLOGI ELS IOCB:\n");
> +		ql_dump_buffer(ql_log_info, vha, 0x0109,
> +		    (uint8_t *)els_iocb, 0x70);
> +	} else {
> +		els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
> +		els_iocb->tx_address[0] =
> +		    cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
> +		els_iocb->tx_address[1] =
> +		    cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
> +		els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
>  
> -	els_iocb->rx_byte_count = 0;
> -	els_iocb->rx_address[0] = 0;
> -	els_iocb->rx_address[1] = 0;
> -	els_iocb->rx_len = 0;
> +		els_iocb->rx_byte_count = 0;
> +		els_iocb->rx_address[0] = 0;
> +		els_iocb->rx_address[1] = 0;
> +		els_iocb->rx_len = 0;
> +	}
>  
>  	sp->vha->qla_stats.control_requests++;
>  }
>  
>  static void
> +qla2x00_els_dcmd2_sp_free(void *data)
> +{
> +	srb_t *sp = data;
> +	struct srb_iocb *elsio = &sp->u.iocb_cmd;
> +
> +	if (elsio->u.els_plogi.els_plogi_pyld)
> +		dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
> +		    elsio->u.els_plogi.els_plogi_pyld,
> +		    elsio->u.els_plogi.els_plogi_pyld_dma);
> +
> +	if (elsio->u.els_plogi.els_resp_pyld)
> +		dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
> +		    elsio->u.els_plogi.els_resp_pyld,
> +		    elsio->u.els_plogi.els_resp_pyld_dma);
> +
> +	del_timer(&elsio->timer);
> +	qla2x00_rel_sp(sp);
> +}
> +
> +static void
> +qla2x00_els_dcmd2_iocb_timeout(void *data)
> +{
> +	srb_t *sp = data;
> +	fc_port_t *fcport = sp->fcport;
> +	struct scsi_qla_host *vha = sp->vha;
> +	struct qla_hw_data *ha = vha->hw;
> +	struct srb_iocb *lio = &sp->u.iocb_cmd;
> +	unsigned long flags = 0;
> +	int res;
> +
> +	ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3069,
> +	    "%s hdl=%x ELS Timeout, %8phC portid=%06x\n",
> +	    sp->name, sp->handle, fcport->port_name, fcport->d_id.b24);
> +
> +	/* Abort the exchange */
> +	spin_lock_irqsave(&ha->hardware_lock, flags);
> +	res = ha->isp_ops->abort_command(sp);
> +	ql_dbg(ql_dbg_io, vha, 0x3070,
> +	    "mbx abort_command %s\n",
> +	    (res == QLA_SUCCESS) ? "successful" : "failed");
> +	spin_unlock_irqrestore(&ha->hardware_lock, flags);
> +
> +	complete(&lio->u.els_plogi.comp);
> +}
> +
> +static void
> +qla2x00_els_dcmd2_sp_done(void *ptr, int res)
> +{
> +	srb_t *sp = ptr;
> +	fc_port_t *fcport = sp->fcport;
> +	struct srb_iocb *lio = &sp->u.iocb_cmd;
> +	struct scsi_qla_host *vha = sp->vha;
> +
> +	ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3072,
> +	    "%s ELS hdl=%x, portid=%06x done %8pC\n",
> +	    sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
> +
> +	complete(&lio->u.els_plogi.comp);
> +}
> +
> +int
> +qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
> +    fc_port_t *fcport, port_id_t remote_did)
> +{
> +	srb_t *sp;
> +	struct srb_iocb *elsio = NULL;
> +	struct qla_hw_data *ha = vha->hw;
> +	int rval = QLA_SUCCESS;
> +	void	*ptr, *resp_ptr;
> +	dma_addr_t ptr_dma;
> +
> +	/* Alloc SRB structure */
> +	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> +	if (!sp) {
> +		ql_log(ql_log_info, vha, 0x70e6,
> +		 "SRB allocation failed\n");
> +		return -ENOMEM;
> +	}
> +
> +	elsio = &sp->u.iocb_cmd;
> +	fcport->d_id.b.domain = remote_did.b.domain;
> +	fcport->d_id.b.area = remote_did.b.area;
> +	fcport->d_id.b.al_pa = remote_did.b.al_pa;
> +
> +	ql_dbg(ql_dbg_io, vha, 0x3073,
> +	    "Enter: PLOGI portid=%06x\n", fcport->d_id.b24);
> +
> +	sp->type = SRB_ELS_DCMD;
> +	sp->name = "ELS_DCMD";
> +	sp->fcport = fcport;
> +	qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
> +	elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
> +	sp->done = qla2x00_els_dcmd2_sp_done;
> +	sp->free = qla2x00_els_dcmd2_sp_free;
> +
> +	ptr = elsio->u.els_plogi.els_plogi_pyld =
> +	    dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
> +		&elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL);
> +	ptr_dma = elsio->u.els_plogi.els_plogi_pyld_dma;
> +
> +	if (!elsio->u.els_plogi.els_plogi_pyld) {
> +		rval = QLA_FUNCTION_FAILED;
> +		goto out;
> +	}
> +
> +	resp_ptr = elsio->u.els_plogi.els_resp_pyld =
> +	    dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
> +		&elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL);
> +
> +	if (!elsio->u.els_plogi.els_resp_pyld) {
> +		rval = QLA_FUNCTION_FAILED;
> +		goto out;
> +	}
> +
> +	ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr);
> +
> +	memset(ptr, 0, sizeof(struct els_plogi_payload));
> +	memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
> +	elsio->u.els_plogi.els_cmd = els_opcode;
> +	elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
> +	qla24xx_get_port_login_templ(vha, ptr_dma + 4,
> +		&elsio->u.els_plogi.els_plogi_pyld->data[0],
> +		sizeof(struct els_plogi_payload));
> +
> +	ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
> +	ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109,
> +	    (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
> +
> +	init_completion(&elsio->u.els_plogi.comp);
> +	rval = qla2x00_start_sp(sp);
> +	if (rval != QLA_SUCCESS) {
> +		rval = QLA_FUNCTION_FAILED;
> +		goto out;
> +	}
> +
> +	ql_dbg(ql_dbg_io, vha, 0x3074,
> +	    "%s PLOGI sent, hdl=%x, loopid=%x, portid=%06x\n",
> +	    sp->name, sp->handle, fcport->loop_id, fcport->d_id.b24);
> +
> +	wait_for_completion(&elsio->u.els_plogi.comp);
> +
> +	if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
> +		rval = QLA_FUNCTION_FAILED;
> +
> +out:
> +	sp->free(sp);
> +	return rval;
> +}
> +
> +static void
>  qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
>  {
>  	struct bsg_job *bsg_job = sp->u.bsg_job;
> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> index ab97fb06c239..d06a1a809188 100644
> --- a/drivers/scsi/qla2xxx/qla_isr.c
> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> @@ -1041,6 +1041,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
>  		 */
>  		atomic_set(&vha->loop_down_timer, 0);
>  		if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
> +			!ha->flags.n2n_ae  &&
>  		    atomic_read(&vha->loop_state) != LOOP_DEAD) {
>  			ql_dbg(ql_dbg_async, vha, 0x5011,
>  			    "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
> @@ -1545,6 +1546,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
>  	uint32_t fw_status[3];
>  	uint8_t* fw_sts_ptr;
>  	int res;
> +	struct 	srb_iocb *els;
>  
>  	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
>  	if (!sp)
> @@ -1561,10 +1563,14 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
>  		break;
>  	case SRB_ELS_DCMD:
>  		type = "Driver ELS logo";
> -		ql_dbg(ql_dbg_user, vha, 0x5047,
> -		    "Completing %s: (%p) type=%d.\n", type, sp, sp->type);
> -		sp->done(sp, 0);
> -		return;
> +		if (iocb_type != ELS_IOCB_TYPE) {
> +			ql_dbg(ql_dbg_user, vha, 0x5047,
> +			    "Completing %s: (%p) type=%d.\n",
> +			    type, sp, sp->type);
> +			sp->done(sp, 0);
> +			return;
> +		}
> +		break;
>  	case SRB_CT_PTHRU_CMD:
>  		/* borrowing sts_entry_24xx.comp_status.
>  		   same location as ct_entry_24xx.comp_status
> @@ -1584,6 +1590,33 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
>  	fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1);
>  	fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2);
>  
> +	if (iocb_type == ELS_IOCB_TYPE) {
> +		els = &sp->u.iocb_cmd;
> +		els->u.els_plogi.fw_status[0] = fw_status[0];
> +		els->u.els_plogi.fw_status[1] = fw_status[1];
> +		els->u.els_plogi.fw_status[2] = fw_status[2];
> +		els->u.els_plogi.comp_status = fw_status[0];
> +		if (comp_status == CS_COMPLETE) {
> +			res =  DID_OK << 16;
> +		} else {
> +			if (comp_status == CS_DATA_UNDERRUN) {
> +				res =  DID_OK << 16;
> +				els->u.els_plogi.len =
> +				le16_to_cpu(((struct els_sts_entry_24xx *)
> +					pkt)->total_byte_count);
> +			} else {
> +				els->u.els_plogi.len = 0;
> +				res = DID_ERROR << 16;
> +			}
> +		}
> +		ql_log(ql_log_info, vha, 0x503f,
> +		    "ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
> +		    type, sp->handle, comp_status, fw_status[1], fw_status[2],
> +		    le16_to_cpu(((struct els_sts_entry_24xx *)
> +			pkt)->total_byte_count));
> +		goto els_ct_done;
> +	}
> +
>  	/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
>  	 * fc payload  to the caller
>  	 */
> @@ -1631,6 +1664,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
>  		bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
>  		bsg_job->reply_len = 0;
>  	}
> +els_ct_done:
>  
>  	sp->done(sp, res);
>  }
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index 71e56877e1eb..d44f65fe9434 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -1786,6 +1786,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
>  	if (pd  == NULL) {
>  		ql_log(ql_log_warn, vha, 0x1050,
>  		    "Failed to allocate port database structure.\n");
> +		fcport->query = 0;
>  		return QLA_MEMORY_ALLOC_FAILED;
>  	}
>  
> @@ -1926,6 +1927,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
>  
>  gpd_error_out:
>  	dma_pool_free(ha->s_dma_pool, pd, pd_dma);
> +	fcport->query = 0;
>  
>  	if (rval != QLA_SUCCESS) {
>  		ql_dbg(ql_dbg_mbx, vha, 0x1052,
> @@ -3762,6 +3764,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
>  			rptid_entry->vp_status,
>  		    rptid_entry->port_id[2], rptid_entry->port_id[1],
>  		    rptid_entry->port_id[0]);
> +		ql_dbg(ql_dbg_async, vha, 0x5075,
> +		   "Format 1: Remote WWPN %8phC.\n",
> +		   rptid_entry->u.f1.port_name);
> +
> +		ql_dbg(ql_dbg_async, vha, 0x5075,
> +		   "Format 1: WWPN %8phC.\n",
> +		   vha->port_name);
> +
> +		/* N2N.  direct connect */
> +		if (IS_QLA27XX(ha) &&
> +		    ((rptid_entry->u.f1.flags>>1) & 0x7) == 2) {
> +			/* if our portname is higher then initiate N2N login */
> +			if (wwn_to_u64(vha->port_name) >
> +			    wwn_to_u64(rptid_entry->u.f1.port_name)) {
> +				// ??? qlt_update_host_map(vha, id);
> +				vha->n2n_id = 0x1;
> +				ql_dbg(ql_dbg_async, vha, 0x5075,
> +				    "Format 1: Setting n2n_update_needed for id %d\n",
> +				    vha->n2n_id);
> +			} else {
> +				ql_dbg(ql_dbg_async, vha, 0x5075,
> +				    "Format 1: Remote login - Waiting for WWPN %8phC.\n",
> +				    rptid_entry->u.f1.port_name);
> +			}
> +
> +			memcpy(vha->n2n_port_name, rptid_entry->u.f1.port_name,
> +			    WWN_SIZE);
> +			set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
> +			set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
> +			set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
> +			return;
> +		}
>  
>  		/* buffer to buffer credit flag */
>  		vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
> @@ -4599,6 +4633,48 @@ qla25xx_set_driver_version(scsi_qla_host_t *vha, char *version)
>  	return rval;
>  }
>  
> +int
> +qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
> +    void	*buf, uint16_t bufsiz)
> +{
> +	int rval, i;
> +	mbx_cmd_t mc;
> +	mbx_cmd_t *mcp = &mc;
> +	uint32_t	*bp;
> +
> +	if (!IS_FWI2_CAPABLE(vha->hw))
> +		return QLA_FUNCTION_FAILED;
> +
> +	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
> +	    "Entered %s.\n", __func__);
> +
> +	mcp->mb[0] = MBC_GET_RNID_PARAMS;
> +	mcp->mb[1] = RNID_TYPE_PORT_LOGIN << 8;
> +	mcp->mb[2] = MSW(buf_dma);
> +	mcp->mb[3] = LSW(buf_dma);
> +	mcp->mb[6] = MSW(MSD(buf_dma));
> +	mcp->mb[7] = LSW(MSD(buf_dma));
> +	mcp->mb[8] = bufsiz/4;
> +	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
> +	mcp->in_mb = MBX_1|MBX_0;
> +	mcp->tov = MBX_TOV_SECONDS;
> +	mcp->flags = 0;
> +	rval = qla2x00_mailbox_command(vha, mcp);
> +
> +	if (rval != QLA_SUCCESS) {
> +		ql_dbg(ql_dbg_mbx, vha, 0x115a,
> +		    "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
> +	} else {
> +		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
> +		    "Done %s.\n", __func__);
> +		bp = (uint32_t *) buf;
> +		for (i = 0; i < (bufsiz-4)/4; i++, bp++)
> +			*bp = cpu_to_be32(*bp);
> +	}
> +
> +	return rval;
> +}
> +
>  static int
>  qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
>  {

Thanks.

Tested-by: Ewan D. Milne <emilne@redhat.com>

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

* Re: [PATCH v2 0/5] qla2xxx: Patches for scsi-misc
  2017-10-13 16:34 [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Madhani, Madhani
                   ` (4 preceding siblings ...)
  2017-10-13 16:34 ` [PATCH v2 5/5] qla2xxx: Update driver version to 10.00.00.02-k Madhani, Madhani
@ 2017-10-17  3:08 ` Martin K. Petersen
  2017-10-26  3:48   ` Madhani, Himanshu
  5 siblings, 1 reply; 9+ messages in thread
From: Martin K. Petersen @ 2017-10-17  3:08 UTC (permalink / raw)
  To: Madhani, Madhani; +Cc: James.Bottomley, martin.petersen, linux-scsi


Madhani,

> This series adds support for INTx mode for qla2xxx driver. Also, adds
> support for N2N login for FC-NVMe.
>
> Please apply to 4.15/scsi-queue at your earliest convenience.

Several of the patches had bad whitespace. Please run checkpatch before
submitting. Also, you did not apply the review tags you got from
Johannes for v1.

I fixed those things up. Applied to 4.15/scsi-queue.

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH v2 0/5] qla2xxx: Patches for scsi-misc
  2017-10-17  3:08 ` [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Martin K. Petersen
@ 2017-10-26  3:48   ` Madhani, Himanshu
  0 siblings, 0 replies; 9+ messages in thread
From: Madhani, Himanshu @ 2017-10-26  3:48 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: James.Bottomley@HansenPartnership.com, linux-scsi@vger.kernel.org

Hi Martin, 

> On Oct 16, 2017, at 8:08 PM, Martin K. Petersen <martin.petersen@oracle.com> wrote:
> 
> 
> Madhani,
> 
>> This series adds support for INTx mode for qla2xxx driver. Also, adds
>> support for N2N login for FC-NVMe.
>> 
>> Please apply to 4.15/scsi-queue at your earliest convenience.
> 
> Several of the patches had bad whitespace. Please run checkpatch before
> submitting. Also, you did not apply the review tags you got from
> Johannes for v1.
> 

Appreciate the feedback. Will check for those misses more closely for next submissions. 

> I fixed those things up. Applied to 4.15/scsi-queue.
> 
> -- 
> Martin K. Petersen	Oracle Linux Engineering

Thanks,
- Himanshu

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

end of thread, other threads:[~2017-10-26  3:48 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-13 16:34 [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Madhani, Madhani
2017-10-13 16:34 ` [PATCH v2 1/5] qla2xxx: Add module param ql2xenablemsix Madhani, Madhani
2017-10-13 16:34 ` [PATCH v2 2/5] qla2xxx: Add ATIO-Q processing for INTx mode Madhani, Madhani
2017-10-13 16:34 ` [PATCH v2 3/5] qla2xxx: Allow MBC_GET_PORT_DATABASE to query and save the port states Madhani, Madhani
2017-10-13 16:34 ` [PATCH v2 4/5] qla2xxx: Changes to support N2N logins Madhani, Madhani
2017-10-13 17:01   ` Ewan D. Milne
2017-10-13 16:34 ` [PATCH v2 5/5] qla2xxx: Update driver version to 10.00.00.02-k Madhani, Madhani
2017-10-17  3:08 ` [PATCH v2 0/5] qla2xxx: Patches for scsi-misc Martin K. Petersen
2017-10-26  3:48   ` Madhani, Himanshu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).