All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/43] qla2xxx: Driver update
@ 2017-12-20  6:56 Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer Himanshu Madhani
                   ` (42 more replies)
  0 siblings, 43 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

Hi Martin, 

This series contains number of improvments in handling of switch 
registration commands in the driver. Switch commands are now submitted
via IOCB patch asynchronously instead of mailbox interface.

Please apply this series to 4.16/scsi-queue branch at your earliest
convenience. 

Thanks,
Himanshu

Anil Gurumurthy (1):
  qla2xxx: Add counters for Exchange Buffer to debugfs

Giridhar Malavali (1):
  qla2xxx: Don't call dma_free_coherent with IRQ disabled.

Himanshu Madhani (4):
  qla2xxx: Use known NPort ID for Management Server login
  qla2xxx: Allow relogin and session creation after reset
  qla2xxx: Check FCF_ASYNC_SENT flag
  qla2xxx: Update driver version to 10.00.00.04-k

Quinn Tran (36):
  qla2xxx: Fix stale memory access for name pointer
  qla2xxx: Fix NULL pointer access for fcport structure
  qla2xxx: Use IOCB path to submit Control VP MBX command
  qla2xxx: Use chip reset to bring down laser on unload.
  qla2xxx: Add boundary checks for exchanges to be offloaded
  qla2xxx: Fix stale mem access for IRQ name
  qla2xxx: Add ability to track IOCB resource for FW
  qla2xxx: Chip reset uses wrong lock during IO flush.
  qla2xxx: Fix Firmware dump size for Extended login and Exchange
    Offload
  qla2xxx: Replace GPDB with async ADISC command
  qla2xxx: Move work element processing out of DPC thread
  qla2xxx: Enable ATIO interrupt handshake for ISP27XX
  qla2xxx: Use shadow register for ISP27XX
  qla2xxx: Add option for use reserve exch for ELS
  qla2xxx: Add ability to send PRLO
  qla2xxx: Allow target mode to accept PRLI in dual mode
  qla2xxx: Tweak resource count dump
  qla2xxx: Fix session cleanup for N2N
  qla2xxx: Add switch command to simplify fabric discovery
  qla2xxx: Add lock protection around host lookup
  qla2xxx: Reduce the use of terminate exchange
  qla2xxx: Reduce trace noise for Async Events
  qla2xxx: Fix login state machine freeze
  qla2xxx: Migrate switch registration commands away from mailbox
    interface
  qla2xxx: Remove session creation redundant code
  qla2xxx: Fix GPNFT/GNNFT error handling
  qla2xxx: Properly extract ADISC error codes
  qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling
  qla2xxx: Increase verbosity of debug messages logged
  qla2xxx: Delay loop id allocation at login
  qla2xxx: Add retry limit for fabric scan logic
  qla2xxx: Prevent multiple active discovery commands per session
  qla2xxx: Prevent relogin trigger from sending too many commands
  qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion()
  qla2xxx: Serialize session deletion by using work_lock
  qla2xxx: Serialize session free in  qlt_free_session_done

Sawan Chandak (1):
  qla2xxx: Remove calling cancel_work_sync()

 drivers/scsi/qla2xxx/qla_attr.c    |    2 +
 drivers/scsi/qla2xxx/qla_bsg.c     |    7 +-
 drivers/scsi/qla2xxx/qla_def.h     |  220 +++++-
 drivers/scsi/qla2xxx/qla_dfs.c     |  354 +++++++++-
 drivers/scsi/qla2xxx/qla_fw.h      |    2 +-
 drivers/scsi/qla2xxx/qla_gbl.h     |   37 +-
 drivers/scsi/qla2xxx/qla_gs.c      | 1339 +++++++++++++++++++++++++++++++-----
 drivers/scsi/qla2xxx/qla_init.c    | 1019 +++++++++++++++++----------
 drivers/scsi/qla2xxx/qla_inline.h  |  103 +++
 drivers/scsi/qla2xxx/qla_iocb.c    |   93 ++-
 drivers/scsi/qla2xxx/qla_isr.c     |   64 +-
 drivers/scsi/qla2xxx/qla_mbx.c     |  153 ++--
 drivers/scsi/qla2xxx/qla_mid.c     |  113 ++-
 drivers/scsi/qla2xxx/qla_mr.c      |    2 +-
 drivers/scsi/qla2xxx/qla_nvme.c    |    4 +-
 drivers/scsi/qla2xxx/qla_os.c      |  449 ++++++++----
 drivers/scsi/qla2xxx/qla_target.c  |  728 +++++++++++---------
 drivers/scsi/qla2xxx/qla_target.h  |    7 +-
 drivers/scsi/qla2xxx/qla_tmpl.c    |   40 +-
 drivers/scsi/qla2xxx/qla_version.h |    2 +-
 20 files changed, 3593 insertions(+), 1145 deletions(-)

-- 
2.12.0

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

* [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 16:25   ` Bart Van Assche
                     ` (2 more replies)
  2017-12-20  6:56 ` [PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure Himanshu Madhani
                   ` (41 subsequent siblings)
  42 siblings, 3 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Name pointer for sp describing each command is assigned with stack
frame's memory. The stack frame could eventually be re-use, where
name pointer access can get get garbage. This patch designates
static memory for name pointer to fix this problem.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c    |  7 +++---
 drivers/scsi/qla2xxx/qla_def.h    | 36 +++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_gbl.h    |  1 +
 drivers/scsi/qla2xxx/qla_gs.c     | 51 ++++++++++++++++++++++++++++++++++++---
 drivers/scsi/qla2xxx/qla_init.c   | 16 ++++++------
 drivers/scsi/qla2xxx/qla_iocb.c   |  4 +--
 drivers/scsi/qla2xxx/qla_mbx.c    |  5 ++--
 drivers/scsi/qla2xxx/qla_mr.c     |  2 +-
 drivers/scsi/qla2xxx/qla_nvme.c   |  4 +--
 drivers/scsi/qla2xxx/qla_target.c |  2 +-
 10 files changed, 105 insertions(+), 23 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index e3ac7078d2aa..3fc3ae9abb39 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -376,7 +376,8 @@ qla2x00_process_els(struct bsg_job *bsg_job)
 		 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
 	sp->name =
 		(bsg_request->msgcode == FC_BSG_RPT_ELS ?
-		 "bsg_els_rpt" : "bsg_els_hst");
+		 sp_to_str(SPCN_BSG_RPT) : sp_to_str(SPCN_BSG_HST));
+
 	sp->u.bsg_job = bsg_job;
 	sp->free = qla2x00_bsg_sp_free;
 	sp->done = qla2x00_bsg_job_done;
@@ -522,7 +523,7 @@ qla2x00_process_ct(struct bsg_job *bsg_job)
 	}
 
 	sp->type = SRB_CT_CMD;
-	sp->name = "bsg_ct";
+	sp->name = sp_to_str(SPCN_BSG_CT);
 	sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
 	sp->u.bsg_job = bsg_job;
 	sp->free = qla2x00_bsg_sp_free;
@@ -2028,7 +2029,7 @@ qlafx00_mgmt_cmd(struct bsg_job *bsg_job)
 	fcport->loop_id = piocb_rqst->dataword;
 
 	sp->type = SRB_FXIOCB_BCMD;
-	sp->name = "bsg_fx_mgmt";
+	sp->name = sp_to_str(SPCN_BSG_FX_MGMT);
 	sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
 	sp->u.bsg_job = bsg_job;
 	sp->free = qla2x00_bsg_sp_free;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 93ff92e2363f..4d65fd973a12 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -478,6 +478,42 @@ struct srb_iocb {
 	void (*timeout)(void *);
 };
 
+enum {
+	SPCN_UNKNOWN,
+	SPCN_GIDPN,
+	SPCN_GPSC,
+	SPCN_GPNID,
+	SPCN_GPNFT,
+	SPCN_GNNID,
+	SPCN_GFPNID,
+	SPCN_LOGIN,
+	SPCN_LOGOUT,
+	SPCN_ADISC,
+	SPCN_GNLIST,
+	SPCN_GPDB,
+	SPCN_TMF,
+	SPCN_ABORT,
+	SPCN_NACK,
+	SPCN_BSG_RPT,
+	SPCN_BSG_HST,
+	SPCN_BSG_CT,
+	SPCN_BSG_FX_MGMT,
+	SPCN_ELS_DCMD,
+	SPCN_FXDISC,
+	SPCN_GIDLIST,
+	SPCN_STATS,
+	SPCN_MB_GPDB,
+	SPCN_GFFID,
+	SPCN_PRLI,
+	SPCN_NVME_LS,
+	SPCN_NVME_CMD,
+};
+
+struct sp_name {
+	uint16_t cmd;
+	const char *str;
+};
+
 /* Values for srb_ctx type */
 #define SRB_LOGIN_CMD	1
 #define SRB_LOGOUT_CMD	2
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index fa115c7433e5..bf907386f177 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -647,6 +647,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
 int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
 void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
 int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport);
+const char *sp_to_str(uint16_t);
 /*
  * Global Function Prototypes in qla_attr.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 07fe17a986b0..7e88e8289157 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -15,6 +15,49 @@ static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
 
+struct sp_name sp_str[] = {
+	{ SPCN_UNKNOWN, "unknown" },
+	{ SPCN_GIDPN, "gidpn" },
+	{ SPCN_GPSC, "gpsc" },
+	{ SPCN_GPNID, "gpnid" },
+	{ SPCN_GPNFT, "gpnft" },
+	{ SPCN_GNNID, "gnnid" },
+	{ SPCN_GFPNID, "gfpnid" },
+	{ SPCN_GFFID, "gffid" },
+	{ SPCN_LOGIN, "login" },
+	{ SPCN_LOGOUT, "logout" },
+	{ SPCN_ADISC, "adisc" },
+	{ SPCN_GNLIST, "gnlist" },
+	{ SPCN_GPDB, "gpdb" },
+	{ SPCN_TMF, "tmf" },
+	{ SPCN_ABORT, "abort" },
+	{ SPCN_NACK, "nack" },
+	{ SPCN_BSG_RPT, "bsg_els_rpt" },
+	{ SPCN_BSG_HST, "bsg_els_hst" },
+	{ SPCN_BSG_CT, "bsg_ct" },
+	{ SPCN_BSG_FX_MGMT, "bsg_fx_mgmt" },
+	{ SPCN_ELS_DCMD, "ELS_DCMD" },
+	{ SPCN_FXDISC, "fxdisc" },
+	{ SPCN_PRLI, "prli" },
+	{ SPCN_NVME_LS, "nvme_ls" },
+	{ SPCN_NVME_CMD, "nvme_cmd" },
+};
+
+const char *sp_to_str(uint16_t cmd)
+{
+	int i;
+	struct sp_name *e;
+
+	for (i = 1; i < ARRAY_SIZE(sp_str); i++) {
+		e = sp_str + i;
+		if (cmd == e->cmd)
+			return e->str;
+	}
+
+	return sp_str[0].str;
+}
+
+
 /**
  * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
  * @ha: HA context
@@ -2931,7 +2974,7 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
 		goto done;
 
 	sp->type = SRB_CT_PTHRU_CMD;
-	sp->name = "gidpn";
+	sp->name = sp_to_str(SPCN_GIDPN);
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
 
@@ -3091,7 +3134,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
 		goto done;
 
 	sp->type = SRB_CT_PTHRU_CMD;
-	sp->name = "gpsc";
+	sp->name = sp_to_str(SPCN_GPSC);
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
 
@@ -3398,7 +3441,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
 		goto done;
 
 	sp->type = SRB_CT_PTHRU_CMD;
-	sp->name = "gpnid";
+	sp->name = sp_to_str(SPCN_GPNID);
 	sp->u.iocb_cmd.u.ctarg.id = *id;
 	sp->gen1 = 0;
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
@@ -3550,7 +3593,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 
 	fcport->flags |= FCF_ASYNC_SENT;
 	sp->type = SRB_CT_PTHRU_CMD;
-	sp->name = "gffid";
+	sp->name = sp_to_str(SPCN_GFFID);
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
 
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 58663df38627..7fa71170d6ff 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -186,7 +186,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 	fcport->logout_completed = 0;
 
 	sp->type = SRB_LOGIN_CMD;
-	sp->name = "login";
+	sp->name = sp_to_str(SPCN_LOGIN);
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
 	lio = &sp->u.iocb_cmd;
@@ -248,7 +248,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 		goto done;
 
 	sp->type = SRB_LOGOUT_CMD;
-	sp->name = "logout";
+	sp->name = sp_to_str(SPCN_LOGOUT);
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
 	lio = &sp->u.iocb_cmd;
@@ -300,7 +300,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 		goto done;
 
 	sp->type = SRB_ADISC_CMD;
-	sp->name = "adisc";
+	sp->name = sp_to_str(SPCN_ADISC);
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
 	lio = &sp->u.iocb_cmd;
@@ -583,7 +583,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	if (!sp)
 		goto done;
 	sp->type = SRB_MB_IOCB;
-	sp->name = "gnlist";
+	sp->name = sp_to_str(SPCN_GNLIST);
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
 
@@ -741,7 +741,7 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
 	fcport->logout_completed = 0;
 
 	sp->type = SRB_PRLI_CMD;
-	sp->name = "prli";
+	sp->name = sp_to_str(SPCN_PRLI);
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
 	lio = &sp->u.iocb_cmd;
@@ -807,7 +807,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 		goto done;
 
 	sp->type = SRB_MB_IOCB;
-	sp->name = "gpdb";
+	sp->name = sp_to_str(SPCN_GPDB);
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
@@ -1298,7 +1298,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 
 	tm_iocb = &sp->u.iocb_cmd;
 	sp->type = SRB_TM_CMD;
-	sp->name = "tmf";
+	sp->name = sp_to_str(SPCN_TMF);
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
 	tm_iocb->u.tmf.flags = flags;
 	tm_iocb->u.tmf.lun = lun;
@@ -1376,7 +1376,7 @@ qla24xx_async_abort_cmd(srb_t *cmd_sp)
 
 	abt_iocb = &sp->u.iocb_cmd;
 	sp->type = SRB_ABT_CMD;
-	sp->name = "abort";
+	sp->name = sp_to_str(SPCN_ABORT);
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
 	abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
 	sp->done = qla24xx_abort_sp_done;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 8ea59586f4f1..b5d1423f933d 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2454,7 +2454,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa);
 
 	sp->type = SRB_ELS_DCMD;
-	sp->name = "ELS_DCMD";
+	sp->name = sp_to_str(SPCN_ELS_DCMD);
 	sp->fcport = fcport;
 	qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
 	elsio->timeout = qla2x00_els_dcmd_iocb_timeout;
@@ -2652,7 +2652,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 	    "Enter: PLOGI portid=%06x\n", fcport->d_id.b24);
 
 	sp->type = SRB_ELS_DCMD;
-	sp->name = "ELS_DCMD";
+	sp->name = sp_to_str(SPCN_ELS_DCMD);
 	sp->fcport = fcport;
 	qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
 	elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index e2b5fa47bb57..f5cbdaeaea1f 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -14,6 +14,7 @@ static struct mb_cmd_name {
 	uint16_t cmd;
 	const char *str;
 } mb_str[] = {
+	{0, "unknown mb"},
 	{MBC_GET_PORT_DATABASE,		"GPDB"},
 	{MBC_GET_ID_LIST,		"GIDList"},
 	{MBC_GET_LINK_PRIV_STATS,	"Stats"},
@@ -24,12 +25,12 @@ static const char *mb_to_str(uint16_t cmd)
 	int i;
 	struct mb_cmd_name *e;
 
-	for (i = 0; i < ARRAY_SIZE(mb_str); i++) {
+	for (i = 1; i < ARRAY_SIZE(mb_str); i++) {
 		e = mb_str + i;
 		if (cmd == e->cmd)
 			return e->str;
 	}
-	return "unknown";
+	return mb_str[0].str;
 }
 
 static struct rom_cmd {
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index d5da3981cefe..9184f6016fe0 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1820,7 +1820,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
 		goto done;
 
 	sp->type = SRB_FXIOCB_DCMD;
-	sp->name = "fxdisc";
+	sp->name = sp_to_str(SPCN_FXDISC);
 	qla2x00_init_timer(sp, FXDISC_TIMEOUT);
 
 	fdisc = &sp->u.iocb_cmd;
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 6b33a1f24f56..d398d45f937f 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -239,7 +239,7 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
 		return rval;
 
 	sp->type = SRB_NVME_LS;
-	sp->name = "nvme_ls";
+	sp->name = sp_to_str(SPCN_NVME_LS);
 	sp->done = qla_nvme_sp_ls_done;
 	atomic_set(&sp->ref_count, 1);
 	nvme = &sp->u.iocb_cmd;
@@ -526,7 +526,7 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
 	init_waitqueue_head(&sp->nvme_ls_waitq);
 	priv->sp = sp;
 	sp->type = SRB_NVME_CMD;
-	sp->name = "nvme_cmd";
+	sp->name = sp_to_str(SPCN_NVME_CMD);
 	sp->done = qla_nvme_sp_done;
 	sp->qpair = qpair;
 	nvme = &sp->u.iocb_cmd;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 067bcc57a9ad..fcfdbe1420cd 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -661,7 +661,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
 		goto done;
 
 	sp->type = type;
-	sp->name = "nack";
+	sp->name = sp_to_str(SPCN_NACK);
 
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
 
-- 
2.12.0

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

* [PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 16:26   ` Bart Van Assche
  2017-12-20  6:56 ` [PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command Himanshu Madhani
                   ` (40 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

when preocessing iocb in a timeout case, driver was trying to log messages
without verifying if the fcport structure could have valid data. This
results in a NULL pointer access.

Fixes: 726b85487067("qla2xxx: Add framework for async fabric discovery")
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 7fa71170d6ff..9d65fbe85e30 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -102,11 +102,16 @@ qla2x00_async_iocb_timeout(void *data)
 	struct srb_iocb *lio = &sp->u.iocb_cmd;
 	struct event_arg ea;
 
-	ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
-	    "Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
-	    sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
+	if (fcport) {
+		ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
+		    "Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
+		    sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
 
-	fcport->flags &= ~FCF_ASYNC_SENT;
+		fcport->flags &= ~FCF_ASYNC_SENT;
+	} else {
+		pr_info("Async-%s timeout - hdl=%x.\n",
+		    sp->name, sp->handle);
+	}
 
 	switch (sp->type) {
 	case SRB_LOGIN_CMD:
-- 
2.12.0

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

* [PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 16:29   ` Bart Van Assche
  2017-12-20  6:56 ` [PATCH 04/43] qla2xxx: Use chip reset to bring down laser on unload Himanshu Madhani
                   ` (39 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Use IOCB patch to submit Control VP MBX command to reduce
bottle-neck for mbx interface.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h    |  9 ++++-
 drivers/scsi/qla2xxx/qla_gs.c     |  1 +
 drivers/scsi/qla2xxx/qla_init.c   |  1 +
 drivers/scsi/qla2xxx/qla_inline.h |  1 +
 drivers/scsi/qla2xxx/qla_iocb.c   | 23 +++++++++++
 drivers/scsi/qla2xxx/qla_isr.c    | 35 ++++++++++++++++
 drivers/scsi/qla2xxx/qla_mbx.c    | 77 -----------------------------------
 drivers/scsi/qla2xxx/qla_mid.c    | 85 +++++++++++++++++++++++++++++++++++++++
 8 files changed, 154 insertions(+), 78 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 4d65fd973a12..50a570595969 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -472,6 +472,10 @@ struct srb_iocb {
 			uint32_t timeout_sec;
 			struct	list_head   entry;
 		} nvme;
+		struct {
+			u16 cmd;
+			u16 vp_index;
+		} ctrlvp;
 	} u;
 
 	struct timer_list timer;
@@ -507,6 +511,7 @@ enum {
 	SPCN_PRLI,
 	SPCN_NVME_LS,
 	SPCN_NVME_CMD,
+	SPCN_CTRL_VP,
 };
 
 struct sp_name {
@@ -536,7 +541,7 @@ struct sp_name {
 #define SRB_NVME_CMD	19
 #define SRB_NVME_LS	20
 #define SRB_PRLI_CMD	21
-
+#define SRB_CTRL_VP	22
 enum {
 	TYPE_SRB,
 	TYPE_TGT_CMD,
@@ -562,6 +567,8 @@ typedef struct srb {
 	struct list_head elem;
 	u32 gen1;	/* scratch */
 	u32 gen2;	/* scratch */
+	int rc;
+	struct completion comp;
 	union {
 		struct srb_iocb iocb_cmd;
 		struct bsg_job *bsg_job;
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 7e88e8289157..6aa6dd74fe86 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -41,6 +41,7 @@ struct sp_name sp_str[] = {
 	{ SPCN_PRLI, "prli" },
 	{ SPCN_NVME_LS, "nvme_ls" },
 	{ SPCN_NVME_CMD, "nvme_cmd" },
+	{ SPCN_CTRL_VP, "ctrl_vp" },
 };
 
 const char *sp_to_str(uint16_t cmd)
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9d65fbe85e30..24d0f9d419d2 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -135,6 +135,7 @@ qla2x00_async_iocb_timeout(void *data)
 	case SRB_NACK_PLOGI:
 	case SRB_NACK_PRLI:
 	case SRB_NACK_LOGO:
+	case SRB_CTRL_VP:
 		sp->done(sp, QLA_FUNCTION_TIMEOUT);
 		break;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 17d2c20f1f75..4d32426393c7 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -273,6 +273,7 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
 	sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
 	add_timer(&sp->u.iocb_cmd.timer);
 	sp->free = qla2x00_sp_free;
+	init_completion(&sp->comp);
 	if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD))
 		init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
 	if (sp->type == SRB_ELS_DCMD)
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index b5d1423f933d..62b3d0a8a961 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -3368,6 +3368,26 @@ qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt)
 	return rval;
 }
 
+static void
+qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx *vce)
+{
+	int map, pos;
+
+	vce->entry_type = VP_CTRL_IOCB_TYPE;
+	vce->handle = sp->handle;
+	vce->entry_count = 1;
+	vce->command = cpu_to_le16(sp->u.iocb_cmd.u.ctrlvp.cmd);
+	vce->vp_count = cpu_to_le16(1);
+
+	/*
+	 * index map in firmware starts with 1; decrement index
+	 * this is ok as we never use index 0
+	 */
+	map = (sp->u.iocb_cmd.u.ctrlvp.vp_index - 1) / 8;
+	pos = (sp->u.iocb_cmd.u.ctrlvp.vp_index - 1) & 7;
+	vce->vp_idx_map[map] |= 1 << pos;
+}
+
 int
 qla2x00_start_sp(srb_t *sp)
 {
@@ -3446,6 +3466,9 @@ qla2x00_start_sp(srb_t *sp)
 	case SRB_NACK_LOGO:
 		qla2x00_send_notify_ack_iocb(sp, pkt);
 		break;
+	case SRB_CTRL_VP:
+		qla25xx_ctrlvp_iocb(sp, pkt);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a55bfaa790a3..a265c2d8c9cc 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1937,6 +1937,37 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
 	sp->done(sp, ret);
 }
 
+static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req,
+    struct vp_ctrl_entry_24xx *vce)
+{
+	const char func[] = "CTRLVP-IOCB";
+	srb_t *sp;
+	int rval = QLA_SUCCESS;
+
+	sp = qla2x00_get_sp_from_handle(vha, func, req, vce);
+	if (!sp)
+		return;
+
+	if (vce->entry_status != 0) {
+		ql_dbg(ql_dbg_vport, vha, 0x10c4,
+		    "%s: Failed to complete IOCB -- error status (%x)\n",
+		    sp->name, vce->entry_status);
+		rval = QLA_FUNCTION_FAILED;
+	} else if (vce->comp_status != cpu_to_le16(CS_COMPLETE)) {
+		ql_dbg(ql_dbg_vport, vha, 0x10c5,
+		    "%s: Failed to complete IOCB -- completion status (%x) vpidx %x\n",
+		    sp->name, le16_to_cpu(vce->comp_status),
+		    le16_to_cpu(vce->vp_idx_failed));
+		rval = QLA_FUNCTION_FAILED;
+	} else {
+		ql_dbg(ql_dbg_vport, vha, 0x10c6,
+		    "Done %s.\n", __func__);
+	}
+
+	sp->rc = rval;
+	sp->done(sp, rval);
+}
+
 /**
  * qla2x00_process_response_queue() - Process response queue entries.
  * @ha: SCSI driver HA context
@@ -3001,6 +3032,10 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 			qla24xx_mbx_iocb_entry(vha, rsp->req,
 			    (struct mbx_24xx_entry *)pkt);
 			break;
+		case VP_CTRL_IOCB_TYPE:
+			qla_ctrlvp_completed(vha, rsp->req,
+			    (struct vp_ctrl_entry_24xx *)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 f5cbdaeaea1f..956d121cc396 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3946,83 +3946,6 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
 }
 
 /*
- * qla24xx_control_vp
- *	Enable a virtual port for given host
- *
- * Input:
- *	ha = adapter block pointer.
- *	vhba = virtual adapter (unused)
- *	index = index number for enabled VP
- *
- * Returns:
- *	qla2xxx local function return status code.
- *
- * Context:
- *	Kernel context.
- */
-int
-qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
-{
-	int		rval;
-	int		map, pos;
-	struct vp_ctrl_entry_24xx   *vce;
-	dma_addr_t	vce_dma;
-	struct qla_hw_data *ha = vha->hw;
-	int	vp_index = vha->vp_idx;
-	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
-
-	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c1,
-	    "Entered %s enabling index %d.\n", __func__, vp_index);
-
-	if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
-		return QLA_PARAMETER_ERROR;
-
-	vce = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma);
-	if (!vce) {
-		ql_log(ql_log_warn, vha, 0x10c2,
-		    "Failed to allocate VP control IOCB.\n");
-		return QLA_MEMORY_ALLOC_FAILED;
-	}
-
-	vce->entry_type = VP_CTRL_IOCB_TYPE;
-	vce->entry_count = 1;
-	vce->command = cpu_to_le16(cmd);
-	vce->vp_count = cpu_to_le16(1);
-
-	/* index map in firmware starts with 1; decrement index
-	 * this is ok as we never use index 0
-	 */
-	map = (vp_index - 1) / 8;
-	pos = (vp_index - 1) & 7;
-	mutex_lock(&ha->vport_lock);
-	vce->vp_idx_map[map] |= 1 << pos;
-	mutex_unlock(&ha->vport_lock);
-
-	rval = qla2x00_issue_iocb(base_vha, vce, vce_dma, 0);
-	if (rval != QLA_SUCCESS) {
-		ql_dbg(ql_dbg_mbx, vha, 0x10c3,
-		    "Failed to issue VP control IOCB (%x).\n", rval);
-	} else if (vce->entry_status != 0) {
-		ql_dbg(ql_dbg_mbx, vha, 0x10c4,
-		    "Failed to complete IOCB -- error status (%x).\n",
-		    vce->entry_status);
-		rval = QLA_FUNCTION_FAILED;
-	} else if (vce->comp_status != cpu_to_le16(CS_COMPLETE)) {
-		ql_dbg(ql_dbg_mbx, vha, 0x10c5,
-		    "Failed to complete IOCB -- completion status (%x).\n",
-		    le16_to_cpu(vce->comp_status));
-		rval = QLA_FUNCTION_FAILED;
-	} else {
-		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c6,
-		    "Done %s.\n", __func__);
-	}
-
-	dma_pool_free(ha->s_dma_pool, vce, vce_dma);
-
-	return rval;
-}
-
-/*
  * qla2x00_send_change_request
  *	Receive or disable RSCN request from fabric controller
  *
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 522d585a1a08..fc61fef5e305 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -894,3 +894,88 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
 failed:
 	return 0;
 }
+
+static void qla_ctrlvp_sp_done(void *s, int res)
+{
+	struct srb *sp = s;
+
+	complete(&sp->comp);
+	/* don't free sp here. Let the caller do the free */
+}
+
+/*
+ * qla24xx_control_vp
+ *	Enable a virtual port for given host
+ *
+ * Input:
+ *	ha = adapter block pointer.
+ *	vhba = virtual adapter (unused)
+ *	index = index number for enabled VP
+ *
+ * Returns:
+ *	qla2xxx local function return status code.
+ *
+ * Context:
+ *	Kernel context.
+ */
+int
+qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
+{
+	int rval = QLA_MEMORY_ALLOC_FAILED;
+	struct qla_hw_data *ha = vha->hw;
+	int	vp_index = vha->vp_idx;
+	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+	srb_t *sp;
+
+	ql_dbg(ql_dbg_vport, vha, 0x10c1,
+	    "Entered %s cmd %x index %d.\n", __func__, cmd, vp_index);
+
+	if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
+		return QLA_PARAMETER_ERROR;
+
+	sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
+	if (!sp)
+		goto done;
+
+	sp->type = SRB_CTRL_VP;
+	sp->name = sp_to_str(SPCN_CTRL_VP);
+	sp->done = qla_ctrlvp_sp_done;
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->u.iocb_cmd.u.ctrlvp.cmd = cmd;
+	sp->u.iocb_cmd.u.ctrlvp.vp_index = vp_index;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS) {
+		ql_dbg(ql_dbg_async, vha, 0xffff,
+		    "%s: %s Failed submission. %x.\n",
+		    __func__, sp->name, rval);
+		goto done_free_sp;
+	}
+
+	ql_dbg(ql_dbg_vport, vha, 0x113f, "%s hndl %x submitted\n",
+	    sp->name, sp->handle);
+
+	wait_for_completion(&sp->comp);
+	rval = sp->rc;
+	switch (rval) {
+	case QLA_FUNCTION_TIMEOUT:
+		ql_dbg(ql_dbg_vport, vha, 0xffff, "%s: %s Timeout. %x.\n",
+		    __func__, sp->name, rval);
+		break;
+	case QLA_SUCCESS:
+		ql_dbg(ql_dbg_vport, vha, 0xffff, "%s: %s done.\n",
+		    __func__, sp->name);
+		goto done_free_sp;
+	default:
+		ql_dbg(ql_dbg_vport, vha, 0xffff, "%s: %s Failed. %x.\n",
+		    __func__, sp->name, rval);
+		goto done_free_sp;
+	}
+done:
+	return rval;
+
+done_free_sp:
+	sp->free(sp);
+	return rval;
+}
-- 
2.12.0

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

* [PATCH 04/43] qla2xxx: Use chip reset to bring down laser on unload.
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (2 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 05/43] qla2xxx: Add boundary checks for exchanges to be offloaded Himanshu Madhani
                   ` (38 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Current code uses Stop Firmware MB cmd to stop the chip before
driver unload.  This will leave the laser in its current state.
This give the illusion of this adapter is still alive.
For 8G & newer adapters, use chip reset to stop the chip and
bring down the laser.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_os.c | 52 ++++++++++++++-----------------------------
 1 file changed, 17 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 789030c9dd26..987bade1c606 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -294,7 +294,6 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
 
 static void qla2x00_clear_drv_active(struct qla_hw_data *);
 static void qla2x00_free_device(scsi_qla_host_t *);
-static void qla83xx_disable_laser(scsi_qla_host_t *vha);
 static int qla2xxx_map_queues(struct Scsi_Host *shost);
 static void qla2x00_destroy_deferred_work(struct qla_hw_data *);
 
@@ -3449,8 +3448,13 @@ qla2x00_shutdown(struct pci_dev *pdev)
 	if (ha->eft)
 		qla2x00_disable_eft_trace(vha);
 
-	/* Stop currently executing firmware. */
-	qla2x00_try_to_stop_firmware(vha);
+	if (IS_QLA25XX(ha) ||  IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+		if (ha->flags.fw_started)
+			qla2x00_abort_isp_cleanup(vha);
+	} else {
+		/* Stop currently executing firmware. */
+		qla2x00_try_to_stop_firmware(vha);
+	}
 
 	/* Turn adapter off line */
 	vha->flags.online = 0;
@@ -3629,10 +3633,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
 	qla84xx_put_chip(base_vha);
 
-	/* Laser should be disabled only for ISP2031 */
-	if (IS_QLA2031(ha))
-		qla83xx_disable_laser(base_vha);
-
 	/* Disable timer */
 	if (base_vha->timer_active)
 		qla2x00_stop_timer(base_vha);
@@ -3693,8 +3693,16 @@ qla2x00_free_device(scsi_qla_host_t *vha)
 	if (ha->eft)
 		qla2x00_disable_eft_trace(vha);
 
-	/* Stop currently executing firmware. */
-	qla2x00_try_to_stop_firmware(vha);
+	if (IS_QLA25XX(ha) ||  IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+		if (ha->flags.fw_started)
+			qla2x00_abort_isp_cleanup(vha);
+	} else {
+		if (ha->flags.fw_started) {
+			/* Stop currently executing firmware. */
+			qla2x00_try_to_stop_firmware(vha);
+			ha->flags.fw_started = 0;
+		}
+	}
 
 	vha->flags.online = 0;
 
@@ -6617,32 +6625,6 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
 	ha->flags.eeh_busy = 0;
 }
 
-static void
-qla83xx_disable_laser(scsi_qla_host_t *vha)
-{
-	uint32_t reg, data, fn;
-	struct qla_hw_data *ha = vha->hw;
-	struct device_reg_24xx __iomem *isp_reg = &ha->iobase->isp24;
-
-	/* pci func #/port # */
-	ql_dbg(ql_dbg_init, vha, 0x004b,
-	    "Disabling Laser for hba: %p\n", vha);
-
-	fn = (RD_REG_DWORD(&isp_reg->ctrl_status) &
-		(BIT_15|BIT_14|BIT_13|BIT_12));
-
-	fn = (fn >> 12);
-
-	if (fn & 1)
-		reg = PORT_1_2031;
-	else
-		reg = PORT_0_2031;
-
-	data = LASER_OFF_2031;
-
-	qla83xx_wr_reg(vha, reg, data);
-}
-
 static int qla2xxx_map_queues(struct Scsi_Host *shost)
 {
 	int rc;
-- 
2.12.0

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

* [PATCH 05/43] qla2xxx: Add boundary checks for exchanges to be offloaded
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (3 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 04/43] qla2xxx: Use chip reset to bring down laser on unload Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name Himanshu Madhani
                   ` (37 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Max boundary for exchange off load is 32k exchanges. If system
is unable to allocate large memory buffer to support this feature,
then driver will reduce the number exchanges down to a value
system can support.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  3 +++
 drivers/scsi/qla2xxx/qla_os.c  | 39 ++++++++++++++++++++++++++++++---------
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 50a570595969..ca3ef9360ab9 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -288,6 +288,8 @@ struct name_list_extended {
 #define ATIO_ENTRY_CNT_24XX		4096	/* Number of ATIO entries. */
 #define RESPONSE_ENTRY_CNT_FX00		256     /* Number of response entries.*/
 #define FW_DEF_EXCHANGES_CNT 2048
+#define FW_MAX_EXCHANGES_CNT (32 * 1024)
+#define REDUCE_EXCHANGES_CNT  (8 * 1024)
 
 struct req_que;
 struct qla_tgt_sess;
@@ -3542,6 +3544,7 @@ struct qla_hw_data {
 		uint32_t	using_lr_setting:1;
 	} flags;
 
+	uint16_t max_exchg;
 	uint16_t long_range_distance;	/* 32G & above */
 #define LR_DISTANCE_5K  1
 #define LR_DISTANCE_10K 0
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 987bade1c606..029b95b2bd8a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2789,6 +2789,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	ha->init_cb_size = sizeof(init_cb_t);
 	ha->link_data_rate = PORT_SPEED_UNKNOWN;
 	ha->optrom_size = OPTROM_SIZE_2300;
+	ha->max_exchg = FW_MAX_EXCHANGES_CNT;
 
 	/* Assign ISP specific operations. */
 	if (IS_QLA2100(ha)) {
@@ -4230,6 +4231,9 @@ qla2x00_number_of_exch(scsi_qla_host_t *vha, u32 *ret_cnt, u16 max_cnt)
 	u32 temp;
 	*ret_cnt = FW_DEF_EXCHANGES_CNT;
 
+	if (max_cnt > vha->hw->max_exchg)
+		max_cnt = vha->hw->max_exchg;
+
 	if (qla_ini_mode_enabled(vha)) {
 		if (ql2xiniexchg > max_cnt)
 			ql2xiniexchg = max_cnt;
@@ -4259,8 +4263,8 @@ int
 qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
 {
 	int rval;
-	u16 size, max_cnt;
-	u32 temp;
+	u16	size, max_cnt;
+	u32 actual_cnt, totsz;
 	struct qla_hw_data *ha = vha->hw;
 
 	if (!ha->flags.exchoffld_enabled)
@@ -4277,16 +4281,19 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
 		return rval;
 	}
 
-	qla2x00_number_of_exch(vha, &temp, max_cnt);
-	temp *= size;
+	qla2x00_number_of_exch(vha, &actual_cnt, max_cnt);
+	ql_log(ql_log_info, vha, 0xd014,
+	    "Actual exchange offload count: %d.\n", actual_cnt);
+
+	totsz = actual_cnt * size;
 
-	if (temp != ha->exchoffld_size) {
+	if (totsz != ha->exchoffld_size) {
 		qla2x00_free_exchoffld_buffer(ha);
-		ha->exchoffld_size = temp;
+		ha->exchoffld_size = totsz;
 
 		ql_log(ql_log_info, vha, 0xd016,
-		    "Exchange offload: max_count=%d, buffers=0x%x, total=%d.\n",
-		    max_cnt, size, temp);
+		    "Exchange offload: max_count=%d, actual count=%d entry sz=0x%x, total sz=0x%x\n",
+		    max_cnt, actual_cnt, size, totsz);
 
 		ql_log(ql_log_info, vha, 0xd017,
 		    "Exchange Buffers requested size = 0x%x\n",
@@ -4297,7 +4304,21 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
 			ha->exchoffld_size, &ha->exchoffld_buf_dma, GFP_KERNEL);
 		if (!ha->exchoffld_buf) {
 			ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
-			"Failed to allocate memory for exchoffld_buf_dma.\n");
+			"Failed to allocate memory for Exchange Offload.\n");
+
+			if (ha->max_exchg >
+			    (FW_DEF_EXCHANGES_CNT + REDUCE_EXCHANGES_CNT)) {
+				ha->max_exchg -= REDUCE_EXCHANGES_CNT;
+			} else if (ha->max_exchg >
+			    (FW_DEF_EXCHANGES_CNT + 512)) {
+				ha->max_exchg -= 512;
+			} else {
+				ha->flags.exchoffld_enabled = 0;
+				ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
+				    "Disabling Exchange offload due to lack of memory\n");
+			}
+			ha->exchoffld_size = 0;
+
 			return -ENOMEM;
 		}
 	}
-- 
2.12.0

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

* [PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (4 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 05/43] qla2xxx: Add boundary checks for exchanges to be offloaded Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 16:39   ` Bart Van Assche
  2017-12-20  6:56 ` [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW Himanshu Madhani
                   ` (36 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

IRQ name pointer for INTx/MSI was pointing at stale stack frame.
cat /proc/interrupts will trigger stale mem access. Fix it by
creating dedicated space for IRQ name.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  4 +++-
 drivers/scsi/qla2xxx/qla_isr.c | 10 +++++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ca3ef9360ab9..5e509763a419 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3140,12 +3140,13 @@ struct scsi_qla_host;
 
 #define QLA83XX_RSPQ_MSIX_ENTRY_NUMBER 1 /* refer to qla83xx_msix_entries */
 
+#define IRQNAME_SZ 32
 struct qla_msix_entry {
 	int have_irq;
 	int in_use;
 	uint32_t vector;
 	uint16_t entry;
-	char name[30];
+	char name[IRQNAME_SZ];
 	void *handle;
 	int cpuid;
 };
@@ -4025,6 +4026,7 @@ struct qla_hw_data {
 	uint16_t        zio_timer;
 
 	struct qla_msix_entry *msix_entries;
+	u8 irqname[IRQNAME_SZ];	/* msi/intx */
 
 	struct list_head        vp_list;        /* list of VP */
 	unsigned long   vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) /
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a265c2d8c9cc..33865e0bb29f 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3607,9 +3607,17 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
 	if (!ha->flags.msi_enabled && IS_QLA82XX(ha))
 		return QLA_FUNCTION_FAILED;
 
+	memset(ha->irqname, 0, IRQNAME_SZ);
+	if (ha->flags.msi_enabled)
+		scnprintf(ha->irqname, IRQNAME_SZ,
+		    "qla2xxx%lu_msi", vha->host_no);
+	else
+		scnprintf(ha->irqname, IRQNAME_SZ,
+		    "qla2xxx%lu_intx", vha->host_no);
 	ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
 	    ha->flags.msi_enabled ? 0 : IRQF_SHARED,
-	    QLA2XXX_DRIVER_NAME, rsp);
+	    ha->irqname, rsp);
+
 	if (ret) {
 		ql_log(ql_log_warn, vha, 0x003a,
 		    "Failed to reserve interrupt %d already in use.\n",
-- 
2.12.0

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

* [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (5 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 16:51   ` Bart Van Assche
  2017-12-20  6:56 ` [PATCH 08/43] qla2xxx: Chip reset uses wrong lock during IO flush Himanshu Madhani
                   ` (35 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

FW has a finite number of IOCB resource. Driver will
track it via the ql2xtrackfwres module parameter. User
will be able to reserve X number of IOCBs for either
the target path or initiator path. The left over IOCBs
are shared between the 2 modes. The shared pool will be
used 1st before tapping into the reserve pool.

usage:
    modprobe qla2xxx ql2xtrackfwres=1 qlini_mode=dual
    echo 256 > /sys/class/scsi_host/hostX/device/reserve_ini_iocbs
    echo 256 > /sys/class/scsi_host/hostX/device/reserve_tgt_iocbs

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h    |  50 +++++-
 drivers/scsi/qla2xxx/qla_dfs.c    | 315 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_gbl.h    |   1 +
 drivers/scsi/qla2xxx/qla_init.c   |  36 +++++
 drivers/scsi/qla2xxx/qla_inline.h | 102 ++++++++++++
 drivers/scsi/qla2xxx/qla_iocb.c   |  45 ++++++
 drivers/scsi/qla2xxx/qla_isr.c    |  10 +-
 drivers/scsi/qla2xxx/qla_os.c     |  10 ++
 drivers/scsi/qla2xxx/qla_target.c |  24 +++
 drivers/scsi/qla2xxx/qla_target.h |   3 +-
 10 files changed, 592 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 5e509763a419..8fbe1736a1a4 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -549,6 +549,12 @@ enum {
 	TYPE_TGT_CMD,
 };
 
+struct iocb_resource {
+	u8 res_type;
+	u8 pad;
+	u16 iocb_cnt;
+};
+
 typedef struct srb {
 	/*
 	 * Do not move cmd_type field, it needs to
@@ -556,6 +562,7 @@ typedef struct srb {
 	 */
 	uint8_t cmd_type;
 	uint8_t pad[3];
+	struct iocb_resource iores;
 	atomic_t ref_count;
 	wait_queue_head_t nvme_ls_waitq;
 	struct fc_port *fcport;
@@ -3396,6 +3403,7 @@ struct qla_qpair {
 	uint32_t fw_started:1;
 	uint32_t enable_class_2:1;
 	uint32_t enable_explicit_conf:1;
+	uint32_t fw_res_tracking:1;
 	uint32_t use_shadow_reg:1;
 
 	uint16_t id;			/* qp number used with FW */
@@ -3433,6 +3441,24 @@ struct scsi_qlt_host {
 	struct qla_tgt *qla_tgt;
 };
 
+struct qla_fw_resources {
+	spinlock_t rescnt_lock;
+#define DEF_RES_INI_IOCBS 256
+#define DEF_RES_TGT_IOCBS 256
+#define DEF_RES_BUSY_IOCBS 32
+	u32 tgt_iocbs_reserve;
+	u32 ini_iocbs_reserve;
+	u32 busy_iocbs_reserve;
+	u32 tgt_iocbs_max;
+	u32 ini_iocbs_max;
+	u32 share_iocbs_max;
+
+	/* these fields start high */
+	atomic_t share_iocbs_used;
+	atomic_t tgt_iocbs_used;
+	atomic_t ini_iocbs_used;
+};
+
 struct qlt_hw_data {
 	/* Protected by hw lock */
 	uint32_t node_name_set:1;
@@ -3461,6 +3487,9 @@ struct qlt_hw_data {
 	struct dentry *dfs_tgt_sess;
 	struct dentry *dfs_tgt_port_database;
 	struct dentry *dfs_naqp;
+	struct dentry *dfs_ini_iocbs;
+	struct dentry *dfs_tgt_iocbs;
+	struct dentry *dfs_busy_iocbs;
 
 	struct list_head q_full_list;
 	uint32_t num_pend_cmds;
@@ -3540,7 +3569,6 @@ struct qla_hw_data {
 		uint32_t	n2n_ae:1;
 		uint32_t	fw_started:1;
 		uint32_t	fw_init_done:1;
-
 		uint32_t	detected_lr_sfp:1;
 		uint32_t	using_lr_setting:1;
 	} flags;
@@ -4103,6 +4131,7 @@ struct qla_hw_data {
 
 	struct qlt_hw_data tgt;
 	int	allow_cna_fw_dump;
+	struct qla_fw_resources fwres;
 	uint32_t fw_ability_mask;
 	uint16_t min_link_speed;
 	uint16_t max_speed_sup;
@@ -4406,7 +4435,6 @@ struct qla2_sgx {
 #define QLA_QPAIR_MARK_NOT_BUSY(__qpair)		\
 	atomic_dec(&__qpair->ref_count);		\
 
-
 #define QLA_ENA_CONF(_ha) {\
     int i;\
     _ha->base_qpair->enable_explicit_conf = 1;	\
@@ -4425,6 +4453,24 @@ struct qla2_sgx {
     }						\
 }
 
+#define QLA_ENA_FW_RES_TRACKING(_ha) { \
+	int i; \
+	_ha->base_qpair->fw_res_tracking = 1; \
+	for (i = 0; i < _ha->max_qpairs; i++) { \
+		if (_ha->queue_pair_map[i]) \
+		_ha->queue_pair_map[i]->fw_res_tracking = 1; \
+	} \
+}
+
+#define QLA_DIS_FW_RES_TRACKING(_ha) { \
+	int i; \
+	_ha->base_qpair->fw_res_tracking = 0; \
+	for (i = 0; i < _ha->max_qpairs; i++) { \
+		if (_ha->queue_pair_map[i]) \
+		_ha->queue_pair_map[i]->fw_res_tracking = 0; \
+	} \
+}
+
 /*
  * qla2x00 local function return status codes
  */
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index d231e7156134..87a18a00d509 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -418,6 +418,278 @@ static const struct file_operations dfs_naqp_ops = {
 	.write		= qla_dfs_naqp_write,
 };
 
+static int
+qla_dfs_ini_iocbs_show(struct seq_file *s, void *unused)
+{
+	struct scsi_qla_host *vha = s->private;
+	struct qla_hw_data *ha = vha->hw;
+
+	if (!qla_dual_mode_enabled(vha)) {
+		seq_puts(s,
+		    "This field requires Dual Mode to be enabled\n");
+		return 0;
+	}
+
+	seq_printf(s, "%d\n", ha->fwres.ini_iocbs_reserve);
+
+	return 0;
+}
+
+static int
+qla_dfs_ini_iocbs_open(struct inode *inode, struct file *file)
+{
+	struct scsi_qla_host *vha = inode->i_private;
+
+	return single_open(file, qla_dfs_ini_iocbs_show, vha);
+}
+
+static ssize_t qla_dfs_ini_iocbs_write(struct file *file,
+    const char __user *buffer, size_t count, loff_t *pos)
+{
+	struct seq_file *s = file->private_data;
+	struct scsi_qla_host *vha = s->private;
+	struct qla_hw_data *ha = vha->hw;
+	char *buf;
+	int rc = 0;
+	u32 v = 0;
+
+	buf = memdup_user_nul(buffer, count);
+	if (IS_ERR(buf)) {
+		pr_err("host%ld: fail to copy user buffer",
+		    vha->host_no);
+		return PTR_ERR(buf);
+	}
+
+	rc = kstrtouint(buf, 0, &v);
+	if (rc < 0) {
+		ql_log(ql_log_info, vha, 0x707b,
+		    "Unable to set initiator reserve iocbs\n");
+		goto out_free;
+	}
+
+	if (qla_dual_mode_enabled(vha)) {
+		if ((v < ha->orig_fw_iocb_count) &&
+			(ha->fwres.ini_iocbs_reserve != v)) {
+			ha->fwres.ini_iocbs_reserve = v;
+			ql_log(ql_log_info, vha, 0x7024,
+			    "Resetting. User change initiator reserve iocbs (%d/%d)\n",
+			    v, ha->orig_fw_iocb_count);
+
+			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+			qla2xxx_wake_dpc(vha);
+			qla2x00_wait_for_chip_reset(vha);
+		} else {
+			ql_log(ql_log_warn, vha, 0x702e,
+			    "Unable to set initiator reserve iocbs (%d/%d)\n",
+			    v, ha->orig_fw_iocb_count);
+		}
+	} else {
+		if (v < (ha->orig_fw_iocb_count - ha->fwres.tgt_iocbs_reserve -
+			ha->fwres.busy_iocbs_reserve))
+			ha->fwres.ini_iocbs_reserve = v;
+		else
+			ql_log(ql_log_warn, vha, 0x7039,
+			    "Unable to set initiator reserve iocbs (%d/%d/%d/%d)\n",
+			    v, ha->orig_fw_iocb_count,
+			    ha->fwres.tgt_iocbs_reserve,
+			    ha->fwres.busy_iocbs_reserve);
+	}
+
+	rc = count;
+out_free:
+	kfree(buf);
+	return rc;
+}
+
+static const struct file_operations dfs_ini_iocbs_ops = {
+	.open		= qla_dfs_ini_iocbs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= qla_dfs_ini_iocbs_write,
+};
+
+
+static int
+qla_dfs_tgt_iocbs_show(struct seq_file *s, void *unused)
+{
+	struct scsi_qla_host *vha = s->private;
+	struct qla_hw_data *ha = vha->hw;
+
+	if (!qla_dual_mode_enabled(vha)) {
+		seq_puts(s,
+		    "This field requires Dual Mode to be enabled\n");
+		return 0;
+	}
+
+	seq_printf(s, "%d\n", ha->fwres.tgt_iocbs_reserve);
+
+	return 0;
+}
+
+static int
+qla_dfs_tgt_iocbs_open(struct inode *inode, struct file *file)
+{
+	struct scsi_qla_host *vha = inode->i_private;
+
+	return single_open(file, qla_dfs_tgt_iocbs_show, vha);
+}
+
+static ssize_t
+qla_dfs_tgt_iocbs_write(struct file *file, const char __user *buffer,
+    size_t count, loff_t *pos)
+{
+	struct seq_file *s = file->private_data;
+	struct scsi_qla_host *vha = s->private;
+	struct qla_hw_data *ha = vha->hw;
+	char *buf;
+	int rc = 0;
+	u32 v = 0;
+
+	buf = memdup_user_nul(buffer, count);
+	if (IS_ERR(buf)) {
+		pr_err("host%ld: fail to copy user buffer.",
+		    vha->host_no);
+		return PTR_ERR(buf);
+	}
+	rc = kstrtouint(buf, 0, &v);
+	if (rc < 0) {
+		ql_log(ql_log_info, vha, 0x70a5,
+		    "Unable to set initiator reserve iocbs.\n");
+		goto out_free;
+	}
+
+	if (qla_dual_mode_enabled(vha)) {
+		if ((v < ha->orig_fw_iocb_count) &&
+			(ha->fwres.ini_iocbs_reserve != v)) {
+			ha->fwres.ini_iocbs_reserve = v;
+			ql_log(ql_log_info, vha, 0x703b,
+			    "Resetting. User changed target reserve iocbs (%d/%d).\n",
+			    v, ha->orig_fw_iocb_count);
+			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+			qla2xxx_wake_dpc(vha);
+			qla2x00_wait_for_chip_reset(vha);
+		} else
+			ql_log(ql_log_warn, vha, 0x7045,
+			    "Unable to set target reserve iocbs (%d/%d).\n",
+			    v, ha->orig_fw_iocb_count);
+	} else {
+		if (v < (ha->orig_fw_iocb_count - ha->fwres.ini_iocbs_reserve -
+			ha->fwres.busy_iocbs_reserve))
+			ha->fwres.tgt_iocbs_reserve = v;
+		else
+			ql_log(ql_log_warn, vha, 0x7047,
+			    "Unable to set target reserve iocbs (%d/%d/%d/%d).\n",
+			    v, ha->orig_fw_iocb_count,
+			    ha->fwres.ini_iocbs_reserve,
+			    ha->fwres.busy_iocbs_reserve);
+	}
+
+	rc = count;
+out_free:
+	kfree(buf);
+	return rc;
+}
+
+static const struct file_operations dfs_tgt_iocbs_ops = {
+	.open		= qla_dfs_tgt_iocbs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= qla_dfs_tgt_iocbs_write,
+};
+
+static int
+qla_dfs_busy_iocbs_show(struct seq_file *s, void *unused)
+{
+	struct scsi_qla_host *vha = s->private;
+	struct qla_hw_data *ha = vha->hw;
+
+	if (!qla_dual_mode_enabled(vha)) {
+		seq_puts(s,
+		    "This field requires Dual Mode to be enabled\n");
+		return 0;
+	}
+
+	seq_printf(s, "%d\n", ha->fwres.busy_iocbs_reserve);
+
+	return 0;
+}
+
+static int
+qla_dfs_busy_iocbs_open(struct inode *inode, struct file *file)
+{
+	struct scsi_qla_host *vha = inode->i_private;
+
+	return single_open(file, qla_dfs_busy_iocbs_show, vha);
+}
+
+static ssize_t
+qla_dfs_busy_iocbs_write(struct file *file, const char __user *buffer,
+    size_t count, loff_t *pos)
+{
+	struct seq_file *s = file->private_data;
+	struct scsi_qla_host *vha = s->private;
+	struct qla_hw_data *ha = vha->hw;
+	char *buf;
+	int rc = 0;
+	u32 v = 0;
+
+	buf = memdup_user_nul(buffer, count);
+	if (IS_ERR(buf)) {
+		pr_err("host%ld: fail to copy user buffer.",
+		    vha->host_no);
+		return PTR_ERR(buf);
+	}
+
+	rc = kstrtouint(buf, 0, &v);
+	if (rc < 0) {
+		ql_log(ql_log_info, vha, 0x70a6,
+		    "Unable to set initiator reserve iocbs.\n");
+		goto out_free;
+	}
+
+	if (qla_dual_mode_enabled(vha)) {
+		if ((v < ha->orig_fw_iocb_count) &&
+			(ha->fwres.busy_iocbs_reserve != v)) {
+			ha->fwres.busy_iocbs_reserve = v;
+			ql_log(ql_log_info, vha, 0x7073,
+			    "Resetting. User change Busy reserve iocbs (%d/%d).\n",
+			    v, ha->orig_fw_iocb_count);
+			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+			qla2xxx_wake_dpc(vha);
+			qla2x00_wait_for_chip_reset(vha);
+		} else {
+			ql_log(ql_log_warn, vha, 0x7074,
+			    "Unable to set busy reserve iocbs (%d/%d).\n",
+			    v, ha->orig_fw_iocb_count);
+		}
+	} else {
+		if (v < (ha->orig_fw_iocb_count - ha->fwres.ini_iocbs_reserve -
+			ha->fwres.tgt_iocbs_reserve))
+			ha->fwres.busy_iocbs_reserve = v;
+		else
+			ql_log(ql_log_warn, vha, 0x7075,
+			    "Unable to set busy reserve iocbs (%d/%d/%d/%d).\n",
+			    v, ha->orig_fw_iocb_count,
+			    ha->fwres.ini_iocbs_reserve,
+			    ha->fwres.tgt_iocbs_reserve);
+	}
+
+	rc = count;
+out_free:
+	kfree(buf);
+	return rc;
+}
+
+static const struct file_operations dfs_busy_iocbs_ops = {
+	.open		= qla_dfs_busy_iocbs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= qla_dfs_busy_iocbs_write,
+};
+
 
 int
 qla2x00_dfs_setup(scsi_qla_host_t *vha)
@@ -504,6 +776,33 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
 			    "Unable to create debugFS naqp node.\n");
 			goto out;
 		}
+
+		if (ql2xtrackfwres) {
+			ha->tgt.dfs_ini_iocbs =
+				debugfs_create_file("reserve_ini_iocbs",
+				0400, ha->dfs_dir, vha, &dfs_ini_iocbs_ops);
+			if (!ha->tgt.dfs_ini_iocbs) {
+				ql_log(ql_log_warn, vha, 0xd011,
+				    "Unable to create debugFS reserve_ini_iocbs node.\n");
+				goto out;
+			}
+			ha->tgt.dfs_tgt_iocbs =
+				debugfs_create_file("reserve_tgt_iocbs",
+				0400, ha->dfs_dir, vha, &dfs_tgt_iocbs_ops);
+			if (!ha->tgt.dfs_tgt_iocbs) {
+				ql_log(ql_log_warn, vha, 0xd011,
+				    "Unable to create debugFS reserve_tgt_iocbs node.\n");
+				goto out;
+			}
+			ha->tgt.dfs_busy_iocbs =
+				debugfs_create_file("reserve_busy_iocbs",
+				0400, ha->dfs_dir, vha, &dfs_busy_iocbs_ops);
+			if (!ha->tgt.dfs_busy_iocbs) {
+				ql_log(ql_log_warn, vha, 0xd011,
+				    "Unable to create debugFS reserve_busy_iocbs node.\n");
+				goto out;
+			}
+		}
 	}
 out:
 	return 0;
@@ -514,6 +813,22 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha)
 {
 	struct qla_hw_data *ha = vha->hw;
 
+
+	if (ha->tgt.dfs_ini_iocbs) {
+		debugfs_remove(ha->tgt.dfs_ini_iocbs);
+		ha->tgt.dfs_ini_iocbs = NULL;
+	}
+
+	if (ha->tgt.dfs_tgt_iocbs) {
+		debugfs_remove(ha->tgt.dfs_tgt_iocbs);
+		ha->tgt.dfs_tgt_iocbs = NULL;
+	}
+
+	if (ha->tgt.dfs_busy_iocbs) {
+		debugfs_remove(ha->tgt.dfs_busy_iocbs);
+		ha->tgt.dfs_busy_iocbs = NULL;
+	}
+
 	if (ha->tgt.dfs_naqp) {
 		debugfs_remove(ha->tgt.dfs_naqp);
 		ha->tgt.dfs_naqp = NULL;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index bf907386f177..66dcbdb91244 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -148,6 +148,7 @@ extern int ql2xuctrlirq;
 extern int ql2xnvmeenable;
 extern int ql2xautodetectsfp;
 extern int ql2xenablemsix;
+extern int ql2xtrackfwres;
 
 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_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 24d0f9d419d2..429305caef47 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3108,6 +3108,42 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
 						    MIN_MULTI_ID_FABRIC - 1;
 				}
 				qla2x00_get_resource_cnts(vha);
+				if (ql2xtrackfwres) {
+					if (qla_dual_mode_enabled(vha)) {
+						ha->fwres.tgt_iocbs_max =
+						  ha->orig_fw_iocb_count -
+						  ha->fwres.ini_iocbs_reserve -
+						  ha->fwres.busy_iocbs_reserve;
+						ha->fwres.ini_iocbs_max =
+						  ha->orig_fw_iocb_count -
+						  ha->fwres.tgt_iocbs_reserve -
+						  ha->fwres.busy_iocbs_reserve;
+						ha->fwres.share_iocbs_max =
+						  ha->orig_fw_iocb_count -
+						  ha->fwres.ini_iocbs_reserve -
+						  ha->fwres.tgt_iocbs_reserve -
+						  ha->fwres.busy_iocbs_reserve;
+
+					} else if (qla_tgt_mode_enabled(vha)) {
+						ha->fwres.tgt_iocbs_max =
+						  ha->orig_fw_iocb_count -
+						  ha->fwres.busy_iocbs_reserve;
+						ha->fwres.ini_iocbs_max = 0;
+						ha->fwres.share_iocbs_max =
+						  ha->orig_fw_iocb_count -
+						  ha->fwres.ini_iocbs_reserve -
+						  ha->fwres.tgt_iocbs_reserve -
+						  ha->fwres.busy_iocbs_reserve;
+					} else
+						QLA_DIS_FW_RES_TRACKING(ha);
+
+					atomic_set(&ha->fwres.ini_iocbs_used,
+						ha->fwres.ini_iocbs_max);
+					atomic_set(&ha->fwres.tgt_iocbs_used,
+						ha->fwres.tgt_iocbs_max);
+					atomic_set(&ha->fwres.share_iocbs_used,
+						ha->fwres.share_iocbs_max);
+				}
 
 				/*
 				 * Allocate the array of outstanding commands
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 4d32426393c7..d8dc6dea1525 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -221,6 +221,7 @@ qla2xxx_get_qpair_sp(struct qla_qpair *qpair, fc_port_t *fcport, gfp_t flag)
 	sp->fcport = fcport;
 	sp->iocbs = 1;
 	sp->vha = qpair->vha;
+	sp->qpair = qpair;
 done:
 	if (!sp)
 		QLA_QPAIR_MARK_NOT_BUSY(qpair);
@@ -253,6 +254,7 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
 	sp->cmd_type = TYPE_SRB;
 	sp->iocbs = 1;
 	sp->vha = vha;
+	sp->qpair = vha->hw->base_qpair;
 done:
 	if (!sp)
 		QLA_VHA_MARK_NOT_BUSY(vha);
@@ -366,3 +368,103 @@ qla_83xx_start_iocbs(struct qla_qpair *qpair)
 
 	WRT_REG_DWORD(req->req_q_in, req->ring_index);
 }
+
+enum {
+	RESOURCE_NONE,
+	RESOURCE_INI,
+	RESOURCE_TGT,
+	RESOURCE_SHR,
+};
+
+static inline int
+qla_get_iocbs(struct qla_hw_data *ha, struct iocb_resource *iores)
+{
+	unsigned long flags;
+
+	switch (iores->res_type) {
+	case RESOURCE_TGT:
+		/* spin lock is required here because atomic lib is unable
+		 * to do "check 1st and sub" under 1 atomic operaton.
+		 */
+		spin_lock_irqsave(&ha->fwres.rescnt_lock, flags);
+		if (atomic_read(&ha->fwres.share_iocbs_used) <
+		    iores->iocb_cnt) {
+			/* share pool is emptied */
+			if (atomic_read(&ha->fwres.tgt_iocbs_used) <
+			    iores->iocb_cnt) {
+				iores->res_type = RESOURCE_NONE;
+				spin_unlock_irqrestore(&ha->fwres.rescnt_lock,
+				    flags);
+				return -EAGAIN;
+			}
+
+			atomic_sub(iores->iocb_cnt, &ha->fwres.tgt_iocbs_used);
+			iores->res_type = RESOURCE_TGT;
+			spin_unlock_irqrestore(&ha->fwres.rescnt_lock, flags);
+			return 0;
+		}
+
+		atomic_sub(iores->iocb_cnt, &ha->fwres.share_iocbs_used);
+		iores->res_type = RESOURCE_SHR;
+		spin_unlock_irqrestore(&ha->fwres.rescnt_lock, flags);
+
+		return 0;
+
+	case RESOURCE_INI:
+		spin_lock_irqsave(&ha->fwres.rescnt_lock, flags);
+		if (atomic_read(&ha->fwres.share_iocbs_used) <
+		    iores->iocb_cnt) {
+			if (atomic_read(&ha->fwres.ini_iocbs_used) <
+			    iores->iocb_cnt) {
+				/* fail to get resource */
+				iores->res_type = RESOURCE_NONE;
+				spin_unlock_irqrestore(&ha->fwres.rescnt_lock,
+				    flags);
+				return -EAGAIN;
+			} else {
+				atomic_sub(iores->iocb_cnt,
+				    &ha->fwres.ini_iocbs_used);
+				iores->res_type = RESOURCE_INI;
+				spin_unlock_irqrestore(&ha->fwres.rescnt_lock,
+				    flags);
+				return 0;
+			}
+		}
+		atomic_sub(iores->iocb_cnt, &ha->fwres.share_iocbs_used);
+		iores->res_type = RESOURCE_SHR;
+		spin_unlock_irqrestore(&ha->fwres.rescnt_lock, flags);
+		return 0;
+
+	default:
+		break;
+	}
+
+	return -EIO;
+}
+
+static inline void
+qla_put_iocbs(struct qla_qpair *qpair, struct iocb_resource *iores)
+{
+	struct scsi_qla_host *vha;
+
+	if (!qpair || !qpair->fw_res_tracking)
+		return;
+
+	vha = qpair->vha;
+
+	switch (iores->res_type) {
+	case RESOURCE_TGT:
+		atomic_add(iores->iocb_cnt, &vha->hw->fwres.tgt_iocbs_used);
+		break;
+	case RESOURCE_INI:
+		atomic_add(iores->iocb_cnt, &vha->hw->fwres.ini_iocbs_used);
+		break;
+	case RESOURCE_SHR:
+		atomic_add(iores->iocb_cnt, &vha->hw->fwres.share_iocbs_used);
+		break;
+	default:
+		break;
+	}
+
+	iores->res_type = RESOURCE_NONE;
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 62b3d0a8a961..417c40f21244 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1460,6 +1460,14 @@ qla24xx_start_scsi(srb_t *sp)
 
 	tot_dsds = nseg;
 	req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+
+	if (ha->base_qpair->fw_res_tracking) {
+		sp->iores.iocb_cnt = req_cnt;
+		sp->iores.res_type = RESOURCE_INI;
+		if (qla_get_iocbs(ha, &sp->iores))
+			goto queuing_error;
+	}
+
 	if (req->cnt < (req_cnt + 2)) {
 		cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
 		    RD_REG_DWORD_RELAXED(req->req_q_out);
@@ -1538,6 +1546,7 @@ qla24xx_start_scsi(srb_t *sp)
 	if (tot_dsds)
 		scsi_dma_unmap(cmd);
 
+	qla_put_iocbs(ha->base_qpair, &sp->iores);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	return QLA_FUNCTION_FAILED;
@@ -1661,6 +1670,13 @@ qla24xx_dif_start_scsi(srb_t *sp)
 	/* Total Data and protection sg segment(s) */
 	tot_prot_dsds = nseg;
 	tot_dsds += nseg;
+	if (ha->base_qpair->fw_res_tracking) {
+		sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+		sp->iores.res_type = RESOURCE_INI;
+		if (qla_get_iocbs(ha, &sp->iores))
+			goto queuing_error;
+	}
+
 	if (req->cnt < (req_cnt + 2)) {
 		cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
 		    RD_REG_DWORD_RELAXED(req->req_q_out);
@@ -1739,6 +1755,7 @@ qla24xx_dif_start_scsi(srb_t *sp)
 		req->outstanding_cmds[handle] = NULL;
 		req->cnt += req_cnt;
 	}
+	qla_put_iocbs(ha->base_qpair, &sp->iores);
 	/* Cleanup will be performed by the caller (queuecommand) */
 
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1813,6 +1830,13 @@ qla2xxx_start_scsi_mq(srb_t *sp)
 
 	tot_dsds = nseg;
 	req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+	if (qpair->fw_res_tracking) {
+		sp->iores.iocb_cnt = req_cnt;
+		sp->iores.res_type = RESOURCE_INI;
+		if (qla_get_iocbs(ha, &sp->iores))
+			goto queuing_error;
+	}
+
 	if (req->cnt < (req_cnt + 2)) {
 		cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
 		    RD_REG_DWORD_RELAXED(req->req_q_out);
@@ -1890,6 +1914,7 @@ qla2xxx_start_scsi_mq(srb_t *sp)
 	if (tot_dsds)
 		scsi_dma_unmap(cmd);
 
+	qla_put_iocbs(qpair, &sp->iores);
 	spin_unlock_irqrestore(&qpair->qp_lock, flags);
 
 	return QLA_FUNCTION_FAILED;
@@ -2028,6 +2053,14 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
 	/* Total Data and protection sg segment(s) */
 	tot_prot_dsds = nseg;
 	tot_dsds += nseg;
+
+	if (qpair->fw_res_tracking) {
+		sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+		sp->iores.res_type = RESOURCE_INI;
+		if (qla_get_iocbs(ha, &sp->iores))
+			goto queuing_error;
+	}
+
 	if (req->cnt < (req_cnt + 2)) {
 		cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
 		    RD_REG_DWORD_RELAXED(req->req_q_out);
@@ -2103,6 +2136,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
 		req->outstanding_cmds[handle] = NULL;
 		req->cnt += req_cnt;
 	}
+	qla_put_iocbs(qpair, &sp->iores);
 	/* Cleanup will be performed by the caller (queuecommand) */
 
 	spin_unlock_irqrestore(&qpair->qp_lock, flags);
@@ -3625,6 +3659,14 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
 
 	/* Calculate number of IOCB required */
 	req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+	if (ha->base_qpair->fw_res_tracking) {
+		sp->iores.iocb_cnt = req_cnt;
+		sp->iores.res_type = RESOURCE_INI;
+		if (qla_get_iocbs(ha, &sp->iores)) {
+			rval = EXT_STATUS_BUSY;
+			goto queuing_error;
+		}
+	}
 
 	/* Check for room on request queue. */
 	if (req->cnt < req_cnt + 2) {
@@ -3667,6 +3709,9 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
 	wmb();
 	qla2x00_start_iocbs(vha, req);
 queuing_error:
+	if (rval)
+		qla_put_iocbs(ha->base_qpair, &sp->iores);
+
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 	return rval;
 }
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 33865e0bb29f..7ae8d4d22952 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1283,6 +1283,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
 		/* Free outstanding command slot. */
 		req->outstanding_cmds[index] = NULL;
 
+		qla_put_iocbs(sp->qpair, &sp->iores);
+
 		/* Save ISP completion status */
 		sp->done(sp, DID_OK << 16);
 	} else {
@@ -2368,6 +2370,9 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
 	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
 	/* Always return DID_OK, bsg will send the vendor specific response
 	 * in this case only */
+
+	qla_put_iocbs(sp->qpair, &sp->iores);
+
 	sp->done(sp, DID_OK << 6);
 
 }
@@ -2745,8 +2750,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		    cp->cmnd, scsi_bufflen(cp), rsp_info_len,
 		    resid_len, fw_resid_len, sp, cp);
 
-	if (rsp->status_srb == NULL)
+	if (rsp->status_srb == NULL) {
+		qla_put_iocbs(sp->qpair, &sp->iores);
 		sp->done(sp, res);
+	}
 }
 
 /**
@@ -2849,6 +2856,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
 	case MBX_IOCB_TYPE:
 		sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 		if (sp) {
+			qla_put_iocbs(sp->qpair, &sp->iores);
 			sp->done(sp, res);
 			return 0;
 		}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 029b95b2bd8a..7f361e93c593 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -277,6 +277,11 @@ MODULE_PARM_DESC(ql2xenablemsix,
 		 " 1 -- enable MSI-X interrupt mechanism.\n"
 		 " 2 -- enable MSI interrupt mechanism.\n");
 
+int ql2xtrackfwres;
+module_param(ql2xtrackfwres, int, 0444);
+MODULE_PARM_DESC(ql2xtrackfwres,
+		 "Track FW resource.  0(default): disabled");
+
 /*
  * SCSI host template entry points
  */
@@ -1772,6 +1777,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
 							atomic_dec(
 							    &sp->ref_count);
 					}
+					qla_put_iocbs(sp->qpair, &sp->iores);
 					sp->done(sp, res);
 				} else {
 					if (!vha->hw->tgt.tgt_ops || !tgt ||
@@ -2790,6 +2796,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	ha->link_data_rate = PORT_SPEED_UNKNOWN;
 	ha->optrom_size = OPTROM_SIZE_2300;
 	ha->max_exchg = FW_MAX_EXCHANGES_CNT;
+	ha->fwres.ini_iocbs_reserve = DEF_RES_INI_IOCBS;
+	ha->fwres.tgt_iocbs_reserve = DEF_RES_TGT_IOCBS;
+	ha->fwres.busy_iocbs_reserve = DEF_RES_BUSY_IOCBS;
+	spin_lock_init(&ha->fwres.rescnt_lock);
 
 	/* Assign ISP specific operations. */
 	if (IS_QLA2100(ha)) {
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index fcfdbe1420cd..0d77b2f67077 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -2628,6 +2628,14 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
 		}
 	}
 
+	if (cmd->qpair->fw_res_tracking) {
+		cmd->iores.iocb_cnt = *full_req_cnt;
+		cmd->iores.res_type = RESOURCE_TGT;
+		if (qla_get_iocbs(cmd->vha->hw, &cmd->iores)) {
+			qlt_unmap_sg(cmd->vha, cmd);
+			return -EAGAIN;
+		}
+	}
 	return 0;
 }
 
@@ -3202,6 +3210,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
 out_unmap_unlock:
 	qlt_unmap_sg(vha, cmd);
 	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+	qla_put_iocbs(qpair, &cmd->iores);
 
 	return res;
 }
@@ -3243,6 +3252,14 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
 	}
 
 	spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+
+	if (cmd->qpair->fw_res_tracking) {
+		cmd->iores.iocb_cnt = prm.req_cnt;
+		cmd->iores.res_type = RESOURCE_TGT;
+		if (qla_get_iocbs(cmd->vha->hw, &cmd->iores))
+			goto out_unlock_free_unmap;
+	}
+
 	/* Does F/W have an IOCBs for this request */
 	res = qlt_check_reserve_free_req(qpair, prm.req_cnt);
 	if (res != 0)
@@ -3281,6 +3298,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
 	qlt_unmap_sg(vha, cmd);
 	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
 
+	qla_put_iocbs(qpair, &cmd->iores);
 	return res;
 }
 EXPORT_SYMBOL(qlt_rdy_to_xfer);
@@ -3810,6 +3828,8 @@ qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
 		dump_stack();
 	}
 
+	qla_put_iocbs(cmd->qpair, &cmd->iores);
+
 	cmd->trc_flags |= TRC_FLUSH;
 	ha->tgt.tgt_ops->free_cmd(cmd);
 }
@@ -3841,6 +3861,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
 
 	se_cmd = &cmd->se_cmd;
 	cmd->cmd_sent_to_fw = 0;
+	qla_put_iocbs(cmd->qpair, &cmd->iores);
 
 	qlt_unmap_sg(vha, cmd);
 
@@ -6412,6 +6433,9 @@ qlt_enable_vha(struct scsi_qla_host *vha)
 		qla24xx_disable_vp(vha);
 		qla24xx_enable_vp(vha);
 	} else {
+		if (ql2xtrackfwres && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
+			QLA_ENA_FW_RES_TRACKING(ha);
+
 		set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
 		qla2xxx_wake_dpc(base_vha);
 		qla2x00_wait_for_hba_online(base_vha);
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index aba58d3848a6..588c8bcf1192 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -877,7 +877,8 @@ struct qla_tgt_cmd {
 	 * Do not move cmd_type field. it needs to line up with srb->cmd_type
 	 */
 	uint8_t cmd_type;
-	uint8_t pad[7];
+	uint8_t pad[3];
+	struct iocb_resource iores;
 	struct se_cmd se_cmd;
 	struct fc_port *sess;
 	struct qla_qpair *qpair;
-- 
2.12.0

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

* [PATCH 08/43] qla2xxx: Chip reset uses wrong lock during IO flush.
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (6 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 09/43] qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload Himanshu Madhani
                   ` (34 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

As part of chip reset, all commands from all QPairs are
flushed. This patch fixes code to use Q Pair lock for flush
instead of using old hardware_lock.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_os.c | 139 +++++++++++++++++++-----------------------
 1 file changed, 64 insertions(+), 75 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7f361e93c593..4a542a5a976d 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1709,94 +1709,83 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
 	return QLA_SUCCESS;
 }
 
-void
-qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
+static void
+__qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
 {
-	int que, cnt, status;
+	int cnt;
 	unsigned long flags;
 	srb_t *sp;
+	scsi_qla_host_t *vha = qp->vha;
 	struct qla_hw_data *ha = vha->hw;
 	struct req_que *req;
 	struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
 	struct qla_tgt_cmd *cmd;
 	uint8_t trace = 0;
 
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	for (que = 0; que < ha->max_req_queues; que++) {
-		req = ha->req_q_map[que];
-		if (!req)
-			continue;
-		if (!req->outstanding_cmds)
-			continue;
-		for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
-			sp = req->outstanding_cmds[cnt];
-			if (sp) {
-				req->outstanding_cmds[cnt] = NULL;
-				if (sp->cmd_type == TYPE_SRB) {
-					if (sp->type == SRB_NVME_CMD ||
-					    sp->type == SRB_NVME_LS) {
-						sp_get(sp);
-						spin_unlock_irqrestore(
-						    &ha->hardware_lock, flags);
-						qla_nvme_abort(ha, sp);
-						spin_lock_irqsave(
-						    &ha->hardware_lock, flags);
-					} else if (GET_CMD_SP(sp) &&
-					    !ha->flags.eeh_busy &&
-					    (!test_bit(ABORT_ISP_ACTIVE,
-						&vha->dpc_flags)) &&
-					    (sp->type == SRB_SCSI_CMD)) {
-						/*
-						 * Don't abort commands in
-						 * adapter during EEH
-						 * recovery as it's not
-						 * accessible/responding.
-						 *
-						 * Get a reference to the sp
-						 * and drop the lock. The
-						 * reference ensures this
-						 * sp->done() call and not the
-						 * call in qla2xxx_eh_abort()
-						 * ends the SCSI command (with
-						 * result 'res').
-						 */
-						sp_get(sp);
-						spin_unlock_irqrestore(
-						    &ha->hardware_lock, flags);
-						status = qla2xxx_eh_abort(
-						    GET_CMD_SP(sp));
-						spin_lock_irqsave(
-						    &ha->hardware_lock, flags);
-						/*
-						 * Get rid of extra reference
-						 * if immediate exit from
-						 * ql2xxx_eh_abort
-						 */
-						if (status == FAILED &&
-						    (qla2x00_isp_reg_stat(ha)))
-							atomic_dec(
-							    &sp->ref_count);
-					}
-					qla_put_iocbs(sp->qpair, &sp->iores);
-					sp->done(sp, res);
-				} else {
-					if (!vha->hw->tgt.tgt_ops || !tgt ||
-					    qla_ini_mode_enabled(vha)) {
-						if (!trace)
-							ql_dbg(ql_dbg_tgt_mgt,
-							    vha, 0xf003,
-							    "HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
-							    vha->dpc_flags);
-						continue;
-					}
-					cmd = (struct qla_tgt_cmd *)sp;
-					qlt_abort_cmd_on_host_reset(cmd->vha,
-					    cmd);
+	spin_lock_irqsave(qp->qp_lock_ptr, flags);
+	req = qp->req;
+	for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
+		sp = req->outstanding_cmds[cnt];
+		if (sp) {
+			req->outstanding_cmds[cnt] = NULL;
+			if (sp->cmd_type == TYPE_SRB) {
+				/*
+				 * Don't abort commands in adapter during EEH
+				 * recovery as it's not accessible/responding.
+				 */
+				if (GET_CMD_SP(sp) && !ha->flags.eeh_busy &&
+				    (!test_bit(ABORT_ISP_ACTIVE,
+					&vha->dpc_flags)) &&
+				    (sp->type == SRB_SCSI_CMD)) {
+					/*
+					 * Get a reference to the sp and drop
+					 * the lock. The reference ensures this
+					 * sp->done() call and
+					 * - not the call in qla2xxx_eh_abort()
+					 * - ends the SCSI command (with result
+					 *   'res').
+					 */
+					sp_get(sp);
+					spin_unlock_irqrestore(qp->qp_lock_ptr,
+					    flags);
+					qla2xxx_eh_abort(GET_CMD_SP(sp));
+					spin_lock_irqsave(qp->qp_lock_ptr,
+					    flags);
 				}
+				qla_put_iocbs(sp->qpair, &sp->iores);
+				sp->done(sp, res);
+			} else {
+				if (!vha->hw->tgt.tgt_ops ||
+				    !tgt || qla_ini_mode_enabled(vha)) {
+					if (!trace)
+						ql_dbg(ql_dbg_tgt_mgt, vha,
+						    0xf003,
+						    "HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
+						    vha->dpc_flags);
+					continue;
+				}
+				cmd = (struct qla_tgt_cmd *)sp;
+				qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
 			}
 		}
 	}
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
+}
+
+void
+qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
+{
+	int que;
+	struct qla_hw_data *ha = vha->hw;
+
+	__qla2x00_abort_all_cmds(ha->base_qpair, res);
+
+	for (que = 0; que < ha->max_qpairs; que++) {
+		if (!ha->queue_pair_map[que])
+			continue;
+
+		__qla2x00_abort_all_cmds(ha->queue_pair_map[que], res);
+	}
 }
 
 static int
-- 
2.12.0

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

* [PATCH 09/43] qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (7 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 08/43] qla2xxx: Chip reset uses wrong lock during IO flush Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 10/43] qla2xxx: Replace GPDB with async ADISC command Himanshu Madhani
                   ` (33 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

This patch adjusts and reallocates fw_dump memory for target mode
to save for extended login and exchange offload buffers into
dump captured.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 209 +++++++++++++++++++++-------------------
 drivers/scsi/qla2xxx/qla_tmpl.c |  40 +++++++-
 2 files changed, 147 insertions(+), 102 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 429305caef47..5cd04bfa5cae 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2593,70 +2593,27 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
 	return rval;
 }
 
-void
-qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+static void
+qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
 {
 	int rval;
-	uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
-	    eft_size, fce_size, mq_size;
 	dma_addr_t tc_dma;
 	void *tc;
 	struct qla_hw_data *ha = vha->hw;
-	struct req_que *req = ha->req_q_map[0];
-	struct rsp_que *rsp = ha->rsp_q_map[0];
 
-	if (ha->fw_dump) {
+	if (ha->eft) {
 		ql_dbg(ql_dbg_init, vha, 0x00bd,
-		    "Firmware dump already allocated.\n");
+		    "%s: Offload Mem is already allocated.\n",
+		    __func__);
 		return;
 	}
 
-	ha->fw_dumped = 0;
-	ha->fw_dump_cap_flags = 0;
-	dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
-	req_q_size = rsp_q_size = 0;
-
-	if (IS_QLA27XX(ha))
-		goto try_fce;
-
-	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-		fixed_size = sizeof(struct qla2100_fw_dump);
-	} else if (IS_QLA23XX(ha)) {
-		fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
-		mem_size = (ha->fw_memory_size - 0x11000 + 1) *
-		    sizeof(uint16_t);
-	} else if (IS_FWI2_CAPABLE(ha)) {
-		if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
-			fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
-		else if (IS_QLA81XX(ha))
-			fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
-		else if (IS_QLA25XX(ha))
-			fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem);
-		else
-			fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
-
-		mem_size = (ha->fw_memory_size - 0x100000 + 1) *
-		    sizeof(uint32_t);
-		if (ha->mqenable) {
-			if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
-				mq_size = sizeof(struct qla2xxx_mq_chain);
-			/*
-			 * Allocate maximum buffer size for all queues.
-			 * Resizing must be done at end-of-dump processing.
-			 */
-			mq_size += ha->max_req_queues *
-			    (req->length * sizeof(request_t));
-			mq_size += ha->max_rsp_queues *
-			    (rsp->length * sizeof(response_t));
-		}
-		if (ha->tgt.atio_ring)
-			mq_size += ha->tgt.atio_q_length * sizeof(request_t);
+	if (IS_FWI2_CAPABLE(ha)) {
 		/* Allocate memory for Fibre Channel Event Buffer. */
 		if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
 		    !IS_QLA27XX(ha))
 			goto try_eft;
 
-try_fce:
 		if (ha->fce)
 			dma_free_coherent(&ha->pdev->dev,
 			    FCE_SIZE, ha->fce, ha->fce_dma);
@@ -2684,7 +2641,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 		ql_dbg(ql_dbg_init, vha, 0x00c0,
 		    "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
 
-		fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
 		ha->flags.fce_enabled = 1;
 		ha->fce_dma = tc_dma;
 		ha->fce = tc;
@@ -2701,7 +2657,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 			ql_log(ql_log_warn, vha, 0x00c1,
 			    "Unable to allocate (%d KB) for EFT.\n",
 			    EFT_SIZE / 1024);
-			goto cont_alloc;
+			goto eft_err;
 		}
 
 		rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
@@ -2710,17 +2666,76 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 			    "Unable to initialize EFT (%d).\n", rval);
 			dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
 			    tc_dma);
-			goto cont_alloc;
+			goto eft_err;
 		}
 		ql_dbg(ql_dbg_init, vha, 0x00c3,
 		    "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
 
-		eft_size = EFT_SIZE;
 		ha->eft_dma = tc_dma;
 		ha->eft = tc;
 	}
 
-cont_alloc:
+eft_err:
+	return;
+}
+
+void
+qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+{
+	uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
+	    eft_size, fce_size, mq_size;
+	struct qla_hw_data *ha = vha->hw;
+	struct req_que *req = ha->req_q_map[0];
+	struct rsp_que *rsp = ha->rsp_q_map[0];
+	struct qla2xxx_fw_dump *fw_dump;
+
+	dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
+	req_q_size = rsp_q_size = 0;
+
+	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
+		fixed_size = sizeof(struct qla2100_fw_dump);
+	} else if (IS_QLA23XX(ha)) {
+		fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
+		mem_size = (ha->fw_memory_size - 0x11000 + 1) *
+		    sizeof(uint16_t);
+	} else if (IS_FWI2_CAPABLE(ha)) {
+		if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+			fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
+		else if (IS_QLA81XX(ha))
+			fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
+		else if (IS_QLA25XX(ha))
+			fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem);
+		else
+			fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
+
+		mem_size = (ha->fw_memory_size - 0x100000 + 1) *
+		    sizeof(uint32_t);
+		if (ha->mqenable) {
+			if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+				mq_size = sizeof(struct qla2xxx_mq_chain);
+			/*
+			 * Allocate maximum buffer size for all queues.
+			 * Resizing must be done at end-of-dump processing.
+			 */
+			mq_size += ha->max_req_queues *
+			    (req->length * sizeof(request_t));
+			mq_size += ha->max_rsp_queues *
+			    (rsp->length * sizeof(response_t));
+		}
+		if (ha->tgt.atio_ring)
+			mq_size += ha->tgt.atio_q_length * sizeof(request_t);
+		/* Allocate memory for Fibre Channel Event Buffer. */
+		if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+		    !IS_QLA27XX(ha))
+			goto try_eft;
+
+		fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
+try_eft:
+		ql_dbg(ql_dbg_init, vha, 0x00c3,
+		    "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
+		eft_size = EFT_SIZE;
+	}
+
 	if (IS_QLA27XX(ha)) {
 		if (!ha->fw_dump_template) {
 			ql_log(ql_log_warn, vha, 0x00ba,
@@ -2748,51 +2763,44 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 			ha->exlogin_size;
 
 allocate:
-	ha->fw_dump = vmalloc(dump_size);
-	if (!ha->fw_dump) {
-		ql_log(ql_log_warn, vha, 0x00c4,
-		    "Unable to allocate (%d KB) for firmware dump.\n",
-		    dump_size / 1024);
-
-		if (ha->fce) {
-			dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
-			    ha->fce_dma);
-			ha->fce = NULL;
-			ha->fce_dma = 0;
-		}
-
-		if (ha->eft) {
-			dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft,
-			    ha->eft_dma);
-			ha->eft = NULL;
-			ha->eft_dma = 0;
+	if (!ha->fw_dump_len || dump_size != ha->fw_dump_len) {
+		fw_dump = vmalloc(dump_size);
+		if (!fw_dump) {
+			ql_log(ql_log_warn, vha, 0x00c4,
+			    "Unable to allocate (%d KB) for firmware dump.\n",
+			    dump_size / 1024);
+		} else {
+			if (ha->fw_dump)
+				vfree(ha->fw_dump);
+			ha->fw_dump = fw_dump;
+
+			ha->fw_dump_len = dump_size;
+			ql_dbg(ql_dbg_init, vha, 0x00c5,
+			    "Allocated (%d KB) for firmware dump.\n",
+			    dump_size / 1024);
+
+			if (IS_QLA27XX(ha))
+				return;
+
+			ha->fw_dump->signature[0] = 'Q';
+			ha->fw_dump->signature[1] = 'L';
+			ha->fw_dump->signature[2] = 'G';
+			ha->fw_dump->signature[3] = 'C';
+			ha->fw_dump->version = htonl(1);
+
+			ha->fw_dump->fixed_size = htonl(fixed_size);
+			ha->fw_dump->mem_size = htonl(mem_size);
+			ha->fw_dump->req_q_size = htonl(req_q_size);
+			ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
+
+			ha->fw_dump->eft_size = htonl(eft_size);
+			ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
+			ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
+
+			ha->fw_dump->header_size =
+				htonl(offsetof(struct qla2xxx_fw_dump, isp));
 		}
-		return;
 	}
-	ha->fw_dump_len = dump_size;
-	ql_dbg(ql_dbg_init, vha, 0x00c5,
-	    "Allocated (%d KB) for firmware dump.\n", dump_size / 1024);
-
-	if (IS_QLA27XX(ha))
-		return;
-
-	ha->fw_dump->signature[0] = 'Q';
-	ha->fw_dump->signature[1] = 'L';
-	ha->fw_dump->signature[2] = 'G';
-	ha->fw_dump->signature[3] = 'C';
-	ha->fw_dump->version = htonl(1);
-
-	ha->fw_dump->fixed_size = htonl(fixed_size);
-	ha->fw_dump->mem_size = htonl(mem_size);
-	ha->fw_dump->req_q_size = htonl(req_q_size);
-	ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
-
-	ha->fw_dump->eft_size = htonl(eft_size);
-	ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
-	ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
-
-	ha->fw_dump->header_size =
-	    htonl(offsetof(struct qla2xxx_fw_dump, isp));
 }
 
 static int
@@ -3154,9 +3162,12 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
 				if (rval != QLA_SUCCESS)
 					goto failed;
 
-				if (!fw_major_version && ql2xallocfwdump
-				    && !(IS_P3P_TYPE(ha)))
+				if (!fw_major_version && !(IS_P3P_TYPE(ha)))
+					qla2x00_alloc_offload_mem(vha);
+
+				if (ql2xallocfwdump && !(IS_P3P_TYPE(ha)))
 					qla2x00_alloc_fw_dump(vha);
+
 			} else {
 				goto failed;
 			}
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index 733e8dcccf5c..731ca0d8520a 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -526,7 +526,8 @@ qla27xx_fwdt_entry_t268(struct scsi_qla_host *vha,
 {
 	ql_dbg(ql_dbg_misc, vha, 0xd20c,
 	    "%s: gethb(%x) [%lx]\n", __func__, ent->t268.buf_type, *len);
-	if (ent->t268.buf_type == T268_BUF_TYPE_EXTD_TRACE) {
+	switch (ent->t268.buf_type) {
+	case T268_BUF_TYPE_EXTD_TRACE:
 		if (vha->hw->eft) {
 			if (buf) {
 				ent->t268.buf_size = EFT_SIZE;
@@ -538,10 +539,43 @@ qla27xx_fwdt_entry_t268(struct scsi_qla_host *vha,
 			    "%s: missing eft\n", __func__);
 			qla27xx_skip_entry(ent, buf);
 		}
-	} else {
-		ql_dbg(ql_dbg_misc, vha, 0xd02b,
+		break;
+	case T268_BUF_TYPE_EXCH_BUFOFF:
+		if (vha->hw->exchoffld_buf) {
+			if (buf) {
+				ent->t268.buf_size = vha->hw->exchoffld_size;
+				ent->t268.start_addr =
+					vha->hw->exchoffld_buf_dma;
+			}
+			qla27xx_insertbuf(vha->hw->exchoffld_buf,
+			    vha->hw->exchoffld_size, buf, len);
+		} else {
+			ql_dbg(ql_dbg_misc, vha, 0xd028,
+			    "%s: missing exch offld\n", __func__);
+			qla27xx_skip_entry(ent, buf);
+		}
+		break;
+	case T268_BUF_TYPE_EXTD_LOGIN:
+		if (vha->hw->exlogin_buf) {
+			if (buf) {
+				ent->t268.buf_size = vha->hw->exlogin_size;
+				ent->t268.start_addr =
+					vha->hw->exlogin_buf_dma;
+			}
+			qla27xx_insertbuf(vha->hw->exlogin_buf,
+			    vha->hw->exlogin_size, buf, len);
+		} else {
+			ql_dbg(ql_dbg_misc, vha, 0xd028,
+			    "%s: missing ext login\n", __func__);
+			qla27xx_skip_entry(ent, buf);
+		}
+		break;
+
+	default:
+		ql_dbg(ql_dbg_async, vha, 0xd02b,
 		    "%s: unknown buffer %x\n", __func__, ent->t268.buf_type);
 		qla27xx_skip_entry(ent, buf);
+		break;
 	}
 
 	return false;
-- 
2.12.0

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

* [PATCH 10/43] qla2xxx: Replace GPDB with async ADISC command
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (8 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 09/43] qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 11/43] qla2xxx: Move work element processing out of DPC thread Himanshu Madhani
                   ` (32 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Replace call to Get Port DataBase MB with PDO_FORCE_ADISC
flag with async ADISC command so driver can see ADISC command
has error or not.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |  2 ++
 drivers/scsi/qla2xxx/qla_gs.c   | 20 +++++++-----
 drivers/scsi/qla2xxx/qla_init.c | 68 +++++++++++++++++++++++------------------
 3 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 8fbe1736a1a4..18b393453002 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2320,6 +2320,7 @@ enum discovery_state {
 	DSC_GPSC,
 	DSC_UPD_FCPORT,
 	DSC_LOGIN_COMPLETE,
+	DSC_ADISC,
 	DSC_DELETE_PEND,
 };
 
@@ -2346,6 +2347,7 @@ enum fcport_mgt_event {
 	FCME_GPNID_DONE,
 	FCME_GFFID_DONE,
 	FCME_DELETE_DONE,
+	FCME_ADISC_DONE,
 };
 
 enum rscn_addr_format {
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 6aa6dd74fe86..b1c6485c307b 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -2867,15 +2867,19 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 					    "%s %d %8phC post %s\n", __func__,
 					    __LINE__, fcport->port_name,
 					    (atomic_read(&fcport->state) ==
-					    FCS_ONLINE) ? "gpdb" : "gnl");
+					    FCS_ONLINE) ? "adisc" : "gnl");
 
 					if (atomic_read(&fcport->state) ==
-					    FCS_ONLINE)
-						qla24xx_post_gpdb_work(vha,
-						    fcport, PDO_FORCE_ADISC);
-					else
+					    FCS_ONLINE) {
+						u16 data[2];
+
+						data[0] = data[1] = 0;
+						qla2x00_post_async_adisc_work(
+						    vha, fcport, data);
+					} else {
 						qla24xx_post_gnl_work(vha,
 						    fcport);
+					}
 					break;
 				}
 			} else { /* fcport->d_id.b24 != ea->id.b24 */
@@ -3216,6 +3220,7 @@ void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
 void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
 	fc_port_t *fcport, *conflict, *t;
+	u16 data[2];
 
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "%s %d port_id: %06x\n",
@@ -3290,8 +3295,9 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 				ql_dbg(ql_dbg_disc, vha, 0x210d,
 				    "%s %d %8phC revalidate session with ADISC\n",
 				    __func__, __LINE__, fcport->port_name);
-				qla24xx_post_gpdb_work(vha, fcport,
-				    PDO_FORCE_ADISC);
+				data[0] = data[1] = 0;
+				qla2x00_post_async_adisc_work(vha, fcport,
+				    data);
 				break;
 			case DSC_DELETED:
 				ql_dbg(ql_dbg_disc, vha, 0x210d,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 5cd04bfa5cae..0a1c287c2d66 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -41,6 +41,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
     struct event_arg *);
 static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
     struct event_arg *);
+static void qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
 
 /* SRB Extensions ---------------------------------------------------------- */
 
@@ -277,17 +278,31 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 	fcport->flags &= ~FCF_ASYNC_SENT;
 	return rval;
 }
+static
+void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+	qla24xx_handle_gpdb_event(vha, ea);
+}
 
 static void
 qla2x00_async_adisc_sp_done(void *ptr, int res)
 {
 	srb_t *sp = ptr;
 	struct scsi_qla_host *vha = sp->vha;
-	struct srb_iocb *lio = &sp->u.iocb_cmd;
+	struct event_arg ea;
+
+	ql_dbg(ql_dbg_disc, vha, 0x2066,
+	    "Async done-%s res %x %8phC\n",
+	    sp->name, res, sp->fcport->port_name);
+
+	memset(&ea, 0, sizeof(ea));
+	ea.event = FCME_ADISC_DONE;
+	ea.rc = res;
+	ea.fcport = sp->fcport;
+	ea.sp = sp;
+
+	qla2x00_fcport_event_handler(vha, &ea);
 
-	if (!test_bit(UNLOADING, &vha->dpc_flags))
-		qla2x00_post_async_adisc_done_work(sp->vha, sp->fcport,
-		    lio->u.logio.data);
 	sp->free(sp);
 }
 
@@ -305,8 +320,11 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 	if (!sp)
 		goto done;
 
+	fcport->disc_state = DSC_ADISC;
 	sp->type = SRB_ADISC_CMD;
 	sp->name = sp_to_str(SPCN_ADISC);
+	sp->gen1 = fcport->rscn_gen;
+	sp->gen2 = fcport->login_gen;
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
 	lio = &sp->u.iocb_cmd;
@@ -319,15 +337,15 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 		goto done_free_sp;
 
 	ql_dbg(ql_dbg_disc, vha, 0x206f,
-	    "Async-adisc - hdl=%x loopid=%x portid=%02x%02x%02x.\n",
-	    sp->handle, fcport->loop_id, fcport->d_id.b.domain,
-	    fcport->d_id.b.area, fcport->d_id.b.al_pa);
+	    "Async-adisc - hdl=%x loopid=%x portid=%06x %8phC.\n",
+	    sp->handle, fcport->loop_id, fcport->d_id.b24, fcport->port_name);
 	return rval;
 
 done_free_sp:
 	sp->free(sp);
 done:
 	fcport->flags &= ~FCF_ASYNC_SENT;
+	qla2x00_post_async_adisc_work(vha, fcport, data);
 	return rval;
 }
 
@@ -869,7 +887,6 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	int rval = ea->rc;
 	fc_port_t *fcport = ea->fcport;
 	unsigned long flags;
-	u16 opt = ea->sp->u.iocb_cmd.u.mbx.out_mb[10];
 
 	fcport->flags &= ~FCF_ASYNC_SENT;
 
@@ -900,8 +917,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	}
 
 	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
-	if (opt != PDO_FORCE_ADISC)
-		ea->fcport->login_gen++;
+	ea->fcport->login_gen++;
 	ea->fcport->deleted = 0;
 	ea->fcport->logout_on_delete = 1;
 
@@ -941,6 +957,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 
 int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
+	u16 data[2];
 	if (fcport->login_retry == 0)
 		return 0;
 
@@ -999,23 +1016,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 			break;
 		}
 
-		if (fcport->flags & FCF_FCP2_DEVICE) {
-			u8 opt = PDO_FORCE_ADISC;
-
-			ql_dbg(ql_dbg_disc, vha, 0x20c9,
-			    "%s %d %8phC post gpdb\n",
-			    __func__, __LINE__, fcport->port_name);
-
-			fcport->disc_state = DSC_GPDB;
-			qla24xx_post_gpdb_work(vha, fcport, opt);
-		} else {
-			ql_dbg(ql_dbg_disc, vha, 0x20cf,
-			    "%s %d %8phC post login\n",
-			    __func__, __LINE__, fcport->port_name);
-			fcport->disc_state = DSC_LOGIN_PEND;
-			qla2x00_post_async_login_work(vha, fcport, NULL);
-		}
-
+		ql_dbg(ql_dbg_disc, vha, 0x20cf,
+		    "%s %d %8phC post login\n",
+		    __func__, __LINE__, fcport->port_name);
+		fcport->disc_state = DSC_LOGIN_PEND;
+		qla2x00_post_async_login_work(vha, fcport, NULL);
 		break;
 
 	case DSC_LOGIN_FAILED:
@@ -1029,10 +1034,10 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 	case DSC_LOGIN_COMPLETE:
 		/* recheck login state */
 		ql_dbg(ql_dbg_disc, vha, 0x20d1,
-		    "%s %d %8phC post gpdb\n",
+		    "%s %d %8phC post adisc\n",
 		    __func__, __LINE__, fcport->port_name);
-
-		qla24xx_post_gpdb_work(vha, fcport, PDO_FORCE_ADISC);
+		data[0] = data[1] = 0;
+		qla2x00_post_async_adisc_work(vha, fcport, data);
 		break;
 
 	default:
@@ -1264,6 +1269,9 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 	case FCME_DELETE_DONE:
 		qla24xx_handle_delete_done_event(vha, ea);
 		break;
+	case FCME_ADISC_DONE:
+		qla24xx_handle_adisc_event(vha, ea);
+		break;
 	default:
 		BUG_ON(1);
 		break;
-- 
2.12.0

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

* [PATCH 11/43] qla2xxx: Move work element processing out of DPC thread
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (9 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 10/43] qla2xxx: Replace GPDB with async ADISC command Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 12/43] qla2xxx: Enable ATIO interrupt handshake for ISP27XX Himanshu Madhani
                   ` (31 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

DPC thread can stall during switch scan due to slow switch response.
This will stall other work element that needs attention. Moving work
element processing and relogin logic out of DPC thread and into its
own work queue.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |  6 ++--
 drivers/scsi/qla2xxx/qla_gbl.h  |  2 +-
 drivers/scsi/qla2xxx/qla_init.c |  1 +
 drivers/scsi/qla2xxx/qla_mid.c  |  6 +---
 drivers/scsi/qla2xxx/qla_os.c   | 76 +++++++++++++++++++++++++++++++----------
 5 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 18b393453002..a2c0f3d78b35 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3183,6 +3183,7 @@ enum qla_work_type {
 	QLA_EVT_UPD_FCPORT,
 	QLA_EVT_GNL,
 	QLA_EVT_NACK,
+	QLA_EVT_RELOGIN,
 };
 
 
@@ -3513,10 +3514,6 @@ struct qlt_hw_data {
 
 #define LEAK_EXCHG_THRESH_HOLD_PERCENT 75	/* 75 percent */
 
-#define QLA_EARLY_LINKUP(_ha) \
-	((_ha->flags.n2n_ae || _ha->flags.lip_ae) && \
-	 _ha->flags.fw_started && !_ha->flags.fw_init_done)
-
 /*
  * Qlogic host adapter specific data structure.
 */
@@ -4222,6 +4219,7 @@ typedef struct scsi_qla_host {
 #define SET_ZIO_THRESHOLD_NEEDED	28
 #define DETECT_SFP_CHANGE	29
 #define N2N_LOGIN_NEEDED	30
+#define IOCB_WORK_ACTIVE	31
 
 	unsigned long	pci_flags;
 #define PFLG_DISCONNECTED	0	/* PCI device removed */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 66dcbdb91244..fb1c9ffdc05a 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -204,7 +204,7 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
 	uint16_t *);
 int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_abort_cmd(srb_t *);
-
+int qla24xx_post_relogin_work(struct scsi_qla_host *vha);
 /*
  * Global Functions in qla_mid.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 0a1c287c2d66..61b74fd220a3 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -901,6 +901,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 		    __func__, fcport->port_name, fcport->last_rscn_gen,
 		    fcport->rscn_gen, fcport->last_login_gen,
 		    fcport->login_gen);
+		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 		return;
 	} else if (ea->sp->gen1 != fcport->rscn_gen) {
 		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index fc61fef5e305..b2fda398a098 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -319,8 +319,6 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
 	ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x4012,
 	    "Entering %s vp_flags: 0x%lx.\n", __func__, vha->vp_flags);
 
-	qla2x00_do_work(vha);
-
 	/* Check if Fw is ready to configure VP first */
 	if (test_bit(VP_CONFIG_OK, &base_vha->vp_flags)) {
 		if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
@@ -354,9 +352,7 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
 
 			ql_dbg(ql_dbg_dpc, vha, 0x4018,
 			    "Relogin needed scheduled.\n");
-			qla2x00_relogin(vha);
-			ql_dbg(ql_dbg_dpc, vha, 0x4019,
-			    "Relogin needed end.\n");
+			qla24xx_post_relogin_work(vha);
 		}
 	}
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4a542a5a976d..66e6fe73a035 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2683,14 +2683,22 @@ static void qla2x00_iocb_work_fn(struct work_struct *work)
 {
 	struct scsi_qla_host *vha = container_of(work,
 		struct scsi_qla_host, iocb_work);
-	int cnt = 0;
+	struct qla_hw_data *ha = vha->hw;
+	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+	int i = 20;
+	unsigned long flags;
+
+	if (test_bit(UNLOADING, &base_vha->dpc_flags))
+		return;
 
-	while (!list_empty(&vha->work_list)) {
+	while (!list_empty(&vha->work_list) && i > 0) {
 		qla2x00_do_work(vha);
-		cnt++;
-		if (cnt > 10)
-			break;
+		i--;
 	}
+
+	spin_lock_irqsave(&vha->work_lock, flags);
+	clear_bit(IOCB_WORK_ACTIVE, &vha->dpc_flags);
+	spin_unlock_irqrestore(&vha->work_lock, flags);
 }
 
 /*
@@ -3192,7 +3200,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	    host->can_queue, base_vha->req,
 	    base_vha->mgmt_svr_loop_id, host->sg_tablesize);
 
-	ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 0);
+	ha->wq = alloc_workqueue("qla2xxx_wq", 0, 0);
 
 	if (ha->mqenable) {
 		bool mq = false;
@@ -4544,6 +4552,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
 	INIT_LIST_HEAD(&vha->gnl.fcports);
 	INIT_LIST_HEAD(&vha->nvme_rport_list);
 	INIT_LIST_HEAD(&vha->gpnid_list);
+	INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn);
 
 	spin_lock_init(&vha->work_lock);
 	spin_lock_init(&vha->cmd_list_lock);
@@ -4596,15 +4605,18 @@ int
 qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
 {
 	unsigned long flags;
+	bool q = false;
 
 	spin_lock_irqsave(&vha->work_lock, flags);
 	list_add_tail(&e->list, &vha->work_list);
+
+	if (!test_and_set_bit(IOCB_WORK_ACTIVE, &vha->dpc_flags))
+		q = true;
+
 	spin_unlock_irqrestore(&vha->work_lock, flags);
 
-	if (QLA_EARLY_LINKUP(vha->hw))
-		schedule_work(&vha->iocb_work);
-	else
-		qla2xxx_wake_dpc(vha);
+	if (q)
+		queue_work(vha->hw->wq, &vha->iocb_work);
 
 	return QLA_SUCCESS;
 }
@@ -4736,6 +4748,9 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 		fcport->d_id = e->u.new_sess.id;
 		if (pla) {
 			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
+			memcpy(fcport->node_name,
+			    pla->iocb.u.isp24.u.plogi.node_name,
+			    WWN_SIZE);
 			qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN);
 			/* we took an extra ref_count to prevent PLOGI ACK when
 			 * fcport/sess has not been created.
@@ -4886,6 +4901,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 		case QLA_EVT_GPNID_DONE:
 			qla24xx_async_gpnid_done(vha, e->u.iosb.sp);
 			break;
+		case QLA_EVT_RELOGIN:
+			qla2x00_relogin(vha);
+			break;
 		case QLA_EVT_NEW_SESS:
 			qla24xx_create_new_sess(vha, e);
 			break;
@@ -4917,6 +4935,20 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 	}
 }
 
+int qla24xx_post_relogin_work(struct scsi_qla_host *vha)
+{
+	struct qla_work_evt *e;
+
+	e = qla2x00_alloc_work(vha, QLA_EVT_RELOGIN);
+
+	if (!e) {
+		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+		return QLA_FUNCTION_FAILED;
+	}
+
+	return qla2x00_post_work(vha, e);
+}
+
 /* Relogins all the fcports of a vport
  * Context: dpc thread
  */
@@ -4972,6 +5004,9 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 		if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
 			break;
 	}
+
+	ql_dbg(ql_dbg_disc, vha, 0x400e,
+	    "Relogin end.\n");
 }
 
 /* Schedule work on any of the dpc-workqueues */
@@ -5747,8 +5782,6 @@ qla2x00_do_dpc(void *data)
 		if (test_bit(UNLOADING, &base_vha->dpc_flags))
 			break;
 
-		qla2x00_do_work(base_vha);
-
 		if (IS_P3P_TYPE(ha)) {
 			if (IS_QLA8044(ha)) {
 				if (test_and_clear_bit(ISP_UNRECOVERABLE,
@@ -5936,11 +5969,9 @@ qla2x00_do_dpc(void *data)
 				base_vha->relogin_jif = jiffies + HZ;
 				clear_bit(RELOGIN_NEEDED, &base_vha->dpc_flags);
 
-				ql_dbg(ql_dbg_dpc, base_vha, 0x400d,
+				ql_dbg(ql_dbg_disc, base_vha, 0x400d,
 				    "Relogin scheduled.\n");
-				qla2x00_relogin(base_vha);
-				ql_dbg(ql_dbg_dpc, base_vha, 0x400e,
-				    "Relogin end.\n");
+				qla24xx_post_relogin_work(base_vha);
 			}
 		}
 loop_resync_check:
@@ -6200,8 +6231,17 @@ qla2x00_timer(struct timer_list *t)
 	}
 
 	/* Process any deferred work. */
-	if (!list_empty(&vha->work_list))
-		start_dpc++;
+	if (!list_empty(&vha->work_list)) {
+		unsigned long flags;
+		bool q = false;
+
+		spin_lock_irqsave(&vha->work_lock, flags);
+		if (!test_and_set_bit(IOCB_WORK_ACTIVE, &vha->dpc_flags))
+			q = true;
+		spin_unlock_irqrestore(&vha->work_lock, flags);
+		if (q)
+			queue_work(vha->hw->wq, &vha->iocb_work);
+	}
 
 	/*
 	 * FC-NVME
-- 
2.12.0

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

* [PATCH 12/43] qla2xxx: Enable ATIO interrupt handshake for ISP27XX
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (10 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 11/43] qla2xxx: Move work element processing out of DPC thread Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 13/43] qla2xxx: Use shadow register " Himanshu Madhani
                   ` (30 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Enable ATIO Q interrupt handshake for ISP27XX. This patch
coalesce ATIO's interrupts for Quad port ISP27XX adapter.
Interrupt coalesce allows performance to scale for this
specific case.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_target.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 0d77b2f67077..835721f077f6 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -6598,7 +6598,9 @@ void
 qlt_24xx_config_rings(struct scsi_qla_host *vha)
 {
 	struct qla_hw_data *ha = vha->hw;
-	struct init_cb_24xx *icb;
+	struct qla_msix_entry *msix = &ha->msix_entries[2];
+	struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb;
+
 	if (!QLA_TGT_MODE_ENABLED())
 		return;
 
@@ -6606,19 +6608,28 @@ 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));
 
-	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];
-
-		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");
+	if (ha->flags.msix_enabled) {
+		if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+			if (IS_QLA2071(ha)) {
+				/* 4 ports Baker: Enable Interrupt Handshake */
+				icb->msix_atio = 0;
+				icb->firmware_options_2 |= BIT_26;
+			} else {
+				icb->msix_atio = cpu_to_le16(msix->entry);
+				icb->firmware_options_2 &= ~BIT_26;
+			}
+			ql_dbg(ql_dbg_init, vha, 0xf072,
+			    "Registering ICB vector 0x%x for atio que.\n",
+			    msix->entry);
+		}
+	} else {
+		/* INTx|MSI */
+		if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+			icb->msix_atio = 0;
+			icb->firmware_options_2 |= BIT_26;
+			ql_dbg(ql_dbg_init, vha, 0xf072,
+			    "%s: Use INTx for ATIOQ.\n", __func__);
+		}
 	}
 }
 
-- 
2.12.0

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

* [PATCH 13/43] qla2xxx: Use shadow register for ISP27XX
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (11 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 12/43] qla2xxx: Enable ATIO interrupt handshake for ISP27XX Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS Himanshu Madhani
                   ` (29 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

For ISP27XX, use shadow register to read FW provided REQQ's consumer
index. The shadow register is dma'ed by firmware.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_iocb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 417c40f21244..519a0d2920b8 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2192,7 +2192,9 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
 skip_cmd_array:
 	/* Check for room on request queue. */
 	if (req->cnt < req_cnt + 2) {
-		if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+		if (qpair->use_shadow_reg)
+			cnt = *req->out_ptr;
+		else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
 			cnt = RD_REG_DWORD(&reg->isp25mq.req_q_out);
 		else if (IS_P3P_TYPE(ha))
 			cnt = RD_REG_DWORD(&reg->isp82.req_q_out);
-- 
2.12.0

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

* [PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (12 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 13/43] qla2xxx: Use shadow register " Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 16:53   ` Bart Van Assche
  2017-12-20  6:56 ` [PATCH 15/43] qla2xxx: Add ability to send PRLO Himanshu Madhani
                   ` (28 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Add option to tell FW to reserve 1/2 of emergency exchanges for ELS.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h  | 1 +
 drivers/scsi/qla2xxx/qla_init.c | 6 ++++++
 drivers/scsi/qla2xxx/qla_os.c   | 6 ++++++
 3 files changed, 13 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index fb1c9ffdc05a..88c7746c023a 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -149,6 +149,7 @@ extern int ql2xnvmeenable;
 extern int ql2xautodetectsfp;
 extern int ql2xenablemsix;
 extern int ql2xtrackfwres;
+extern int qla2xuseresexchforels;
 
 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_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 61b74fd220a3..6223dfe20767 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3387,6 +3387,12 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
 			ha->fw_options[2] |= BIT_4;
 		else
 			ha->fw_options[2] &= ~BIT_4;
+
+		/* Reserve 1/2 of emergency exchanges for ELS.*/
+		if (qla2xuseresexchforels)
+			ha->fw_options[2] |= BIT_8;
+		else
+			ha->fw_options[2] &= ~BIT_8;
 	}
 
 	ql_dbg(ql_dbg_init, vha, 0x00e8,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 66e6fe73a035..fd107c4feda5 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -282,6 +282,12 @@ module_param(ql2xtrackfwres, int, 0444);
 MODULE_PARM_DESC(ql2xtrackfwres,
 		 "Track FW resource.  0(default): disabled");
 
+int qla2xuseresexchforels;
+module_param(qla2xuseresexchforels, int, 0444);
+MODULE_PARM_DESC(qla2xuseresexchforels,
+		 "Reserve 1/2 of emergency exchanges for ELS.\n"
+		 " 0 (default): disabled");
+
 /*
  * SCSI host template entry points
  */
-- 
2.12.0

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

* [PATCH 15/43] qla2xxx: Add ability to send PRLO
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (13 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 16/43] qla2xxx: Don't call dma_free_coherent with IRQ disabled Himanshu Madhani
                   ` (27 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Add ability to send Implicit PRLO to flush IOs
from FW back to driver.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |  5 ++++
 drivers/scsi/qla2xxx/qla_gbl.h  |  8 ++++++
 drivers/scsi/qla2xxx/qla_gs.c   |  1 +
 drivers/scsi/qla2xxx/qla_init.c | 59 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_iocb.c | 17 ++++++++++++
 drivers/scsi/qla2xxx/qla_os.c   |  9 +++++++
 6 files changed, 99 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a2c0f3d78b35..ba659aa9ae83 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -514,6 +514,7 @@ enum {
 	SPCN_NVME_LS,
 	SPCN_NVME_CMD,
 	SPCN_CTRL_VP,
+	SPCN_PRLO,
 };
 
 struct sp_name {
@@ -544,6 +545,8 @@ struct sp_name {
 #define SRB_NVME_LS	20
 #define SRB_PRLI_CMD	21
 #define SRB_CTRL_VP	22
+#define SRB_PRLO_CMD	23
+
 enum {
 	TYPE_SRB,
 	TYPE_TGT_CMD,
@@ -3184,6 +3187,8 @@ enum qla_work_type {
 	QLA_EVT_GNL,
 	QLA_EVT_NACK,
 	QLA_EVT_RELOGIN,
+	QLA_EVT_ASYNC_PRLO,
+	QLA_EVT_ASYNC_PRLO_DONE,
 };
 
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 88c7746c023a..ea8f24e07409 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -66,6 +66,7 @@ extern void qla84xx_put_chip(struct scsi_qla_host *);
 extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
+extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *);
 extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
@@ -109,6 +110,13 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
 int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_detect_sfp(scsi_qla_host_t *vha);
 int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
+void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *,
+    uint16_t *);
+extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *,
+    uint16_t *);
+extern int qla2x00_post_async_prlo_done_work(struct scsi_qla_host *,
+    fc_port_t *, uint16_t *);
+
 /*
  * Global Data in qla_os.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index b1c6485c307b..22702a8f5ce6 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -42,6 +42,7 @@ struct sp_name sp_str[] = {
 	{ SPCN_NVME_LS, "nvme_ls" },
 	{ SPCN_NVME_CMD, "nvme_cmd" },
 	{ SPCN_CTRL_VP, "ctrl_vp" },
+	{ SPCN_PRLO, "prlo" },
 };
 
 const char *sp_to_str(uint16_t cmd)
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 6223dfe20767..900f6d3f3a3a 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -278,6 +278,65 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 	fcport->flags &= ~FCF_ASYNC_SENT;
 	return rval;
 }
+
+void
+qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+    uint16_t *data)
+{
+	/* Don't re-login in target mode */
+	if (!fcport->tgt_session)
+		qla2x00_mark_device_lost(vha, fcport, 1, 0);
+	qlt_logo_completion_handler(fcport, data[0]);
+}
+
+static void
+qla2x00_async_prlo_sp_done(void *s, int res)
+{
+	srb_t *sp = (srb_t *)s;
+	struct srb_iocb *lio = &sp->u.iocb_cmd;
+	struct scsi_qla_host *vha = sp->vha;
+
+	if (!test_bit(UNLOADING, &vha->dpc_flags))
+		qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
+		    lio->u.logio.data);
+	sp->free(sp);
+}
+
+int
+qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+	srb_t *sp;
+	struct srb_iocb *lio;
+	int rval;
+
+	rval = QLA_FUNCTION_FAILED;
+	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+	if (!sp)
+		goto done;
+
+	sp->type = SRB_PRLO_CMD;
+	sp->name = sp_to_str(SPCN_PRLO);
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	lio = &sp->u.iocb_cmd;
+	lio->timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_prlo_sp_done;
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+
+	ql_dbg(ql_dbg_disc, vha, 0x2070,
+	    "Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
+	    sp->handle, fcport->loop_id, fcport->d_id.b.domain,
+	    fcport->d_id.b.area, fcport->d_id.b.al_pa);
+	return rval;
+
+done_free_sp:
+	sp->free(sp);
+done:
+	return rval;
+}
+
 static
 void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 519a0d2920b8..b2cec8313f27 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -3424,6 +3424,20 @@ qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx *vce)
 	vce->vp_idx_map[map] |= 1 << pos;
 }
 
+static void
+qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio)
+{
+	logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
+	logio->control_flags =
+	    cpu_to_le16(LCF_COMMAND_PRLO|LCF_IMPL_PRLO);
+
+	logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+	logio->port_id[0] = sp->fcport->d_id.b.al_pa;
+	logio->port_id[1] = sp->fcport->d_id.b.area;
+	logio->port_id[2] = sp->fcport->d_id.b.domain;
+	logio->vp_index = sp->fcport->vha->vp_idx;
+}
+
 int
 qla2x00_start_sp(srb_t *sp)
 {
@@ -3505,6 +3519,9 @@ qla2x00_start_sp(srb_t *sp)
 	case SRB_CTRL_VP:
 		qla25xx_ctrlvp_iocb(sp, pkt);
 		break;
+	case SRB_PRLO_CMD:
+		qla24xx_prlo_iocb(sp, pkt);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index fd107c4feda5..13550a8584ca 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4679,6 +4679,8 @@ qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
 qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
 qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
 qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE);
+qla2x00_post_async_work(prlo, QLA_EVT_ASYNC_PRLO);
+qla2x00_post_async_work(prlo_done, QLA_EVT_ASYNC_PRLO_DONE);
 
 int
 qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code)
@@ -4932,6 +4934,13 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 		case QLA_EVT_NACK:
 			qla24xx_do_nack_work(vha, e);
 			break;
+		case QLA_EVT_ASYNC_PRLO:
+			qla2x00_async_prlo(vha, e->u.logio.fcport);
+			break;
+		case QLA_EVT_ASYNC_PRLO_DONE:
+			qla2x00_async_prlo_done(vha, e->u.logio.fcport,
+			    e->u.logio.data);
+			break;
 		}
 		if (e->flags & QLA_EVT_FLAG_FREE)
 			kfree(e);
-- 
2.12.0

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

* [PATCH 16/43] qla2xxx: Don't call dma_free_coherent with IRQ disabled.
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (14 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 15/43] qla2xxx: Add ability to send PRLO Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 17/43] qla2xxx: Allow target mode to accept PRLI in dual mode Himanshu Madhani
                   ` (26 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Giridhar Malavali <giridhar.malavali@cavium.com>

The logo ELS command allocates dma coherent memory for the
data payload and serialize the completions. When this command
times out, the timeout routine completes the thread waiting
for completion which in turn cleanup resources allocated for
this ELS command processing. Don't call generic sp->free
routine when this ELS command times out to avoid to double
freeing of the same resources.

Signed-off-by: Giridhar Malavali <giridhar.malavali@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 900f6d3f3a3a..28248adb611d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -59,7 +59,8 @@ qla2x00_sp_timeout(struct timer_list *t)
 	req->outstanding_cmds[sp->handle] = NULL;
 	iocb = &sp->u.iocb_cmd;
 	iocb->timeout(sp);
-	sp->free(sp);
+	if (sp->type != SRB_ELS_DCMD)
+		sp->free(sp);
 	spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
 }
 
-- 
2.12.0

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

* [PATCH 17/43] qla2xxx: Allow target mode to accept PRLI in dual mode
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (15 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 16/43] qla2xxx: Don't call dma_free_coherent with IRQ disabled Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 18/43] qla2xxx: Tweak resource count dump Himanshu Madhani
                   ` (25 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

For Dual Mode, Initiator side of the driver finish login,
target side receive PRLI, but driver terminates PRLI.
This patch allows target side to go ahead and accept PRLI.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c   |  5 +++++
 drivers/scsi/qla2xxx/qla_target.c | 16 +++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 28248adb611d..7a8c6ead6d0e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1540,6 +1540,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 	port_id_t cid;	/* conflict Nport id */
 	u16 lid;
 	struct fc_port *conflict_fcport;
+	unsigned long flags;
 
 	switch (ea->data[0]) {
 	case MBS_COMMAND_COMPLETE:
@@ -1560,10 +1561,14 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 			    ea->fcport->loop_id, ea->fcport->d_id.b24);
 
 			set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
+			spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 			ea->fcport->loop_id = FC_NO_LOOP_ID;
 			ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
 			ea->fcport->logout_on_delete = 1;
 			ea->fcport->send_els_logo = 0;
+			ea->fcport->fw_login_state = DSC_LS_PRLI_COMP;
+			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
 			qla24xx_post_gpdb_work(vha, ea->fcport, 0);
 		}
 		break;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 835721f077f6..eaa43d3d5a91 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -4703,7 +4703,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 	uint16_t wd3_lo;
 	int res = 0;
 	struct qlt_plogi_ack_t *pla;
-	unsigned long flags;
+	unsigned long flags = 0;
 
 	wwn = wwn_to_u64(iocb->u.isp24.port_name);
 
@@ -4839,8 +4839,14 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 		}
 
 		if (sess != NULL) {
-			if (sess->fw_login_state != DSC_LS_PLOGI_PEND &&
-			    sess->fw_login_state != DSC_LS_PLOGI_COMP) {
+			spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
+			switch (sess->fw_login_state) {
+			case DSC_LS_PLOGI_COMP:
+			case DSC_LS_PRLI_COMP:
+				break;
+			default:
+				spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock,
+				    flags);
 				/*
 				 * Impatient initiator sent PRLI before last
 				 * PLOGI could finish. Will force him to re-try,
@@ -4851,6 +4857,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 				    sess);
 				qlt_send_term_imm_notif(vha, iocb, 1);
 				res = 0;
+				spin_lock_irqsave(&tgt->ha->tgt.sess_lock,
+				    flags);
 				break;
 			}
 
@@ -4874,6 +4882,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 				sess->port_type = FCT_INITIATOR;
 			else
 				sess->port_type = FCT_TARGET;
+
+			spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
 		}
 		res = 1; /* send notify ack */
 
-- 
2.12.0

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

* [PATCH 18/43] qla2xxx: Tweak resource count dump
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (16 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 17/43] qla2xxx: Allow target mode to accept PRLI in dual mode Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 19/43] qla2xxx: Fix session cleanup for N2N Himanshu Madhani
                   ` (24 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@qlogic.com>

Fetch actual data from firmware instead of static data
at chip reset time.

Signed-off-by: Quinn Tran <quinn.tran@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_dfs.c | 30 ++++++++++++++++--------------
 drivers/scsi/qla2xxx/qla_gbl.h |  1 +
 drivers/scsi/qla2xxx/qla_mbx.c | 30 ++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 87a18a00d509..4f0415e158cb 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -127,21 +127,23 @@ static int
 qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
 {
 	struct scsi_qla_host *vha = s->private;
-	struct qla_hw_data *ha = vha->hw;
+	uint16_t mb[MAX_IOCB_MB_REG];
+	int rc;
 
-	seq_puts(s, "FW Resource count\n\n");
-	seq_printf(s, "Original TGT exchg count[%d]\n",
-	    ha->orig_fw_tgt_xcb_count);
-	seq_printf(s, "current TGT exchg count[%d]\n",
-	    ha->cur_fw_tgt_xcb_count);
-	seq_printf(s, "original Initiator Exchange count[%d]\n",
-	    ha->orig_fw_xcb_count);
-	seq_printf(s, "Current Initiator Exchange count[%d]\n",
-	    ha->cur_fw_xcb_count);
-	seq_printf(s, "Original IOCB count[%d]\n", ha->orig_fw_iocb_count);
-	seq_printf(s, "Current IOCB count[%d]\n", ha->cur_fw_iocb_count);
-	seq_printf(s, "MAX VP count[%d]\n", ha->max_npiv_vports);
-	seq_printf(s, "MAX FCF count[%d]\n", ha->fw_max_fcf_count);
+	rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG);
+	if (rc != QLA_SUCCESS) {
+		seq_printf(s, "Mailbox Command failed %d, mb %#x", rc, mb[0]);
+	} else {
+		seq_puts(s, "FW Resource count\n\n");
+		seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]);
+		seq_printf(s, "current TGT exchg count[%d]\n", mb[2]);
+		seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]);
+		seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]);
+		seq_printf(s, "Original IOCB count[%d]\n", mb[7]);
+		seq_printf(s, "Current IOCB count[%d]\n", mb[10]);
+		seq_printf(s, "MAX VP count[%d]\n", mb[11]);
+		seq_printf(s, "MAX FCF count[%d]\n", mb[12]);
+	}
 
 	return 0;
 }
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index ea8f24e07409..2e0907994579 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -504,6 +504,7 @@ int qla24xx_get_port_login_templ(scsi_qla_host_t *, dma_addr_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);
+int qla24xx_res_count_wait(struct scsi_qla_host *, uint16_t *, int);
 
 /*
  * Global Function Prototypes in qla_isr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 956d121cc396..0c8ad7b31294 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -18,6 +18,7 @@ static struct mb_cmd_name {
 	{MBC_GET_PORT_DATABASE,		"GPDB"},
 	{MBC_GET_ID_LIST,		"GIDList"},
 	{MBC_GET_LINK_PRIV_STATS,	"Stats"},
+	{MBC_GET_RESOURCE_COUNTS,	"ResCnt"},
 };
 
 static const char *mb_to_str(uint16_t cmd)
@@ -6273,3 +6274,32 @@ qla2x00_read_sfp_dev(struct scsi_qla_host *vha, char *buf, int count)
 
 	return rval;
 }
+
+int qla24xx_res_count_wait(struct scsi_qla_host *vha,
+    uint16_t *out_mb, int out_mb_sz)
+{
+	int rval = QLA_FUNCTION_FAILED;
+	mbx_cmd_t mc;
+
+	if (!vha->hw->flags.fw_started)
+		goto done;
+
+	memset(&mc, 0, sizeof(mc));
+	mc.mb[0] = MBC_GET_RESOURCE_COUNTS;
+
+	rval = qla24xx_send_mb_cmd(vha, &mc);
+	if (rval != QLA_SUCCESS) {
+		ql_dbg(ql_dbg_mbx, vha, 0xffff,
+			"%s:  fail\n", __func__);
+	} else {
+		if (out_mb_sz <= SIZEOF_IOCB_MB_REG)
+			memcpy(out_mb, mc.mb, out_mb_sz);
+		else
+			memcpy(out_mb, mc.mb, SIZEOF_IOCB_MB_REG);
+
+		ql_dbg(ql_dbg_mbx, vha, 0xffff,
+			"%s:  done\n", __func__);
+	}
+done:
+	return rval;
+}
-- 
2.12.0

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

* [PATCH 19/43] qla2xxx: Fix session cleanup for N2N
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (17 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 18/43] qla2xxx: Tweak resource count dump Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-21  6:01   ` kbuild test robot
  2017-12-20  6:56 ` [PATCH 20/43] qla2xxx: Use known NPort ID for Management Server login Himanshu Madhani
                   ` (23 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

When connection type is N_Port to N_Port (point-to-point), there
is a possibilty where initiator will not send PLOGI request and
will directly send PRLI. In N2N connection the port has higher
port name sends the PLOGI but not allow to send PRLI if is a
target mode. Only initiator is allowed to send PRLI.

Current driver code deletes old session when it receives PLOGI
request. If we will not receive PLOGI request then we will not
delete old session and create new session. Add check for N2N
with PRLI receive only and trigger cleanup. For this case, the
cleanup requires individual cmd abort instead of using implicit
logout as a broad stroke flush.

Signed-off-by: Krishna Kant <krishna.kant@purestorage.com>
Signed-off-by: Alexei Potashnik <alexei@purestorage.com>
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h    |  11 ++
 drivers/scsi/qla2xxx/qla_fw.h     |   2 +-
 drivers/scsi/qla2xxx/qla_init.c   | 151 +++++++++++++-------
 drivers/scsi/qla2xxx/qla_isr.c    |   4 +-
 drivers/scsi/qla2xxx/qla_mbx.c    |  38 ++++-
 drivers/scsi/qla2xxx/qla_os.c     |  41 +++++-
 drivers/scsi/qla2xxx/qla_target.c | 286 +++++++++++++++++++++++++-------------
 7 files changed, 378 insertions(+), 155 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ba659aa9ae83..9fcc0a5ff8df 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3575,6 +3575,7 @@ struct qla_hw_data {
 		uint32_t	fw_init_done:1;
 		uint32_t	detected_lr_sfp:1;
 		uint32_t	using_lr_setting:1;
+		uint32_t	rida_fmt2:1;
 	} flags;
 
 	uint16_t max_exchg;
@@ -4615,6 +4616,16 @@ struct sff_8247_a0 {
 #define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \
 	(IS_QLA27XX(_ha) || IS_QLA83XX(_ha)))
 
+#define SAVE_TOPO(_ha) { \
+	if (_ha->current_topology)				\
+		_ha->prev_topology = _ha->current_topology;     \
+}
+
+#define N2N_TOPO(ha) \
+	((ha->prev_topology == ISP_CFG_N && !ha->current_topology) || \
+	 ha->current_topology == ISP_CFG_N || \
+	 !ha->current_topology)
+
 #include "qla_target.h"
 #include "qla_gbl.h"
 #include "qla_dbg.h"
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index d5cef0727e72..5d8688e5bc7c 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1392,7 +1392,7 @@ struct vp_rpt_id_entry_24xx {
 
 		    uint8_t port_name[8];
 		    uint8_t node_name[8];
-		    uint32_t remote_nport_id;
+		    uint8_t remote_nport_id[4];
 		    uint32_t reserved_5;
 		} f2;
 	} u;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 7a8c6ead6d0e..b4a96c80853f 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -181,11 +181,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 	if (!vha->flags.online)
 		goto done;
 
-	if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
-	    (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
-	    (fcport->fw_login_state == DSC_LS_PRLI_PEND))
-		goto done;
-
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -1016,6 +1011,43 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 } /* gpdb event */
 
+
+static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+	u8 login = 0;
+
+	if (qla_tgt_mode_enabled(vha))
+		return;
+
+	if (qla_dual_mode_enabled(vha)) {
+		if (N2N_TOPO(vha->hw)) {
+			u64 mywwn, wwn;
+
+			mywwn = wwn_to_u64(vha->port_name);
+			wwn = wwn_to_u64(fcport->port_name);
+			if (mywwn > wwn)
+				login = 1;
+			else if ((fcport->fw_login_state == DSC_LS_PLOGI_COMP)
+			    && time_after_eq(jiffies,
+				    fcport->plogi_nack_done_deadline))
+				login = 1;
+		} else {
+			login = 1;
+		}
+	} else {
+		/* initiator mode */
+		login = 1;
+	}
+
+	if (login) {
+		ql_dbg(ql_dbg_disc, vha, 0x20bf,
+		    "%s %d %8phC post login\n",
+		    __func__, __LINE__, fcport->port_name);
+		fcport->disc_state = DSC_LOGIN_PEND;
+		qla2x00_post_async_login_work(vha, fcport, NULL);
+	}
+}
+
 int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
 	u16 data[2];
@@ -1040,8 +1072,10 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 		return 0;
 
 	if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
-		if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline))
+		if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) {
+			set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 			return 0;
+		}
 	}
 
 	/* for pure Target Mode. Login will not be initiated */
@@ -1061,11 +1095,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 			    __func__, __LINE__, fcport->port_name);
 			qla24xx_post_gnl_work(vha, fcport);
 		} else {
-			ql_dbg(ql_dbg_disc, vha, 0x20bf,
-			    "%s %d %8phC post login\n",
-			    __func__, __LINE__, fcport->port_name);
-			fcport->disc_state = DSC_LOGIN_PEND;
-			qla2x00_post_async_login_work(vha, fcport, NULL);
+			qla_chk_n2n_b4_login(vha, fcport);
 		}
 		break;
 
@@ -1077,19 +1107,17 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 			break;
 		}
 
-		ql_dbg(ql_dbg_disc, vha, 0x20cf,
-		    "%s %d %8phC post login\n",
-		    __func__, __LINE__, fcport->port_name);
-		fcport->disc_state = DSC_LOGIN_PEND;
-		qla2x00_post_async_login_work(vha, fcport, NULL);
+		qla_chk_n2n_b4_login(vha, fcport);
 		break;
 
 	case DSC_LOGIN_FAILED:
 		ql_dbg(ql_dbg_disc, vha, 0x20d0,
 		    "%s %d %8phC post gidpn\n",
 		    __func__, __LINE__, fcport->port_name);
-
-		qla24xx_post_gidpn_work(vha, fcport);
+		if (N2N_TOPO(vha->hw))
+			qla_chk_n2n_b4_login(vha, fcport);
+		else
+			qla24xx_post_gidpn_work(vha, fcport);
 		break;
 
 	case DSC_LOGIN_COMPLETE:
@@ -1196,8 +1224,10 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 		return;
 
 	if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
-		if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline))
+		if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) {
+			set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 			return;
+		}
 	}
 
 	if (fcport->flags & FCF_ASYNC_SENT) {
@@ -4473,6 +4503,21 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
 
 	} else if (ha->current_topology == ISP_CFG_N) {
 		clear_bit(RSCN_UPDATE, &flags);
+		if (ha->flags.rida_fmt2) {
+			/* With Rida Format 2, the login is already triggered.
+			 * We know who is on the other side of the wire.
+			 * No need to login to do login to find out or drop into
+			 * qla2x00_configure_local_loop().
+			 */
+			clear_bit(LOCAL_LOOP_UPDATE, &flags);
+			set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+		} else {
+			if (qla_tgt_mode_enabled(vha)) {
+				/* allow the other side to start the login */
+				clear_bit(LOCAL_LOOP_UPDATE, &flags);
+				set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+			}
+		}
 	} else if (ha->current_topology == ISP_CFG_NL) {
 		clear_bit(RSCN_UPDATE, &flags);
 		set_bit(LOCAL_LOOP_UPDATE, &flags);
@@ -4701,6 +4746,10 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 	    (uint8_t *)ha->gid_list,
 	    entries * sizeof(struct gid_list_info));
 
+	list_for_each_entry(fcport, &vha->vp_fcports, list) {
+		fcport->scan_state = QLA_FCPORT_SCAN;
+	}
+
 	/* Allocate temporary fcport for any new fcports discovered. */
 	new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 	if (new_fcport == NULL) {
@@ -4711,22 +4760,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 	}
 	new_fcport->flags &= ~FCF_FABRIC_DEVICE;
 
-	/*
-	 * Mark local devices that were present with FCF_DEVICE_LOST for now.
-	 */
-	list_for_each_entry(fcport, &vha->vp_fcports, list) {
-		if (atomic_read(&fcport->state) == FCS_ONLINE &&
-		    fcport->port_type != FCT_BROADCAST &&
-		    (fcport->flags & FCF_FABRIC_DEVICE) == 0) {
-
-			ql_dbg(ql_dbg_disc, vha, 0x2096,
-			    "Marking port lost loop_id=0x%04x.\n",
-			    fcport->loop_id);
-
-			qla2x00_mark_device_lost(vha, fcport, 0, 0);
-		}
-	}
-
 	/* Inititae N2N login. */
 	if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
 		rval = qla24xx_n2n_handle_login(vha, new_fcport);
@@ -4769,6 +4802,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 		new_fcport->d_id.b.area = area;
 		new_fcport->d_id.b.al_pa = al_pa;
 		new_fcport->loop_id = loop_id;
+		new_fcport->scan_state = QLA_FCPORT_FOUND;
 
 		rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
 		if (rval2 != QLA_SUCCESS) {
@@ -4800,13 +4834,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 			fcport->d_id.b24 = new_fcport->d_id.b24;
 			memcpy(fcport->node_name, new_fcport->node_name,
 			    WWN_SIZE);
-
-			if (!fcport->login_succ) {
-				vha->fcport_count++;
-				fcport->login_succ = 1;
-				fcport->disc_state = DSC_LOGIN_COMPLETE;
-			}
-
+			fcport->scan_state = QLA_FCPORT_FOUND;
 			found++;
 			break;
 		}
@@ -4817,11 +4845,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 
 			/* Allocate a new replacement fcport. */
 			fcport = new_fcport;
-			if (!fcport->login_succ) {
-				vha->fcport_count++;
-				fcport->login_succ = 1;
-				fcport->disc_state = DSC_LOGIN_COMPLETE;
-			}
 
 			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
@@ -4842,11 +4865,39 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 		/* Base iIDMA settings on HBA port speed. */
 		fcport->fp_speed = ha->link_data_rate;
 
-		qla2x00_update_fcport(vha, fcport);
-
 		found_devs++;
 	}
 
+	list_for_each_entry(fcport, &vha->vp_fcports, list) {
+		if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+			break;
+
+		if (fcport->scan_state == QLA_FCPORT_SCAN) {
+			if ((qla_dual_mode_enabled(vha) ||
+			    qla_ini_mode_enabled(vha)) &&
+			    atomic_read(&fcport->state) == FCS_ONLINE) {
+				qla2x00_mark_device_lost(vha, fcport,
+					ql2xplogiabsentdevice, 0);
+				if (fcport->loop_id != FC_NO_LOOP_ID &&
+				    (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
+				    fcport->port_type != FCT_INITIATOR &&
+				    fcport->port_type != FCT_BROADCAST) {
+					ql_dbg(ql_dbg_disc, vha, 0x20f0,
+					    "%s %d %8phC post del sess\n",
+					    __func__, __LINE__,
+					    fcport->port_name);
+
+					qlt_schedule_sess_for_deletion_lock
+						(fcport);
+					continue;
+				}
+			}
+		}
+
+		if (fcport->scan_state == QLA_FCPORT_FOUND)
+			qla24xx_fcport_handle_login(vha, fcport);
+	}
+
 cleanup_allocation:
 	kfree(new_fcport);
 
@@ -6154,6 +6205,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
 	if (!(IS_P3P_TYPE(ha)))
 		ha->isp_ops->reset_chip(vha);
 
+	SAVE_TOPO(ha);
+	ha->flags.rida_fmt2 = 0;
 	ha->flags.n2n_ae = 0;
 	ha->flags.lip_ae = 0;
 	ha->current_topology = 0;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 7ae8d4d22952..f02c98b3e8a7 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -809,6 +809,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		break;
 
 	case MBA_LOOP_DOWN:		/* Loop Down Event */
+		SAVE_TOPO(ha);
 		ha->flags.n2n_ae = 0;
 		ha->flags.lip_ae = 0;
 		ha->current_topology = 0;
@@ -922,7 +923,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
 		set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
 
-		ha->flags.gpsc_supported = 1;
 		vha->flags.management_server_logged_in = 0;
 		break;
 
@@ -1060,8 +1060,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		 */
 		atomic_set(&vha->loop_state, LOOP_UP);
 
-		qla2x00_mark_all_devices_lost(vha, 1);
-
 		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
 		set_bit(VP_CONFIG_OK, &vha->vp_flags);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 0c8ad7b31294..acf6c7c0f2c8 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3733,6 +3733,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 	unsigned long   flags;
 	int found;
 	port_id_t id;
+	struct fc_port *fcport;
 
 	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6,
 	    "Entered %s.\n", __func__);
@@ -3755,7 +3756,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 		    "Primary port id %02x%02x%02x.\n",
 		    rptid_entry->port_id[2], rptid_entry->port_id[1],
 		    rptid_entry->port_id[0]);
-
+		ha->current_topology = ISP_CFG_NL;
 		qlt_update_host_map(vha, id);
 
 	} else if (rptid_entry->format == 1) {
@@ -3799,6 +3800,8 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 			return;
 		}
 
+		ha->flags.gpsc_supported = 1;
+		ha->current_topology = ISP_CFG_F;
 		/* buffer to buffer credit flag */
 		vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
 
@@ -3864,6 +3867,8 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 		    rptid_entry->u.f2.port_name);
 
 		/* N2N.  direct connect */
+		ha->current_topology = ISP_CFG_N;
+		ha->flags.rida_fmt2 = 1;
 		vha->d_id.b.domain = rptid_entry->port_id[2];
 		vha->d_id.b.area = rptid_entry->port_id[1];
 		vha->d_id.b.al_pa = rptid_entry->port_id[0];
@@ -3871,6 +3876,37 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 		spin_lock_irqsave(&ha->vport_slock, flags);
 		qlt_update_vp_map(vha, SET_AL_PA);
 		spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+		list_for_each_entry(fcport, &vha->vp_fcports, list) {
+			fcport->scan_state = QLA_FCPORT_SCAN;
+		}
+
+		fcport = qla2x00_find_fcport_by_wwpn(vha,
+		    rptid_entry->u.f2.port_name, 1);
+
+		if (fcport) {
+			fcport->plogi_nack_done_deadline = jiffies + HZ;
+			fcport->scan_state = QLA_FCPORT_FOUND;
+			switch (fcport->disc_state) {
+			case DSC_DELETED:
+				ql_dbg(ql_dbg_disc, vha, 0x210d,
+				    "%s %d %8phC login\n",
+				    __func__, __LINE__, fcport->port_name);
+				qla24xx_fcport_handle_login(vha, fcport);
+				break;
+			case DSC_DELETE_PEND:
+				break;
+			default:
+				qlt_schedule_sess_for_deletion_lock(fcport);
+				break;
+			}
+		} else {
+			id.b.al_pa  = rptid_entry->u.f2.remote_nport_id[0];
+			id.b.area   = rptid_entry->u.f2.remote_nport_id[1];
+			id.b.domain = rptid_entry->u.f2.remote_nport_id[2];
+			qla24xx_post_newsess_work(vha, &id,
+			    rptid_entry->u.f2.port_name, NULL);
+		}
 	}
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 13550a8584ca..4ba249b9921d 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4750,6 +4750,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 	    (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
 	uint8_t free_fcport = 0;
 
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "%s %d %8phC enter\n",
+	    __func__, __LINE__, e->u.new_sess.port_name);
+
 	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 	fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
 	if (fcport) {
@@ -4811,7 +4815,31 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
 	if (fcport) {
+		if (N2N_TOPO(vha->hw))
+			fcport->flags &= ~FCF_FABRIC_DEVICE;
+
 		if (pla) {
+			if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) {
+				u16 wd3_lo;
+
+				fcport->fw_login_state = DSC_LS_PRLI_PEND;
+				fcport->local = 0;
+				fcport->loop_id =
+					le16_to_cpu(
+					    pla->iocb.u.isp24.nport_handle);
+				fcport->fw_login_state = DSC_LS_PRLI_PEND;
+				wd3_lo =
+				    le16_to_cpu(
+					pla->iocb.u.isp24.u.prli.wd3_lo);
+
+				if (wd3_lo & BIT_7)
+					fcport->conf_compl_supported = 1;
+
+				if ((wd3_lo & BIT_4) == 0)
+					fcport->port_type = FCT_INITIATOR;
+				else
+					fcport->port_type = FCT_TARGET;
+			}
 			qlt_plogi_ack_unref(vha, pla);
 		} else {
 			spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
@@ -4974,14 +5002,13 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 	struct event_arg ea;
 
 	list_for_each_entry(fcport, &vha->vp_fcports, list) {
-	/*
-	 * If the port is not ONLINE then try to login
-	 * to it if we haven't run out of retries.
-	 */
+		/*
+		 * If the port is not ONLINE then try to login
+		 * to it if we haven't run out of retries.
+		 */
 		if (atomic_read(&fcport->state) != FCS_ONLINE &&
 		    fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
-
-			if (fcport->flags & FCF_FABRIC_DEVICE) {
+			if (vha->hw->current_topology != ISP_CFG_NL) {
 				ql_dbg(ql_dbg_disc, fcport->vha, 0x2108,
 				    "%s %8phC DS %d LS %d\n", __func__,
 				    fcport->port_name, fcport->disc_state,
@@ -4990,7 +5017,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 				ea.event = FCME_RELOGIN;
 				ea.fcport = fcport;
 				qla2x00_fcport_event_handler(vha, &ea);
-			} else {
+			} else if (vha->hw->current_topology == ISP_CFG_NL) {
 				fcport->login_retry--;
 				status = qla2x00_local_device_login(vha,
 								fcport);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index eaa43d3d5a91..71be1a95ba86 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -607,7 +607,7 @@ void qla2x00_async_nack_sp_done(void *s, int res)
 				    __func__, __LINE__,
 				    sp->fcport->port_name,
 				    vha->fcport_count);
-
+				sp->fcport->disc_state = DSC_UPD_FCPORT;
 				qla24xx_post_upd_fcport_work(vha, sp->fcport);
 			} else {
 				ql_dbg(ql_dbg_disc, vha, 0x20f5,
@@ -862,7 +862,10 @@ void qlt_plogi_ack_unref(struct scsi_qla_host *vha,
 
 	fcport->loop_id = loop_id;
 	fcport->d_id = port_id;
-	qla24xx_post_nack_work(vha, fcport, iocb, SRB_NACK_PLOGI);
+	if (iocb->u.isp24.status_subcode == ELS_PLOGI)
+		qla24xx_post_nack_work(vha, fcport, iocb, SRB_NACK_PLOGI);
+	else
+		qla24xx_post_nack_work(vha, fcport, iocb, SRB_NACK_PRLI);
 
 	list_for_each_entry(fcport, &vha->vp_fcports, list) {
 		if (fcport->plogi_link[QLT_PLOGI_LINK_SAME_WWN] == pla)
@@ -968,6 +971,8 @@ static void qlt_free_session_done(struct work_struct *work)
 	bool logout_started = false;
 	struct event_arg ea;
 	scsi_qla_host_t *base_vha;
+	struct qlt_plogi_ack_t *own =
+		sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
 
 	ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084,
 		"%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
@@ -989,13 +994,28 @@ static void qlt_free_session_done(struct work_struct *work)
 		if (sess->logout_on_delete && sess->loop_id != FC_NO_LOOP_ID) {
 			int rc;
 
-			rc = qla2x00_post_async_logout_work(vha, sess, NULL);
-			if (rc != QLA_SUCCESS)
-				ql_log(ql_log_warn, vha, 0xf085,
-				    "Schedule logo failed sess %p rc %d\n",
-				    sess, rc);
-			else
-				logout_started = true;
+			if (!own ||
+			    (own &&
+			     (own->iocb.u.isp24.status_subcode == ELS_PLOGI))) {
+				rc = qla2x00_post_async_logout_work(vha, sess,
+				    NULL);
+				if (rc != QLA_SUCCESS)
+					ql_log(ql_log_warn, vha, 0xf085,
+					    "Schedule logo failed sess %p rc %d\n",
+					    sess, rc);
+				else
+					logout_started = true;
+			} else if (own && (own->iocb.u.isp24.status_subcode ==
+				ELS_PRLI) && ha->flags.rida_fmt2) {
+				rc = qla2x00_post_async_prlo_work(vha, sess,
+				    NULL);
+				if (rc != QLA_SUCCESS)
+					ql_log(ql_log_warn, vha, 0xf085,
+					    "Schedule PRLO failed sess %p rc %d\n",
+					    sess, rc);
+				else
+					logout_started = true;
+			}
 		}
 	}
 
@@ -1019,7 +1039,7 @@ static void qlt_free_session_done(struct work_struct *work)
 		}
 
 		ql_dbg(ql_dbg_disc, vha, 0xf087,
-		    "%s: sess %p logout completed\n",__func__, sess);
+		    "%s: sess %p logout completed\n", __func__, sess);
 	}
 
 	if (sess->logo_ack_needed) {
@@ -1055,8 +1075,6 @@ static void qlt_free_session_done(struct work_struct *work)
 	}
 
 	{
-		struct qlt_plogi_ack_t *own =
-		    sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
 		struct qlt_plogi_ack_t *con =
 		    sess->plogi_link[QLT_PLOGI_LINK_CONFLICT];
 		struct imm_ntfy_from_isp *iocb;
@@ -1216,6 +1234,8 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess,
 	ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
 	    "Scheduling sess %p for deletion\n", sess);
 
+	/* use cancel to push work element through before re-queue */
+	cancel_work_sync(&sess->del_work);
 	INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn);
 	queue_work(sess->vha->hw->wq, &sess->del_work);
 }
@@ -4688,6 +4708,130 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
 	return count;
 }
 
+static int qlt_handle_login(struct scsi_qla_host *vha,
+    struct imm_ntfy_from_isp *iocb)
+{
+	struct fc_port *sess = NULL, *conflict_sess = NULL;
+	uint64_t wwn;
+	port_id_t port_id;
+	uint16_t loop_id, wd3_lo;
+	int res = 0;
+	struct qlt_plogi_ack_t *pla;
+	unsigned long flags;
+
+	wwn = wwn_to_u64(iocb->u.isp24.port_name);
+
+	port_id.b.domain = iocb->u.isp24.port_id[2];
+	port_id.b.area   = iocb->u.isp24.port_id[1];
+	port_id.b.al_pa  = iocb->u.isp24.port_id[0];
+	port_id.b.rsvd_1 = 0;
+
+	loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
+
+	/* Mark all stale commands sitting in qla_tgt_wq for deletion */
+	abort_cmds_for_s_id(vha, &port_id);
+
+	if (wwn) {
+		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+		sess = qlt_find_sess_invalidate_other(vha, wwn,
+		    port_id, loop_id, &conflict_sess);
+		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+	}
+
+	if (IS_SW_RESV_ADDR(port_id)) {
+		res = 1;
+		goto out;
+	}
+
+	pla = qlt_plogi_ack_find_add(vha, &port_id, iocb);
+	if (!pla) {
+		qlt_send_term_imm_notif(vha, iocb, 1);
+		goto out;
+	}
+
+	if (conflict_sess) {
+		conflict_sess->login_gen++;
+		qlt_plogi_ack_link(vha, pla, conflict_sess,
+		    QLT_PLOGI_LINK_CONFLICT);
+	}
+
+	if (!sess) {
+		pla->ref_count++;
+		ql_dbg(ql_dbg_disc, vha, 0xffff,
+		    "%s %d %8phC post new sess\n",
+		    __func__, __LINE__, iocb->u.isp24.port_name);
+		qla24xx_post_newsess_work(vha, &port_id,
+		    iocb->u.isp24.port_name, pla);
+		goto out;
+	}
+
+	qlt_plogi_ack_link(vha, pla, sess, QLT_PLOGI_LINK_SAME_WWN);
+	sess->d_id = port_id;
+	sess->login_gen++;
+
+	if (iocb->u.isp24.status_subcode == ELS_PRLI) {
+		sess->fw_login_state = DSC_LS_PRLI_PEND;
+		sess->local = 0;
+		sess->loop_id = loop_id;
+		sess->d_id = port_id;
+		sess->fw_login_state = DSC_LS_PRLI_PEND;
+		wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
+
+		if (wd3_lo & BIT_7)
+			sess->conf_compl_supported = 1;
+
+		if ((wd3_lo & BIT_4) == 0)
+			sess->port_type = FCT_INITIATOR;
+		else
+			sess->port_type = FCT_TARGET;
+
+	} else
+		sess->fw_login_state = DSC_LS_PLOGI_PEND;
+
+
+	ql_dbg(ql_dbg_disc, vha, 0x20f9,
+	    "%s %d %8phC  DS %d\n",
+	    __func__, __LINE__, sess->port_name, sess->disc_state);
+
+	switch (sess->disc_state) {
+	case DSC_DELETED:
+		qlt_plogi_ack_unref(vha, pla);
+		break;
+
+	default:
+		/*
+		 * Under normal circumstances we want to release nport handle
+		 * during LOGO process to avoid nport handle leaks inside FW.
+		 * The exception is when LOGO is done while another PLOGI with
+		 * the same nport handle is waiting as might be the case here.
+		 * Note: there is always a possibily of a race where session
+		 * deletion has already started for other reasons (e.g. ACL
+		 * removal) and now PLOGI arrives:
+		 * 1. if PLOGI arrived in FW after nport handle has been freed,
+		 *    FW must have assigned this PLOGI a new/same handle and we
+		 *    can proceed ACK'ing it as usual when session deletion
+		 *    completes.
+		 * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
+		 *    bit reached it, the handle has now been released. We'll
+		 *    get an error when we ACK this PLOGI. Nothing will be sent
+		 *    back to initiator. Initiator should eventually retry
+		 *    PLOGI and situation will correct itself.
+		 */
+		sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
+		    (sess->d_id.b24 == port_id.b24));
+
+		ql_dbg(ql_dbg_disc, vha, 0x20f9,
+		    "%s %d %8phC post del sess\n",
+		    __func__, __LINE__, sess->port_name);
+
+
+		qlt_schedule_sess_for_deletion_lock(sess);
+		break;
+	}
+out:
+	return res;
+}
+
 /*
  * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
  */
@@ -4702,8 +4846,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 	uint16_t loop_id;
 	uint16_t wd3_lo;
 	int res = 0;
-	struct qlt_plogi_ack_t *pla;
-	unsigned long flags = 0;
+	unsigned long flags;
 
 	wwn = wwn_to_u64(iocb->u.isp24.port_name);
 
@@ -4726,92 +4869,27 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 	 */
 	switch (iocb->u.isp24.status_subcode) {
 	case ELS_PLOGI:
+		res = qlt_handle_login(vha, iocb);
+		break;
 
-		/* Mark all stale commands in qla_tgt_wq for deletion */
-		abort_cmds_for_s_id(vha, &port_id);
-
-		if (wwn) {
-			spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
-			sess = qlt_find_sess_invalidate_other(vha, wwn,
-				port_id, loop_id, &conflict_sess);
-			spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
-		}
-
-		if (IS_SW_RESV_ADDR(port_id)) {
-			res = 1;
-			break;
-		}
-
-		pla = qlt_plogi_ack_find_add(vha, &port_id, iocb);
-		if (!pla) {
-			qlt_send_term_imm_notif(vha, iocb, 1);
-			break;
-		}
-
-		res = 0;
-
-		if (conflict_sess) {
-			conflict_sess->login_gen++;
-			qlt_plogi_ack_link(vha, pla, conflict_sess,
-				QLT_PLOGI_LINK_CONFLICT);
-		}
-
-		if (!sess) {
-			pla->ref_count++;
-			qla24xx_post_newsess_work(vha, &port_id,
-				iocb->u.isp24.port_name, pla);
-			res = 0;
-			break;
-		}
-
-		qlt_plogi_ack_link(vha, pla, sess, QLT_PLOGI_LINK_SAME_WWN);
-		sess->fw_login_state = DSC_LS_PLOGI_PEND;
-		sess->d_id = port_id;
-		sess->login_gen++;
-
-		ql_dbg(ql_dbg_disc, vha, 0x20f9,
-		    "%s %d %8phC  DS %d\n",
-		    __func__, __LINE__, sess->port_name, sess->disc_state);
-
-		switch (sess->disc_state) {
-		case DSC_DELETED:
-			qlt_plogi_ack_unref(vha, pla);
-			break;
-
-		default:
-			/*
-			 * Under normal circumstances we want to release nport handle
-			 * during LOGO process to avoid nport handle leaks inside FW.
-			 * The exception is when LOGO is done while another PLOGI with
-			 * the same nport handle is waiting as might be the case here.
-			 * Note: there is always a possibily of a race where session
-			 * deletion has already started for other reasons (e.g. ACL
-			 * removal) and now PLOGI arrives:
-			 * 1. if PLOGI arrived in FW after nport handle has been freed,
-			 *    FW must have assigned this PLOGI a new/same handle and we
-			 *    can proceed ACK'ing it as usual when session deletion
-			 *    completes.
-			 * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
-			 *    bit reached it, the handle has now been released. We'll
-			 *    get an error when we ACK this PLOGI. Nothing will be sent
-			 *    back to initiator. Initiator should eventually retry
-			 *    PLOGI and situation will correct itself.
-			 */
-			sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
-			   (sess->d_id.b24 == port_id.b24));
-
-			ql_dbg(ql_dbg_disc, vha, 0x20f9,
-			    "%s %d %8phC post del sess\n",
-			    __func__, __LINE__, sess->port_name);
+	case ELS_PRLI:
+		if (N2N_TOPO(ha)) {
+			sess = qla2x00_find_fcport_by_wwpn(vha,
+			    iocb->u.isp24.port_name, 1);
 
+			if (sess && sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]) {
+				ql_dbg(ql_dbg_disc, vha, 0xffff,
+				    "%s %d %8phC Term PRLI due to PLOGI ACK not completed\n",
+				    __func__, __LINE__,
+				    iocb->u.isp24.port_name);
+				qlt_send_term_imm_notif(vha, iocb, 1);
+				break;
+			}
 
-			qlt_schedule_sess_for_deletion_lock(sess);
+			res = qlt_handle_login(vha, iocb);
 			break;
 		}
 
-		break;
-
-	case ELS_PRLI:
 		wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
 
 		if (wwn) {
@@ -4988,6 +5066,10 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 		break;
 	}
 
+	ql_dbg(ql_dbg_disc, vha, 0xf026,
+	    "qla_target(%d): Exit ELS opcode: 0x%02x res %d\n",
+	    vha->vp_idx, iocb->u.isp24.status_subcode, res);
+
 	return res;
 }
 
@@ -6647,6 +6729,7 @@ void
 qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
 {
 	struct qla_hw_data *ha = vha->hw;
+	u32 tmp;
 
 	if (!QLA_TGT_MODE_ENABLED())
 		return;
@@ -6698,6 +6781,14 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
 		nv->firmware_options_1 &= cpu_to_le32(~BIT_15);
 		/* Enable target PRLI control */
 		nv->firmware_options_2 |= cpu_to_le32(BIT_14);
+
+		if (IS_QLA25XX(ha)) {
+			/* Change Loop-prefer to Pt-Pt */
+			tmp = ~(BIT_4|BIT_5|BIT_6);
+			nv->firmware_options_2 &= cpu_to_le32(tmp);
+			tmp = P2P << 4;
+			nv->firmware_options_2 |= cpu_to_le32(tmp);
+		}
 	} else {
 		if (ha->tgt.saved_set) {
 			nv->exchange_count = ha->tgt.saved_exchange_count;
@@ -6752,6 +6843,7 @@ void
 qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
 {
 	struct qla_hw_data *ha = vha->hw;
+	u32 tmp;
 
 	if (!QLA_TGT_MODE_ENABLED())
 		return;
@@ -6802,6 +6894,12 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
 		nv->host_p &= cpu_to_le32(~BIT_10);
 		/* Enable target PRLI control */
 		nv->firmware_options_2 |= cpu_to_le32(BIT_14);
+
+		/* Change Loop-prefer to Pt-Pt */
+		tmp = ~(BIT_4|BIT_5|BIT_6);
+		nv->firmware_options_2 &= cpu_to_le32(tmp);
+		tmp = P2P << 4;
+		nv->firmware_options_2 |= cpu_to_le32(tmp);
 	} else {
 		if (ha->tgt.saved_set) {
 			nv->exchange_count = ha->tgt.saved_exchange_count;
-- 
2.12.0

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

* [PATCH 20/43] qla2xxx: Use known NPort ID for Management Server login
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (18 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 19/43] qla2xxx: Fix session cleanup for N2N Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 21/43] qla2xxx: Remove calling cancel_work_sync() Himanshu Madhani
                   ` (22 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h | 4 ++--
 drivers/scsi/qla2xxx/qla_mid.c | 2 +-
 drivers/scsi/qla2xxx/qla_os.c  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 9fcc0a5ff8df..749f3e457346 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -246,8 +246,8 @@
  * There is no correspondence between an N-PORT id and an AL_PA.  Therefore the
  * valid range of an N-PORT id is 0 through 0x7ef.
  */
-#define NPH_LAST_HANDLE		0x7ef
-#define NPH_MGMT_SERVER		0x7fa		/*  FFFFFA */
+#define NPH_LAST_HANDLE		0x7ee
+#define NPH_MGMT_SERVER		0x7ef		/*  FFFFEF */
 #define NPH_SNS			0x7fc		/*  FFFFFC */
 #define NPH_FABRIC_CONTROLLER	0x7fd		/*  FFFFFD */
 #define NPH_F_PORT		0x7fe		/*  FFFFFE */
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index b2fda398a098..a823fa6b7060 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -477,7 +477,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
 		    "Couldn't allocate vp_id.\n");
 		goto create_vhost_failed;
 	}
-	vha->mgmt_svr_loop_id = 10 + vha->vp_idx;
+	vha->mgmt_svr_loop_id = NPH_MGMT_SERVER;
 
 	vha->dpc_flags = 0L;
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4ba249b9921d..4e7763848d81 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3036,7 +3036,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	host = base_vha->host;
 	base_vha->req = req;
 	if (IS_QLA2XXX_MIDTYPE(ha))
-		base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
+		base_vha->mgmt_svr_loop_id = NPH_MGMT_SERVER;
 	else
 		base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
 						base_vha->vp_idx;
-- 
2.12.0

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

* [PATCH 21/43] qla2xxx: Remove calling cancel_work_sync()
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (19 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 20/43] qla2xxx: Use known NPort ID for Management Server login Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 16:56   ` Bart Van Assche
  2017-12-20  6:56 ` [PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery Himanshu Madhani
                   ` (21 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Sawan Chandak <sawan.chandak@cavium.com>

This is blocking call and issue is seen, when called in interrupt context.

__cancel_work_timer+0x140/0x210
? ql_dbg+0xcb/0x110 [qla2xxx]
cancel_work_sync+0x10/0x20
qlt_schedule_sess_for_deletion+0x89/0x170 [qla2xxx]
qla24xx_handle_gpnid_event+0x146/0x4a0 [qla2xxx]
qla2x00_fcport_event_handler+0x14b/0x290 [qla2xxx]
qla2x00_async_gpnid_sp_done+0x118/0x240 [qla2xxx]
qla24xx_els_ct_entry.isra.15+0x1df/0x2b0 [qla2xxx]
? qla24xx_msix_rsp_q+0x39/0xf0 [qla2xxx]
qla24xx_process_response_queue+0xae/0x270 [qla2xxx]
qla24xx_msix_rsp_q+0x8a/0xf0 [qla2xxx]
__handle_irq_event_percpu+0x3c/0x350
handle_irq_event_percpu+0x32/0x80
handle_irq_event+0x39/0x60
handle_edge_irq+0x8c/0x140
handle_irq+0xab/0x130
? _local_bh_enable+0x21/0x50
do_IRQ+0x5e/0x120
common_interrupt+0x9d/0x9d
RIP: 0010:cpuidle_enter_state+0xe9/0x320

Signed-off-by: Sawan Chandak <sawan.chandak@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_target.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 71be1a95ba86..002fe05dd344 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1234,8 +1234,6 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess,
 	ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
 	    "Scheduling sess %p for deletion\n", sess);
 
-	/* use cancel to push work element through before re-queue */
-	cancel_work_sync(&sess->del_work);
 	INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn);
 	queue_work(sess->vha->hw->wq, &sess->del_work);
 }
-- 
2.12.0

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

* [PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (20 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 21/43] qla2xxx: Remove calling cancel_work_sync() Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20 18:09   ` Ewan D. Milne
  2017-12-20  6:56 ` [PATCH 23/43] qla2xxx: Add lock protection around host lookup Himanshu Madhani
                   ` (20 subsequent siblings)
  42 siblings, 1 reply; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

- add "async" gpn_ft, gnn_ft, gfpn_id, gnn_id switch commands.
- For 8G and newer adapters, use async commands when it comes to
fabric scan to reduce bottle neck.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_attr.c   |   2 +
 drivers/scsi/qla2xxx/qla_def.h    |  73 +++-
 drivers/scsi/qla2xxx/qla_gbl.h    |  17 +-
 drivers/scsi/qla2xxx/qla_gs.c     | 711 +++++++++++++++++++++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_init.c   | 309 +++++++++++------
 drivers/scsi/qla2xxx/qla_mbx.c    |   5 +-
 drivers/scsi/qla2xxx/qla_os.c     |  47 ++-
 drivers/scsi/qla2xxx/qla_target.c |  62 +++-
 drivers/scsi/qla2xxx/qla_target.h |   2 +-
 9 files changed, 1105 insertions(+), 123 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 9ce28c4f9812..b360df9936ff 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2170,6 +2170,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
 	dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
 	    vha->gnl.ldma);
 
+	vfree(vha->scan.l);
+
 	if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
 		if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
 			ql_log(ql_log_warn, vha, 0x7087,
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 749f3e457346..3042697b92ae 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -490,6 +490,7 @@ enum {
 	SPCN_GPSC,
 	SPCN_GPNID,
 	SPCN_GPNFT,
+	SPCN_GNNFT,
 	SPCN_GNNID,
 	SPCN_GFPNID,
 	SPCN_LOGIN,
@@ -2315,11 +2316,13 @@ struct ct_sns_desc {
 
 enum discovery_state {
 	DSC_DELETED,
+	DSC_GNN_ID,
 	DSC_GID_PN,
 	DSC_GNL,
 	DSC_LOGIN_PEND,
 	DSC_LOGIN_FAILED,
 	DSC_GPDB,
+	DSC_GFPN_ID,
 	DSC_GPSC,
 	DSC_UPD_FCPORT,
 	DSC_LOGIN_COMPLETE,
@@ -2349,8 +2352,9 @@ enum fcport_mgt_event {
 	FCME_GPDB_DONE,
 	FCME_GPNID_DONE,
 	FCME_GFFID_DONE,
-	FCME_DELETE_DONE,
 	FCME_ADISC_DONE,
+	FCME_GNNID_DONE,
+	FCME_GFPNID_DONE,
 };
 
 enum rscn_addr_format {
@@ -2383,6 +2387,7 @@ typedef struct fc_port {
 	unsigned int login_pause:1;
 	unsigned int login_succ:1;
 	unsigned int query:1;
+	unsigned int id_changed:1;
 
 	struct work_struct nvme_del_work;
 	struct completion nvme_del_done;
@@ -2530,6 +2535,11 @@ static const char * const port_state_str[] = {
 #define	GA_NXT_REQ_SIZE	(16 + 4)
 #define	GA_NXT_RSP_SIZE	(16 + 620)
 
+#define	GPN_FT_CMD	0x172
+#define	GPN_FT_REQ_SIZE	(16 + 4)
+#define	GNN_FT_CMD	0x173
+#define	GNN_FT_REQ_SIZE	(16 + 4)
+
 #define	GID_PT_CMD	0x1A1
 #define	GID_PT_REQ_SIZE	(16 + 4)
 
@@ -2785,6 +2795,13 @@ struct ct_sns_req {
 		} port_id;
 
 		struct {
+			uint8_t reserved;
+			uint8_t domain;
+			uint8_t area;
+			uint8_t port_type;
+		} gpn_ft;
+
+		struct {
 			uint8_t port_type;
 			uint8_t domain;
 			uint8_t area;
@@ -2897,6 +2914,27 @@ struct ct_sns_gid_pt_data {
 	uint8_t port_id[3];
 };
 
+/* It's the same for both GPN_FT and GNN_FT */
+struct ct_sns_gpnft_rsp {
+	struct {
+		struct ct_cmd_hdr header;
+		uint16_t response;
+		uint16_t residual;
+		uint8_t fragment_id;
+		uint8_t reason_code;
+		uint8_t explanation_code;
+		uint8_t vendor_unique;
+	};
+	/* Assume the largest number of targets for the union */
+	struct ct_sns_gpn_ft_data {
+		u8 control_byte;
+		u8 port_id[3];
+		u32 reserved;
+		u8 port_name[8];
+	} entries[1];
+};
+
+/* CT command response */
 struct ct_sns_rsp {
 	struct ct_rsp_hdr header;
 
@@ -2972,6 +3010,24 @@ struct ct_sns_pkt {
 	} p;
 };
 
+struct ct_sns_gpnft_pkt {
+	union {
+		struct ct_sns_req req;
+		struct ct_sns_gpnft_rsp rsp;
+	} p;
+};
+
+struct fab_scan_rp {
+	port_id_t id;
+	u8 port_name[8];
+	u8 node_name[8];
+};
+
+struct fab_scan {
+	struct fab_scan_rp *l;
+	u32 size;
+};
+
 /*
  * SNS command structures -- for 2200 compatibility.
  */
@@ -3189,6 +3245,11 @@ enum qla_work_type {
 	QLA_EVT_RELOGIN,
 	QLA_EVT_ASYNC_PRLO,
 	QLA_EVT_ASYNC_PRLO_DONE,
+	QLA_EVT_GPNFT,
+	QLA_EVT_GPNFT_DONE,
+	QLA_EVT_GNNFT_DONE,
+	QLA_EVT_GNNID,
+	QLA_EVT_GFPNID,
 };
 
 
@@ -3230,7 +3291,9 @@ struct qla_work_evt {
 		struct {
 			port_id_t id;
 			u8 port_name[8];
+			u8 node_name[8];
 			void *pla;
+			u8 fc4_type;
 		} new_sess;
 		struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
 			fc_port_t *fcport;
@@ -3241,6 +3304,9 @@ struct qla_work_evt {
 			u8 iocb[IOCB_SIZE];
 			int type;
 		} nack;
+		struct {
+			u8 fc4_type;
+		} gpnft;
 	 } u;
 };
 
@@ -3796,6 +3862,8 @@ struct qla_hw_data {
 	(IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
 #define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
 	(IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\
+	IS_QLA83XX(ha) || IS_QLA27XX(ha))
 
 	/* HBA serial number */
 	uint8_t		serial0;
@@ -3878,7 +3946,7 @@ struct qla_hw_data {
 	int		exchoffld_size;
 	int 		exchoffld_count;
 
-	void		*swl;
+	void            *swl;
 
 	/* These are used by mailbox operations. */
 	uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
@@ -4340,6 +4408,7 @@ typedef struct scsi_qla_host {
 	uint8_t n2n_port_name[WWN_SIZE];
 	uint16_t	n2n_id;
 	struct list_head gpnid_list;
+	struct fab_scan scan;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2e0907994579..43799e8dc68a 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -105,8 +105,8 @@ int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
 int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
 	struct imm_ntfy_from_isp *, int);
-int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
-    void *);
+int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*,
+    void *, u8);
 int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_detect_sfp(scsi_qla_host_t *vha);
 int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
@@ -655,10 +655,21 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
 
 int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
+void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *);
 int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
-void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
+void qla24xx_handle_gffid_event(scsi_qla_host_t *, struct event_arg *);
 int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport);
 const char *sp_to_str(uint16_t);
+int qla24xx_async_gpnft(scsi_qla_host_t *, u8);
+void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *);
+void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *);
+int qla24xx_async_gnnid(scsi_qla_host_t *, fc_port_t *);
+void qla24xx_handle_gnnid_event(scsi_qla_host_t *, struct event_arg *);
+int qla24xx_post_gnnid_work(struct scsi_qla_host *, fc_port_t *);
+int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
+int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
+void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea);
+
 /*
  * Global Function Prototypes in qla_attr.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 22702a8f5ce6..643ce1578cbe 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -2841,6 +2841,9 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	    "%s %8phC login state %d\n",
 	    __func__, fcport->port_name, fcport->fw_login_state);
 
+	if (fcport->disc_state == DSC_DELETE_PEND)
+		return;
+
 	if (ea->sp->gen2 != fcport->login_gen) {
 		/* PLOGI/PRLI/LOGO came in while cmd was out.*/
 		ql_dbg(ql_dbg_disc, vha, 0x201e,
@@ -2859,7 +2862,21 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 				/* cable plugged into the same place */
 				switch (vha->host->active_mode) {
 				case MODE_TARGET:
-					/* NOOP. let the other guy login to us.*/
+					if (fcport->fw_login_state ==
+					    DSC_LS_PRLI_COMP) {
+						u16 data[2];
+						/*
+						 * Late RSCN was delivered.
+						 * Remote port already login'ed.
+						 */
+						ql_dbg(ql_dbg_disc, vha, 0x201f,
+						    "%s %d %8phC post adisc\n",
+						    __func__, __LINE__,
+						    fcport->port_name);
+						data[0] = data[1] = 0;
+						qla2x00_post_async_adisc_work(
+						    vha, fcport, data);
+					}
 					break;
 				case MODE_INITIATOR:
 				case MODE_DUAL:
@@ -2885,6 +2902,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 				}
 			} else { /* fcport->d_id.b24 != ea->id.b24 */
 				fcport->d_id.b24 = ea->id.b24;
+				fcport->id_changed = 1;
 				if (fcport->deleted != QLA_SESS_DELETED) {
 					ql_dbg(ql_dbg_disc, vha, 0x2021,
 					    "%s %d %8phC post del sess\n",
@@ -3054,6 +3072,38 @@ int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 	return qla2x00_post_work(vha, e);
 }
 
+void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+	struct fc_port *fcport = ea->fcport;
+
+	ql_dbg(ql_dbg_disc, vha, 0x20d8,
+	    "%s %8phC DS %d LS %d rscn %d|%d login %d|%d lid %d\n",
+	    __func__, fcport->port_name, fcport->disc_state,
+	    fcport->fw_login_state, fcport->last_rscn_gen, fcport->rscn_gen,
+	    fcport->last_login_gen, fcport->login_gen,
+	    fcport->loop_id);
+
+	if (fcport->disc_state == DSC_DELETE_PEND)
+		return;
+
+	if (ea->sp->gen2 != fcport->login_gen) {
+		/* target side must have changed it. */
+		ql_dbg(ql_dbg_disc, vha, 0x20d3,
+		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
+		    __func__, fcport->port_name, fcport->last_rscn_gen,
+		    fcport->rscn_gen, fcport->last_login_gen,
+		    fcport->login_gen);
+		return;
+	} else if (ea->sp->gen1 != fcport->rscn_gen) {
+		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
+		    __func__, __LINE__, fcport->port_name);
+		qla24xx_post_gidpn_work(vha, fcport);
+		return;
+	}
+
+	qla24xx_post_upd_fcport_work(vha, ea->fcport);
+}
+
 static void qla24xx_async_gpsc_sp_done(void *s, int res)
 {
 	struct srb *sp = s;
@@ -3120,6 +3170,7 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
 	ea.event = FCME_GPSC_DONE;
 	ea.rc = res;
 	ea.fcport = fcport;
+	ea.sp = sp;
 	qla2x00_fcport_event_handler(vha, &ea);
 
 	sp->free(sp);
@@ -3350,7 +3401,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 			    "%s %d %8phC post new sess\n",
 			    __func__, __LINE__, ea->port_name);
 			qla24xx_post_newsess_work(vha, &ea->id,
-			    ea->port_name, NULL);
+			    ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN);
 		}
 	}
 }
@@ -3640,3 +3691,659 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	fcport->flags &= ~FCF_ASYNC_SENT;
 	return rval;
 }
+
+/* GPN_FT + GNN_FT*/
+static int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn)
+{
+	struct qla_hw_data *ha = vha->hw;
+	scsi_qla_host_t *vp;
+	unsigned long flags;
+	u64 twwn;
+	int rc = 0;
+
+	if (!ha->num_vhosts)
+		return 0;
+
+	spin_lock_irqsave(&ha->vport_slock, flags);
+	list_for_each_entry(vp, &ha->vp_list, list) {
+		twwn = wwn_to_u64(vp->port_name);
+		if (wwn == twwn) {
+			rc = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+	return rc;
+}
+
+void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
+{
+	fc_port_t *fcport;
+	u32 i, rc;
+	bool found;
+	u8 fc4type = sp->gen2;
+	struct fab_scan_rp *rp;
+
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "%s enter\n", __func__);
+
+	if (sp->gen1 != vha->hw->base_qpair->chip_reset) {
+		ql_dbg(ql_dbg_disc, vha, 0xffff,
+		    "%s scan stop due to chip reset %x/%x\n",
+		    sp->name, sp->gen1, vha->hw->base_qpair->chip_reset);
+		goto out;
+	}
+
+	rc = sp->rc;
+	if (rc) {
+		ql_dbg(ql_dbg_disc, vha, 0xffff,
+		    "GPNFT failed. FC4type %x. Rescanning.\n",
+		    fc4type);
+		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+		goto out;
+	}
+
+	list_for_each_entry(fcport, &vha->vp_fcports, list)
+		fcport->scan_state = QLA_FCPORT_SCAN;
+
+	for (i = 0; i < vha->hw->max_fibre_devices; i++) {
+		u64 wwn;
+
+		rp = &vha->scan.l[i];
+		found = false;
+
+		wwn = wwn_to_u64(rp->port_name);
+		if (wwn == 0)
+			continue;
+
+		if (!memcmp(rp->port_name, vha->port_name, WWN_SIZE))
+			continue;
+
+		/* Bypass reserved domain fields. */
+		if ((rp->id.b.domain & 0xf0) == 0xf0)
+			continue;
+
+		/* Bypass virtual ports of the same host. */
+		if (qla2x00_is_a_vp(vha, wwn))
+			continue;
+
+		list_for_each_entry(fcport, &vha->vp_fcports, list) {
+			if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))
+				continue;
+			fcport->scan_state = QLA_FCPORT_FOUND;
+			fcport->d_id.b24 = rp->id.b24;
+			found = true;
+			/*
+			 * If device was not a fabric device before.
+			 */
+			if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
+				qla2x00_clear_loop_id(fcport);
+				fcport->flags |= FCF_FABRIC_DEVICE;
+			}
+			break;
+		}
+
+		if (!found) {
+			ql_dbg(ql_dbg_disc, vha, 0xffff,
+			    "%s %d %8phC post new sess\n",
+			    __func__, __LINE__, rp->port_name);
+			qla24xx_post_newsess_work(vha, &rp->id, rp->port_name,
+			    rp->node_name, NULL, fc4type);
+		}
+	}
+
+	/*
+	 * Logout all previous fabric dev marked lost, except FCP2 devices.
+	 */
+	list_for_each_entry(fcport, &vha->vp_fcports, list) {
+		if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
+			continue;
+
+		if (fcport->scan_state == QLA_FCPORT_SCAN) {
+			if ((qla_dual_mode_enabled(vha) ||
+				qla_ini_mode_enabled(vha)) &&
+			    atomic_read(&fcport->state) == FCS_ONLINE) {
+				qla2x00_mark_device_lost(vha, fcport,
+				    ql2xplogiabsentdevice, 0);
+				if (fcport->loop_id != FC_NO_LOOP_ID &&
+				    (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
+				    fcport->port_type != FCT_INITIATOR &&
+				    fcport->port_type != FCT_BROADCAST) {
+					ql_dbg(ql_dbg_disc, vha, 0x20f0,
+					    "%s %d %8phC post del sess\n",
+					    __func__, __LINE__,
+					    fcport->port_name);
+
+					qlt_schedule_sess_for_deletion_lock
+						(fcport);
+					continue;
+				}
+			}
+		}
+
+		if (fcport->scan_state == QLA_FCPORT_FOUND)
+			qla24xx_fcport_handle_login(vha, fcport);
+	}
+
+out:
+	/* re-use gpnid_done to free resource */
+	qla24xx_async_gpnid_done(vha, sp);
+}
+
+static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
+{
+	struct srb *sp = s;
+	struct scsi_qla_host *vha = sp->vha;
+	struct qla_work_evt *e;
+	struct ct_sns_req *ct_req =
+		(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
+	struct ct_sns_gpnft_rsp *ct_rsp =
+		(struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
+	struct ct_sns_gpn_ft_data *d = &ct_rsp->entries[0];
+	struct fab_scan_rp *rp;
+	int i, j, k;
+	u16 cmd = be16_to_cpu(ct_req->command);
+
+	/* gen2 field is holding the fc4type */
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async done-%s res %x FC4Type %x\n",
+	    sp->name, res, sp->gen2);
+
+	if (!res) {
+		port_id_t id;
+		u64 wwn;
+
+		j = 0;
+		for (i = 0; i < vha->hw->max_fibre_devices; i++) {
+			d  = &ct_rsp->entries[i];
+
+			id.b.rsvd_1 = 0;
+			id.b.domain = d->port_id[0];
+			id.b.area   = d->port_id[1];
+			id.b.al_pa  = d->port_id[2];
+			wwn = wwn_to_u64(d->port_name);
+
+			if (id.b24 == 0 || wwn == 0)
+				continue;
+
+			if (cmd == GPN_FT_CMD) {
+				rp = &vha->scan.l[j];
+				rp->id = id;
+				memcpy(rp->port_name, d->port_name, 8);
+				j++;
+			} else {/* GNN_FT_CMD */
+				for (k = 0; k < vha->hw->max_fibre_devices;
+				    k++) {
+					rp = &vha->scan.l[k];
+					if (id.b24 == rp->id.b24) {
+						memcpy(rp->node_name,
+						    d->port_name, 8);
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	if (cmd == GPN_FT_CMD)
+		e = qla2x00_alloc_work(vha, QLA_EVT_GPNFT_DONE);
+	else
+		e = qla2x00_alloc_work(vha, QLA_EVT_GNNFT_DONE);
+	if (!e) {
+		/* please ignore kernel warning. Otherwise, we have mem leak. */
+		if (sp->u.iocb_cmd.u.ctarg.req) {
+			dma_free_coherent(&vha->hw->pdev->dev,
+			    sizeof(struct ct_sns_pkt),
+			    sp->u.iocb_cmd.u.ctarg.req,
+			    sp->u.iocb_cmd.u.ctarg.req_dma);
+			sp->u.iocb_cmd.u.ctarg.req = NULL;
+		}
+		if (sp->u.iocb_cmd.u.ctarg.rsp) {
+			dma_free_coherent(&vha->hw->pdev->dev,
+			    sizeof(struct ct_sns_pkt),
+			    sp->u.iocb_cmd.u.ctarg.rsp,
+			    sp->u.iocb_cmd.u.ctarg.rsp_dma);
+			sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+		}
+
+		ql_dbg(ql_dbg_disc, vha, 0xffff,
+		    "Async done-%s unable to alloc work element\n",
+		    sp->name);
+		sp->free(sp);
+		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+		return;
+	}
+
+	sp->rc = res;
+	e->u.iosb.sp = sp;
+
+	qla2x00_post_work(vha, e);
+}
+
+/*
+ * Get WWNN list for fc4_type
+ *
+ * It is assumed the same SRB is re-used from GPNFT to avoid
+ * mem free & re-alloc
+ */
+static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
+    u8 fc4_type)
+{
+	int rval = QLA_FUNCTION_FAILED;
+	struct ct_sns_req *ct_req;
+	struct ct_sns_pkt *ct_sns;
+
+	if (!vha->flags.online)
+		goto done_free_sp;
+
+	if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
+		ql_log(ql_log_warn, vha, 0xffff,
+		    "%s: req %p rsp %p are not setup\n",
+		    __func__, sp->u.iocb_cmd.u.ctarg.req,
+		    sp->u.iocb_cmd.u.ctarg.rsp);
+		WARN_ON(1);
+		goto done_free_sp;
+	}
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_GNNFT);
+	sp->gen1 = vha->hw->base_qpair->chip_reset;
+	sp->gen2 = fc4_type;
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
+	memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
+
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
+	/* CT_IU preamble  */
+	ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD,
+	    sp->u.iocb_cmd.u.ctarg.rsp_size);
+
+	/* GPN_FT req */
+	ct_req->req.gpn_ft.port_type = fc4_type;
+
+	sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_gpnft_gnnft_sp_done;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+	    sp->handle, ct_req->req.gpn_ft.port_type);
+	return rval;
+
+done_free_sp:
+	if (sp->u.iocb_cmd.u.ctarg.req) {
+		dma_free_coherent(&vha->hw->pdev->dev,
+		    sizeof(struct ct_sns_pkt),
+		    sp->u.iocb_cmd.u.ctarg.req,
+		    sp->u.iocb_cmd.u.ctarg.req_dma);
+		sp->u.iocb_cmd.u.ctarg.req = NULL;
+	}
+	if (sp->u.iocb_cmd.u.ctarg.rsp) {
+		dma_free_coherent(&vha->hw->pdev->dev,
+		    sizeof(struct ct_sns_pkt),
+		    sp->u.iocb_cmd.u.ctarg.rsp,
+		    sp->u.iocb_cmd.u.ctarg.rsp_dma);
+		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+	}
+
+	sp->free(sp);
+
+	return rval;
+} /* GNNFT */
+
+void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
+{
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "%s enter\n", __func__);
+	del_timer(&sp->u.iocb_cmd.timer);
+	qla24xx_async_gnnft(vha, sp, sp->gen2);
+}
+
+/* Get WWPN list for certain fc4_type */
+int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
+{
+	int rval = QLA_FUNCTION_FAILED;
+	struct ct_sns_req       *ct_req;
+	srb_t *sp;
+	struct ct_sns_pkt *ct_sns;
+	u32 rspsz;
+
+	if (!vha->flags.online)
+		return rval;
+
+	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+	if (!sp)
+		return rval;
+
+
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_GPNFT);
+	sp->gen1 = vha->hw->base_qpair->chip_reset;
+	sp->gen2 = fc4_type;
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.req) {
+		ql_log(ql_log_warn, vha, 0xffff,
+		    "Failed to allocate ct_sns request.\n");
+		goto done_free_sp;
+	}
+
+	rspsz = sizeof(struct ct_sns_gpnft_rsp) +
+		((vha->hw->max_fibre_devices - 1) *
+		    sizeof(struct ct_sns_gpn_ft_data));
+
+	sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(&vha->hw->pdev->dev,
+	    rspsz, &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
+		ql_log(ql_log_warn, vha, 0xffff,
+		    "Failed to allocate ct_sns request.\n");
+		goto done_free_sp;
+	}
+
+	memset(vha->scan.l, 0, vha->scan.size);
+
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
+	/* CT_IU preamble  */
+	ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
+
+	/* GPN_FT req */
+	ct_req->req.gpn_ft.port_type = fc4_type;
+
+	sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
+	sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_gpnft_gnnft_sp_done;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+	    sp->handle, ct_req->req.gpn_ft.port_type);
+	return rval;
+
+done_free_sp:
+	if (sp->u.iocb_cmd.u.ctarg.req) {
+		dma_free_coherent(&vha->hw->pdev->dev,
+		    sizeof(struct ct_sns_pkt),
+		    sp->u.iocb_cmd.u.ctarg.req,
+		    sp->u.iocb_cmd.u.ctarg.req_dma);
+		sp->u.iocb_cmd.u.ctarg.req = NULL;
+	}
+	if (sp->u.iocb_cmd.u.ctarg.rsp) {
+		dma_free_coherent(&vha->hw->pdev->dev,
+		    sizeof(struct ct_sns_pkt),
+		    sp->u.iocb_cmd.u.ctarg.rsp,
+		    sp->u.iocb_cmd.u.ctarg.rsp_dma);
+		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+	}
+
+	sp->free(sp);
+
+	return rval;
+}
+
+/* GNN_ID */
+void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+	qla24xx_post_gnl_work(vha, ea->fcport);
+}
+
+static void qla2x00_async_gnnid_sp_done(void *s, int res)
+{
+	struct srb *sp = s;
+	struct scsi_qla_host *vha = sp->vha;
+	fc_port_t *fcport = sp->fcport;
+	u8 *node_name = fcport->ct_desc.ct_sns->p.rsp.rsp.gnn_id.node_name;
+	struct event_arg ea;
+	u64 wwnn;
+
+	fcport->flags &= ~FCF_ASYNC_SENT;
+	wwnn = wwn_to_u64(node_name);
+	if (wwnn)
+		memcpy(fcport->node_name, node_name, WWN_SIZE);
+
+	memset(&ea, 0, sizeof(ea));
+	ea.fcport = fcport;
+	ea.sp = sp;
+	ea.rc = res;
+	ea.event = FCME_GNNID_DONE;
+
+	ql_dbg(ql_dbg_disc, vha, 0x204f,
+	    "Async done-%s res %x, WWPN %8phC %8phC\n",
+	    sp->name, res, fcport->port_name, fcport->node_name);
+
+	qla2x00_fcport_event_handler(vha, &ea);
+
+	sp->free(sp);
+}
+
+int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+{
+	int rval = QLA_FUNCTION_FAILED;
+	struct ct_sns_req       *ct_req;
+	srb_t *sp;
+
+	if (!vha->flags.online)
+		goto done;
+
+	fcport->flags |= FCF_ASYNC_SENT;
+	fcport->disc_state = DSC_GNN_ID;
+	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+	if (!sp)
+		goto done;
+
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_GNNID);
+	sp->gen1 = fcport->rscn_gen;
+	sp->gen2 = fcport->login_gen;
+
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	/* CT_IU preamble  */
+	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GNN_ID_CMD,
+	    GNN_ID_RSP_SIZE);
+
+	/* GNN_ID req */
+	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
+	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
+	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
+
+
+	/* req & rsp use the same buffer */
+	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
+	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
+	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
+	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
+	sp->u.iocb_cmd.u.ctarg.req_size = GNN_ID_REQ_SIZE;
+	sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_gnnid_sp_done;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
+	    sp->name, fcport->port_name,
+	    sp->handle, fcport->loop_id, fcport->d_id.b24);
+	return rval;
+
+done_free_sp:
+	sp->free(sp);
+done:
+	fcport->flags &= ~FCF_ASYNC_SENT;
+	return rval;
+}
+
+int qla24xx_post_gnnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+	struct qla_work_evt *e;
+	int ls;
+
+	ls = atomic_read(&vha->loop_state);
+	if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
+		test_bit(UNLOADING, &vha->dpc_flags))
+		return 0;
+
+	e = qla2x00_alloc_work(vha, QLA_EVT_GNNID);
+	if (!e)
+		return QLA_FUNCTION_FAILED;
+
+	e->u.fcport.fcport = fcport;
+	return qla2x00_post_work(vha, e);
+}
+
+/* GPFN_ID */
+void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+	fc_port_t *fcport = ea->fcport;
+
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "%s %d %8phC post gpsc fcp_cnt %d\n",
+	    __func__, __LINE__, fcport->port_name,
+	    vha->fcport_count);
+
+	if (fcport->disc_state == DSC_DELETE_PEND)
+		return;
+
+	if (ea->sp->gen2 != fcport->login_gen) {
+		/* target side must have changed it. */
+		ql_dbg(ql_dbg_disc, vha, 0x20d3,
+		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
+		    __func__, fcport->port_name, fcport->last_rscn_gen,
+		    fcport->rscn_gen, fcport->last_login_gen,
+		    fcport->login_gen);
+		return;
+	} else if (ea->sp->gen1 != fcport->rscn_gen) {
+		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
+		    __func__, __LINE__, fcport->port_name);
+		qla24xx_post_gidpn_work(vha, fcport);
+		return;
+	}
+
+	qla24xx_post_gpsc_work(vha, fcport);
+}
+
+static void qla2x00_async_gfpnid_sp_done(void *s, int res)
+{
+	struct srb *sp = s;
+	struct scsi_qla_host *vha = sp->vha;
+	fc_port_t *fcport = sp->fcport;
+	u8 *fpn = fcport->ct_desc.ct_sns->p.rsp.rsp.gfpn_id.port_name;
+	struct event_arg ea;
+	u64 wwn;
+
+	fcport->flags &= ~FCF_ASYNC_SENT;
+	wwn = wwn_to_u64(fpn);
+	if (wwn)
+		memcpy(fcport->fabric_port_name, fpn, WWN_SIZE);
+
+	memset(&ea, 0, sizeof(ea));
+	ea.fcport = fcport;
+	ea.sp = sp;
+	ea.rc = res;
+	ea.event = FCME_GFPNID_DONE;
+
+	ql_dbg(ql_dbg_disc, vha, 0x204f,
+	    "Async done-%s res %x, WWPN %8phC %8phC\n",
+	    sp->name, res, fcport->port_name, fcport->fabric_port_name);
+
+	qla2x00_fcport_event_handler(vha, &ea);
+
+	sp->free(sp);
+}
+
+int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+{
+	int rval = QLA_FUNCTION_FAILED;
+	struct ct_sns_req       *ct_req;
+	srb_t *sp;
+
+	if (!vha->flags.online)
+		goto done;
+
+	fcport->flags |= FCF_ASYNC_SENT;
+	fcport->disc_state = DSC_GFPN_ID;
+	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+	if (!sp)
+		goto done;
+
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_GFPNID);
+	sp->gen1 = fcport->rscn_gen;
+	sp->gen2 = fcport->login_gen;
+
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	/* CT_IU preamble  */
+	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFPN_ID_CMD,
+	    GFPN_ID_RSP_SIZE);
+
+	/* GFPN_ID req */
+	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
+	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
+	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
+
+
+	/* req & rsp use the same buffer */
+	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
+	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
+	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
+	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
+	sp->u.iocb_cmd.u.ctarg.req_size = GFPN_ID_REQ_SIZE;
+	sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_gfpnid_sp_done;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
+	    sp->name, fcport->port_name,
+	    sp->handle, fcport->loop_id, fcport->d_id.b24);
+	return rval;
+
+done_free_sp:
+	sp->free(sp);
+done:
+	fcport->flags &= ~FCF_ASYNC_SENT;
+	return rval;
+}
+
+int qla24xx_post_gfpnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+	struct qla_work_evt *e;
+	int ls;
+
+	ls = atomic_read(&vha->loop_state);
+	if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
+		test_bit(UNLOADING, &vha->dpc_flags))
+		return 0;
+
+	e = qla2x00_alloc_work(vha, QLA_EVT_GFPNID);
+	if (!e)
+		return QLA_FUNCTION_FAILED;
+
+	e->u.fcport.fcport = fcport;
+	return qla2x00_post_work(vha, e);
+}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b4a96c80853f..cdcd84278fd0 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -41,7 +41,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
     struct event_arg *);
 static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
     struct event_arg *);
-static void qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
+static void __qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
 
 /* SRB Extensions ---------------------------------------------------------- */
 
@@ -187,9 +187,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 
 	fcport->flags |= FCF_ASYNC_SENT;
 	fcport->logout_completed = 0;
-
+	fcport->disc_state = DSC_LOGIN_PEND;
 	sp->type = SRB_LOGIN_CMD;
 	sp->name = sp_to_str(SPCN_LOGIN);
+	sp->gen1 = fcport->rscn_gen;
+	sp->gen2 = fcport->login_gen;
 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
 	lio = &sp->u.iocb_cmd;
@@ -336,7 +338,36 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
 static
 void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-	qla24xx_handle_gpdb_event(vha, ea);
+	if (ea->rc) {
+		ql_dbg(ql_dbg_disc, vha, 0x2066,
+		    "%s %8phC: adisc fail: post delete\n",
+		    __func__, ea->fcport->port_name);
+		qlt_schedule_sess_for_deletion(ea->fcport, 1);
+		return;
+	}
+	ql_dbg(ql_dbg_disc, vha, 0x20d2,
+	    "%s %8phC DS %d LS %d\n", __func__, ea->fcport->port_name,
+	    ea->fcport->disc_state, ea->fcport->fw_login_state);
+
+	if (ea->fcport->disc_state == DSC_DELETE_PEND)
+		return;
+
+	if (ea->sp->gen2 != ea->fcport->login_gen) {
+		/* target side must have changed it. */
+		ql_dbg(ql_dbg_disc, vha, 0x20d3,
+		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
+		    __func__, ea->fcport->port_name, ea->fcport->last_rscn_gen,
+		    ea->fcport->rscn_gen, ea->fcport->last_login_gen,
+		    ea->fcport->login_gen);
+		return;
+	} else if (ea->sp->gen1 != ea->fcport->rscn_gen) {
+		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
+		    __func__, __LINE__, ea->fcport->port_name);
+		qla24xx_post_gidpn_work(vha, ea->fcport);
+		return;
+	}
+
+	__qla24xx_handle_gpdb_event(vha, ea);
 }
 
 static void
@@ -412,10 +443,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 	u16 i, n, found = 0, loop_id;
 	port_id_t id;
 	u64 wwn;
-	u8 opt = 0, current_login_state;
+	u16 data[2];
+	u8 current_login_state;
 
 	fcport = ea->fcport;
 
+	if (fcport->disc_state == DSC_DELETE_PEND)
+		return;
+
 	if (ea->rc) { /* rval */
 		if (fcport->login_retry == 0) {
 			fcport->login_retry = vha->hw->login_retry_count;
@@ -509,8 +544,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 			ql_dbg(ql_dbg_disc, vha, 0x20e4,
 			    "%s %d %8phC post gpdb\n",
 			    __func__, __LINE__, fcport->port_name);
-			opt = PDO_FORCE_ADISC;
-			qla24xx_post_gpdb_work(vha, fcport, opt);
+
+			if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
+				fcport->port_type = FCT_INITIATOR;
+			else
+				fcport->port_type = FCT_TARGET;
+
+			data[0] = data[1] = 0;
+			qla2x00_post_async_adisc_work(vha, fcport, data);
 			break;
 		case DSC_LS_PORT_UNAVAIL:
 		default:
@@ -575,6 +616,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 	struct get_name_list_extended *e;
 	u64 wwn;
 	struct list_head h;
+	bool found = false;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20e7,
 	    "Async done-%s res %x mb[1]=%x mb[2]=%x \n",
@@ -624,6 +666,38 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 		qla2x00_fcport_event_handler(vha, &ea);
 	}
 
+	/* create new fcport if fw has knowledge of new sessions */
+	for (i = 0; i < n; i++) {
+		port_id_t id;
+		u64 wwnn;
+
+		e = &vha->gnl.l[i];
+		wwn = wwn_to_u64(e->port_name);
+
+		found = false;
+		list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+			if (!memcmp((u8 *)&wwn, fcport->port_name,
+			    WWN_SIZE)) {
+				found = true;
+				break;
+			}
+		}
+
+		id.b.domain = e->port_id[0];
+		id.b.area = e->port_id[1];
+		id.b.al_pa = e->port_id[2];
+		id.b.rsvd_1 = 0;
+
+		if (!found && wwn && !IS_SW_RESV_ADDR(id)) {
+			ql_dbg(ql_dbg_disc, vha, 0x2065,
+			    "%s %d %8phC post new sess\n",
+			    __func__, __LINE__, (u8 *)&wwn);
+			wwnn = wwn_to_u64(e->node_name);
+			qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn,
+			    (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN);
+		}
+	}
+
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
 	sp->free(sp);
@@ -718,10 +792,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
 	struct srb *sp = s;
 	struct scsi_qla_host *vha = sp->vha;
 	struct qla_hw_data *ha = vha->hw;
-	struct port_database_24xx *pd;
 	fc_port_t *fcport = sp->fcport;
 	u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
-	int rval = QLA_SUCCESS;
 	struct event_arg ea;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20db,
@@ -730,19 +802,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
 
 	fcport->flags &= ~FCF_ASYNC_SENT;
 
-	if (res) {
-		rval = res;
-		goto gpd_error_out;
-	}
-
-	pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
-
-	rval = __qla24xx_parse_gpdb(vha, fcport, pd);
-
-gpd_error_out:
 	memset(&ea, 0, sizeof(ea));
 	ea.event = FCME_GPDB_DONE;
-	ea.rc = rval;
 	ea.fcport = fcport;
 	ea.sp = sp;
 
@@ -937,41 +998,10 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 }
 
 static
-void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
+void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-	int rval = ea->rc;
-	fc_port_t *fcport = ea->fcport;
 	unsigned long flags;
 
-	fcport->flags &= ~FCF_ASYNC_SENT;
-
-	ql_dbg(ql_dbg_disc, vha, 0x20d2,
-	    "%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
-	    fcport->disc_state, fcport->fw_login_state, rval);
-
-	if (ea->sp->gen2 != fcport->login_gen) {
-		/* target side must have changed it. */
-		ql_dbg(ql_dbg_disc, vha, 0x20d3,
-		    "%s %8phC generation changed rscn %d|%d login %d|%d \n",
-		    __func__, fcport->port_name, fcport->last_rscn_gen,
-		    fcport->rscn_gen, fcport->last_login_gen,
-		    fcport->login_gen);
-		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
-		return;
-	} else if (ea->sp->gen1 != fcport->rscn_gen) {
-		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
-		    __func__, __LINE__, fcport->port_name);
-		qla24xx_post_gidpn_work(vha, fcport);
-		return;
-	}
-
-	if (rval != QLA_SUCCESS) {
-		ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
-		    __func__, __LINE__, fcport->port_name);
-		qlt_schedule_sess_for_deletion_lock(fcport);
-		return;
-	}
-
 	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 	ea->fcport->login_gen++;
 	ea->fcport->deleted = 0;
@@ -985,32 +1015,81 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 		    !vha->hw->flags.gpsc_supported) {
 			ql_dbg(ql_dbg_disc, vha, 0x20d6,
 			    "%s %d %8phC post upd_fcport fcp_cnt %d\n",
-			    __func__, __LINE__, fcport->port_name,
+			    __func__, __LINE__,  ea->fcport->port_name,
 			    vha->fcport_count);
 
-			qla24xx_post_upd_fcport_work(vha, fcport);
+			qla24xx_post_upd_fcport_work(vha, ea->fcport);
 		} else {
-			ql_dbg(ql_dbg_disc, vha, 0x20d7,
-			    "%s %d %8phC post gpsc fcp_cnt %d\n",
-			    __func__, __LINE__, fcport->port_name,
-			    vha->fcport_count);
-
-			qla24xx_post_gpsc_work(vha, fcport);
+			if (ea->fcport->id_changed) {
+				ea->fcport->id_changed = 0;
+				ql_dbg(ql_dbg_disc, vha, 0x20d7,
+				    "%s %d %8phC post gfpnid fcp_cnt %d\n",
+				    __func__, __LINE__, ea->fcport->port_name,
+				    vha->fcport_count);
+				qla24xx_post_gfpnid_work(vha, ea->fcport);
+			} else {
+				ql_dbg(ql_dbg_disc, vha, 0x20d7,
+				    "%s %d %8phC post gpsc fcp_cnt %d\n",
+				    __func__, __LINE__, ea->fcport->port_name,
+				    vha->fcport_count);
+				qla24xx_post_gpsc_work(vha, ea->fcport);
+			}
 		}
 	} else if (ea->fcport->login_succ) {
 		/*
 		 * We have an existing session. A late RSCN delivery
 		 * must have triggered the session to be re-validate.
-		 * session is still valid.
+		 * Session is still valid.
 		 */
 		ql_dbg(ql_dbg_disc, vha, 0x20d6,
 		    "%s %d %8phC session revalidate success\n",
-		    __func__, __LINE__, fcport->port_name);
-		fcport->disc_state = DSC_LOGIN_COMPLETE;
+		    __func__, __LINE__, ea->fcport->port_name);
+		 ea->fcport->disc_state = DSC_LOGIN_COMPLETE;
 	}
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
-} /* gpdb event */
+}
 
+static
+void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+	int rval = ea->rc;
+	fc_port_t *fcport = ea->fcport;
+	struct port_database_24xx *pd;
+	struct srb *sp = ea->sp;
+
+	pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
+
+	fcport->flags &= ~FCF_ASYNC_SENT;
+
+	ql_dbg(ql_dbg_disc, vha, 0x20d2,
+	    "%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
+	    fcport->disc_state, pd->current_login_state, rval);
+
+	if (fcport->disc_state == DSC_DELETE_PEND)
+		return;
+
+	switch (pd->current_login_state) {
+	case PDS_PRLI_COMPLETE:
+		__qla24xx_parse_gpdb(vha, fcport, pd);
+		break;
+	case PDS_PLOGI_PENDING:
+	case PDS_PLOGI_COMPLETE:
+	case PDS_PRLI_PENDING:
+	case PDS_PRLI2_PENDING:
+		ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC relogin needed\n",
+		    __func__, __LINE__, fcport->port_name);
+		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+		return;
+	case PDS_LOGO_PENDING:
+	case PDS_PORT_UNAVAILABLE:
+	default:
+		ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
+		    __func__, __LINE__, fcport->port_name);
+		qlt_schedule_sess_for_deletion_lock(fcport);
+		return;
+	}
+	__qla24xx_handle_gpdb_event(vha, ea);
+} /* gpdb event */
 
 static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
@@ -1051,21 +1130,21 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
 	u16 data[2];
-	if (fcport->login_retry == 0)
-		return 0;
-
-	if (fcport->scan_state != QLA_FCPORT_FOUND)
-		return 0;
+	u64 wwn;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20d8,
-	    "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d\n",
+	    "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d scan %d\n",
 	    __func__, fcport->port_name, fcport->disc_state,
 	    fcport->fw_login_state, fcport->login_pause, fcport->flags,
 	    fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
 	    fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
-	    fcport->loop_id);
+	    fcport->loop_id, fcport->scan_state);
 
-	fcport->login_retry--;
+	if (fcport->login_retry == 0)
+		return 0;
+
+	if (fcport->scan_state != QLA_FCPORT_FOUND)
+		return 0;
 
 	if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
 	    (fcport->fw_login_state == DSC_LS_PRLI_PEND))
@@ -1087,9 +1166,17 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 		return 0;
 	}
 
+	fcport->login_retry--;
+
 	switch (fcport->disc_state) {
 	case DSC_DELETED:
-		if (fcport->loop_id == FC_NO_LOOP_ID) {
+		wwn = wwn_to_u64(fcport->node_name);
+		if (wwn == 0) {
+			ql_dbg(ql_dbg_disc, vha, 0xffff,
+			    "%s %d %8phC post GNNID\n",
+			    __func__, __LINE__, fcport->port_name);
+			qla24xx_post_gnnid_work(vha, fcport);
+		} else if (fcport->loop_id == FC_NO_LOOP_ID) {
 			ql_dbg(ql_dbg_disc, vha, 0x20bd,
 			    "%s %d %8phC post gnl\n",
 			    __func__, __LINE__, fcport->port_name);
@@ -1160,7 +1247,7 @@ void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
 }
 
 int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
-	u8 *port_name, void *pla)
+    u8 *port_name, u8 *node_name, void *pla, u8 fc4_type)
 {
 	struct qla_work_evt *e;
 	e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
@@ -1169,37 +1256,15 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
 
 	e->u.new_sess.id = *id;
 	e->u.new_sess.pla = pla;
+	e->u.new_sess.fc4_type = fc4_type;
 	memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
+	if (node_name)
+		memcpy(e->u.new_sess.node_name, node_name, WWN_SIZE);
 
 	return qla2x00_post_work(vha, e);
 }
 
 static
-int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
-	struct event_arg *ea)
-{
-	fc_port_t *fcport = ea->fcport;
-
-	if (test_bit(UNLOADING, &vha->dpc_flags))
-		return 0;
-
-	switch (vha->host->active_mode) {
-	case MODE_INITIATOR:
-	case MODE_DUAL:
-		if (fcport->scan_state == QLA_FCPORT_FOUND)
-			qla24xx_fcport_handle_login(vha, fcport);
-		break;
-
-	case MODE_TARGET:
-	default:
-		/* no-op */
-		break;
-	}
-
-	return 0;
-}
-
-static
 void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 	struct event_arg *ea)
 {
@@ -1264,6 +1329,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 	case FCME_GIDPN_DONE:
 	case FCME_GPSC_DONE:
 	case FCME_GPNID_DONE:
+	case FCME_GNNID_DONE:
 		if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
 		    test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
 			return;
@@ -1340,7 +1406,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 		qla24xx_handle_gnl_done_event(vha, ea);
 		break;
 	case FCME_GPSC_DONE:
-		qla24xx_post_upd_fcport_work(vha, ea->fcport);
+		qla24xx_handle_gpsc_event(vha, ea);
 		break;
 	case FCME_PLOGI_DONE:	/* Initiator side sent LLIOCB */
 		qla24xx_handle_plogi_done_event(vha, ea);
@@ -1357,12 +1423,15 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 	case FCME_GFFID_DONE:
 		qla24xx_handle_gffid_event(vha, ea);
 		break;
-	case FCME_DELETE_DONE:
-		qla24xx_handle_delete_done_event(vha, ea);
-		break;
 	case FCME_ADISC_DONE:
 		qla24xx_handle_adisc_event(vha, ea);
 		break;
+	case FCME_GNNID_DONE:
+		qla24xx_handle_gnnid_event(vha, ea);
+		break;
+	case FCME_GFPNID_DONE:
+		qla24xx_handle_gfpnid_event(vha, ea);
+		break;
 	default:
 		BUG_ON(1);
 		break;
@@ -1571,6 +1640,33 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 	u16 lid;
 	struct fc_port *conflict_fcport;
 	unsigned long flags;
+	struct fc_port *fcport = ea->fcport;
+
+	if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
+	    (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
+		ql_dbg(ql_dbg_disc, vha, 0x20ea,
+		    "%s %d %8phC Remote is trying to login\n",
+		    __func__, __LINE__, fcport->port_name);
+		return;
+	}
+
+	if (fcport->disc_state == DSC_DELETE_PEND)
+		return;
+
+	if (ea->sp->gen2 != fcport->login_gen) {
+		/* target side must have changed it. */
+		ql_dbg(ql_dbg_disc, vha, 0x20d3,
+		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
+		    __func__, fcport->port_name, fcport->last_rscn_gen,
+		    fcport->rscn_gen, fcport->last_login_gen,
+		    fcport->login_gen);
+		return;
+	} else if (ea->sp->gen1 != fcport->rscn_gen) {
+		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
+		    __func__, __LINE__, fcport->port_name);
+		qla24xx_post_gidpn_work(vha, fcport);
+		return;
+	}
 
 	switch (ea->data[0]) {
 	case MBS_COMMAND_COMPLETE:
@@ -5163,7 +5259,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
 		 * will be newer than discovery_gen. */
 		qlt_do_generation_tick(vha, &discovery_gen);
 
-		rval = qla2x00_find_all_fabric_devs(vha);
+		if (USE_ASYNC_SCAN(ha)) {
+			rval = QLA_SUCCESS;
+			rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI);
+			if (rval)
+				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+		} else  {
+			rval = qla2x00_find_all_fabric_devs(vha);
+		}
 		if (rval != QLA_SUCCESS)
 			break;
 	} while (0);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index acf6c7c0f2c8..68587e631f60 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3905,7 +3905,10 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 			id.b.area   = rptid_entry->u.f2.remote_nport_id[1];
 			id.b.domain = rptid_entry->u.f2.remote_nport_id[2];
 			qla24xx_post_newsess_work(vha, &id,
-			    rptid_entry->u.f2.port_name, NULL);
+			    rptid_entry->u.f2.port_name,
+			    rptid_entry->u.f2.node_name,
+			    NULL,
+			    FC4_TYPE_UNKNOWN);
 		}
 	}
 }
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4e7763848d81..cab39a6d9776 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3628,6 +3628,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
 	dma_free_coherent(&ha->pdev->dev,
 		base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
 
+	vfree(base_vha->scan.l);
+
 	if (IS_QLAFX00(ha))
 		qlafx00_driver_shutdown(base_vha, 20);
 
@@ -4576,6 +4578,18 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
 		return NULL;
 	}
 
+	/* todo: what about ext login? */
+	vha->scan.size = ha->max_fibre_devices * sizeof(struct fab_scan_rp);
+	vha->scan.l = vmalloc(vha->scan.size);
+	if (!vha->scan.l) {
+		ql_log(ql_log_fatal, vha, 0xd04a,
+		    "Alloc failed for scan database.\n");
+		dma_free_coherent(&ha->pdev->dev, vha->gnl.size,
+		    vha->gnl.l, vha->gnl.ldma);
+		scsi_remove_host(vha->host);
+		return NULL;
+	}
+
 	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
 	ql_dbg(ql_dbg_init, vha, 0x0041,
 	    "Allocated the host=%p hw=%p vha=%p dev_name=%s",
@@ -4749,6 +4763,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 	struct qlt_plogi_ack_t *pla =
 	    (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
 	uint8_t free_fcport = 0;
+	u64 wwn;
 
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "%s %d %8phC enter\n",
@@ -4774,9 +4789,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 		fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 		if (fcport) {
 			fcport->d_id = e->u.new_sess.id;
-			fcport->scan_state = QLA_FCPORT_FOUND;
 			fcport->flags |= FCF_FABRIC_DEVICE;
 			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
+			if (e->u.new_sess.fc4_type == FC4_TYPE_FCP_SCSI)
+				fcport->fc4_type = FC4_TYPE_FCP_SCSI;
 
 			memcpy(fcport->port_name, e->u.new_sess.port_name,
 			    WWN_SIZE);
@@ -4791,7 +4807,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 		}
 
 		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
-		/* search again to make sure one else got ahead */
+		/* search again to make sure no one else got ahead */
 		tfcp = qla2x00_find_fcport_by_wwpn(vha,
 		    e->u.new_sess.port_name, 1);
 		if (tfcp) {
@@ -4818,6 +4834,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 		if (N2N_TOPO(vha->hw))
 			fcport->flags &= ~FCF_FABRIC_DEVICE;
 
+		fcport->id_changed = 1;
+		fcport->scan_state = QLA_FCPORT_FOUND;
+		memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE);
+
 		if (pla) {
 			if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) {
 				u16 wd3_lo;
@@ -4870,7 +4890,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 				}
 			}
 			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
-			qla24xx_async_gnl(vha, fcport);
+
+			wwn = wwn_to_u64(fcport->node_name);
+
+			if (!wwn)
+				qla24xx_async_gnnid(vha, fcport);
+			else
+				qla24xx_async_gnl(vha, fcport);
 		}
 	}
 
@@ -4969,6 +4995,21 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 			qla2x00_async_prlo_done(vha, e->u.logio.fcport,
 			    e->u.logio.data);
 			break;
+		case QLA_EVT_GPNFT:
+			qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type);
+			break;
+		case QLA_EVT_GPNFT_DONE:
+			qla24xx_async_gpnft_done(vha, e->u.iosb.sp);
+			break;
+		case QLA_EVT_GNNFT_DONE:
+			qla24xx_async_gnnft_done(vha, e->u.iosb.sp);
+			break;
+		case QLA_EVT_GNNID:
+			qla24xx_async_gnnid(vha, e->u.fcport.fcport);
+			break;
+		case QLA_EVT_GFPNID:
+			qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
+			break;
 		}
 		if (e->flags & QLA_EVT_FLAG_FREE)
 			kfree(e);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 002fe05dd344..48e0a12dca61 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -969,7 +969,6 @@ static void qlt_free_session_done(struct work_struct *work)
 	struct qla_hw_data *ha = vha->hw;
 	unsigned long flags;
 	bool logout_started = false;
-	struct event_arg ea;
 	scsi_qla_host_t *base_vha;
 	struct qlt_plogi_ack_t *own =
 		sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
@@ -1121,11 +1120,18 @@ static void qlt_free_session_done(struct work_struct *work)
 	if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags))
 		return;
 
-	if (!tgt || !tgt->tgt_stop) {
-		memset(&ea, 0, sizeof(ea));
-		ea.event = FCME_DELETE_DONE;
-		ea.fcport = sess;
-		qla2x00_fcport_event_handler(vha, &ea);
+	if ((!tgt || !tgt->tgt_stop) && !LOOP_TRANSITION(vha)) {
+		switch (vha->host->active_mode) {
+		case MODE_INITIATOR:
+		case MODE_DUAL:
+			set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+			qla2xxx_wake_dpc(vha);
+			break;
+		case MODE_TARGET:
+		default:
+			/* no-op */
+			break;
+		}
 	}
 }
 
@@ -4337,6 +4343,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 	struct fc_port *sess;
 	struct qla_tgt_cmd *cmd;
 	unsigned long flags;
+	port_id_t id;
 
 	if (unlikely(tgt->tgt_stop)) {
 		ql_dbg(ql_dbg_io, vha, 0x3061,
@@ -4344,6 +4351,12 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 		return -EFAULT;
 	}
 
+	id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
+	id.b.area = atio->u.isp24.fcp_hdr.s_id[1];
+	id.b.domain = atio->u.isp24.fcp_hdr.s_id[0];
+	if (IS_SW_RESV_ADDR(id))
+		return -EBUSY;
+
 	sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id);
 	if (unlikely(!sess)) {
 		struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op),
@@ -4758,8 +4771,16 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
 		ql_dbg(ql_dbg_disc, vha, 0xffff,
 		    "%s %d %8phC post new sess\n",
 		    __func__, __LINE__, iocb->u.isp24.port_name);
-		qla24xx_post_newsess_work(vha, &port_id,
-		    iocb->u.isp24.port_name, pla);
+		if (iocb->u.isp24.status_subcode == ELS_PLOGI)
+			qla24xx_post_newsess_work(vha, &port_id,
+			    iocb->u.isp24.port_name,
+			    iocb->u.isp24.u.plogi.node_name,
+			    pla, FC4_TYPE_UNKNOWN);
+		else
+			qla24xx_post_newsess_work(vha, &port_id,
+			    iocb->u.isp24.port_name, NULL,
+			    pla, FC4_TYPE_UNKNOWN);
+
 		goto out;
 	}
 
@@ -4888,6 +4909,11 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 			break;
 		}
 
+		if (IS_SW_RESV_ADDR(port_id)) {
+			res = 1;
+			break;
+		}
+
 		wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
 
 		if (wwn) {
@@ -4915,12 +4941,32 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 		}
 
 		if (sess != NULL) {
+			bool delete = false;
 			spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
 			switch (sess->fw_login_state) {
+			case DSC_LS_PLOGI_PEND:
 			case DSC_LS_PLOGI_COMP:
 			case DSC_LS_PRLI_COMP:
 				break;
 			default:
+			    	delete = true;
+				break;
+			}
+
+			switch (sess->disc_state) {
+			case DSC_LOGIN_PEND:
+			case DSC_GPDB:
+			case DSC_GPSC:
+			case DSC_UPD_FCPORT:
+			case DSC_LOGIN_COMPLETE:
+			case DSC_ADISC:
+				delete = false;
+				break;
+			default:
+				break;
+			}
+
+			if (delete) {
 				spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock,
 				    flags);
 				/*
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 588c8bcf1192..dc11b83700c1 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -994,7 +994,7 @@ struct qla_tgt_prm {
 
 /* Check for Switch reserved address */
 #define IS_SW_RESV_ADDR(_s_id) \
-	((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
+	((_s_id.b.domain == 0xff) && ((_s_id.b.area & 0xf0) == 0xf0))
 
 #define QLA_TGT_XMIT_DATA		1
 #define QLA_TGT_XMIT_STATUS		2
-- 
2.12.0

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

* [PATCH 23/43] qla2xxx: Add lock protection around host lookup
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (21 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 24/43] qla2xxx: Reduce the use of terminate exchange Himanshu Madhani
                   ` (19 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Host lookup via btree is currently protected by the hardware_lock.
Add hardware_lock when modifying btree to store host pointer.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c   | 3 +++
 drivers/scsi/qla2xxx/qla_mid.c    | 9 +++++----
 drivers/scsi/qla2xxx/qla_target.c | 6 ------
 3 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index cdcd84278fd0..300cd795dad4 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3977,6 +3977,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
 	struct qla_hw_data *ha = vha->hw;
 	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 	port_id_t id;
+	unsigned long flags;
 
 	/* Get host addresses. */
 	rval = qla2x00_get_adapter_id(vha,
@@ -4058,7 +4059,9 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
 	id.b.area = area;
 	id.b.al_pa = al_pa;
 	id.b.rsvd_1 = 0;
+	spin_lock_irqsave(&ha->hardware_lock, flags);
 	qlt_update_host_map(vha, id);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	if (!vha->flags.init_done)
 		ql_log(ql_log_info, vha, 0x2010,
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index a823fa6b7060..12a29eca02e1 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -50,10 +50,11 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
 
 	spin_lock_irqsave(&ha->vport_slock, flags);
 	list_add_tail(&vha->list, &ha->vp_list);
+	spin_unlock_irqrestore(&ha->vport_slock, flags);
 
+	spin_lock_irqsave(&ha->hardware_lock, flags);
 	qlt_update_vp_map(vha, SET_VP_IDX);
-
-	spin_unlock_irqrestore(&ha->vport_slock, flags);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	mutex_unlock(&ha->vport_lock);
 	return vp_id;
@@ -158,9 +159,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
 	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 
 	/* Remove port id from vp target map */
-	spin_lock_irqsave(&vha->hw->vport_slock, flags);
+	spin_lock_irqsave(&vha->hw->hardware_lock, flags);
 	qlt_update_vp_map(vha, RESET_AL_PA);
-	spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
+	spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
 
 	qla2x00_mark_vp_devices_dead(vha);
 	atomic_set(&vha->vp_state, VP_FAILED);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 48e0a12dca61..c7c81d5cf69c 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -7206,20 +7206,14 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
 
 void qlt_update_host_map(struct scsi_qla_host *vha, port_id_t id)
 {
-	unsigned long flags;
-	struct qla_hw_data *ha = vha->hw;
 
 	if (!vha->d_id.b24) {
-		spin_lock_irqsave(&ha->vport_slock, flags);
 		vha->d_id = id;
 		qlt_update_vp_map(vha, SET_AL_PA);
-		spin_unlock_irqrestore(&ha->vport_slock, flags);
 	} else if (vha->d_id.b24 != id.b24) {
-		spin_lock_irqsave(&ha->vport_slock, flags);
 		qlt_update_vp_map(vha, RESET_AL_PA);
 		vha->d_id = id;
 		qlt_update_vp_map(vha, SET_AL_PA);
-		spin_unlock_irqrestore(&ha->vport_slock, flags);
 	}
 }
 
-- 
2.12.0

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

* [PATCH 24/43] qla2xxx: Reduce the use of terminate exchange
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (22 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 23/43] qla2xxx: Add lock protection around host lookup Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 25/43] qla2xxx: Reduce trace noise for Async Events Himanshu Madhani
                   ` (18 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

reduce usage of terminate exchange when command encounter
resource bottle neck.  Remote initiator view it as command
drop.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_target.c | 140 ++++++++++++++++++++------------------
 1 file changed, 74 insertions(+), 66 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index c7c81d5cf69c..e7e0689d9ca5 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -75,7 +75,8 @@ MODULE_PARM_DESC(ql2xuctrlirq,
 
 int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
 
-static int temp_sam_status = SAM_STAT_BUSY;
+static int qla_sam_status = SAM_STAT_BUSY;
+static int tc_sam_status = SAM_STAT_TASK_SET_FULL; /* target core */
 
 /*
  * From scsi/fc/fc_fcp.h
@@ -4294,14 +4295,14 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
 	if (op->atio.u.raw.entry_count > 1) {
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
 		    "Dropping multy entry atio %p\n", &op->atio);
-		goto out_term;
+		goto out_busy;
 	}
 
 	sess = qlt_make_local_sess(vha, s_id);
 	/* sess has an extra creation ref. */
 
 	if (!sess)
-		goto out_term;
+		goto out_busy;
 	/*
 	 * Now obtain a pre-allocated session tag using the original op->atio
 	 * packet header, and dispatch into __qlt_do_work() using the existing
@@ -4312,7 +4313,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
 		struct qla_qpair *qpair = ha->base_qpair;
 
 		spin_lock_irqsave(qpair->qp_lock_ptr, flags);
-		qlt_send_busy(qpair, &op->atio, SAM_STAT_BUSY);
+		qlt_send_busy(qpair, &op->atio, tc_sam_status);
 		spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
 
 		spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -4332,6 +4333,17 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
 out_term:
 	qlt_send_term_exchange(vha->hw->base_qpair, NULL, &op->atio, 0, 0);
 	kfree(op);
+	return;
+out_busy:
+	{
+		struct qla_qpair *qpair = ha->base_qpair;
+
+		spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+		qlt_send_busy(qpair, &op->atio, qla_sam_status);
+		spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+		kfree(op);
+	}
+	return;
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -4348,7 +4360,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 	if (unlikely(tgt->tgt_stop)) {
 		ql_dbg(ql_dbg_io, vha, 0x3061,
 		    "New command while device %p is shutting down\n", tgt);
-		return -EFAULT;
+		return -ENODEV;
 	}
 
 	id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
@@ -4403,7 +4415,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 		spin_lock_irqsave(&ha->tgt.sess_lock, flags);
 		ha->tgt.tgt_ops->put_sess(sess);
 		spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-		return -ENOMEM;
+		return -EBUSY;
 	}
 
 	cmd->cmd_in_wq = 1;
@@ -5504,7 +5516,6 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, struct qla_qpair *qpair,
 	struct atio_from_isp *atio, uint8_t ha_locked)
 {
 	struct qla_hw_data *ha = vha->hw;
-	uint16_t status;
 	unsigned long flags;
 
 	if (ha->tgt.num_pend_cmds < Q_FULL_THRESH_HOLD(ha))
@@ -5512,8 +5523,7 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, struct qla_qpair *qpair,
 
 	if (!ha_locked)
 		spin_lock_irqsave(&ha->hardware_lock, flags);
-	status = temp_sam_status;
-	qlt_send_busy(qpair, atio, status);
+	qlt_send_busy(qpair, atio, qla_sam_status);
 	if (!ha_locked)
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
@@ -5528,7 +5538,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
 	struct qla_hw_data *ha = vha->hw;
 	struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
 	int rc;
-	unsigned long flags;
+	unsigned long flags = 0;
 
 	if (unlikely(tgt == NULL)) {
 		ql_dbg(ql_dbg_tgt, vha, 0x3064,
@@ -5552,8 +5562,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
 			    "sending QUEUE_FULL\n", vha->vp_idx);
 			if (!ha_locked)
 				spin_lock_irqsave(&ha->hardware_lock, flags);
-			qlt_send_busy(ha->base_qpair, atio,
-			    SAM_STAT_TASK_SET_FULL);
+			qlt_send_busy(ha->base_qpair, atio, qla_sam_status);
 			if (!ha_locked)
 				spin_unlock_irqrestore(&ha->hardware_lock,
 				    flags);
@@ -5572,42 +5581,37 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
 			rc = qlt_handle_task_mgmt(vha, atio);
 		}
 		if (unlikely(rc != 0)) {
-			if (rc == -ESRCH) {
-				if (!ha_locked)
-					spin_lock_irqsave(&ha->hardware_lock,
-					    flags);
-
-#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
-				qlt_send_busy(ha->base_qpair, atio,
-				    SAM_STAT_BUSY);
-#else
+			if (!ha_locked)
+				spin_lock_irqsave(&ha->hardware_lock, flags);
+			switch (rc) {
+			case -ENODEV:
+				ql_dbg(ql_dbg_tgt, vha, 0xe05f,
+				    "qla_target: Unable to send command to target\n");
+				break;
+			case -EBADF:
+				ql_dbg(ql_dbg_tgt, vha, 0xe05f,
+				    "qla_target: Unable to send command to target, sending TERM EXCHANGE for rsp\n");
 				qlt_send_term_exchange(ha->base_qpair, NULL,
 				    atio, 1, 0);
-#endif
-				if (!ha_locked)
-					spin_unlock_irqrestore(
-					    &ha->hardware_lock, flags);
-			} else {
-				if (tgt->tgt_stop) {
-					ql_dbg(ql_dbg_tgt, vha, 0xe059,
-					    "qla_target: Unable to send "
-					    "command to target for req, "
-					    "ignoring.\n");
-				} else {
-					ql_dbg(ql_dbg_tgt, vha, 0xe05a,
-					    "qla_target(%d): Unable to send "
-					    "command to target, sending BUSY "
-					    "status.\n", vha->vp_idx);
-					if (!ha_locked)
-						spin_lock_irqsave(
-						    &ha->hardware_lock, flags);
-					qlt_send_busy(ha->base_qpair,
-					    atio, SAM_STAT_BUSY);
-					if (!ha_locked)
-						spin_unlock_irqrestore(
-						    &ha->hardware_lock, flags);
-				}
+				break;
+			case -EBUSY:
+				ql_dbg(ql_dbg_tgt, vha, 0xe060,
+				    "qla_target(%d): Unable to send command to target, sending BUSY status\n",
+				    vha->vp_idx);
+				qlt_send_busy(ha->base_qpair, atio,
+				    tc_sam_status);
+				break;
+			default:
+				ql_dbg(ql_dbg_tgt, vha, 0xe060,
+				    "qla_target(%d): Unable to send command to target, sending BUSY status\n",
+				    vha->vp_idx);
+				qlt_send_busy(ha->base_qpair, atio,
+				    qla_sam_status);
+				break;
 			}
+			if (!ha_locked)
+				spin_unlock_irqrestore(&ha->hardware_lock,
+				    flags);
 		}
 		break;
 
@@ -5690,27 +5694,31 @@ static void qlt_response_pkt(struct scsi_qla_host *vha,
 
 		rc = qlt_handle_cmd_for_atio(vha, atio);
 		if (unlikely(rc != 0)) {
-			if (rc == -ESRCH) {
-#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
-				qlt_send_busy(rsp->qpair, atio, 0);
-#else
-				qlt_send_term_exchange(rsp->qpair, NULL, atio, 1, 0);
-#endif
-			} else {
-				if (tgt->tgt_stop) {
-					ql_dbg(ql_dbg_tgt, vha, 0xe05f,
-					    "qla_target: Unable to send "
-					    "command to target, sending TERM "
-					    "EXCHANGE for rsp\n");
-					qlt_send_term_exchange(rsp->qpair, NULL,
-					    atio, 1, 0);
-				} else {
-					ql_dbg(ql_dbg_tgt, vha, 0xe060,
-					    "qla_target(%d): Unable to send "
-					    "command to target, sending BUSY "
-					    "status\n", vha->vp_idx);
-					qlt_send_busy(rsp->qpair, atio, 0);
-				}
+			switch (rc) {
+			case -ENODEV:
+				ql_dbg(ql_dbg_tgt, vha, 0xe05f,
+				    "qla_target: Unable to send command to target\n");
+				break;
+			case -EBADF:
+				ql_dbg(ql_dbg_tgt, vha, 0xe05f,
+				    "qla_target: Unable to send command to target, sending TERM EXCHANGE for rsp\n");
+				qlt_send_term_exchange(rsp->qpair, NULL,
+				    atio, 1, 0);
+				break;
+			case -EBUSY:
+				ql_dbg(ql_dbg_tgt, vha, 0xe060,
+				    "qla_target(%d): Unable to send command to target, sending BUSY status\n",
+				    vha->vp_idx);
+				qlt_send_busy(rsp->qpair, atio,
+				    tc_sam_status);
+				break;
+			default:
+				ql_dbg(ql_dbg_tgt, vha, 0xe060,
+				    "qla_target(%d): Unable to send command to target, sending BUSY status\n",
+				    vha->vp_idx);
+				qlt_send_busy(rsp->qpair, atio,
+				    qla_sam_status);
+				break;
 			}
 		}
 	}
-- 
2.12.0

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

* [PATCH 25/43] qla2xxx: Reduce trace noise for Async Events
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (23 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 24/43] qla2xxx: Reduce the use of terminate exchange Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 26/43] qla2xxx: Fix login state machine freeze Himanshu Madhani
                   ` (17 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Add NPIV id check to reduce multiple debug messages
of the same RSCN event.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_mid.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 12a29eca02e1..11a424df5f52 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -265,13 +265,20 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
 			case MBA_LIP_RESET:
 			case MBA_POINT_TO_POINT:
 			case MBA_CHG_IN_CONNECTION:
-			case MBA_PORT_UPDATE:
-			case MBA_RSCN_UPDATE:
 				ql_dbg(ql_dbg_async, vha, 0x5024,
 				    "Async_event for VP[%d], mb=0x%x vha=%p.\n",
 				    i, *mb, vha);
 				qla2x00_async_event(vha, rsp, mb);
 				break;
+			case MBA_PORT_UPDATE:
+			case MBA_RSCN_UPDATE:
+				if ((mb[3] & 0xff) == vha->vp_idx) {
+					ql_dbg(ql_dbg_async, vha, 0x5024,
+					    "Async_event for VP[%d], mb=0x%x vha=%p\n",
+					    i, *mb, vha);
+					qla2x00_async_event(vha, rsp, mb);
+				}
+				break;
 			}
 
 			spin_lock_irqsave(&ha->vport_slock, flags);
-- 
2.12.0

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

* [PATCH 26/43] qla2xxx: Fix login state machine freeze
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (24 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 25/43] qla2xxx: Reduce trace noise for Async Events Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 27/43] qla2xxx: Migrate switch registration commands away from mailbox interface Himanshu Madhani
                   ` (16 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Relogin stop moving forward due to improper check of scan_state flag.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 300cd795dad4..152c808b272b 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1270,11 +1270,6 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 {
 	fc_port_t *fcport = ea->fcport;
 
-	if (fcport->scan_state != QLA_FCPORT_FOUND) {
-		fcport->login_retry++;
-		return;
-	}
-
 	ql_dbg(ql_dbg_disc, vha, 0x2102,
 	    "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
 	    __func__, fcport->port_name, fcport->disc_state,
@@ -1324,7 +1319,6 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 	int rc;
 
 	switch (ea->event) {
-	case FCME_RELOGIN:
 	case FCME_RSCN:
 	case FCME_GIDPN_DONE:
 	case FCME_GPSC_DONE:
-- 
2.12.0

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

* [PATCH 27/43] qla2xxx: Migrate switch registration commands away from mailbox interface
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (25 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 26/43] qla2xxx: Fix login state machine freeze Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 28/43] qla2xxx: Remove session creation redundant code Himanshu Madhani
                   ` (15 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Migrate switch registration commands: RFTID, RFFID, RNNID and RSNN_NN
out of mailbox interface to reduce fabric scan bottle neck.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h    |   8 +-
 drivers/scsi/qla2xxx/qla_gbl.h    |   2 +-
 drivers/scsi/qla2xxx/qla_gs.c     | 454 +++++++++++++++++++++++++++-----------
 drivers/scsi/qla2xxx/qla_os.c     |  20 +-
 drivers/scsi/qla2xxx/qla_target.c |  13 +-
 drivers/scsi/qla2xxx/qla_target.h |   2 +-
 6 files changed, 355 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 3042697b92ae..db1f68c3e074 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -516,6 +516,10 @@ enum {
 	SPCN_NVME_CMD,
 	SPCN_CTRL_VP,
 	SPCN_PRLO,
+	SPCN_RFTID,
+	SPCN_RFFID,
+	SPCN_RNNID,
+	SPCN_RSNNNN,
 };
 
 struct sp_name {
@@ -581,6 +585,7 @@ typedef struct srb {
 	u32 gen1;	/* scratch */
 	u32 gen2;	/* scratch */
 	int rc;
+	int retry_count;
 	struct completion comp;
 	union {
 		struct srb_iocb iocb_cmd;
@@ -3234,7 +3239,7 @@ enum qla_work_type {
 	QLA_EVT_AENFX,
 	QLA_EVT_GIDPN,
 	QLA_EVT_GPNID,
-	QLA_EVT_GPNID_DONE,
+	QLA_EVT_UNMAP,
 	QLA_EVT_NEW_SESS,
 	QLA_EVT_GPDB,
 	QLA_EVT_PRLI,
@@ -3250,6 +3255,7 @@ enum qla_work_type {
 	QLA_EVT_GNNFT_DONE,
 	QLA_EVT_GNNID,
 	QLA_EVT_GFPNID,
+	QLA_EVT_SP_RETRY,
 };
 
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 43799e8dc68a..650ec54e3255 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -650,7 +650,6 @@ extern void qla2x00_free_fcport(fc_port_t *);
 
 extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
 extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
-void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
 void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
 
 int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
@@ -669,6 +668,7 @@ int qla24xx_post_gnnid_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
 void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea);
+void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);
 
 /*
  * Global Function Prototypes in qla_attr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 643ce1578cbe..0e84381e227e 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -14,6 +14,10 @@ static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
+static int qla_async_rftid(scsi_qla_host_t *, port_id_t *);
+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 *);
 
 struct sp_name sp_str[] = {
 	{ SPCN_UNKNOWN, "unknown" },
@@ -43,6 +47,10 @@ struct sp_name sp_str[] = {
 	{ SPCN_NVME_CMD, "nvme_cmd" },
 	{ SPCN_CTRL_VP, "ctrl_vp" },
 	{ SPCN_PRLO, "prlo" },
+	{ SPCN_RFTID, "rftid" },
+	{ SPCN_RFFID, "rffid" },
+	{ SPCN_RNNID, "rnnid" },
+	{ SPCN_RSNNNN, "rsnn_nn" },
 };
 
 const char *sp_to_str(uint16_t cmd)
@@ -556,6 +564,72 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
 	return (rval);
 }
 
+static void qla2x00_async_sns_sp_done(void *s, int rc)
+{
+	struct srb *sp = s;
+	struct scsi_qla_host *vha = sp->vha;
+	struct ct_sns_pkt *ct_sns;
+	struct qla_work_evt *e;
+
+	sp->rc = rc;
+	if (rc == QLA_SUCCESS) {
+		ql_dbg(ql_dbg_disc, vha, 0x204f,
+		    "Async done-%s exiting normally.\n",
+		    sp->name);
+	} else if (rc == QLA_FUNCTION_TIMEOUT) {
+		ql_dbg(ql_dbg_disc, vha, 0x204f,
+		    "Async done-%s timeout\n", sp->name);
+	} else {
+		ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
+		memset(ct_sns, 0, sizeof(*ct_sns));
+		sp->retry_count++;
+		if (sp->retry_count > 3)
+			goto err;
+
+		ql_dbg(ql_dbg_disc, vha, 0x204f,
+		    "Async done-%s fail rc %x.  Retry count %d\n",
+		    sp->name, rc, sp->retry_count);
+
+		e = qla2x00_alloc_work(vha, QLA_EVT_SP_RETRY);
+		if (!e)
+			goto err2;
+
+		del_timer(&sp->u.iocb_cmd.timer);
+		e->u.iosb.sp = sp;
+		qla2x00_post_work(vha, e);
+		return;
+	}
+
+err:
+	e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
+err2:
+	if (!e) {
+		/* please ignore kernel warning. otherwise, we have mem leak. */
+		if (sp->u.iocb_cmd.u.ctarg.req) {
+			dma_free_coherent(&vha->hw->pdev->dev,
+			    sizeof(struct ct_sns_pkt),
+			    sp->u.iocb_cmd.u.ctarg.req,
+			    sp->u.iocb_cmd.u.ctarg.req_dma);
+			sp->u.iocb_cmd.u.ctarg.req = NULL;
+		}
+
+		if (sp->u.iocb_cmd.u.ctarg.rsp) {
+			dma_free_coherent(&vha->hw->pdev->dev,
+			    sizeof(struct ct_sns_pkt),
+			    sp->u.iocb_cmd.u.ctarg.rsp,
+			    sp->u.iocb_cmd.u.ctarg.rsp_dma);
+			sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+		}
+
+		sp->free(sp);
+
+		return;
+	}
+
+	e->u.iosb.sp = sp;
+	qla2x00_post_work(vha, e);
+}
+
 /**
  * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
  * @ha: HA context
@@ -565,57 +639,87 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
 int
 qla2x00_rft_id(scsi_qla_host_t *vha)
 {
-	int		rval;
 	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;
-	struct ct_arg arg;
 
 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 		return qla2x00_sns_rft_id(vha);
 
-	arg.iocb = ha->ms_iocb;
-	arg.req_dma = ha->ct_sns_dma;
-	arg.rsp_dma = ha->ct_sns_dma;
-	arg.req_size = RFT_ID_REQ_SIZE;
-	arg.rsp_size = RFT_ID_RSP_SIZE;
-	arg.nport_handle = NPH_SNS;
+	return qla_async_rftid(vha, &vha->d_id);
+}
 
-	/* Issue RFT_ID */
-	/* Prepare common MS IOCB */
-	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
+static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
+{
+	int rval = QLA_MEMORY_ALLOC_FAILED;
+	struct ct_sns_req *ct_req;
+	srb_t *sp;
+	struct ct_sns_pkt *ct_sns;
+
+	if (!vha->flags.online)
+		goto done;
+
+	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+	if (!sp)
+		goto done;
+
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_RFTID);
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.req) {
+		ql_log(ql_log_warn, vha, 0xd041,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
+
+	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
+		ql_log(ql_log_warn, vha, 0xd042,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
+	memset(ct_sns, 0, sizeof(*ct_sns));
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 
 	/* Prepare CT request */
-	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
-	    RFT_ID_RSP_SIZE);
-	ct_rsp = &ha->ct_sns->p.rsp;
+	ct_req = qla2x00_prep_ct_req(ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE);
 
 	/* Prepare CT arguments -- port_id, FC-4 types */
 	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
 	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
 	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
-
 	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
 
 	if (vha->flags.nvme_enabled)
 		ct_req->req.rft_id.fc4_types[6] = 1;    /* NVMe type 28h */
-	/* Execute MS IOCB */
-	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
-	    sizeof(ms_iocb_entry_t));
+
+	sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;
+	sp->u.iocb_cmd.u.ctarg.rsp_size = RFT_ID_RSP_SIZE;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_sns_sp_done;
+
+	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
-		/*EMPTY*/
 		ql_dbg(ql_dbg_disc, vha, 0x2043,
 		    "RFT_ID issue IOCB failed (%d).\n", rval);
-	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
-	    QLA_SUCCESS) {
-		rval = QLA_FUNCTION_FAILED;
-	} else {
-		ql_dbg(ql_dbg_disc, vha, 0x2044,
-		    "RFT_ID exiting normally.\n");
+		goto done_free_sp;
 	}
-
-	return (rval);
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s - hdl=%x portid %06x.\n",
+	    sp->name, sp->handle, d_id->b24);
+	return rval;
+done_free_sp:
+	sp->free(sp);
+done:
+	return rval;
 }
 
 /**
@@ -627,12 +731,7 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
 int
 qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
 {
-	int		rval;
 	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;
-	struct ct_arg arg;
 
 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 		ql_dbg(ql_dbg_disc, vha, 0x2046,
@@ -640,47 +739,81 @@ qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
 		return (QLA_SUCCESS);
 	}
 
-	arg.iocb = ha->ms_iocb;
-	arg.req_dma = ha->ct_sns_dma;
-	arg.rsp_dma = ha->ct_sns_dma;
-	arg.req_size = RFF_ID_REQ_SIZE;
-	arg.rsp_size = RFF_ID_RSP_SIZE;
-	arg.nport_handle = NPH_SNS;
+	return qla_async_rffid(vha, &vha->d_id, qlt_rff_id(vha),
+	    FC4_TYPE_FCP_SCSI);
+}
 
-	/* Issue RFF_ID */
-	/* Prepare common MS IOCB */
-	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
+static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
+    u8 fc4feature, u8 fc4type)
+{
+	int rval = QLA_MEMORY_ALLOC_FAILED;
+	struct ct_sns_req *ct_req;
+	srb_t *sp;
+	struct ct_sns_pkt *ct_sns;
 
-	/* Prepare CT request */
-	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
-	    RFF_ID_RSP_SIZE);
-	ct_rsp = &ha->ct_sns->p.rsp;
+	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+	if (!sp)
+		goto done;
 
-	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
-	ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
-	ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
-	ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_RFFID);
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
-	qlt_rff_id(vha, ct_req);
+	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.req) {
+		ql_log(ql_log_warn, vha, 0xd041,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
 
-	ct_req->req.rff_id.fc4_type = type;		/* SCSI - FCP */
+	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
+		ql_log(ql_log_warn, vha, 0xd042,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
+	memset(ct_sns, 0, sizeof(*ct_sns));
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 
-	/* Execute MS IOCB */
-	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
-	    sizeof(ms_iocb_entry_t));
+	/* Prepare CT request */
+	ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE);
+
+	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
+	ct_req->req.rff_id.port_id[0] = d_id->b.domain;
+	ct_req->req.rff_id.port_id[1] = d_id->b.area;
+	ct_req->req.rff_id.port_id[2] = d_id->b.al_pa;
+	ct_req->req.rff_id.fc4_feature = fc4feature;
+	ct_req->req.rff_id.fc4_type = fc4type;		/* SCSI - FCP */
+
+	sp->u.iocb_cmd.u.ctarg.req_size = RFF_ID_REQ_SIZE;
+	sp->u.iocb_cmd.u.ctarg.rsp_size = RFF_ID_RSP_SIZE;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_sns_sp_done;
+
+	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
-		/*EMPTY*/
 		ql_dbg(ql_dbg_disc, vha, 0x2047,
 		    "RFF_ID issue IOCB failed (%d).\n", rval);
-	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
-	    QLA_SUCCESS) {
-		rval = QLA_FUNCTION_FAILED;
-	} else {
-		ql_dbg(ql_dbg_disc, vha, 0x2048,
-		    "RFF_ID exiting normally.\n");
+		goto done_free_sp;
 	}
 
-	return (rval);
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
+	    sp->name, sp->handle, d_id->b24, fc4feature, fc4type);
+	return rval;
+
+done_free_sp:
+	sp->free(sp);
+done:
+	return rval;
 }
 
 /**
@@ -692,54 +825,85 @@ qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
 int
 qla2x00_rnn_id(scsi_qla_host_t *vha)
 {
-	int		rval;
 	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;
-	struct ct_arg arg;
 
 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 		return qla2x00_sns_rnn_id(vha);
 
-	arg.iocb = ha->ms_iocb;
-	arg.req_dma = ha->ct_sns_dma;
-	arg.rsp_dma = ha->ct_sns_dma;
-	arg.req_size = RNN_ID_REQ_SIZE;
-	arg.rsp_size = RNN_ID_RSP_SIZE;
-	arg.nport_handle = NPH_SNS;
+	return  qla_async_rnnid(vha, &vha->d_id, vha->node_name);
+}
 
-	/* Issue RNN_ID */
-	/* Prepare common MS IOCB */
-	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
+static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
+	u8 *node_name)
+{
+	int rval = QLA_MEMORY_ALLOC_FAILED;
+	struct ct_sns_req *ct_req;
+	srb_t *sp;
+	struct ct_sns_pkt *ct_sns;
+
+	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+	if (!sp)
+		goto done;
+
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_RNNID);
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.req) {
+		ql_log(ql_log_warn, vha, 0xd041,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
+
+	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
+		ql_log(ql_log_warn, vha, 0xd042,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
+	memset(ct_sns, 0, sizeof(*ct_sns));
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 
 	/* Prepare CT request */
-	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
-	ct_rsp = &ha->ct_sns->p.rsp;
+	ct_req = qla2x00_prep_ct_req(ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
 
 	/* Prepare CT arguments -- port_id, node_name */
 	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
 	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
 	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
-
 	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
 
-	/* Execute MS IOCB */
-	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
-	    sizeof(ms_iocb_entry_t));
+	sp->u.iocb_cmd.u.ctarg.req_size = RNN_ID_REQ_SIZE;
+	sp->u.iocb_cmd.u.ctarg.rsp_size = RNN_ID_RSP_SIZE;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_sns_sp_done;
+
+	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
-		/*EMPTY*/
 		ql_dbg(ql_dbg_disc, vha, 0x204d,
 		    "RNN_ID issue IOCB failed (%d).\n", rval);
-	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
-	    QLA_SUCCESS) {
-		rval = QLA_FUNCTION_FAILED;
-	} else {
-		ql_dbg(ql_dbg_disc, vha, 0x204e,
-		    "RNN_ID exiting normally.\n");
+		goto done_free_sp;
 	}
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s - hdl=%x portid %06x\n",
+	    sp->name, sp->handle, d_id->b24);
 
-	return (rval);
+	return rval;
+
+done_free_sp:
+	sp->free(sp);
+done:
+	return rval;
 }
 
 void
@@ -766,12 +930,7 @@ qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
 int
 qla2x00_rsnn_nn(scsi_qla_host_t *vha)
 {
-	int		rval;
 	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;
-	struct ct_arg arg;
 
 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 		ql_dbg(ql_dbg_disc, vha, 0x2050,
@@ -779,22 +938,49 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
 		return (QLA_SUCCESS);
 	}
 
-	arg.iocb = ha->ms_iocb;
-	arg.req_dma = ha->ct_sns_dma;
-	arg.rsp_dma = ha->ct_sns_dma;
-	arg.req_size = 0;
-	arg.rsp_size = RSNN_NN_RSP_SIZE;
-	arg.nport_handle = NPH_SNS;
+	return qla_async_rsnn_nn(vha);
+}
 
-	/* Issue RSNN_NN */
-	/* Prepare common MS IOCB */
-	/*   Request size adjusted after CT preparation */
-	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
+static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
+{
+	int rval = QLA_MEMORY_ALLOC_FAILED;
+	struct ct_sns_req *ct_req;
+	srb_t *sp;
+	struct ct_sns_pkt *ct_sns;
+
+	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+	if (!sp)
+		goto done;
+
+	sp->type = SRB_CT_PTHRU_CMD;
+	sp->name = sp_to_str(SPCN_RSNNNN);
+	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.req) {
+		ql_log(ql_log_warn, vha, 0xd041,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
+
+	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
+	    GFP_KERNEL);
+	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
+		ql_log(ql_log_warn, vha, 0xd042,
+		    "%s: Failed to allocate ct_sns request.\n",
+		    __func__);
+		goto done_free_sp;
+	}
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
+	memset(ct_sns, 0, sizeof(*ct_sns));
+	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 
 	/* Prepare CT request */
-	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
-	    RSNN_NN_RSP_SIZE);
-	ct_rsp = &ha->ct_sns->p.rsp;
+	ct_req = qla2x00_prep_ct_req(ct_sns, RSNN_NN_CMD, RSNN_NN_RSP_SIZE);
 
 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
 	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
@@ -802,32 +988,33 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
 	/* Prepare the Symbolic Node Name */
 	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
 	    sizeof(ct_req->req.rsnn_nn.sym_node_name));
-
-	/* Calculate SNN length */
 	ct_req->req.rsnn_nn.name_len =
 	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
 
-	/* Update MS IOCB request */
-	ms_pkt->req_bytecount =
-	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
-	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
 
-	/* Execute MS IOCB */
-	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
-	    sizeof(ms_iocb_entry_t));
+	sp->u.iocb_cmd.u.ctarg.req_size = 24 + 1 + ct_req->req.rsnn_nn.name_len;
+	sp->u.iocb_cmd.u.ctarg.rsp_size = RSNN_NN_RSP_SIZE;
+	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->done = qla2x00_async_sns_sp_done;
+
+	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
-		/*EMPTY*/
-		ql_dbg(ql_dbg_disc, vha, 0x2051,
-		    "RSNN_NN issue IOCB failed (%d).\n", rval);
-	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
-	    QLA_SUCCESS) {
-		rval = QLA_FUNCTION_FAILED;
-	} else {
-		ql_dbg(ql_dbg_disc, vha, 0x2052,
-		    "RSNN_NN exiting normally.\n");
+		ql_dbg(ql_dbg_disc, vha, 0x2043,
+		    "RFT_ID issue IOCB failed (%d).\n", rval);
+		goto done_free_sp;
 	}
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "Async-%s - hdl=%x.\n",
+	    sp->name, sp->handle);
 
-	return (rval);
+	return rval;
+
+done_free_sp:
+	sp->free(sp);
+done:
+	return rval;
 }
 
 /**
@@ -3249,7 +3436,7 @@ int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
 	return qla2x00_post_work(vha, e);
 }
 
-void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
+void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
 {
 	if (sp->u.iocb_cmd.u.ctarg.req) {
 		dma_free_coherent(&vha->hw->pdev->dev,
@@ -3457,7 +3644,7 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
 
 	qla2x00_fcport_event_handler(vha, &ea);
 
-	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID_DONE);
+	e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
 	if (!e) {
 		/* please ignore kernel warning. otherwise, we have mem leak. */
 		if (sp->u.iocb_cmd.u.ctarg.req) {
@@ -3827,8 +4014,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 	}
 
 out:
-	/* re-use gpnid_done to free resource */
-	qla24xx_async_gpnid_done(vha, sp);
+	qla24xx_sp_unmap(vha, sp);
 }
 
 static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index cab39a6d9776..d4a967410893 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4907,6 +4907,20 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 	}
 }
 
+static void qla_sp_retry(struct scsi_qla_host *vha, struct qla_work_evt *e)
+{
+	struct srb *sp = e->u.iosb.sp;
+	int rval;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS) {
+		ql_dbg(ql_dbg_disc, vha, 0x2043,
+		    "%s: %s: Re-issue IOCB failed (%d).\n",
+		    __func__, sp->name, rval);
+		qla24xx_sp_unmap(vha, sp);
+	}
+}
+
 void
 qla2x00_do_work(struct scsi_qla_host *vha)
 {
@@ -4960,8 +4974,8 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 		case QLA_EVT_GPNID:
 			qla24xx_async_gpnid(vha, &e->u.gpnid.id);
 			break;
-		case QLA_EVT_GPNID_DONE:
-			qla24xx_async_gpnid_done(vha, e->u.iosb.sp);
+		case QLA_EVT_UNMAP:
+			qla24xx_sp_unmap(vha, e->u.iosb.sp);
 			break;
 		case QLA_EVT_RELOGIN:
 			qla2x00_relogin(vha);
@@ -5010,6 +5024,8 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 		case QLA_EVT_GFPNID:
 			qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
 			break;
+		case QLA_EVT_SP_RETRY:
+			qla_sp_retry(vha, e);
 		}
 		if (e->flags & QLA_EVT_FLAG_FREE)
 			kfree(e);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index e7e0689d9ca5..93910e56643d 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -6641,18 +6641,21 @@ qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha)
 	qlt_add_target(ha, vha);
 }
 
-void
-qlt_rff_id(struct scsi_qla_host *vha, struct ct_sns_req *ct_req)
+u8
+qlt_rff_id(struct scsi_qla_host *vha)
 {
+	u8 fc4_feature = 0;
 	/*
 	 * FC-4 Feature bit 0 indicates target functionality to the name server.
 	 */
 	if (qla_tgt_mode_enabled(vha)) {
-		ct_req->req.rff_id.fc4_feature = BIT_0;
+		fc4_feature = BIT_0;
 	} else if (qla_ini_mode_enabled(vha)) {
-		ct_req->req.rff_id.fc4_feature = BIT_1;
+		fc4_feature = BIT_1;
 	} else if (qla_dual_mode_enabled(vha))
-		ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1;
+		fc4_feature = BIT_0 | BIT_1;
+
+	return fc4_feature;
 }
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index dc11b83700c1..42a7cadab81a 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -1073,7 +1073,7 @@ extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
 extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
 extern void qlt_enable_vha(struct scsi_qla_host *);
 extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
-extern void qlt_rff_id(struct scsi_qla_host *, struct ct_sns_req *);
+extern u8 qlt_rff_id(struct scsi_qla_host *);
 extern void qlt_init_atio_q_entries(struct scsi_qla_host *);
 extern void qlt_24xx_process_atio_queue(struct scsi_qla_host *, uint8_t);
 extern void qlt_24xx_config_rings(struct scsi_qla_host *);
-- 
2.12.0

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

* [PATCH 28/43] qla2xxx: Remove session creation redundant code
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (26 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 27/43] qla2xxx: Migrate switch registration commands away from mailbox interface Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 29/43] qla2xxx: Fix GPNFT/GNNFT error handling Himanshu Madhani
                   ` (14 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Current code creates a session when a new port is
discovered, and a PLOGI/PRLI is received. There is
no need to create session when command has arrived.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_target.c | 122 ++------------------------------------
 1 file changed, 5 insertions(+), 117 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 93910e56643d..598ec3481a8c 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -2016,15 +2016,10 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012,
 		    "qla_target(%d): task abort for non-existant session\n",
 		    vha->vp_idx);
-		rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt,
-		    QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts));
-
 		spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
 
-		if (rc != 0) {
-			qlt_24xx_send_abts_resp(ha->base_qpair, abts,
-			    FCP_TMF_REJECTED, false);
-		}
+		qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
+			    false);
 		return;
 	}
 	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
@@ -4265,87 +4260,6 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
 	return cmd;
 }
 
-static void qlt_create_sess_from_atio(struct work_struct *work)
-{
-	struct qla_tgt_sess_op *op = container_of(work,
-					struct qla_tgt_sess_op, work);
-	scsi_qla_host_t *vha = op->vha;
-	struct qla_hw_data *ha = vha->hw;
-	struct fc_port *sess;
-	struct qla_tgt_cmd *cmd;
-	unsigned long flags;
-	uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
-
-	spin_lock_irqsave(&vha->cmd_list_lock, flags);
-	list_del(&op->cmd_list);
-	spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
-
-	if (op->aborted) {
-		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083,
-		    "sess_op with tag %u is aborted\n",
-		    op->atio.u.isp24.exchange_addr);
-		goto out_term;
-	}
-
-	ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022,
-	    "qla_target(%d): Unable to find wwn login"
-	    " (s_id %x:%x:%x), trying to create it manually\n",
-	    vha->vp_idx, s_id[0], s_id[1], s_id[2]);
-
-	if (op->atio.u.raw.entry_count > 1) {
-		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
-		    "Dropping multy entry atio %p\n", &op->atio);
-		goto out_busy;
-	}
-
-	sess = qlt_make_local_sess(vha, s_id);
-	/* sess has an extra creation ref. */
-
-	if (!sess)
-		goto out_busy;
-	/*
-	 * Now obtain a pre-allocated session tag using the original op->atio
-	 * packet header, and dispatch into __qlt_do_work() using the existing
-	 * process context.
-	 */
-	cmd = qlt_get_tag(vha, sess, &op->atio);
-	if (!cmd) {
-		struct qla_qpair *qpair = ha->base_qpair;
-
-		spin_lock_irqsave(qpair->qp_lock_ptr, flags);
-		qlt_send_busy(qpair, &op->atio, tc_sam_status);
-		spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-
-		spin_lock_irqsave(&ha->tgt.sess_lock, flags);
-		ha->tgt.tgt_ops->put_sess(sess);
-		spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-		kfree(op);
-		return;
-	}
-
-	/*
-	 * __qlt_do_work() will call qlt_put_sess() to release
-	 * the extra reference taken above by qlt_make_local_sess()
-	 */
-	__qlt_do_work(cmd);
-	kfree(op);
-	return;
-out_term:
-	qlt_send_term_exchange(vha->hw->base_qpair, NULL, &op->atio, 0, 0);
-	kfree(op);
-	return;
-out_busy:
-	{
-		struct qla_qpair *qpair = ha->base_qpair;
-
-		spin_lock_irqsave(qpair->qp_lock_ptr, flags);
-		qlt_send_busy(qpair, &op->atio, qla_sam_status);
-		spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-		kfree(op);
-	}
-	return;
-}
-
 /* ha->hardware_lock supposed to be held on entry */
 static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 	struct atio_from_isp *atio)
@@ -4370,23 +4284,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 		return -EBUSY;
 
 	sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id);
-	if (unlikely(!sess)) {
-		struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op),
-						     GFP_ATOMIC);
-		if (!op)
-			return -ENOMEM;
-
-		memcpy(&op->atio, atio, sizeof(*atio));
-		op->vha = vha;
-
-		spin_lock_irqsave(&vha->cmd_list_lock, flags);
-		list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list);
-		spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
-
-		INIT_WORK(&op->work, qlt_create_sess_from_atio);
-		queue_work(qla_tgt_wq, &op->work);
-		return 0;
-	}
+	if (unlikely(!sess))
+		return -EFAULT;
 
 	/* Another WWN used to have our s_id. Our PLOGI scheduled its
 	 * session deletion, but it's still in sess_del_work wq */
@@ -4496,14 +4395,11 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
 {
 	struct atio_from_isp *a = (struct atio_from_isp *)iocb;
 	struct qla_hw_data *ha = vha->hw;
-	struct qla_tgt *tgt;
 	struct fc_port *sess;
 	u64 unpacked_lun;
 	int fn;
 	unsigned long flags;
 
-	tgt = vha->vha_tgt.qla_tgt;
-
 	fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
 
 	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -4514,15 +4410,7 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
 	unpacked_lun =
 	    scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
 
-	if (!sess) {
-		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf024,
-		    "qla_target(%d): task mgmt fn 0x%x for "
-		    "non-existant session\n", vha->vp_idx, fn);
-		return qlt_sched_sess_work(tgt, QLA_TGT_SESS_WORK_TM, iocb,
-		    sizeof(struct atio_from_isp));
-	}
-
-	if (sess->deleted)
+	if (sess == NULL || sess->deleted)
 		return -EFAULT;
 
 	return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
-- 
2.12.0

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

* [PATCH 29/43] qla2xxx: Fix GPNFT/GNNFT error handling
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (27 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 28/43] qla2xxx: Remove session creation redundant code Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 30/43] qla2xxx: Properly extract ADISC error codes Himanshu Madhani
                   ` (13 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

retry gpnft/gnnft if error is encountered.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_gs.c   | 15 +++++++++++++++
 drivers/scsi/qla2xxx/qla_init.c |  8 ++++----
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 0e84381e227e..0fcbdcaba127 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3927,6 +3927,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 		ql_dbg(ql_dbg_disc, vha, 0xffff,
 		    "GPNFT failed. FC4type %x. Rescanning.\n",
 		    fc4type);
+		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
 		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 		goto out;
 	}
@@ -4036,6 +4037,19 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
 	    "Async done-%s res %x FC4Type %x\n",
 	    sp->name, res, sp->gen2);
 
+	if (res) {
+		unsigned long flags;
+
+		ql_dbg(ql_dbg_disc, sp->vha, 0xffff,
+		    "Async done-%s timed out.\n",
+		    sp->name);
+		sp->free(sp);
+		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+		qla2xxx_wake_dpc(vha);
+		return;
+	}
+
 	if (!res) {
 		port_id_t id;
 		u64 wwn;
@@ -4097,6 +4111,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
 		    "Async done-%s unable to alloc work element\n",
 		    sp->name);
 		sp->free(sp);
+		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
 		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 		return;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 152c808b272b..e58faa1e984c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -683,15 +683,15 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 			}
 		}
 
-		id.b.domain = e->port_id[0];
+		id.b.domain = e->port_id[2];
 		id.b.area = e->port_id[1];
-		id.b.al_pa = e->port_id[2];
+		id.b.al_pa = e->port_id[0];
 		id.b.rsvd_1 = 0;
 
 		if (!found && wwn && !IS_SW_RESV_ADDR(id)) {
 			ql_dbg(ql_dbg_disc, vha, 0x2065,
-			    "%s %d %8phC post new sess\n",
-			    __func__, __LINE__, (u8 *)&wwn);
+			    "%s %d %8phC %06x post new sess\n",
+			    __func__, __LINE__, (u8 *)&wwn, id.b24);
 			wwnn = wwn_to_u64(e->node_name);
 			qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn,
 			    (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN);
-- 
2.12.0

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

* [PATCH 30/43] qla2xxx: Properly extract ADISC error codes
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (28 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 29/43] qla2xxx: Fix GPNFT/GNNFT error handling Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 31/43] qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling Himanshu Madhani
                   ` (12 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

This patch fixes issue with extraction of ADISC error codes
for decoding the error returned

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e58faa1e984c..bd28a0e6a95c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -338,16 +338,21 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
 static
 void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-	if (ea->rc) {
+	struct fc_port *fcport = ea->fcport;
+
+	ql_dbg(ql_dbg_disc, vha, 0x20d2,
+	    "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
+	    __func__, fcport->port_name, fcport->disc_state,
+	    fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
+	    fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
+
+	if (ea->data[0] != MBS_COMMAND_COMPLETE) {
 		ql_dbg(ql_dbg_disc, vha, 0x2066,
 		    "%s %8phC: adisc fail: post delete\n",
 		    __func__, ea->fcport->port_name);
 		qlt_schedule_sess_for_deletion(ea->fcport, 1);
 		return;
 	}
-	ql_dbg(ql_dbg_disc, vha, 0x20d2,
-	    "%s %8phC DS %d LS %d\n", __func__, ea->fcport->port_name,
-	    ea->fcport->disc_state, ea->fcport->fw_login_state);
 
 	if (ea->fcport->disc_state == DSC_DELETE_PEND)
 		return;
@@ -355,10 +360,8 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	if (ea->sp->gen2 != ea->fcport->login_gen) {
 		/* target side must have changed it. */
 		ql_dbg(ql_dbg_disc, vha, 0x20d3,
-		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-		    __func__, ea->fcport->port_name, ea->fcport->last_rscn_gen,
-		    ea->fcport->rscn_gen, ea->fcport->last_login_gen,
-		    ea->fcport->login_gen);
+		    "%s %8phC generation changed\n",
+		    __func__, ea->fcport->port_name);
 		return;
 	} else if (ea->sp->gen1 != ea->fcport->rscn_gen) {
 		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
@@ -376,6 +379,7 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
 	srb_t *sp = ptr;
 	struct scsi_qla_host *vha = sp->vha;
 	struct event_arg ea;
+	struct srb_iocb *lio = &sp->u.iocb_cmd;
 
 	ql_dbg(ql_dbg_disc, vha, 0x2066,
 	    "Async done-%s res %x %8phC\n",
@@ -384,6 +388,10 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
 	memset(&ea, 0, sizeof(ea));
 	ea.event = FCME_ADISC_DONE;
 	ea.rc = res;
+	ea.data[0] = lio->u.logio.data[0];
+	ea.data[1] = lio->u.logio.data[1];
+	ea.iop[0] = lio->u.logio.iop[0];
+	ea.iop[1] = lio->u.logio.iop[1];
 	ea.fcport = sp->fcport;
 	ea.sp = sp;
 
-- 
2.12.0

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

* [PATCH 31/43] qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (29 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 30/43] qla2xxx: Properly extract ADISC error codes Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 32/43] qla2xxx: Allow relogin and session creation after reset Himanshu Madhani
                   ` (11 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

add ability to use gpnft/gnnft to handle RSCN.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |  7 +++
 drivers/scsi/qla2xxx/qla_gbl.h  |  1 +
 drivers/scsi/qla2xxx/qla_gs.c   | 99 ++++++++++++++++++++++++++++-------------
 drivers/scsi/qla2xxx/qla_init.c | 65 ++++++++++++++-------------
 drivers/scsi/qla2xxx/qla_os.c   |  1 +
 5 files changed, 113 insertions(+), 60 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index db1f68c3e074..f061483475ce 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3022,6 +3022,11 @@ struct ct_sns_gpnft_pkt {
 	} p;
 };
 
+enum scan_flags_t {
+	SF_SCANNING = BIT_0,
+	SF_QUEUED = BIT_1,
+};
+
 struct fab_scan_rp {
 	port_id_t id;
 	u8 port_name[8];
@@ -3031,6 +3036,8 @@ struct fab_scan_rp {
 struct fab_scan {
 	struct fab_scan_rp *l;
 	u32 size;
+	enum scan_flags_t scan_flags;
+	struct delayed_work scan_work;
 };
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 650ec54e3255..91db1924ca79 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -669,6 +669,7 @@ int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
 void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea);
 void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);
+void qla_scan_work_fn(struct work_struct *);
 
 /*
  * Global Function Prototypes in qla_attr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 0fcbdcaba127..903f924f6273 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3025,8 +3025,10 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	fc_port_t *fcport = ea->fcport;
 
 	ql_dbg(ql_dbg_disc, vha, 0x201d,
-	    "%s %8phC login state %d\n",
-	    __func__, fcport->port_name, fcport->fw_login_state);
+	    "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
+	    __func__, fcport->port_name, fcport->disc_state,
+	    fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
+	    fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
 
 	if (fcport->disc_state == DSC_DELETE_PEND)
 		return;
@@ -3034,9 +3036,9 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	if (ea->sp->gen2 != fcport->login_gen) {
 		/* PLOGI/PRLI/LOGO came in while cmd was out.*/
 		ql_dbg(ql_dbg_disc, vha, 0x201e,
-		    "%s %8phC generation changed rscn %d|%d login %d|%d \n",
+		    "%s %8phC generation changed rscn %d|%d n",
 		    __func__, fcport->port_name, fcport->last_rscn_gen,
-		    fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen);
+		    fcport->rscn_gen);
 		return;
 	}
 
@@ -3264,11 +3266,10 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	struct fc_port *fcport = ea->fcport;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20d8,
-	    "%s %8phC DS %d LS %d rscn %d|%d login %d|%d lid %d\n",
+	    "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
 	    __func__, fcport->port_name, fcport->disc_state,
-	    fcport->fw_login_state, fcport->last_rscn_gen, fcport->rscn_gen,
-	    fcport->last_login_gen, fcport->login_gen,
-	    fcport->loop_id);
+	    fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
+	    ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1, fcport->loop_id);
 
 	if (fcport->disc_state == DSC_DELETE_PEND)
 		return;
@@ -3276,10 +3277,8 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	if (ea->sp->gen2 != fcport->login_gen) {
 		/* target side must have changed it. */
 		ql_dbg(ql_dbg_disc, vha, 0x20d3,
-		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-		    __func__, fcport->port_name, fcport->last_rscn_gen,
-		    fcport->rscn_gen, fcport->last_login_gen,
-		    fcport->login_gen);
+		    "%s %8phC generation changed\n",
+		    __func__, fcport->port_name);
 		return;
 	} else if (ea->sp->gen1 != fcport->rscn_gen) {
 		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
@@ -3911,6 +3910,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 	bool found;
 	u8 fc4type = sp->gen2;
 	struct fab_scan_rp *rp;
+	unsigned long flags;
 
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "%s enter\n", __func__);
@@ -3988,16 +3988,15 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 		if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
 			continue;
 
-		if (fcport->scan_state == QLA_FCPORT_SCAN) {
+		if (fcport->scan_state != QLA_FCPORT_FOUND) {
 			if ((qla_dual_mode_enabled(vha) ||
 				qla_ini_mode_enabled(vha)) &&
 			    atomic_read(&fcport->state) == FCS_ONLINE) {
 				qla2x00_mark_device_lost(vha, fcport,
 				    ql2xplogiabsentdevice, 0);
+
 				if (fcport->loop_id != FC_NO_LOOP_ID &&
-				    (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
-				    fcport->port_type != FCT_INITIATOR &&
-				    fcport->port_type != FCT_BROADCAST) {
+				    (fcport->flags & FCF_FCP2_DEVICE) == 0) {
 					ql_dbg(ql_dbg_disc, vha, 0x20f0,
 					    "%s %d %8phC post del sess\n",
 					    __func__, __LINE__,
@@ -4008,14 +4007,16 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 					continue;
 				}
 			}
-		}
-
-		if (fcport->scan_state == QLA_FCPORT_FOUND)
+		} else
 			qla24xx_fcport_handle_login(vha, fcport);
 	}
 
 out:
 	qla24xx_sp_unmap(vha, sp);
+
+	spin_lock_irqsave(&vha->work_lock, flags);
+	vha->scan.scan_flags &= ~SF_SCANNING;
+	spin_unlock_irqrestore(&vha->work_lock, flags);
 }
 
 static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
@@ -4044,6 +4045,9 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
 		    "Async done-%s timed out.\n",
 		    sp->name);
 		sp->free(sp);
+		spin_lock_irqsave(&vha->work_lock, flags);
+		vha->scan.scan_flags &= ~SF_SCANNING;
+		spin_unlock_irqrestore(&vha->work_lock, flags);
 		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
 		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 		qla2xxx_wake_dpc(vha);
@@ -4135,14 +4139,17 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
 	struct ct_sns_req *ct_req;
 	struct ct_sns_pkt *ct_sns;
 
-	if (!vha->flags.online)
+	if (!vha->flags.online) {
+		vha->scan.scan_flags &= ~SF_SCANNING;
 		goto done_free_sp;
+	}
 
 	if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
 		ql_log(ql_log_warn, vha, 0xffff,
 		    "%s: req %p rsp %p are not setup\n",
 		    __func__, sp->u.iocb_cmd.u.ctarg.req,
 		    sp->u.iocb_cmd.u.ctarg.rsp);
+		vha->scan.scan_flags &= ~SF_SCANNING;
 		WARN_ON(1);
 		goto done_free_sp;
 	}
@@ -4170,8 +4177,10 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
 	sp->done = qla2x00_async_gpnft_gnnft_sp_done;
 
 	rval = qla2x00_start_sp(sp);
-	if (rval != QLA_SUCCESS)
+	if (rval != QLA_SUCCESS) {
+		vha->scan.scan_flags &= ~SF_SCANNING;
 		goto done_free_sp;
+	}
 
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
@@ -4215,14 +4224,25 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
 	srb_t *sp;
 	struct ct_sns_pkt *ct_sns;
 	u32 rspsz;
+	unsigned long flags;
 
 	if (!vha->flags.online)
 		return rval;
 
-	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
-	if (!sp)
+	spin_lock_irqsave(&vha->work_lock, flags);
+	if (vha->scan.scan_flags & SF_SCANNING) {
+		spin_unlock_irqrestore(&vha->work_lock, flags);
+		ql_dbg(ql_dbg_disc, vha, 0xffff, "scan active\n");
 		return rval;
+	}
+	vha->scan.scan_flags |= SF_SCANNING;
+	spin_unlock_irqrestore(&vha->work_lock, flags);
 
+	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+	if (!sp) {
+		vha->scan.scan_flags &= ~SF_SCANNING;
+		return rval;
+	}
 
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = sp_to_str(SPCN_GPNFT);
@@ -4236,6 +4256,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
 	if (!sp->u.iocb_cmd.u.ctarg.req) {
 		ql_log(ql_log_warn, vha, 0xffff,
 		    "Failed to allocate ct_sns request.\n");
+		vha->scan.scan_flags &= ~SF_SCANNING;
 		goto done_free_sp;
 	}
 
@@ -4248,6 +4269,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
 	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
 		ql_log(ql_log_warn, vha, 0xffff,
 		    "Failed to allocate ct_sns request.\n");
+		vha->scan.scan_flags &= ~SF_SCANNING;
 		goto done_free_sp;
 	}
 
@@ -4297,6 +4319,24 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
 	return rval;
 }
 
+void qla_scan_work_fn(struct work_struct *work)
+{
+	struct fab_scan *s = container_of(to_delayed_work(work),
+	    struct fab_scan, scan_work);
+	struct scsi_qla_host *vha = container_of(s, struct scsi_qla_host,
+	    scan);
+	unsigned long flags;
+
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "%s: schedule loop resync\n", __func__);
+	set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+	set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+	qla2xxx_wake_dpc(vha);
+	spin_lock_irqsave(&vha->work_lock, flags);
+	vha->scan.scan_flags &= ~SF_QUEUED;
+	spin_unlock_irqrestore(&vha->work_lock, flags);
+}
+
 /* GNN_ID */
 void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
@@ -4416,9 +4456,10 @@ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	fc_port_t *fcport = ea->fcport;
 
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
-	    "%s %d %8phC post gpsc fcp_cnt %d\n",
-	    __func__, __LINE__, fcport->port_name,
-	    vha->fcport_count);
+	    "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d fcpcnt %d\n",
+	    __func__, fcport->port_name, fcport->disc_state,
+	    fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
+	    fcport->rscn_gen, ea->sp->gen1, vha->fcport_count);
 
 	if (fcport->disc_state == DSC_DELETE_PEND)
 		return;
@@ -4426,10 +4467,8 @@ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	if (ea->sp->gen2 != fcport->login_gen) {
 		/* target side must have changed it. */
 		ql_dbg(ql_dbg_disc, vha, 0x20d3,
-		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-		    __func__, fcport->port_name, fcport->last_rscn_gen,
-		    fcport->rscn_gen, fcport->last_login_gen,
-		    fcport->login_gen);
+		    "%s %8phC generation changed\n",
+		    __func__, fcport->port_name);
 		return;
 	} else if (ea->sp->gen1 != fcport->rscn_gen) {
 		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index bd28a0e6a95c..ac3f82340315 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -455,6 +455,12 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 	u8 current_login_state;
 
 	fcport = ea->fcport;
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "%s %8phC DS %d LS rc %d %d login %d|%d rscn %d|%d lid %d\n",
+	    __func__, fcport->port_name, fcport->disc_state,
+	    fcport->fw_login_state, ea->rc,
+	    fcport->login_gen, fcport->last_login_gen,
+	    fcport->rscn_gen, fcport->last_rscn_gen, vha->loop_id);
 
 	if (fcport->disc_state == DSC_DELETE_PEND)
 		return;
@@ -478,9 +484,8 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 		return;
 	} else if (fcport->last_login_gen != fcport->login_gen) {
 		ql_dbg(ql_dbg_disc, vha, 0x20e0,
-		    "%s %8phC login gen changed login %d|%d\n",
-		    __func__, fcport->port_name,
-		    fcport->last_login_gen, fcport->login_gen);
+		    "%s %8phC login gen changed\n",
+		    __func__, fcport->port_name);
 		return;
 	}
 
@@ -1060,7 +1065,6 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 static
 void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-	int rval = ea->rc;
 	fc_port_t *fcport = ea->fcport;
 	struct port_database_24xx *pd;
 	struct srb *sp = ea->sp;
@@ -1070,8 +1074,8 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	fcport->flags &= ~FCF_ASYNC_SENT;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20d2,
-	    "%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
-	    fcport->disc_state, pd->current_login_state, rval);
+	    "%s %8phC DS %d LS %d rc %d\n", __func__, fcport->port_name,
+	    fcport->disc_state, pd->current_login_state, ea->rc);
 
 	if (fcport->disc_state == DSC_DELETE_PEND)
 		return;
@@ -1141,11 +1145,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 	u64 wwn;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20d8,
-	    "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d scan %d\n",
+	    "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d retry %d lid %d scan %d\n",
 	    __func__, fcport->port_name, fcport->disc_state,
 	    fcport->fw_login_state, fcport->login_pause, fcport->flags,
 	    fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
-	    fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
+	    fcport->login_gen, fcport->login_retry,
 	    fcport->loop_id, fcport->scan_state);
 
 	if (fcport->login_retry == 0)
@@ -1322,9 +1326,9 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 
 void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-	fc_port_t *fcport, *f, *tf;
+	fc_port_t *f, *tf;
 	uint32_t id = 0, mask, rid;
-	int rc;
+	unsigned long flags;
 
 	switch (ea->event) {
 	case FCME_RSCN:
@@ -1352,20 +1356,15 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 			return;
 		switch (ea->id.b.rsvd_1) {
 		case RSCN_PORT_ADDR:
-			fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
-			if (!fcport) {
-				/* cable moved */
-				rc = qla24xx_post_gpnid_work(vha, &ea->id);
-				if (rc) {
-					ql_log(ql_log_warn, vha, 0xd044,
-					    "RSCN GPNID work failed %02x%02x%02x\n",
-					    ea->id.b.domain, ea->id.b.area,
-					    ea->id.b.al_pa);
-				}
-			} else {
-				ea->fcport = fcport;
-				qla24xx_handle_rscn_event(fcport, ea);
+			spin_lock_irqsave(&vha->work_lock, flags);
+			if (vha->scan.scan_flags == 0) {
+				ql_dbg(ql_dbg_disc, vha, 0xffff,
+				    "%s: schedule\n", __func__);
+				vha->scan.scan_flags |= SF_QUEUED;
+				schedule_delayed_work(&vha->scan.scan_work, 5);
 			}
+			spin_unlock_irqrestore(&vha->work_lock, flags);
+
 			break;
 		case RSCN_AREA_ADDR:
 		case RSCN_DOM_ADDR:
@@ -1644,6 +1643,13 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 	unsigned long flags;
 	struct fc_port *fcport = ea->fcport;
 
+	ql_dbg(ql_dbg_disc, vha, 0xffff,
+	    "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d data %x|%x iop %x|%x\n",
+	    __func__, fcport->port_name, fcport->disc_state,
+	    fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
+	    ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1,
+	    ea->data[0], ea->data[1], ea->iop[0], ea->iop[1]);
+
 	if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
 	    (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
 		ql_dbg(ql_dbg_disc, vha, 0x20ea,
@@ -1658,10 +1664,9 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 	if (ea->sp->gen2 != fcport->login_gen) {
 		/* target side must have changed it. */
 		ql_dbg(ql_dbg_disc, vha, 0x20d3,
-		    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-		    __func__, fcport->port_name, fcport->last_rscn_gen,
-		    fcport->rscn_gen, fcport->last_login_gen,
-		    fcport->login_gen);
+		    "%s %8phC generation changed\n",
+		    __func__, fcport->port_name);
+		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 		return;
 	} else if (ea->sp->gen1 != fcport->rscn_gen) {
 		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
@@ -5252,9 +5257,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
 			}
 		}
 
-		list_for_each_entry(fcport, &vha->vp_fcports, list) {
-			fcport->scan_state = QLA_FCPORT_SCAN;
-		}
 
 		/* Mark the time right before querying FW for connected ports.
 		 * This process is long, asynchronous and by the time it's done,
@@ -5270,6 +5272,9 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
 			if (rval)
 				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 		} else  {
+			list_for_each_entry(fcport, &vha->vp_fcports, list)
+				fcport->scan_state = QLA_FCPORT_SCAN;
+
 			rval = qla2x00_find_all_fabric_devs(vha);
 		}
 		if (rval != QLA_SUCCESS)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d4a967410893..77fa8809cf4a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4589,6 +4589,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
 		scsi_remove_host(vha->host);
 		return NULL;
 	}
+	INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn);
 
 	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
 	ql_dbg(ql_dbg_init, vha, 0x0041,
-- 
2.12.0

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

* [PATCH 32/43] qla2xxx: Allow relogin and session creation after reset
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (30 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 31/43] qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 33/43] qla2xxx: Increase verbosity of debug messages logged Himanshu Madhani
                   ` (10 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

When any kind of reset is issued, current code was setting
state of LOGIN pending too early. This resulted into driver
not retrying relogin until pervious reloin completes.

Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index ac3f82340315..80e9d80cce2b 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1134,7 +1134,6 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 		ql_dbg(ql_dbg_disc, vha, 0x20bf,
 		    "%s %d %8phC post login\n",
 		    __func__, __LINE__, fcport->port_name);
-		fcport->disc_state = DSC_LOGIN_PEND;
 		qla2x00_post_async_login_work(vha, fcport, NULL);
 	}
 }
-- 
2.12.0

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

* [PATCH 33/43] qla2xxx: Increase verbosity of debug messages logged
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (31 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 32/43] qla2xxx: Allow relogin and session creation after reset Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 34/43] qla2xxx: Delay loop id allocation at login Himanshu Madhani
                   ` (9 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Add verbose bit for debug messages to reduce excessive
log messages

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_target.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 598ec3481a8c..43e210757840 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -209,7 +209,7 @@ struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
 
 	host = btree_lookup32(&vha->hw->tgt.host_map, key);
 	if (!host)
-		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005,
+		ql_dbg(ql_dbg_tgt_mgt + ql_dbg_verbose, vha, 0xf005,
 		    "Unable to find host %06x\n", key);
 
 	return host;
@@ -310,17 +310,17 @@ static void qlt_try_to_dequeue_unknown_atios(struct scsi_qla_host *vha,
 
 		host = qlt_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id);
 		if (host != NULL) {
-			ql_dbg(ql_dbg_async, vha, 0x502f,
+			ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x502f,
 			    "Requeuing unknown ATIO_TYPE7 %p\n", u);
 			qlt_24xx_atio_pkt(host, &u->atio, ha_locked);
 		} else if (tgt->tgt_stop) {
-			ql_dbg(ql_dbg_async, vha, 0x503a,
+			ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x503a,
 			    "Freeing unknown %s %p, because tgt is being stopped\n",
 			    "ATIO_TYPE7", u);
 			qlt_send_term_exchange(vha->hw->base_qpair, NULL,
 			    &u->atio, ha_locked, 0);
 		} else {
-			ql_dbg(ql_dbg_async, vha, 0x503d,
+			ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x503d,
 			    "Reschedule u %p, vha %p, host %p\n", u, vha, host);
 			if (!queued) {
 				queued = 1;
-- 
2.12.0

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

* [PATCH 34/43] qla2xxx: Delay loop id allocation at login
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (32 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 33/43] qla2xxx: Increase verbosity of debug messages logged Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 35/43] qla2xxx: Add retry limit for fabric scan logic Himanshu Madhani
                   ` (8 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Delay loop id allocation to login time

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 64 ++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 29 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 80e9d80cce2b..185c106cec0c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -582,36 +582,29 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 
 	if (!found) {
 		/* fw has no record of this port */
-		if (fcport->loop_id == FC_NO_LOOP_ID) {
-			qla2x00_find_new_loop_id(vha, fcport);
-			fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
-		} else {
-			for (i = 0; i < n; i++) {
-				e = &vha->gnl.l[i];
-				id.b.domain = e->port_id[0];
-				id.b.area = e->port_id[1];
-				id.b.al_pa = e->port_id[2];
-				id.b.rsvd_1 = 0;
-				loop_id = le16_to_cpu(e->nport_handle);
-
-				if (fcport->d_id.b24 == id.b24) {
-					conflict_fcport =
-					    qla2x00_find_fcport_by_wwpn(vha,
-						e->port_name, 0);
-
-					ql_dbg(ql_dbg_disc, vha, 0x20e6,
-					    "%s %d %8phC post del sess\n",
-					    __func__, __LINE__,
-					    conflict_fcport->port_name);
-					qlt_schedule_sess_for_deletion
-						(conflict_fcport, 1);
-				}
-
-				if (fcport->loop_id == loop_id) {
-					/* FW already picked this loop id for another fcport */
-					qla2x00_find_new_loop_id(vha, fcport);
-				}
+		for (i = 0; i < n; i++) {
+			e = &vha->gnl.l[i];
+			id.b.domain = e->port_id[0];
+			id.b.area = e->port_id[1];
+			id.b.al_pa = e->port_id[2];
+			id.b.rsvd_1 = 0;
+			loop_id = le16_to_cpu(e->nport_handle);
+
+			if (fcport->d_id.b24 == id.b24) {
+				conflict_fcport =
+					qla2x00_find_fcport_by_wwpn(vha,
+					    e->port_name, 0);
+				ql_dbg(ql_dbg_disc, vha, 0x20e6,
+				    "%s %d %8phC post del sess\n",
+				    __func__, __LINE__,
+				    conflict_fcport->port_name);
+				qlt_schedule_sess_for_deletion
+					(conflict_fcport, 1);
 			}
+
+			/* FW already picked this loop id for another fcport */
+			if (fcport->loop_id == loop_id)
+				fcport->loop_id = FC_NO_LOOP_ID;
 		}
 		qla24xx_fcport_handle_login(vha, fcport);
 	}
@@ -1106,6 +1099,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
 	u8 login = 0;
+	int rc;
 
 	if (qla_tgt_mode_enabled(vha))
 		return;
@@ -1131,6 +1125,18 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 	}
 
 	if (login) {
+		if (fcport->loop_id == FC_NO_LOOP_ID) {
+			fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+			rc = qla2x00_find_new_loop_id(vha, fcport);
+			if (rc) {
+				ql_dbg(ql_dbg_disc, vha, 0x20e6,
+				    "%s %d %8phC post del sess - out of loopid\n",
+				    __func__, __LINE__, fcport->port_name);
+				fcport->scan_state = 0;
+				qlt_schedule_sess_for_deletion(fcport, true);
+				return;
+			}
+		}
 		ql_dbg(ql_dbg_disc, vha, 0x20bf,
 		    "%s %d %8phC post login\n",
 		    __func__, __LINE__, fcport->port_name);
-- 
2.12.0

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

* [PATCH 35/43] qla2xxx: Add retry limit for fabric scan logic
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (33 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 34/43] qla2xxx: Delay loop id allocation at login Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 36/43] qla2xxx: Add counters for Exchange Buffer to debugfs Himanshu Madhani
                   ` (7 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Switch scan is assumed to succeed most of the time.
If the scan failed, then scan is limit 5 retries.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  2 ++
 drivers/scsi/qla2xxx/qla_gs.c  | 33 ++++++++++++++++++++-------------
 drivers/scsi/qla2xxx/qla_isr.c |  1 +
 3 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index f061483475ce..3811ccd1c60b 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3036,6 +3036,8 @@ struct fab_scan_rp {
 struct fab_scan {
 	struct fab_scan_rp *l;
 	u32 size;
+	u16 scan_retry;
+#define MAX_SCAN_RETRIES 5
 	enum scan_flags_t scan_flags;
 	struct delayed_work scan_work;
 };
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 903f924f6273..8256b65e9e7a 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3924,13 +3924,17 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 
 	rc = sp->rc;
 	if (rc) {
-		ql_dbg(ql_dbg_disc, vha, 0xffff,
-		    "GPNFT failed. FC4type %x. Rescanning.\n",
-		    fc4type);
-		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
-		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+		vha->scan.scan_retry++;
+		if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
+			set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+		} else {
+			ql_dbg(ql_dbg_disc, vha, 0xffff,
+			    "Fabric scan failed on all retries.\n");
+		}
 		goto out;
 	}
+	vha->scan.scan_retry = 0;
 
 	list_for_each_entry(fcport, &vha->vp_fcports, list)
 		fcport->scan_state = QLA_FCPORT_SCAN;
@@ -4013,7 +4017,6 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 
 out:
 	qla24xx_sp_unmap(vha, sp);
-
 	spin_lock_irqsave(&vha->work_lock, flags);
 	vha->scan.scan_flags &= ~SF_SCANNING;
 	spin_unlock_irqrestore(&vha->work_lock, flags);
@@ -4041,16 +4044,20 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
 	if (res) {
 		unsigned long flags;
 
-		ql_dbg(ql_dbg_disc, sp->vha, 0xffff,
-		    "Async done-%s timed out.\n",
-		    sp->name);
 		sp->free(sp);
 		spin_lock_irqsave(&vha->work_lock, flags);
 		vha->scan.scan_flags &= ~SF_SCANNING;
-		spin_unlock_irqrestore(&vha->work_lock, flags);
-		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
-		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
-		qla2xxx_wake_dpc(vha);
+		vha->scan.scan_retry++;
+
+		if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
+			set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+			qla2xxx_wake_dpc(vha);
+		} else {
+			ql_dbg(ql_dbg_disc, sp->vha, 0xffff,
+			    "Async done-%s rescan failed on all retries\n",
+			    sp->name);
+		}
 		return;
 	}
 
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f02c98b3e8a7..6974657dd8c6 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1059,6 +1059,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		 * Mark all devices as missing so we will login again.
 		 */
 		atomic_set(&vha->loop_state, LOOP_UP);
+		vha->scan.scan_retry = 0;
 
 		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
-- 
2.12.0

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

* [PATCH 36/43] qla2xxx: Add counters for Exchange Buffer to debugfs
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (34 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 35/43] qla2xxx: Add retry limit for fabric scan logic Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 37/43] qla2xxx: Prevent multiple active discovery commands per session Himanshu Madhani
                   ` (6 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

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

Signed-off-by: Anil Gurumurthy <anil.gurumurthy@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_dfs.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 4f0415e158cb..c05ebc6ebe78 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -143,6 +143,15 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
 		seq_printf(s, "Current IOCB count[%d]\n", mb[10]);
 		seq_printf(s, "MAX VP count[%d]\n", mb[11]);
 		seq_printf(s, "MAX FCF count[%d]\n", mb[12]);
+		seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n",
+		    mb[20]);
+		seq_printf(s, "Original Initiator fast XCB buffer cnt[%d]\n",
+		    mb[21]);
+		seq_printf(s, "Current free Initiator fast XCB buffer cnt[%d]\n",
+		    mb[22]);
+		seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n",
+		    mb[23]);
+
 	}
 
 	return 0;
-- 
2.12.0

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

* [PATCH 37/43] qla2xxx: Prevent multiple active discovery commands per session
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (35 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 36/43] qla2xxx: Add counters for Exchange Buffer to debugfs Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 38/43] qla2xxx: Prevent relogin trigger from sending too many commands Himanshu Madhani
                   ` (5 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Add check to allow single discovery command per session to be sent

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_gs.c   | 16 ++++++++--------
 drivers/scsi/qla2xxx/qla_init.c | 11 ++++++-----
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 8256b65e9e7a..29b63c2a380b 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3176,16 +3176,16 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
 	struct ct_sns_req       *ct_req;
 	srb_t *sp;
 
-	if (!vha->flags.online)
+	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
 		goto done;
 
-	fcport->flags |= FCF_ASYNC_SENT;
 	fcport->disc_state = DSC_GID_PN;
 	fcport->scan_state = QLA_FCPORT_SCAN;
 	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
 	if (!sp)
 		goto done;
 
+	fcport->flags |= FCF_ASYNC_SENT;
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = sp_to_str(SPCN_GIDPN);
 	sp->gen1 = fcport->rscn_gen;
@@ -3226,8 +3226,8 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
 
 done_free_sp:
 	sp->free(sp);
-done:
 	fcport->flags &= ~FCF_ASYNC_SENT;
+done:
 	return rval;
 }
 
@@ -3368,14 +3368,14 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
 	struct ct_sns_req       *ct_req;
 	srb_t *sp;
 
-	if (!vha->flags.online)
+	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
 		goto done;
 
-	fcport->flags |= FCF_ASYNC_SENT;
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
 
+	fcport->flags |= FCF_ASYNC_SENT;
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = sp_to_str(SPCN_GPSC);
 	sp->gen1 = fcport->rscn_gen;
@@ -3415,8 +3415,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
 
 done_free_sp:
 	sp->free(sp);
-done:
 	fcport->flags &= ~FCF_ASYNC_SENT;
+done:
 	return rval;
 }
 
@@ -3829,7 +3829,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	struct ct_sns_req       *ct_req;
 	srb_t *sp;
 
-	if (!vha->flags.online)
+	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
 		return rval;
 
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
@@ -4525,12 +4525,12 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	if (!vha->flags.online)
 		goto done;
 
-	fcport->flags |= FCF_ASYNC_SENT;
 	fcport->disc_state = DSC_GFPN_ID;
 	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
 	if (!sp)
 		goto done;
 
+	fcport->flags |= FCF_ASYNC_SENT;
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = sp_to_str(SPCN_GFPNID);
 	sp->gen1 = fcport->rscn_gen;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 185c106cec0c..f42f2f16343f 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -206,7 +206,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
-		fcport->flags &= ~FCF_ASYNC_SENT;
 		fcport->flags |= FCF_LOGIN_NEEDED;
 		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 		goto done_free_sp;
@@ -221,8 +220,8 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 
 done_free_sp:
 	sp->free(sp);
-done:
 	fcport->flags &= ~FCF_ASYNC_SENT;
+done:
 	return rval;
 }
 
@@ -244,9 +243,11 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
 	srb_t *sp;
 	struct srb_iocb *lio;
-	int rval;
+	int rval = QLA_FUNCTION_FAILED;
+
+	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+		return rval;
 
-	rval = QLA_FUNCTION_FAILED;
 	fcport->flags |= FCF_ASYNC_SENT;
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
@@ -717,7 +718,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	unsigned long flags;
 	u16 *mb;
 
-	if (!vha->flags.online)
+	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
 		goto done;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20d9,
-- 
2.12.0

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

* [PATCH 38/43] qla2xxx: Prevent relogin trigger from sending too many commands
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (36 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 37/43] qla2xxx: Prevent multiple active discovery commands per session Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 39/43] qla2xxx: Check FCF_ASYNC_SENT flag Himanshu Madhani
                   ` (4 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

This patch adds check for pending work event before queueing
relogin work to prevent redundant work to be active at the
same time.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |  1 +
 drivers/scsi/qla2xxx/qla_gs.c   |  6 ++++--
 drivers/scsi/qla2xxx/qla_init.c | 14 +++++++++-----
 drivers/scsi/qla2xxx/qla_os.c   |  4 +++-
 4 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 3811ccd1c60b..0c31c8ad0c1e 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2504,6 +2504,7 @@ static const char * const port_state_str[] = {
 #define FCF_FCP2_DEVICE		BIT_2
 #define FCF_ASYNC_SENT		BIT_3
 #define FCF_CONF_COMP_SUPPORTED BIT_4
+#define FCF_ASYNC_ACTIVE	BIT_5
 
 /* No loop ID flag. */
 #define FC_NO_LOOP_ID		0x1000
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 29b63c2a380b..dd02cbfd0fb1 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3137,7 +3137,7 @@ static void qla2x00_async_gidpn_sp_done(void *s, int res)
 	u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
 	struct event_arg ea;
 
-	fcport->flags &= ~FCF_ASYNC_SENT;
+	fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 
 	memset(&ea, 0, sizeof(ea));
 	ea.fcport = fcport;
@@ -3246,6 +3246,7 @@ int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 		return QLA_FUNCTION_FAILED;
 
 	e->u.fcport.fcport = fcport;
+	fcport->flags |= FCF_ASYNC_ACTIVE;
 	return qla2x00_post_work(vha, e);
 }
 
@@ -3258,6 +3259,7 @@ int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 		return QLA_FUNCTION_FAILED;
 
 	e->u.fcport.fcport = fcport;
+	fcport->flags |= FCF_ASYNC_ACTIVE;
 	return qla2x00_post_work(vha, e);
 }
 
@@ -3305,7 +3307,7 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
 	    "Async done-%s res %x, WWPN %8phC \n",
 	    sp->name, res, fcport->port_name);
 
-	fcport->flags &= ~FCF_ASYNC_SENT;
+	fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 
 	if (res == (DID_ERROR << 16)) {
 		/* entry status error */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f42f2f16343f..85bdb6928ea2 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -109,7 +109,7 @@ qla2x00_async_iocb_timeout(void *data)
 		    "Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
 		    sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
 
-		fcport->flags &= ~FCF_ASYNC_SENT;
+		fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 	} else {
 		pr_info("Async-%s timeout - hdl=%x.\n",
 		    sp->name, sp->handle);
@@ -154,7 +154,8 @@ qla2x00_async_login_sp_done(void *ptr, int res)
 	ql_dbg(ql_dbg_disc, vha, 0x20dd,
 	    "%s %8phC res %d \n", __func__, sp->fcport->port_name, res);
 
-	sp->fcport->flags &= ~FCF_ASYNC_SENT;
+	sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+
 	if (!test_bit(UNLOADING, &vha->dpc_flags)) {
 		memset(&ea, 0, sizeof(ea));
 		ea.event = FCME_PLOGI_DONE;
@@ -231,7 +232,7 @@ qla2x00_async_logout_sp_done(void *ptr, int res)
 	srb_t *sp = ptr;
 	struct srb_iocb *lio = &sp->u.iocb_cmd;
 
-	sp->fcport->flags &= ~FCF_ASYNC_SENT;
+	sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 	if (!test_bit(UNLOADING, &sp->vha->dpc_flags))
 		qla2x00_post_async_logout_done_work(sp->vha, sp->fcport,
 		    lio->u.logio.data);
@@ -667,7 +668,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 
 	list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
 		list_del_init(&fcport->gnl_entry);
-		fcport->flags &= ~FCF_ASYNC_SENT;
+		fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 		ea.fcport = fcport;
 
 		qla2x00_fcport_event_handler(vha, &ea);
@@ -790,6 +791,7 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 		return QLA_FUNCTION_FAILED;
 
 	e->u.fcport.fcport = fcport;
+	fcport->flags |= FCF_ASYNC_ACTIVE;
 	return qla2x00_post_work(vha, e);
 }
 
@@ -807,7 +809,7 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
 	    "Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
 	    sp->name, res, fcport->port_name, mb[1], mb[2]);
 
-	fcport->flags &= ~FCF_ASYNC_SENT;
+	fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 
 	memset(&ea, 0, sizeof(ea));
 	ea.event = FCME_GPDB_DONE;
@@ -930,6 +932,7 @@ int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 
 	e->u.fcport.fcport = fcport;
 	e->u.fcport.opt = opt;
+	fcport->flags |= FCF_ASYNC_ACTIVE;
 	return qla2x00_post_work(vha, e);
 }
 
@@ -1519,6 +1522,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 
 done_free_sp:
 	sp->free(sp);
+	sp->fcport->flags &= ~FCF_ASYNC_SENT;
 done:
 	return rval;
 }
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 77fa8809cf4a..22ab1a6dd577 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4686,6 +4686,7 @@ int qla2x00_post_async_##name##_work(		\
 		e->u.logio.data[0] = data[0];	\
 		e->u.logio.data[1] = data[1];	\
 	}					\
+	fcport->flags |= FCF_ASYNC_ACTIVE;	\
 	return qla2x00_post_work(vha, e);	\
 }
 
@@ -5065,7 +5066,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 		 * to it if we haven't run out of retries.
 		 */
 		if (atomic_read(&fcport->state) != FCS_ONLINE &&
-		    fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
+		    fcport->login_retry &&
+		    !(fcport->flags & (FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE))) {
 			if (vha->hw->current_topology != ISP_CFG_NL) {
 				ql_dbg(ql_dbg_disc, fcport->vha, 0x2108,
 				    "%s %8phC DS %d LS %d\n", __func__,
-- 
2.12.0

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

* [PATCH 39/43] qla2xxx: Check FCF_ASYNC_SENT flag
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (37 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 38/43] qla2xxx: Prevent relogin trigger from sending too many commands Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 40/43] qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion() Himanshu Madhani
                   ` (3 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 85bdb6928ea2..49a8f2666f55 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -720,7 +720,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	u16 *mb;
 
 	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
-		goto done;
+		return rval;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20d9,
 	    "Async-gnlist WWPN %8phC \n", fcport->port_name);
@@ -734,8 +734,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
 	if (vha->gnl.sent) {
 		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
-		rval = QLA_SUCCESS;
-		goto done;
+		return QLA_SUCCESS;
 	}
 	vha->gnl.sent = 1;
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
-- 
2.12.0

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

* [PATCH 40/43] qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion()
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (38 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 39/43] qla2xxx: Check FCF_ASYNC_SENT flag Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 41/43] qla2xxx: Serialize session deletion by using work_lock Himanshu Madhani
                   ` (2 subsequent siblings)
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Immeadiate flag is not used for scheduling session deletion.
Remove it to simplfy session deletion code path.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h    |  2 +-
 drivers/scsi/qla2xxx/qla_init.c   | 10 +++++-----
 drivers/scsi/qla2xxx/qla_target.c | 16 +++++++---------
 3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 91db1924ca79..ab8ffd7933c9 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -888,7 +888,7 @@ void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
 void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *,
 	struct fc_port *, enum qlt_plogi_link_t);
 void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
-extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
+extern void qlt_schedule_sess_for_deletion(struct fc_port *);
 extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
 extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
 	uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 49a8f2666f55..3e03c264f7bd 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -352,7 +352,7 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 		ql_dbg(ql_dbg_disc, vha, 0x2066,
 		    "%s %8phC: adisc fail: post delete\n",
 		    __func__, ea->fcport->port_name);
-		qlt_schedule_sess_for_deletion(ea->fcport, 1);
+		qlt_schedule_sess_for_deletion(ea->fcport);
 		return;
 	}
 
@@ -529,7 +529,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 			ql_dbg(ql_dbg_disc, vha, 0x20e3,
 			    "%s %d %8phC post del sess\n",
 			    __func__, __LINE__, fcport->port_name);
-			qlt_schedule_sess_for_deletion(fcport, 1);
+			qlt_schedule_sess_for_deletion(fcport);
 			return;
 		}
 
@@ -601,7 +601,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 				    __func__, __LINE__,
 				    conflict_fcport->port_name);
 				qlt_schedule_sess_for_deletion
-					(conflict_fcport, 1);
+					(conflict_fcport);
 			}
 
 			/* FW already picked this loop id for another fcport */
@@ -1136,7 +1136,7 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 				    "%s %d %8phC post del sess - out of loopid\n",
 				    __func__, __LINE__, fcport->port_name);
 				fcport->scan_state = 0;
-				qlt_schedule_sess_for_deletion(fcport, true);
+				qlt_schedule_sess_for_deletion(fcport);
 				return;
 			}
 		}
@@ -1782,7 +1782,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 			set_bit(lid, vha->hw->loop_id_map);
 			ea->fcport->loop_id = lid;
 			ea->fcport->keep_nport_handle = 0;
-			qlt_schedule_sess_for_deletion(ea->fcport, false);
+			qlt_schedule_sess_for_deletion(ea->fcport);
 		}
 		break;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 43e210757840..6b16f0dbd588 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1211,8 +1211,7 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess)
 }
 
 /* ha->tgt.sess_lock supposed to be held on entry */
-void qlt_schedule_sess_for_deletion(struct fc_port *sess,
-	bool immediate)
+void qlt_schedule_sess_for_deletion(struct fc_port *sess)
 {
 	struct qla_tgt *tgt = sess->tgt;
 
@@ -1250,7 +1249,7 @@ void qlt_schedule_sess_for_deletion_lock(struct fc_port *sess)
 	unsigned long flags;
 	struct qla_hw_data *ha = sess->vha->hw;
 	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
-	qlt_schedule_sess_for_deletion(sess, 1);
+	qlt_schedule_sess_for_deletion(sess);
 	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
 }
 
@@ -1262,7 +1261,7 @@ static void qlt_clear_tgt_db(struct qla_tgt *tgt)
 
 	list_for_each_entry(sess, &vha->vp_fcports, list) {
 		if (sess->se_sess)
-			qlt_schedule_sess_for_deletion(sess, 1);
+			qlt_schedule_sess_for_deletion(sess);
 	}
 
 	/* At this point tgt could be already dead */
@@ -1437,7 +1436,7 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
 	ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess);
 
 	sess->local = 1;
-	qlt_schedule_sess_for_deletion(sess, false);
+	qlt_schedule_sess_for_deletion(sess);
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 }
 
@@ -4541,7 +4540,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, uint64_t wwn,
 				 * might have cleared it when requested this session
 				 * deletion, so don't touch it
 				 */
-				qlt_schedule_sess_for_deletion(other_sess, true);
+				qlt_schedule_sess_for_deletion(other_sess);
 			} else {
 				/*
 				 * Another wwn used to have our s_id/loop_id
@@ -4554,8 +4553,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, uint64_t wwn,
 				other_sess->keep_nport_handle = 1;
 				if (other_sess->disc_state != DSC_DELETED)
 					*conflict_sess = other_sess;
-				qlt_schedule_sess_for_deletion(other_sess,
-				    true);
+				qlt_schedule_sess_for_deletion(other_sess);
 			}
 			continue;
 		}
@@ -4569,7 +4567,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, uint64_t wwn,
 
 			/* Same loop_id but different s_id
 			 * Ok to kill and logout */
-			qlt_schedule_sess_for_deletion(other_sess, true);
+			qlt_schedule_sess_for_deletion(other_sess);
 		}
 	}
 
-- 
2.12.0

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

* [PATCH 41/43] qla2xxx: Serialize session deletion by using work_lock
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (39 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 40/43] qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion() Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 42/43] qla2xxx: Serialize session free in qlt_free_session_done Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 43/43] qla2xxx: Update driver version to 10.00.00.04-k Himanshu Madhani
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

for session deletion, replace sess_lock with work_lock.
Under certain case sess_lock is not feasiable to acquire.
The lock is needed temporarily to make sure a single
call to schedule of the work element.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h    |  1 -
 drivers/scsi/qla2xxx/qla_gs.c     | 14 ++++++--------
 drivers/scsi/qla2xxx/qla_init.c   |  9 +++------
 drivers/scsi/qla2xxx/qla_isr.c    |  4 ++--
 drivers/scsi/qla2xxx/qla_mbx.c    |  2 +-
 drivers/scsi/qla2xxx/qla_os.c     |  5 ++---
 drivers/scsi/qla2xxx/qla_target.c | 29 ++++++++++++++---------------
 7 files changed, 28 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index ab8ffd7933c9..733906cb6c69 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -889,7 +889,6 @@ void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *,
 	struct fc_port *, enum qlt_plogi_link_t);
 void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
 extern void qlt_schedule_sess_for_deletion(struct fc_port *);
-extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
 extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
 	uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
 void qla24xx_delete_sess_fn(struct work_struct *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index dd02cbfd0fb1..f26d680fe6c1 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3096,7 +3096,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 					ql_dbg(ql_dbg_disc, vha, 0x2021,
 					    "%s %d %8phC post del sess\n",
 					    __func__, __LINE__, fcport->port_name);
-					qlt_schedule_sess_for_deletion_lock(fcport);
+					qlt_schedule_sess_for_deletion(fcport);
 				}
 			}
 		} else { /* ea->sp->gen1 != fcport->rscn_gen */
@@ -3113,7 +3113,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 				ql_dbg(ql_dbg_disc, vha, 0x2042,
 				    "%s %d %8phC post del sess\n", __func__,
 				    __LINE__, fcport->port_name);
-				qlt_schedule_sess_for_deletion_lock(fcport);
+				qlt_schedule_sess_for_deletion(fcport);
 			} else {
 				ql_dbg(ql_dbg_disc, vha, 0x2045,
 				    "%s %d %8phC login\n", __func__, __LINE__,
@@ -3485,8 +3485,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 					    "%s %d %8phC post del sess\n",
 					    __func__, __LINE__,
 					    fcport->port_name);
-					qlt_schedule_sess_for_deletion_lock
-						(fcport);
+					qlt_schedule_sess_for_deletion(fcport);
 					break;
 				}
 			}
@@ -3519,7 +3518,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 						    "%s %d %8phC post del sess\n",
 						    __func__, __LINE__,
 						    conflict->port_name);
-						qlt_schedule_sess_for_deletion_lock
+						qlt_schedule_sess_for_deletion
 							(conflict);
 						break;
 					}
@@ -3577,7 +3576,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 						    "%s %d %8phC post del sess\n",
 						    __func__, __LINE__,
 						    conflict->port_name);
-						qlt_schedule_sess_for_deletion_lock
+						qlt_schedule_sess_for_deletion
 							(conflict);
 						break;
 					}
@@ -4008,8 +4007,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 					    __func__, __LINE__,
 					    fcport->port_name);
 
-					qlt_schedule_sess_for_deletion_lock
-						(fcport);
+					qlt_schedule_sess_for_deletion(fcport);
 					continue;
 				}
 			}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 3e03c264f7bd..fdb453fc9708 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1093,7 +1093,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 	default:
 		ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
 		    __func__, __LINE__, fcport->port_name);
-		qlt_schedule_sess_for_deletion_lock(fcport);
+		qlt_schedule_sess_for_deletion(fcport);
 		return;
 	}
 	__qla24xx_handle_gpdb_event(vha, ea);
@@ -5002,8 +5002,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 					    __func__, __LINE__,
 					    fcport->port_name);
 
-					qlt_schedule_sess_for_deletion_lock
-						(fcport);
+					qlt_schedule_sess_for_deletion(fcport);
 					continue;
 				}
 			}
@@ -5590,9 +5589,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
 					    "%s %d %8phC post del sess\n",
 					    __func__, __LINE__,
 					    fcport->port_name);
-
-					qlt_schedule_sess_for_deletion_lock
-						(fcport);
+					qlt_schedule_sess_for_deletion(fcport);
 					continue;
 				}
 			}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 6974657dd8c6..8c771aaa523c 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1009,7 +1009,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 			if (qla_ini_mode_enabled(vha)) {
 				qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
 				fcport->logout_on_delete = 0;
-				qlt_schedule_sess_for_deletion_lock(fcport);
+				qlt_schedule_sess_for_deletion(fcport);
 			}
 			break;
 
@@ -2706,7 +2706,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 				comp_status);
 
 			qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
-			qlt_schedule_sess_for_deletion_lock(fcport);
+			qlt_schedule_sess_for_deletion(fcport);
 		}
 
 		break;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 68587e631f60..663509e58d9d 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3897,7 +3897,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 			case DSC_DELETE_PEND:
 				break;
 			default:
-				qlt_schedule_sess_for_deletion_lock(fcport);
+				qlt_schedule_sess_for_deletion(fcport);
 				break;
 			}
 		} else {
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 22ab1a6dd577..a58b9de73afa 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3858,7 +3858,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
 
 	list_for_each_entry(fcport, &vha->vp_fcports, list) {
 		fcport->scan_state = 0;
-		qlt_schedule_sess_for_deletion_lock(fcport);
+		qlt_schedule_sess_for_deletion(fcport);
 
 		if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
 			continue;
@@ -4886,8 +4886,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 				default:
 					fcport->login_pause = 1;
 					tfcp->conflict = fcport;
-					qlt_schedule_sess_for_deletion_lock
-						(tfcp);
+					qlt_schedule_sess_for_deletion(tfcp);
 					break;
 				}
 			}
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 6b16f0dbd588..814dfb1036de 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1214,6 +1214,7 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess)
 void qlt_schedule_sess_for_deletion(struct fc_port *sess)
 {
 	struct qla_tgt *tgt = sess->tgt;
+	unsigned long flags;
 
 	if (sess->disc_state == DSC_DELETE_PEND)
 		return;
@@ -1229,12 +1230,19 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
 			return;
 	}
 
-	sess->disc_state = DSC_DELETE_PEND;
-
 	if (sess->deleted == QLA_SESS_DELETED)
 		sess->logout_on_delete = 0;
 
+	spin_lock_irqsave(&sess->vha->work_lock, flags);
+	if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+		spin_unlock_irqrestore(&sess->vha->work_lock, flags);
+		return;
+	}
 	sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+	spin_unlock_irqrestore(&sess->vha->work_lock, flags);
+
+	sess->disc_state = DSC_DELETE_PEND;
+
 	qla24xx_chk_fcp_state(sess);
 
 	ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
@@ -1244,15 +1252,6 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
 	queue_work(sess->vha->hw->wq, &sess->del_work);
 }
 
-void qlt_schedule_sess_for_deletion_lock(struct fc_port *sess)
-{
-	unsigned long flags;
-	struct qla_hw_data *ha = sess->vha->hw;
-	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
-	qlt_schedule_sess_for_deletion(sess);
-	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-}
-
 /* ha->tgt.sess_lock supposed to be held on entry */
 static void qlt_clear_tgt_db(struct qla_tgt *tgt)
 {
@@ -2208,7 +2207,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
 			    "TM response logo %phC status %#x state %#x",
 			    mcmd->sess->port_name, mcmd->fc_tm_rsp,
 			    mcmd->flags);
-			qlt_schedule_sess_for_deletion_lock(mcmd->sess);
+			qlt_schedule_sess_for_deletion(mcmd->sess);
 		} else {
 			qlt_send_notify_ack(vha->hw->base_qpair,
 			    &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0);
@@ -3924,7 +3923,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
 				    "%s %d %8phC post del sess\n",
 				    __func__, __LINE__, cmd->sess->port_name);
 
-				qlt_schedule_sess_for_deletion_lock(cmd->sess);
+				qlt_schedule_sess_for_deletion(cmd->sess);
 			}
 			break;
 		}
@@ -4742,7 +4741,7 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
 		    __func__, __LINE__, sess->port_name);
 
 
-		qlt_schedule_sess_for_deletion_lock(sess);
+		qlt_schedule_sess_for_deletion(sess);
 		break;
 	}
 out:
@@ -4970,7 +4969,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 		} else {
 			/* cmd did not go to upper layer. */
 			if (sess) {
-				qlt_schedule_sess_for_deletion_lock(sess);
+				qlt_schedule_sess_for_deletion(sess);
 				res = 0;
 			}
 			/* else logo will be ack */
-- 
2.12.0

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

* [PATCH 42/43] qla2xxx: Serialize session free in  qlt_free_session_done
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (40 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 41/43] qla2xxx: Serialize session deletion by using work_lock Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  2017-12-20  6:56 ` [PATCH 43/43] qla2xxx: Update driver version to 10.00.00.04-k Himanshu Madhani
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

From: Quinn Tran <quinn.tran@cavium.com>

Add free_pending flag to serialize queueing of
free_work element onto the work queue

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h    |  1 +
 drivers/scsi/qla2xxx/qla_target.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 0c31c8ad0c1e..3feb843ef333 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2384,6 +2384,7 @@ typedef struct fc_port {
 
 	unsigned int conf_compl_supported:1;
 	unsigned int deleted:2;
+	unsigned int free_pending:1;
 	unsigned int local:1;
 	unsigned int logout_on_delete:1;
 	unsigned int logo_ack_needed:1;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 814dfb1036de..225b88c47505 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1105,6 +1105,7 @@ static void qlt_free_session_done(struct work_struct *work)
 			sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] = NULL;
 		}
 	}
+
 	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
 
 	ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
@@ -1118,6 +1119,9 @@ static void qlt_free_session_done(struct work_struct *work)
 		wake_up_all(&vha->fcport_waitQ);
 
 	base_vha = pci_get_drvdata(ha->pdev);
+
+	sess->free_pending = 0;
+
 	if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags))
 		return;
 
@@ -1140,11 +1144,20 @@ static void qlt_free_session_done(struct work_struct *work)
 void qlt_unreg_sess(struct fc_port *sess)
 {
 	struct scsi_qla_host *vha = sess->vha;
+	unsigned long flags;
 
 	ql_dbg(ql_dbg_disc, sess->vha, 0x210a,
 	    "%s sess %p for deletion %8phC\n",
 	    __func__, sess, sess->port_name);
 
+	spin_lock_irqsave(&sess->vha->work_lock, flags);
+	if (sess->free_pending) {
+		spin_unlock_irqrestore(&sess->vha->work_lock, flags);
+		return;
+	}
+	sess->free_pending = 1;
+	spin_unlock_irqrestore(&sess->vha->work_lock, flags);
+
 	if (sess->se_sess)
 		vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
 
-- 
2.12.0

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

* [PATCH 43/43] qla2xxx: Update driver version to 10.00.00.04-k
  2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
                   ` (41 preceding siblings ...)
  2017-12-20  6:56 ` [PATCH 42/43] qla2xxx: Serialize session free in qlt_free_session_done Himanshu Madhani
@ 2017-12-20  6:56 ` Himanshu Madhani
  42 siblings, 0 replies; 63+ messages in thread
From: Himanshu Madhani @ 2017-12-20  6:56 UTC (permalink / raw)
  To: James.Bottomley, martin.petersen; +Cc: himanshu.madhani, linux-scsi

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 911b82226d13..0843def08356 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.03-k"
+#define QLA2XXX_VERSION      "10.00.00.04-k"
 
 #define QLA_DRIVER_MAJOR_VER	10
 #define QLA_DRIVER_MINOR_VER	0
-- 
2.12.0

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

* Re: [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer
  2017-12-20  6:56 ` [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer Himanshu Madhani
@ 2017-12-20 16:25   ` Bart Van Assche
  2017-12-20 20:37     ` Madhani, Himanshu
  2017-12-21  5:26   ` kbuild test robot
  2017-12-21  5:26   ` [RFC PATCH] qla2xxx: sp_str[] can be static kbuild test robot
  2 siblings, 1 reply; 63+ messages in thread
From: Bart Van Assche @ 2017-12-20 16:25 UTC (permalink / raw)
  To: James.Bottomley, himanshu.madhani, martin.petersen; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
> Name pointer for sp describing each command is assigned with stack
> frame's memory. The stack frame could eventually be re-use, where
> name pointer access can get get garbage. This patch designates
> static memory for name pointer to fix this problem.

Which stack memory accesses have been removed by this patch? Sorry but I
haven't found any stack memory access changes in this patch. Additionally,
I haven't found any changes in this patch that look useful to me. Are you
aware that for statements like "str = "unknown"" the compiler allocates
static memory for the string "unknown"?

> +struct sp_name {
> +	uint16_t cmd;
> +	const char *str;
> +};
> +

[ ... ]
 
> +struct sp_name sp_str[] = {
> +	{ SPCN_UNKNOWN, "unknown" },
> +	{ SPCN_GIDPN, "gidpn" },
> +	{ SPCN_GPSC, "gpsc" },
> +	{ SPCN_GPNID, "gpnid" },
> +	{ SPCN_GPNFT, "gpnft" },
> +	{ SPCN_GNNID, "gnnid" },
> +	{ SPCN_GFPNID, "gfpnid" },
> +	{ SPCN_GFFID, "gffid" },
> +	{ SPCN_LOGIN, "login" },
> +	{ SPCN_LOGOUT, "logout" },
> +	{ SPCN_ADISC, "adisc" },
> +	{ SPCN_GNLIST, "gnlist" },
> +	{ SPCN_GPDB, "gpdb" },
> +	{ SPCN_TMF, "tmf" },
> +	{ SPCN_ABORT, "abort" },
> +	{ SPCN_NACK, "nack" },
> +	{ SPCN_BSG_RPT, "bsg_els_rpt" },
> +	{ SPCN_BSG_HST, "bsg_els_hst" },
> +	{ SPCN_BSG_CT, "bsg_ct" },
> +	{ SPCN_BSG_FX_MGMT, "bsg_fx_mgmt" },
> +	{ SPCN_ELS_DCMD, "ELS_DCMD" },
> +	{ SPCN_FXDISC, "fxdisc" },
> +	{ SPCN_PRLI, "prli" },
> +	{ SPCN_NVME_LS, "nvme_ls" },
> +	{ SPCN_NVME_CMD, "nvme_cmd" },
> +};

If you want to keep the sp_str[] array after what I wrote above, please
remove the sp_name structure and change sp_str[] into something like the
following:

static const char *sp_str[] = {
	[SPCN_UNKNOWN] = "unknown",
	...
};

> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -14,6 +14,7 @@ static struct mb_cmd_name {
>  	uint16_t cmd;
>  	const char *str;
>  } mb_str[] = {
> +	{0, "unknown mb"},
>  	{MBC_GET_PORT_DATABASE,		"GPDB"},
>  	{MBC_GET_ID_LIST,		"GIDList"},
>  	{MBC_GET_LINK_PRIV_STATS,	"Stats"},
> @@ -24,12 +25,12 @@ static const char *mb_to_str(uint16_t cmd)
>  	int i;
>  	struct mb_cmd_name *e;
>  
> -	for (i = 0; i < ARRAY_SIZE(mb_str); i++) {
> +	for (i = 1; i < ARRAY_SIZE(mb_str); i++) {
>  		e = mb_str + i;
>  		if (cmd == e->cmd)
>  			return e->str;
>  	}
> -	return "unknown";
> +	return mb_str[0].str;
>  }

Sorry but the above change does not look useful to me in any way. Is this
just code churn?

Thanks,

Bart.

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

* Re: [PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure
  2017-12-20  6:56 ` [PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure Himanshu Madhani
@ 2017-12-20 16:26   ` Bart Van Assche
  2017-12-20 20:38     ` Madhani, Himanshu
  0 siblings, 1 reply; 63+ messages in thread
From: Bart Van Assche @ 2017-12-20 16:26 UTC (permalink / raw)
  To: James.Bottomley, himanshu.madhani, martin.petersen; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
> 
> when preocessing iocb in a timeout case, driver was trying to log messages
       ^^^^^^^^^^^
       processing?

Bart.

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

* Re: [PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command
  2017-12-20  6:56 ` [PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command Himanshu Madhani
@ 2017-12-20 16:29   ` Bart Van Assche
  2017-12-20 20:39     ` Madhani, Himanshu
  0 siblings, 1 reply; 63+ messages in thread
From: Bart Van Assche @ 2017-12-20 16:29 UTC (permalink / raw)
  To: James.Bottomley, himanshu.madhani, martin.petersen; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
> @@ -536,7 +541,7 @@ struct sp_name {
>  #define SRB_NVME_CMD	19
>  #define SRB_NVME_LS	20
>  #define SRB_PRLI_CMD	21
> -
> +#define SRB_CTRL_VP	22
>  enum {

Please keep the blank line between the #define block and the enum definition.

> +/*
> + * qla24xx_control_vp
> + *	Enable a virtual port for given host
> + *
> + * Input:
> + *	ha = adapter block pointer.
> + *	vhba = virtual adapter (unused)
> + *	index = index number for enabled VP
> + *
> + * Returns:
> + *	qla2xxx local function return status code.
> + *
> + * Context:
> + *	Kernel context.
> + */
> +int
> +qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)

Have you considered to use the kernel-doc style for this function header? See
also https://www.kernel.org/doc/Documentation/kernel-doc-nano-HOWTO.txt.

Thanks,

Bart.

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

* Re: [PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name
  2017-12-20  6:56 ` [PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name Himanshu Madhani
@ 2017-12-20 16:39   ` Bart Van Assche
  2017-12-20 20:41     ` Madhani, Himanshu
  0 siblings, 1 reply; 63+ messages in thread
From: Bart Van Assche @ 2017-12-20 16:39 UTC (permalink / raw)
  To: James.Bottomley, himanshu.madhani, martin.petersen; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
> 
> IRQ name pointer for INTx/MSI was pointing at stale stack frame.
> cat /proc/interrupts will trigger stale mem access. Fix it by
> creating dedicated space for IRQ name.

What stale stack frame are you referring to? Just like in the first patch
of this series, I don't see any stack accesses being removed by this patch.
Is this patch useful? If not, can this patch be left out?

Thanks,

Bart.

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

* Re: [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW
  2017-12-20  6:56 ` [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW Himanshu Madhani
@ 2017-12-20 16:51   ` Bart Van Assche
  2017-12-20 20:57     ` Madhani, Himanshu
  0 siblings, 1 reply; 63+ messages in thread
From: Bart Van Assche @ 2017-12-20 16:51 UTC (permalink / raw)
  To: James.Bottomley, himanshu.madhani, martin.petersen; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote: 
> +#define QLA_ENA_FW_RES_TRACKING(_ha) { \
> +	int i; \
> +	_ha->base_qpair->fw_res_tracking = 1; \
> +	for (i = 0; i < _ha->max_qpairs; i++) { \
> +		if (_ha->queue_pair_map[i]) \
> +		_ha->queue_pair_map[i]->fw_res_tracking = 1; \
> +	} \
> +}
> +
> +#define QLA_DIS_FW_RES_TRACKING(_ha) { \
> +	int i; \
> +	_ha->base_qpair->fw_res_tracking = 0; \
> +	for (i = 0; i < _ha->max_qpairs; i++) { \
> +		if (_ha->queue_pair_map[i]) \
> +		_ha->queue_pair_map[i]->fw_res_tracking = 0; \
> +	} \
> +}

Has this patch been verified with checkpatch? Did checkpatch suggest to surround
these macros with do / while (0)?

>  int
>  qla2x00_dfs_setup(scsi_qla_host_t *vha)
> @@ -504,6 +776,33 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
>  			    "Unable to create debugFS naqp node.\n");
>  			goto out;
>  		}
> +
> +		if (ql2xtrackfwres) {
> +			ha->tgt.dfs_ini_iocbs =
> +				debugfs_create_file("reserve_ini_iocbs",
> +				0400, ha->dfs_dir, vha, &dfs_ini_iocbs_ops);
> +			if (!ha->tgt.dfs_ini_iocbs) {
> +				ql_log(ql_log_warn, vha, 0xd011,
> +				    "Unable to create debugFS reserve_ini_iocbs node.\n");
> +				goto out;
> +			}

The patch description shows how to control the new attributes through sysfs
but this code adds new debugfs attributes. Sorry but that really confuses me.

> +int ql2xtrackfwres;
> +module_param(ql2xtrackfwres, int, 0444);
> +MODULE_PARM_DESC(ql2xtrackfwres,
> +		 "Track FW resource.  0(default): disabled");

Why is this a module parameter instead of e.g. a sysfs attribute? Module
parameters are annoying if the qla2xxx driver is not built as a module.

> @@ -6412,6 +6433,9 @@ qlt_enable_vha(struct scsi_qla_host *vha)
>  		qla24xx_disable_vp(vha);
>  		qla24xx_enable_vp(vha);
>  	} else {
> +		if (ql2xtrackfwres && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
> +			QLA_ENA_FW_RES_TRACKING(ha);

Why is there a dependency on the adapter type in the above code?

Thanks,

Bart.

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

* Re: [PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS
  2017-12-20  6:56 ` [PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS Himanshu Madhani
@ 2017-12-20 16:53   ` Bart Van Assche
  2017-12-20 21:40     ` Madhani, Himanshu
  0 siblings, 1 reply; 63+ messages in thread
From: Bart Van Assche @ 2017-12-20 16:53 UTC (permalink / raw)
  To: James.Bottomley, himanshu.madhani, martin.petersen; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
> +int qla2xuseresexchforels;
> +module_param(qla2xuseresexchforels, int, 0444);
> +MODULE_PARM_DESC(qla2xuseresexchforels,
> +		 "Reserve 1/2 of emergency exchanges for ELS.\n"
> +		 " 0 (default): disabled");

Same question here as for another kernel module parameter: does this have to
be a kernel module parameter or could this have been implemented as a sysfs
attribute?

Thanks,

Bart.

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

* Re: [PATCH 21/43] qla2xxx: Remove calling cancel_work_sync()
  2017-12-20  6:56 ` [PATCH 21/43] qla2xxx: Remove calling cancel_work_sync() Himanshu Madhani
@ 2017-12-20 16:56   ` Bart Van Assche
  2017-12-20 21:41     ` Madhani, Himanshu
  0 siblings, 1 reply; 63+ messages in thread
From: Bart Van Assche @ 2017-12-20 16:56 UTC (permalink / raw)
  To: James.Bottomley, himanshu.madhani, martin.petersen; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
> @@ -1234,8 +1234,6 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess,
>  	ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
>  	    "Scheduling sess %p for deletion\n", sess);
>  
> -	/* use cancel to push work element through before re-queue */
> -	cancel_work_sync(&sess->del_work);
>  	INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn);
>  	queue_work(sess->vha->hw->wq, &sess->del_work);

Why had this cancel_work_sync() call been introduced in
qlt_schedule_sess_for_deletion() and why do you think it is safe to remove
this call? Both questions should have been answered in the patch description.

Thanks,

Bart.

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

* Re: [PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery
  2017-12-20  6:56 ` [PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery Himanshu Madhani
@ 2017-12-20 18:09   ` Ewan D. Milne
  2017-12-21  0:04     ` Madhani, Himanshu
  0 siblings, 1 reply; 63+ messages in thread
From: Ewan D. Milne @ 2017-12-20 18:09 UTC (permalink / raw)
  To: Himanshu Madhani; +Cc: linux-scsi

On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
> @@ -4915,12 +4941,32 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
>  		}
>  
>  		if (sess != NULL) {
> +			bool delete = false;
>  			spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
>  			switch (sess->fw_login_state) {
> +			case DSC_LS_PLOGI_PEND:
>  			case DSC_LS_PLOGI_COMP:
>  			case DSC_LS_PRLI_COMP:
>  				break;
>  			default:
> +			    	delete = true;

Nitpick:  git quiltimport complains about the whitespace error
(space before tab) on the above line.

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

* Re: [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer
  2017-12-20 16:25   ` Bart Van Assche
@ 2017-12-20 20:37     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-20 20:37 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: James.Bottomley, martin.petersen, linux-scsi

Hi Bart, 

> On Dec 20, 2017, at 10:25 AM, Bart Van Assche <bart.vanassche@wdc.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
>> Name pointer for sp describing each command is assigned with stack
>> frame's memory. The stack frame could eventually be re-use, where
>> name pointer access can get get garbage. This patch designates
>> static memory for name pointer to fix this problem.
> 
> Which stack memory accesses have been removed by this patch? Sorry but I
> haven't found any stack memory access changes in this patch. Additionally,
> I haven't found any changes in this patch that look useful to me. Are you
> aware that for statements like "str = "unknown"" the compiler allocates
> static memory for the string "unknown”?
> 

Sure. The intention of patch was to cleanup and make sure there is memory allocated
on the stack for name.
 
>> +struct sp_name {
>> +	uint16_t cmd;
>> +	const char *str;
>> +};
>> +
> 
> [ ... ]
> 
>> +struct sp_name sp_str[] = {
>> +	{ SPCN_UNKNOWN, "unknown" },
>> +	{ SPCN_GIDPN, "gidpn" },
>> +	{ SPCN_GPSC, "gpsc" },
>> +	{ SPCN_GPNID, "gpnid" },
>> +	{ SPCN_GPNFT, "gpnft" },
>> +	{ SPCN_GNNID, "gnnid" },
>> +	{ SPCN_GFPNID, "gfpnid" },
>> +	{ SPCN_GFFID, "gffid" },
>> +	{ SPCN_LOGIN, "login" },
>> +	{ SPCN_LOGOUT, "logout" },
>> +	{ SPCN_ADISC, "adisc" },
>> +	{ SPCN_GNLIST, "gnlist" },
>> +	{ SPCN_GPDB, "gpdb" },
>> +	{ SPCN_TMF, "tmf" },
>> +	{ SPCN_ABORT, "abort" },
>> +	{ SPCN_NACK, "nack" },
>> +	{ SPCN_BSG_RPT, "bsg_els_rpt" },
>> +	{ SPCN_BSG_HST, "bsg_els_hst" },
>> +	{ SPCN_BSG_CT, "bsg_ct" },
>> +	{ SPCN_BSG_FX_MGMT, "bsg_fx_mgmt" },
>> +	{ SPCN_ELS_DCMD, "ELS_DCMD" },
>> +	{ SPCN_FXDISC, "fxdisc" },
>> +	{ SPCN_PRLI, "prli" },
>> +	{ SPCN_NVME_LS, "nvme_ls" },
>> +	{ SPCN_NVME_CMD, "nvme_cmd" },
>> +};
> 
> If you want to keep the sp_str[] array after what I wrote above, please
> remove the sp_name structure and change sp_str[] into something like the
> following:
> 
> static const char *sp_str[] = {
> 	[SPCN_UNKNOWN] = "unknown",
> 	...
> };
> 

I will drop this patch from the current submission.

>> --- a/drivers/scsi/qla2xxx/qla_mbx.c
>> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
>> @@ -14,6 +14,7 @@ static struct mb_cmd_name {
>> 	uint16_t cmd;
>> 	const char *str;
>> } mb_str[] = {
>> +	{0, "unknown mb"},
>> 	{MBC_GET_PORT_DATABASE,		"GPDB"},
>> 	{MBC_GET_ID_LIST,		"GIDList"},
>> 	{MBC_GET_LINK_PRIV_STATS,	"Stats"},
>> @@ -24,12 +25,12 @@ static const char *mb_to_str(uint16_t cmd)
>> 	int i;
>> 	struct mb_cmd_name *e;
>> 
>> -	for (i = 0; i < ARRAY_SIZE(mb_str); i++) {
>> +	for (i = 1; i < ARRAY_SIZE(mb_str); i++) {
>> 		e = mb_str + i;
>> 		if (cmd == e->cmd)
>> 			return e->str;
>> 	}
>> -	return "unknown";
>> +	return mb_str[0].str;
>> }
> 
> Sorry but the above change does not look useful to me in any way. Is this
> just code churn?
> 

Sure. will drop this change

> Thanks,
> 
> Bart.

Thanks,
- Himanshu


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

* Re: [PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure
  2017-12-20 16:26   ` Bart Van Assche
@ 2017-12-20 20:38     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-20 20:38 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: James.Bottomley, martin.petersen, linux-scsi


> On Dec 20, 2017, at 10:26 AM, Bart Van Assche <bart.vanassche@wdc.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
>> From: Quinn Tran <quinn.tran@cavium.com>
>> 
>> when preocessing iocb in a timeout case, driver was trying to log messages
>       ^^^^^^^^^^^
>       processing?
> 
> Bart.

Will fix in v2 of the series

Thanks,
- Himanshu

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

* Re: [PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command
  2017-12-20 16:29   ` Bart Van Assche
@ 2017-12-20 20:39     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-20 20:39 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: James.Bottomley, martin.petersen, linux-scsi


> On Dec 20, 2017, at 10:29 AM, Bart Van Assche <bart.vanassche@wdc.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
>> @@ -536,7 +541,7 @@ struct sp_name {
>> #define SRB_NVME_CMD	19
>> #define SRB_NVME_LS	20
>> #define SRB_PRLI_CMD	21
>> -
>> +#define SRB_CTRL_VP	22
>> enum {
> 
> Please keep the blank line between the #define block and the enum definition.
> 

Sure

>> +/*
>> + * qla24xx_control_vp
>> + *	Enable a virtual port for given host
>> + *
>> + * Input:
>> + *	ha = adapter block pointer.
>> + *	vhba = virtual adapter (unused)
>> + *	index = index number for enabled VP
>> + *
>> + * Returns:
>> + *	qla2xxx local function return status code.
>> + *
>> + * Context:
>> + *	Kernel context.
>> + */
>> +int
>> +qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
> 
> Have you considered to use the kernel-doc style for this function header? See
> also https://www.kernel.org/doc/Documentation/kernel-doc-nano-HOWTO.txt.
> 
> Thanks,
> 
> Bart.

Will update to kernel-doc style for the header.

Thanks,
- Himanshu

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

* Re: [PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name
  2017-12-20 16:39   ` Bart Van Assche
@ 2017-12-20 20:41     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-20 20:41 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: James.Bottomley, martin.petersen, linux-scsi


> On Dec 20, 2017, at 10:39 AM, Bart Van Assche <bart.vanassche@wdc.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
>> From: Quinn Tran <quinn.tran@cavium.com>
>> 
>> IRQ name pointer for INTx/MSI was pointing at stale stack frame.
>> cat /proc/interrupts will trigger stale mem access. Fix it by
>> creating dedicated space for IRQ name.
> 
> What stale stack frame are you referring to? Just like in the first patch
> of this series, I don't see any stack accesses being removed by this patch.
> Is this patch useful? If not, can this patch be left out?
> 
> Thanks,
> 
> Bart.

will drop this patch. 

Thanks,
- Himanshu

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

* Re: [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW
  2017-12-20 16:51   ` Bart Van Assche
@ 2017-12-20 20:57     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-20 20:57 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: James.Bottomley, martin.petersen, linux-scsi


> On Dec 20, 2017, at 10:51 AM, Bart Van Assche <bart.vanassche@wdc.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote: 
>> +#define QLA_ENA_FW_RES_TRACKING(_ha) { \
>> +	int i; \
>> +	_ha->base_qpair->fw_res_tracking = 1; \
>> +	for (i = 0; i < _ha->max_qpairs; i++) { \
>> +		if (_ha->queue_pair_map[i]) \
>> +		_ha->queue_pair_map[i]->fw_res_tracking = 1; \
>> +	} \
>> +}
>> +
>> +#define QLA_DIS_FW_RES_TRACKING(_ha) { \
>> +	int i; \
>> +	_ha->base_qpair->fw_res_tracking = 0; \
>> +	for (i = 0; i < _ha->max_qpairs; i++) { \
>> +		if (_ha->queue_pair_map[i]) \
>> +		_ha->queue_pair_map[i]->fw_res_tracking = 0; \
>> +	} \
>> +}
> 
> Has this patch been verified with checkpatch? Did checkpatch suggest to surround
> these macros with do / while (0)?
> 

Checkpatch did not suggest to use do/while loop. 

I did however saw indentation warning which i did not change since it looked like false positive
 
WARNING: suspect code indent for conditional statements (16, 16)
#133: FILE: drivers/scsi/qla2xxx/qla_def.h:4460:
+               if (_ha->queue_pair_map[i]) \
+               _ha->queue_pair_map[i]->fw_res_tracking = 1; \

WARNING: suspect code indent for conditional statements (16, 16)
#142: FILE: drivers/scsi/qla2xxx/qla_def.h:4469:
+               if (_ha->queue_pair_map[i]) \
+               _ha->queue_pair_map[i]->fw_res_tracking = 0; \


>> int
>> qla2x00_dfs_setup(scsi_qla_host_t *vha)
>> @@ -504,6 +776,33 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
>> 			    "Unable to create debugFS naqp node.\n");
>> 			goto out;
>> 		}
>> +
>> +		if (ql2xtrackfwres) {
>> +			ha->tgt.dfs_ini_iocbs =
>> +				debugfs_create_file("reserve_ini_iocbs",
>> +				0400, ha->dfs_dir, vha, &dfs_ini_iocbs_ops);
>> +			if (!ha->tgt.dfs_ini_iocbs) {
>> +				ql_log(ql_log_warn, vha, 0xd011,
>> +				    "Unable to create debugFS reserve_ini_iocbs node.\n");
>> +				goto out;
>> +			}
> 
> The patch description shows how to control the new attributes through sysfs
> but this code adds new debugfs attributes. Sorry but that really confuses me.
> 
>> +int ql2xtrackfwres;
>> +module_param(ql2xtrackfwres, int, 0444);
>> +MODULE_PARM_DESC(ql2xtrackfwres,
>> +		 "Track FW resource.  0(default): disabled");
> 
> Why is this a module parameter instead of e.g. a sysfs attribute? Module
> parameters are annoying if the qla2xxx driver is not built as a module.
> 

Looks like sysfs example is used instead of DebugFS in the commit message

>> @@ -6412,6 +6433,9 @@ qlt_enable_vha(struct scsi_qla_host *vha)
>> 		qla24xx_disable_vp(vha);
>> 		qla24xx_enable_vp(vha);
>> 	} else {
>> +		if (ql2xtrackfwres && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
>> +			QLA_ENA_FW_RES_TRACKING(ha);
> 
> Why is there a dependency on the adapter type in the above code?
> 

We do not want to support this feature on 8G and older adapters. 

> Thanks,
> 
> Bart.

Thanks,
- Himanshu

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

* Re: [PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS
  2017-12-20 16:53   ` Bart Van Assche
@ 2017-12-20 21:40     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-20 21:40 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: James.Bottomley, martin.petersen, linux-scsi

Hi Bart, 

> On Dec 20, 2017, at 10:53 AM, Bart Van Assche <bart.vanassche@wdc.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
>> +int qla2xuseresexchforels;
>> +module_param(qla2xuseresexchforels, int, 0444);
>> +MODULE_PARM_DESC(qla2xuseresexchforels,
>> +		 "Reserve 1/2 of emergency exchanges for ELS.\n"
>> +		 " 0 (default): disabled");
> 
> Same question here as for another kernel module parameter: does this have to
> be a kernel module parameter or could this have been implemented as a sysfs
> attribute?
> 
> Thanks,
> 
> Bart.

This does not have to be module parameter. Let me work on changing this to sysfs and
submit in next series with the correction

Thanks,
- Himanshu

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

* Re: [PATCH 21/43] qla2xxx: Remove calling cancel_work_sync()
  2017-12-20 16:56   ` Bart Van Assche
@ 2017-12-20 21:41     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-20 21:41 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: James.Bottomley, martin.petersen, linux-scsi


> On Dec 20, 2017, at 10:56 AM, Bart Van Assche <bart.vanassche@wdc.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
>> @@ -1234,8 +1234,6 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess,
>> 	ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
>> 	    "Scheduling sess %p for deletion\n", sess);
>> 
>> -	/* use cancel to push work element through before re-queue */
>> -	cancel_work_sync(&sess->del_work);
>> 	INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn);
>> 	queue_work(sess->vha->hw->wq, &sess->del_work);
> 
> Why had this cancel_work_sync() call been introduced in
> qlt_schedule_sess_for_deletion() and why do you think it is safe to remove
> this call? Both questions should have been answered in the patch description.
> 
> Thanks,
> 
> Bart.

I will drop this patch from current series and will update commit message with details
as suggested and submit in next series.

Thanks,
- Himanshu

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

* Re: [PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery
  2017-12-20 18:09   ` Ewan D. Milne
@ 2017-12-21  0:04     ` Madhani, Himanshu
  0 siblings, 0 replies; 63+ messages in thread
From: Madhani, Himanshu @ 2017-12-21  0:04 UTC (permalink / raw)
  To: emilne; +Cc: linux-scsi

Hi Ewan, 

> On Dec 20, 2017, at 12:09 PM, Ewan D. Milne <emilne@redhat.com> wrote:
> 
> On Tue, 2017-12-19 at 22:56 -0800, Himanshu Madhani wrote:
>> @@ -4915,12 +4941,32 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
>> 		}
>> 
>> 		if (sess != NULL) {
>> +			bool delete = false;
>> 			spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
>> 			switch (sess->fw_login_state) {
>> +			case DSC_LS_PLOGI_PEND:
>> 			case DSC_LS_PLOGI_COMP:
>> 			case DSC_LS_PRLI_COMP:
>> 				break;
>> 			default:
>> +			    	delete = true;
> 
> Nitpick:  git quiltimport complains about the whitespace error
> (space before tab) on the above line.
> 
> 

Thanks for review. Will fix in v2

Thanks,
- Himanshu

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

* [RFC PATCH] qla2xxx: sp_str[] can be static
  2017-12-20  6:56 ` [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer Himanshu Madhani
  2017-12-20 16:25   ` Bart Van Assche
  2017-12-21  5:26   ` kbuild test robot
@ 2017-12-21  5:26   ` kbuild test robot
  2 siblings, 0 replies; 63+ messages in thread
From: kbuild test robot @ 2017-12-21  5:26 UTC (permalink / raw)
  Cc: kbuild-all, James.Bottomley, martin.petersen, himanshu.madhani,
	linux-scsi


Fixes: a3e84f0484ea ("qla2xxx: Fix stale memory access for name pointer")
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
---
 qla_gs.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 7e88e828..54c8dfd 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -15,7 +15,7 @@ static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
 
-struct sp_name sp_str[] = {
+static struct sp_name sp_str[] = {
 	{ SPCN_UNKNOWN, "unknown" },
 	{ SPCN_GIDPN, "gidpn" },
 	{ SPCN_GPSC, "gpsc" },

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

* Re: [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer
  2017-12-20  6:56 ` [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer Himanshu Madhani
  2017-12-20 16:25   ` Bart Van Assche
@ 2017-12-21  5:26   ` kbuild test robot
  2017-12-21  5:26   ` [RFC PATCH] qla2xxx: sp_str[] can be static kbuild test robot
  2 siblings, 0 replies; 63+ messages in thread
From: kbuild test robot @ 2017-12-21  5:26 UTC (permalink / raw)
  Cc: kbuild-all, James.Bottomley, martin.petersen, himanshu.madhani,
	linux-scsi

Hi Quinn,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on scsi/for-next]
[also build test WARNING on next-20171220]
[cannot apply to v4.15-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Himanshu-Madhani/qla2xxx-Driver-update/20171221-085840
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)


Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

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

* Re: [PATCH 19/43] qla2xxx: Fix session cleanup for N2N
  2017-12-20  6:56 ` [PATCH 19/43] qla2xxx: Fix session cleanup for N2N Himanshu Madhani
@ 2017-12-21  6:01   ` kbuild test robot
  0 siblings, 0 replies; 63+ messages in thread
From: kbuild test robot @ 2017-12-21  6:01 UTC (permalink / raw)
  Cc: kbuild-all, James.Bottomley, martin.petersen, himanshu.madhani,
	linux-scsi

Hi Quinn,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on scsi/for-next]
[also build test WARNING on next-20171220]
[cannot apply to v4.15-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Himanshu-Madhani/qla2xxx-Driver-update/20171221-085840
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)


vim +4828 drivers/scsi/qla2xxx/qla_os.c

  4743	
  4744	static
  4745	void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
  4746	{
  4747		unsigned long flags;
  4748		fc_port_t *fcport =  NULL, *tfcp;
  4749		struct qlt_plogi_ack_t *pla =
  4750		    (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
  4751		uint8_t free_fcport = 0;
  4752	
  4753		ql_dbg(ql_dbg_disc, vha, 0xffff,
  4754		    "%s %d %8phC enter\n",
  4755		    __func__, __LINE__, e->u.new_sess.port_name);
  4756	
  4757		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
  4758		fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
  4759		if (fcport) {
  4760			fcport->d_id = e->u.new_sess.id;
  4761			if (pla) {
  4762				fcport->fw_login_state = DSC_LS_PLOGI_PEND;
  4763				memcpy(fcport->node_name,
  4764				    pla->iocb.u.isp24.u.plogi.node_name,
  4765				    WWN_SIZE);
  4766				qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN);
  4767				/* we took an extra ref_count to prevent PLOGI ACK when
  4768				 * fcport/sess has not been created.
  4769				 */
  4770				pla->ref_count--;
  4771			}
  4772		} else {
  4773			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
  4774			fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
  4775			if (fcport) {
  4776				fcport->d_id = e->u.new_sess.id;
  4777				fcport->scan_state = QLA_FCPORT_FOUND;
  4778				fcport->flags |= FCF_FABRIC_DEVICE;
  4779				fcport->fw_login_state = DSC_LS_PLOGI_PEND;
  4780	
  4781				memcpy(fcport->port_name, e->u.new_sess.port_name,
  4782				    WWN_SIZE);
  4783			} else {
  4784				ql_dbg(ql_dbg_disc, vha, 0xffff,
  4785					   "%s %8phC mem alloc fail.\n",
  4786					   __func__, e->u.new_sess.port_name);
  4787	
  4788				if (pla)
  4789					kmem_cache_free(qla_tgt_plogi_cachep, pla);
  4790				return;
  4791			}
  4792	
  4793			spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
  4794			/* search again to make sure one else got ahead */
  4795			tfcp = qla2x00_find_fcport_by_wwpn(vha,
  4796			    e->u.new_sess.port_name, 1);
  4797			if (tfcp) {
  4798				/* should rarily happen */
  4799				ql_dbg(ql_dbg_disc, vha, 0xffff,
  4800				    "%s %8phC found existing fcport b4 add. DS %d LS %d\n",
  4801				    __func__, tfcp->port_name, tfcp->disc_state,
  4802				    tfcp->fw_login_state);
  4803	
  4804				free_fcport = 1;
  4805			} else {
  4806				list_add_tail(&fcport->list, &vha->vp_fcports);
  4807	
  4808			}
  4809			if (pla) {
  4810				qlt_plogi_ack_link(vha, pla, fcport,
  4811				    QLT_PLOGI_LINK_SAME_WWN);
  4812				pla->ref_count--;
  4813			}
  4814		}
  4815		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
  4816	
  4817		if (fcport) {
  4818			if (N2N_TOPO(vha->hw))
  4819				fcport->flags &= ~FCF_FABRIC_DEVICE;
  4820	
  4821			if (pla) {
  4822				if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) {
  4823					u16 wd3_lo;
  4824	
  4825					fcport->fw_login_state = DSC_LS_PRLI_PEND;
  4826					fcport->local = 0;
  4827					fcport->loop_id =
> 4828						le16_to_cpu(
  4829						    pla->iocb.u.isp24.nport_handle);
  4830					fcport->fw_login_state = DSC_LS_PRLI_PEND;
  4831					wd3_lo =
  4832					    le16_to_cpu(
  4833						pla->iocb.u.isp24.u.prli.wd3_lo);
  4834	
  4835					if (wd3_lo & BIT_7)
  4836						fcport->conf_compl_supported = 1;
  4837	
  4838					if ((wd3_lo & BIT_4) == 0)
  4839						fcport->port_type = FCT_INITIATOR;
  4840					else
  4841						fcport->port_type = FCT_TARGET;
  4842				}
  4843				qlt_plogi_ack_unref(vha, pla);
  4844			} else {
  4845				spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
  4846				tfcp = qla2x00_find_fcport_by_nportid(vha,
  4847				    &e->u.new_sess.id, 1);
  4848				if (tfcp && (tfcp != fcport)) {
  4849					/*
  4850					 * We have a conflict fcport with same NportID.
  4851					 */
  4852					ql_dbg(ql_dbg_disc, vha, 0xffff,
  4853					    "%s %8phC found conflict b4 add. DS %d LS %d\n",
  4854					    __func__, tfcp->port_name, tfcp->disc_state,
  4855					    tfcp->fw_login_state);
  4856	
  4857					switch (tfcp->disc_state) {
  4858					case DSC_DELETED:
  4859						break;
  4860					case DSC_DELETE_PEND:
  4861						fcport->login_pause = 1;
  4862						tfcp->conflict = fcport;
  4863						break;
  4864					default:
  4865						fcport->login_pause = 1;
  4866						tfcp->conflict = fcport;
  4867						qlt_schedule_sess_for_deletion_lock
  4868							(tfcp);
  4869						break;
  4870					}
  4871				}
  4872				spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
  4873				qla24xx_async_gnl(vha, fcport);
  4874			}
  4875		}
  4876	
  4877		if (free_fcport) {
  4878			qla2x00_free_fcport(fcport);
  4879			if (pla)
  4880				kmem_cache_free(qla_tgt_plogi_cachep, pla);
  4881		}
  4882	}
  4883	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

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

end of thread, other threads:[~2017-12-21  6:01 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-20  6:56 [PATCH 00/43] qla2xxx: Driver update Himanshu Madhani
2017-12-20  6:56 ` [PATCH 01/43] qla2xxx: Fix stale memory access for name pointer Himanshu Madhani
2017-12-20 16:25   ` Bart Van Assche
2017-12-20 20:37     ` Madhani, Himanshu
2017-12-21  5:26   ` kbuild test robot
2017-12-21  5:26   ` [RFC PATCH] qla2xxx: sp_str[] can be static kbuild test robot
2017-12-20  6:56 ` [PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure Himanshu Madhani
2017-12-20 16:26   ` Bart Van Assche
2017-12-20 20:38     ` Madhani, Himanshu
2017-12-20  6:56 ` [PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command Himanshu Madhani
2017-12-20 16:29   ` Bart Van Assche
2017-12-20 20:39     ` Madhani, Himanshu
2017-12-20  6:56 ` [PATCH 04/43] qla2xxx: Use chip reset to bring down laser on unload Himanshu Madhani
2017-12-20  6:56 ` [PATCH 05/43] qla2xxx: Add boundary checks for exchanges to be offloaded Himanshu Madhani
2017-12-20  6:56 ` [PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name Himanshu Madhani
2017-12-20 16:39   ` Bart Van Assche
2017-12-20 20:41     ` Madhani, Himanshu
2017-12-20  6:56 ` [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW Himanshu Madhani
2017-12-20 16:51   ` Bart Van Assche
2017-12-20 20:57     ` Madhani, Himanshu
2017-12-20  6:56 ` [PATCH 08/43] qla2xxx: Chip reset uses wrong lock during IO flush Himanshu Madhani
2017-12-20  6:56 ` [PATCH 09/43] qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload Himanshu Madhani
2017-12-20  6:56 ` [PATCH 10/43] qla2xxx: Replace GPDB with async ADISC command Himanshu Madhani
2017-12-20  6:56 ` [PATCH 11/43] qla2xxx: Move work element processing out of DPC thread Himanshu Madhani
2017-12-20  6:56 ` [PATCH 12/43] qla2xxx: Enable ATIO interrupt handshake for ISP27XX Himanshu Madhani
2017-12-20  6:56 ` [PATCH 13/43] qla2xxx: Use shadow register " Himanshu Madhani
2017-12-20  6:56 ` [PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS Himanshu Madhani
2017-12-20 16:53   ` Bart Van Assche
2017-12-20 21:40     ` Madhani, Himanshu
2017-12-20  6:56 ` [PATCH 15/43] qla2xxx: Add ability to send PRLO Himanshu Madhani
2017-12-20  6:56 ` [PATCH 16/43] qla2xxx: Don't call dma_free_coherent with IRQ disabled Himanshu Madhani
2017-12-20  6:56 ` [PATCH 17/43] qla2xxx: Allow target mode to accept PRLI in dual mode Himanshu Madhani
2017-12-20  6:56 ` [PATCH 18/43] qla2xxx: Tweak resource count dump Himanshu Madhani
2017-12-20  6:56 ` [PATCH 19/43] qla2xxx: Fix session cleanup for N2N Himanshu Madhani
2017-12-21  6:01   ` kbuild test robot
2017-12-20  6:56 ` [PATCH 20/43] qla2xxx: Use known NPort ID for Management Server login Himanshu Madhani
2017-12-20  6:56 ` [PATCH 21/43] qla2xxx: Remove calling cancel_work_sync() Himanshu Madhani
2017-12-20 16:56   ` Bart Van Assche
2017-12-20 21:41     ` Madhani, Himanshu
2017-12-20  6:56 ` [PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery Himanshu Madhani
2017-12-20 18:09   ` Ewan D. Milne
2017-12-21  0:04     ` Madhani, Himanshu
2017-12-20  6:56 ` [PATCH 23/43] qla2xxx: Add lock protection around host lookup Himanshu Madhani
2017-12-20  6:56 ` [PATCH 24/43] qla2xxx: Reduce the use of terminate exchange Himanshu Madhani
2017-12-20  6:56 ` [PATCH 25/43] qla2xxx: Reduce trace noise for Async Events Himanshu Madhani
2017-12-20  6:56 ` [PATCH 26/43] qla2xxx: Fix login state machine freeze Himanshu Madhani
2017-12-20  6:56 ` [PATCH 27/43] qla2xxx: Migrate switch registration commands away from mailbox interface Himanshu Madhani
2017-12-20  6:56 ` [PATCH 28/43] qla2xxx: Remove session creation redundant code Himanshu Madhani
2017-12-20  6:56 ` [PATCH 29/43] qla2xxx: Fix GPNFT/GNNFT error handling Himanshu Madhani
2017-12-20  6:56 ` [PATCH 30/43] qla2xxx: Properly extract ADISC error codes Himanshu Madhani
2017-12-20  6:56 ` [PATCH 31/43] qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling Himanshu Madhani
2017-12-20  6:56 ` [PATCH 32/43] qla2xxx: Allow relogin and session creation after reset Himanshu Madhani
2017-12-20  6:56 ` [PATCH 33/43] qla2xxx: Increase verbosity of debug messages logged Himanshu Madhani
2017-12-20  6:56 ` [PATCH 34/43] qla2xxx: Delay loop id allocation at login Himanshu Madhani
2017-12-20  6:56 ` [PATCH 35/43] qla2xxx: Add retry limit for fabric scan logic Himanshu Madhani
2017-12-20  6:56 ` [PATCH 36/43] qla2xxx: Add counters for Exchange Buffer to debugfs Himanshu Madhani
2017-12-20  6:56 ` [PATCH 37/43] qla2xxx: Prevent multiple active discovery commands per session Himanshu Madhani
2017-12-20  6:56 ` [PATCH 38/43] qla2xxx: Prevent relogin trigger from sending too many commands Himanshu Madhani
2017-12-20  6:56 ` [PATCH 39/43] qla2xxx: Check FCF_ASYNC_SENT flag Himanshu Madhani
2017-12-20  6:56 ` [PATCH 40/43] qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion() Himanshu Madhani
2017-12-20  6:56 ` [PATCH 41/43] qla2xxx: Serialize session deletion by using work_lock Himanshu Madhani
2017-12-20  6:56 ` [PATCH 42/43] qla2xxx: Serialize session free in qlt_free_session_done Himanshu Madhani
2017-12-20  6:56 ` [PATCH 43/43] qla2xxx: Update driver version to 10.00.00.04-k Himanshu Madhani

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.