All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/17] qla2xxx misc bug fixes and features
@ 2022-01-10  5:02 Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 01/17] qla2xxx: Refactor asynchronous command initialization Nilesh Javali
                   ` (18 more replies)
  0 siblings, 19 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

Martin,

Please apply the qla2xxx driver misc bug fixes and features to the scsi
tree at your earliest convenience.

Thanks,
Nilesh

Arun Easi (1):
  qla2xxx: Fix device reconnect in loop topology

Bikash Hazarika (1):
  qla2xxx: Show wrong FDMI data for 64G adaptor

Daniel Wagner (1):
  qla2xxx: Refactor asynchronous command initialization

Joe Carnuccio (3):
  qla2xxx: Fix T10 PI tag escape and IP guard options for 28XX adapters
  qla2xxx: Add devid's and conditionals for 28xx
  qla2xxx: check for firmware dump already collected

Nilesh Javali (2):
  qla2xxx: fix warning for missing error code
  qla2xxx: Update version to 10.02.07.300-k

Quinn Tran (6):
  qla2xxx: fix stuck session in gpdb
  qla2xxx: Fix warning message due to adisc is being flush
  qla2xxx: Fix premature hw access after pci error
  qla2xxx: Fix scheduling while atomic
  qla2xxx: add retry for exec fw
  qla2xxx: edif: Fix clang warning

Saurav Kashyap (2):
  qla2xxx: Implement ref count for srb
  qla2xxx: Suppress a kernel complaint in qla_create_qpair()

Shreyas Deodhar (1):
  qla2xxx: Add ql2xnvme_queues module param to configure number of NVME
    queues

v1->v2:
- update author of patch 13/17, 15/17 and 16/17
- add Fixes tag to 15/17 patch
- separate out the hunk as a separate commit to form patch 16/17
- add detailed description to patch 02/17
- add Reviewed-by tags

 drivers/scsi/qla2xxx/qla_attr.c    |   7 +-
 drivers/scsi/qla2xxx/qla_bsg.c     |   6 +-
 drivers/scsi/qla2xxx/qla_def.h     |  17 ++-
 drivers/scsi/qla2xxx/qla_edif.c    |  25 +++-
 drivers/scsi/qla2xxx/qla_gbl.h     |   5 +-
 drivers/scsi/qla2xxx/qla_gs.c      | 155 +++++++++++-----------
 drivers/scsi/qla2xxx/qla_init.c    | 199 ++++++++++++++++-------------
 drivers/scsi/qla2xxx/qla_inline.h  |   2 +
 drivers/scsi/qla2xxx/qla_iocb.c    |  70 ++++++----
 drivers/scsi/qla2xxx/qla_mbx.c     |  37 ++++--
 drivers/scsi/qla2xxx/qla_mid.c     |   9 +-
 drivers/scsi/qla2xxx/qla_mr.c      |  11 +-
 drivers/scsi/qla2xxx/qla_nvme.c    |  16 ++-
 drivers/scsi/qla2xxx/qla_nvme.h    |   4 +
 drivers/scsi/qla2xxx/qla_os.c      |  40 +++++-
 drivers/scsi/qla2xxx/qla_sup.c     |   4 +-
 drivers/scsi/qla2xxx/qla_target.c  |  14 +-
 drivers/scsi/qla2xxx/qla_tmpl.c    |   9 +-
 drivers/scsi/qla2xxx/qla_version.h |   4 +-
 19 files changed, 389 insertions(+), 245 deletions(-)


base-commit: 4be6181fea1dbfd21a8d73f69d87a6cae2d3023d
-- 
2.23.1


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

* [PATCH v2 01/17] qla2xxx: Refactor asynchronous command initialization
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 02/17] qla2xxx: Implement ref count for srb Nilesh Javali
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Daniel Wagner <dwagner@suse.de>

Move common open coded asynchronous command initializing code such as
setting up the timer and the done callback into one function. This is
a preparation step and allows us later on to change the low level
error flow handling at a central place.

Cc: stable@vger.kernel.org
Signed-off-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h    |  3 +-
 drivers/scsi/qla2xxx/qla_gs.c     | 70 +++++++++-------------------
 drivers/scsi/qla2xxx/qla_init.c   | 77 ++++++++++---------------------
 drivers/scsi/qla2xxx/qla_iocb.c   | 29 ++++++------
 drivers/scsi/qla2xxx/qla_mbx.c    | 11 ++---
 drivers/scsi/qla2xxx/qla_mid.c    |  5 +-
 drivers/scsi/qla2xxx/qla_mr.c     |  7 ++-
 drivers/scsi/qla2xxx/qla_target.c |  6 +--
 8 files changed, 76 insertions(+), 132 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 8d8503a28479..5056564f0d0c 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -316,7 +316,8 @@ extern int qla2x00_start_sp(srb_t *);
 extern int qla24xx_dif_start_scsi(srb_t *);
 extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
 extern int qla2xxx_dif_start_scsi_mq(srb_t *);
-extern void qla2x00_init_timer(srb_t *sp, unsigned long tmo);
+extern void qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
+				  void (*done)(struct srb *, int));
 extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
 
 extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 28b574e20ef3..744eb3192056 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -598,7 +598,8 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
 
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = "rft_id";
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_sns_sp_done);
 
 	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,
@@ -638,8 +639,6 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
 	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;
 
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "Async-%s - hdl=%x portid %06x.\n",
@@ -694,7 +693,8 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
 
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = "rff_id";
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_sns_sp_done);
 
 	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,
@@ -732,8 +732,6 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
 	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;
 
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
@@ -785,7 +783,8 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
 
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = "rnid";
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_sns_sp_done);
 
 	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,
@@ -823,9 +822,6 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
 	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;
-
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "Async-%s - hdl=%x portid %06x\n",
 	    sp->name, sp->handle, d_id->b24);
@@ -892,7 +888,8 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
 
 	sp->type = SRB_CT_PTHRU_CMD;
 	sp->name = "rsnn_nn";
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_sns_sp_done);
 
 	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,
@@ -936,9 +933,6 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
 	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;
-
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "Async-%s - hdl=%x.\n",
 	    sp->name, sp->handle);
@@ -2913,8 +2907,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->name = "gpsc";
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
-
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla24xx_async_gpsc_sp_done);
 
 	/* CT_IU preamble  */
 	ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
@@ -2932,9 +2926,6 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
 	sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
 
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	sp->done = qla24xx_async_gpsc_sp_done;
-
 	ql_dbg(ql_dbg_disc, vha, 0x205e,
 	    "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
 	    sp->name, fcport->port_name, sp->handle,
@@ -3190,7 +3181,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
 	sp->name = "gpnid";
 	sp->u.iocb_cmd.u.ctarg.id = *id;
 	sp->gen1 = 0;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_gpnid_sp_done);
 
 	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 	list_for_each_entry(tsp, &vha->gpnid_list, elem) {
@@ -3238,9 +3230,6 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
 	sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_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_gpnid_sp_done;
-
 	ql_dbg(ql_dbg_disc, vha, 0x2067,
 	    "Async-%s hdl=%x ID %3phC.\n", sp->name,
 	    sp->handle, &ct_req->req.port_id.port_id);
@@ -3348,9 +3337,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->name = "gffid";
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
-
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla24xx_async_gffid_sp_done);
 
 	/* CT_IU preamble  */
 	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD,
@@ -3368,8 +3356,6 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-	sp->done = qla24xx_async_gffid_sp_done;
-
 	ql_dbg(ql_dbg_disc, vha, 0x2132,
 	    "Async-%s hdl=%x  %8phC.\n", sp->name,
 	    sp->handle, fcport->port_name);
@@ -3892,9 +3878,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
 	sp->name = "gnnft";
 	sp->gen1 = vha->hw->base_qpair->chip_reset;
 	sp->gen2 = fc4_type;
-
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_gpnft_gnnft_sp_done);
 
 	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);
@@ -3910,8 +3895,6 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
 	sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-	sp->done = qla2x00_async_gpnft_gnnft_sp_done;
-
 	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);
@@ -4057,9 +4040,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
 	sp->name = "gpnft";
 	sp->gen1 = vha->hw->base_qpair->chip_reset;
 	sp->gen2 = fc4_type;
-
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_gpnft_gnnft_sp_done);
 
 	rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;
 	memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
@@ -4074,8 +4056,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
 
 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-	sp->done = qla2x00_async_gpnft_gnnft_sp_done;
-
 	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);
@@ -4189,9 +4169,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->name = "gnnid";
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
-
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_gnnid_sp_done);
 
 	/* CT_IU preamble  */
 	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GNN_ID_CMD,
@@ -4210,8 +4189,6 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-	sp->done = qla2x00_async_gnnid_sp_done;
-
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
 	    sp->name, fcport->port_name,
@@ -4317,9 +4294,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->name = "gfpnid";
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
-
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_gfpnid_sp_done);
 
 	/* CT_IU preamble  */
 	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFPN_ID_CMD,
@@ -4338,8 +4314,6 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;
 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-	sp->done = qla2x00_async_gfpnid_sp_done;
-
 	ql_dbg(ql_dbg_disc, vha, 0xffff,
 	    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
 	    sp->name, fcport->port_name,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 1fe4966fc2f6..e6f13cb6fa28 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -167,16 +167,14 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
 	if (wait)
 		sp->flags = SRB_WAKEUP_ON_COMP;
 
-	abt_iocb->timeout = qla24xx_abort_iocb_timeout;
 	init_completion(&abt_iocb->u.abt.comp);
 	/* FW can send 2 x ABTS's timeout/20s */
-	qla2x00_init_timer(sp, 42);
+	qla2x00_init_async_sp(sp, 42, qla24xx_abort_sp_done);
+	sp->u.iocb_cmd.timeout = qla24xx_abort_iocb_timeout;
 
 	abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
 	abt_iocb->u.abt.req_que_no = cpu_to_le16(cmd_sp->qpair->req->id);
 
-	sp->done = qla24xx_abort_sp_done;
-
 	ql_dbg(ql_dbg_async, vha, 0x507c,
 	       "Abort command issued - hdl=%x, type=%x\n", cmd_sp->handle,
 	       cmd_sp->type);
@@ -320,12 +318,10 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 	sp->name = "login";
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_login_sp_done);
 
 	lio = &sp->u.iocb_cmd;
-	lio->timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
-
-	sp->done = qla2x00_async_login_sp_done;
 	if (N2N_TOPO(fcport->vha->hw) && fcport_is_bigger(fcport)) {
 		lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY;
 	} else {
@@ -377,7 +373,6 @@ int
 qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
 	srb_t *sp;
-	struct srb_iocb *lio;
 	int rval = QLA_FUNCTION_FAILED;
 
 	fcport->flags |= FCF_ASYNC_SENT;
@@ -387,12 +382,8 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 
 	sp->type = SRB_LOGOUT_CMD;
 	sp->name = "logout";
-
-	lio = &sp->u.iocb_cmd;
-	lio->timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
-
-	sp->done = qla2x00_async_logout_sp_done;
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_logout_sp_done),
 
 	ql_dbg(ql_dbg_disc, vha, 0x2070,
 	    "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC explicit %d.\n",
@@ -439,7 +430,6 @@ 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;
@@ -449,12 +439,8 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
 
 	sp->type = SRB_PRLO_CMD;
 	sp->name = "prlo";
-
-	lio = &sp->u.iocb_cmd;
-	lio->timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
-
-	sp->done = qla2x00_async_prlo_sp_done;
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_prlo_sp_done);
 
 	ql_dbg(ql_dbg_disc, vha, 0x2070,
 	    "Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
@@ -575,16 +561,15 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 
 	sp->type = SRB_ADISC_CMD;
 	sp->name = "adisc";
-
-	lio = &sp->u.iocb_cmd;
-	lio->timeout = qla2x00_async_iocb_timeout;
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_adisc_sp_done);
 
-	sp->done = qla2x00_async_adisc_sp_done;
-	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
+	if (data[1] & QLA_LOGIO_LOGIN_RETRIED) {
+		lio = &sp->u.iocb_cmd;
 		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
+	}
 
 	ql_dbg(ql_dbg_disc, vha, 0x206f,
 	    "Async-adisc - hdl=%x loopid=%x portid=%06x %8phC.\n",
@@ -1084,7 +1069,6 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
 int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
 	srb_t *sp;
-	struct srb_iocb *mbx;
 	int rval = QLA_FUNCTION_FAILED;
 	unsigned long flags;
 	u16 *mb;
@@ -1117,10 +1101,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	sp->name = "gnlist";
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
-
-	mbx = &sp->u.iocb_cmd;
-	mbx->timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla24xx_async_gnl_sp_done);
 
 	mb = sp->u.iocb_cmd.u.mbx.out_mb;
 	mb[0] = MBC_PORT_NODE_NAME_LIST;
@@ -1132,8 +1114,6 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	mb[8] = vha->gnl.size;
 	mb[9] = vha->vp_idx;
 
-	sp->done = qla24xx_async_gnl_sp_done;
-
 	ql_dbg(ql_dbg_disc, vha, 0x20da,
 	    "Async-%s - OUT WWPN %8phC hndl %x\n",
 	    sp->name, fcport->port_name, sp->handle);
@@ -1269,12 +1249,10 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
 
 	sp->type = SRB_PRLI_CMD;
 	sp->name = "prli";
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_prli_sp_done);
 
 	lio = &sp->u.iocb_cmd;
-	lio->timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
-
-	sp->done = qla2x00_async_prli_sp_done;
 	lio->u.logio.flags = 0;
 
 	if (NVME_TARGET(vha->hw, fcport))
@@ -1344,10 +1322,8 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 	sp->name = "gpdb";
 	sp->gen1 = fcport->rscn_gen;
 	sp->gen2 = fcport->login_gen;
-
-	mbx = &sp->u.iocb_cmd;
-	mbx->timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla24xx_async_gpdb_sp_done);
 
 	pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
 	if (pd == NULL) {
@@ -1366,11 +1342,10 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 	mb[9] = vha->vp_idx;
 	mb[10] = opt;
 
-	mbx->u.mbx.in = pd;
+	mbx = &sp->u.iocb_cmd;
+	mbx->u.mbx.in = (void *)pd;
 	mbx->u.mbx.in_dma = pd_dma;
 
-	sp->done = qla24xx_async_gpdb_sp_done;
-
 	ql_dbg(ql_dbg_disc, vha, 0x20dc,
 	    "Async-%s %8phC hndl %x opt %x\n",
 	    sp->name, fcport->port_name, sp->handle, opt);
@@ -1974,18 +1949,16 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 	if (!sp)
 		goto done;
 
-	tm_iocb = &sp->u.iocb_cmd;
 	sp->type = SRB_TM_CMD;
 	sp->name = "tmf";
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha),
+			      qla2x00_tmf_sp_done);
+	sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout;
 
-	tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
+	tm_iocb = &sp->u.iocb_cmd;
 	init_completion(&tm_iocb->u.tmf.comp);
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
-
 	tm_iocb->u.tmf.flags = flags;
 	tm_iocb->u.tmf.lun = lun;
-	tm_iocb->u.tmf.data = tag;
-	sp->done = qla2x00_tmf_sp_done;
 
 	ql_dbg(ql_dbg_taskm, vha, 0x802f,
 	    "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index ed604f2185bf..95aae9a9631e 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2560,11 +2560,15 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
 	}
 }
 
-void qla2x00_init_timer(srb_t *sp, unsigned long tmo)
+void
+qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
+		     void (*done)(struct srb *sp, int res))
 {
 	timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0);
-	sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
+	sp->done = done;
 	sp->free = qla2x00_sp_free;
+	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+	sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
 	if (IS_QLAFX00(sp->vha->hw) && sp->type == SRB_FXIOCB_DCMD)
 		init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
 	sp->start_timer = 1;
@@ -2672,11 +2676,11 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 	sp->type = SRB_ELS_DCMD;
 	sp->name = "ELS_DCMD";
 	sp->fcport = fcport;
-	elsio->timeout = qla2x00_els_dcmd_iocb_timeout;
-	qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
-	init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
-	sp->done = qla2x00_els_dcmd_sp_done;
+	qla2x00_init_async_sp(sp, ELS_DCMD_TIMEOUT,
+			      qla2x00_els_dcmd_sp_done);
 	sp->free = qla2x00_els_dcmd_sp_free;
+	sp->u.iocb_cmd.timeout = qla2x00_els_dcmd_iocb_timeout;
+	init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
 
 	elsio->u.els_logo.els_logo_pyld = dma_alloc_coherent(&ha->pdev->dev,
 			    DMA_POOL_SIZE, &elsio->u.els_logo.els_logo_pyld_dma,
@@ -2993,17 +2997,16 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 	ql_dbg(ql_dbg_io, vha, 0x3073,
 	       "%s Enter: PLOGI portid=%06x\n", __func__, fcport->d_id.b24);
 
-	sp->type = SRB_ELS_DCMD;
-	sp->name = "ELS_DCMD";
-	sp->fcport = fcport;
-
-	elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
 	if (wait)
 		sp->flags = SRB_WAKEUP_ON_COMP;
 
-	qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT + 2);
+	sp->type = SRB_ELS_DCMD;
+	sp->name = "ELS_DCMD";
+	sp->fcport = fcport;
+	qla2x00_init_async_sp(sp, ELS_DCMD_TIMEOUT + 2,
+			     qla2x00_els_dcmd2_sp_done);
+	sp->u.iocb_cmd.timeout = qla2x00_els_dcmd2_iocb_timeout;
 
-	sp->done = qla2x00_els_dcmd2_sp_done;
 	elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE;
 
 	ptr = elsio->u.els_plogi.els_plogi_pyld =
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 10d2655ef676..2aacd3653245 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -6483,19 +6483,16 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
 	if (!sp)
 		goto done;
 
-	sp->type = SRB_MB_IOCB;
-	sp->name = mb_to_str(mcp->mb[0]);
-
 	c = &sp->u.iocb_cmd;
-	c->timeout = qla2x00_async_iocb_timeout;
 	init_completion(&c->u.mbx.comp);
 
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	sp->type = SRB_MB_IOCB;
+	sp->name = mb_to_str(mcp->mb[0]);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_mb_sp_done);
 
 	memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG);
 
-	sp->done = qla2x00_async_mb_sp_done;
-
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
 		ql_dbg(ql_dbg_mbx, vha, 0x1018,
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 1c024055f8c5..c4a967c96fd6 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -972,9 +972,8 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
 	sp->type = SRB_CTRL_VP;
 	sp->name = "ctrl_vp";
 	sp->comp = &comp;
-	sp->done = qla_ctrlvp_sp_done;
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla_ctrlvp_sp_done);
 	sp->u.iocb_cmd.u.ctrlvp.cmd = cmd;
 	sp->u.iocb_cmd.u.ctrlvp.vp_index = vp_index;
 
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 350b0c4346fb..e3ae0894c7a8 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1793,11 +1793,11 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
 
 	sp->type = SRB_FXIOCB_DCMD;
 	sp->name = "fxdisc";
+	qla2x00_init_async_sp(sp, FXDISC_TIMEOUT,
+			      qla2x00_fxdisc_sp_done);
+	sp->u.iocb_cmd.timeout = qla2x00_fxdisc_iocb_timeout;
 
 	fdisc = &sp->u.iocb_cmd;
-	fdisc->timeout = qla2x00_fxdisc_iocb_timeout;
-	qla2x00_init_timer(sp, FXDISC_TIMEOUT);
-
 	switch (fx_type) {
 	case FXDISC_GET_CONFIG_INFO:
 	fdisc->u.fxiocb.flags =
@@ -1898,7 +1898,6 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
 	}
 
 	fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type);
-	sp->done = qla2x00_fxdisc_sp_done;
 
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS)
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 8993d438e0b7..83c8c55017d1 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -656,12 +656,10 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
 
 	sp->type = type;
 	sp->name = "nack";
-
-	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
-	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
+	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+			      qla2x00_async_nack_sp_done);
 
 	sp->u.iocb_cmd.u.nack.ntfy = ntfy;
-	sp->done = qla2x00_async_nack_sp_done;
 
 	ql_dbg(ql_dbg_disc, vha, 0x20f4,
 	    "Async-%s %8phC hndl %x %s\n",
-- 
2.23.1


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

* [PATCH v2 02/17] qla2xxx: Implement ref count for srb
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 01/17] qla2xxx: Refactor asynchronous command initialization Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-02-03 14:44   ` Ewan Milne
  2022-01-10  5:02 ` [PATCH v2 03/17] qla2xxx: fix stuck session in gpdb Nilesh Javali
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Saurav Kashyap <skashyap@marvell.com>

The timeout handler and done function are racing. When
qla2x00_async_iocb_timeout() starts to run it can be preempted by the
normal response path (via the firmware?). qla24xx_async_gpsc_sp_done()
releases the SRB unconditionally. When scheduling back to
qla2x00_async_iocb_timeout() qla24xx_async_abort_cmd() will access an
freed sp->qpair pointer:

  qla2xxx [0000:83:00.0]-2871:0: Async-gpsc timeout - hdl=63d portid=234500 50:06:0e:80:08:77:b6:21.
  qla2xxx [0000:83:00.0]-2853:0: Async done-gpsc res 0, WWPN 50:06:0e:80:08:77:b6:21
  qla2xxx [0000:83:00.0]-2854:0: Async-gpsc OUT WWPN 20:45:00:27:f8:75:33:00 speeds=2c00 speed=0400.
  qla2xxx [0000:83:00.0]-28d8:0: qla24xx_handle_gpsc_event 50:06:0e:80:08:77:b6:21 DS 7 LS 6 rc 0 login 1|1 rscn 1|0 lid 5
  BUG: unable to handle kernel NULL pointer dereference at 0000000000000004
  IP: qla24xx_async_abort_cmd+0x1b/0x1c0 [qla2xxx]

Obvious solution to this is to introduce a reference counter. One
reference is taken for the normal code path (the 'good case') and one
for the timeout path. As we always race between the normal good case
and the timeout/abort handler we need to serialize it. Also we cannot
assume any order between the handlers. Since this is slow path we can
use proper synchronization via locks.

When we are able to cancel a timer (del_timer returns 1) we know there
can't be any error handling in progress because the timeout handler
hasn't expired yet, thus we can safely decrement the refcounter by one.

If we are not able to cancel the timer, we know an abort handler is
running. We have to make sure we call sp->done() in the abort handlers
before calling kref_put().

Cc: stable@vger.kernel.org
Signed-off-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
v1->v2:
- update detailed issue description and the solution

 drivers/scsi/qla2xxx/qla_bsg.c    |  6 ++-
 drivers/scsi/qla2xxx/qla_def.h    |  5 ++
 drivers/scsi/qla2xxx/qla_edif.c   |  3 +-
 drivers/scsi/qla2xxx/qla_gbl.h    |  1 +
 drivers/scsi/qla2xxx/qla_gs.c     | 85 +++++++++++++++++++++----------
 drivers/scsi/qla2xxx/qla_init.c   | 70 +++++++++++++++++--------
 drivers/scsi/qla2xxx/qla_inline.h |  2 +
 drivers/scsi/qla2xxx/qla_iocb.c   | 41 +++++++++++----
 drivers/scsi/qla2xxx/qla_mbx.c    |  4 +-
 drivers/scsi/qla2xxx/qla_mid.c    |  4 +-
 drivers/scsi/qla2xxx/qla_mr.c     |  4 +-
 drivers/scsi/qla2xxx/qla_os.c     | 14 +++--
 drivers/scsi/qla2xxx/qla_target.c |  4 +-
 13 files changed, 173 insertions(+), 70 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 9da8034ccad4..c2f00f076f79 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -29,7 +29,8 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
 	    "%s: sp hdl %x, result=%x bsg ptr %p\n",
 	    __func__, sp->handle, res, bsg_job);
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 
 	bsg_reply->result = res;
 	bsg_job_done(bsg_job, bsg_reply->result,
@@ -3013,7 +3014,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
 
 done:
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	return 0;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 9ebf4a234d9a..a5fc01b4fa96 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -726,6 +726,11 @@ typedef struct srb {
 	 * code.
 	 */
 	void (*put_fn)(struct kref *kref);
+
+	/*
+	 * Report completion for asynchronous commands.
+	 */
+	void (*async_done)(struct srb *sp, int res);
 } srb_t;
 
 #define GET_CMD_SP(sp) (sp->u.scmd.cmd)
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
index 53d2b8562027..c04957c363d8 100644
--- a/drivers/scsi/qla2xxx/qla_edif.c
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -2146,7 +2146,8 @@ edif_doorbell_show(struct device *dev, struct device_attribute *attr,
 
 static void qla_noop_sp_done(srb_t *sp, int res)
 {
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 5056564f0d0c..3f8b8bbabe6d 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -333,6 +333,7 @@ extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
 extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
 extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
 	struct qla_work_evt *e);
+void qla2x00_sp_release(struct kref *kref);
 
 /*
  * Global Function Prototypes in qla_mbx.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 744eb3192056..a812f4a45232 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -529,7 +529,6 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
 		if (!e)
 			goto err2;
 
-		del_timer(&sp->u.iocb_cmd.timer);
 		e->u.iosb.sp = sp;
 		qla2x00_post_work(vha, e);
 		return;
@@ -556,8 +555,8 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
 			sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 		}
 
-		sp->free(sp);
-
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 		return;
 	}
 
@@ -592,6 +591,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
 	if (!vha->flags.online)
 		goto done;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -652,7 +652,8 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
 	}
 	return rval;
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
@@ -687,6 +688,7 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
 	srb_t *sp;
 	struct ct_sns_pkt *ct_sns;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -747,7 +749,8 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
@@ -777,6 +780,7 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
 	srb_t *sp;
 	struct ct_sns_pkt *ct_sns;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -836,7 +840,8 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
@@ -882,6 +887,7 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
 	srb_t *sp;
 	struct ct_sns_pkt *ct_sns;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -947,7 +953,8 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
@@ -2887,7 +2894,8 @@ static void qla24xx_async_gpsc_sp_done(srb_t *sp, int res)
 	qla24xx_handle_gpsc_event(vha, &ea);
 
 done:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
@@ -2899,6 +2907,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
 	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
 		return rval;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -2938,7 +2947,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
@@ -2987,7 +2997,8 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
 		break;
 	}
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
@@ -3126,13 +3137,15 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
 	if (res) {
 		if (res == QLA_FUNCTION_TIMEOUT) {
 			qla24xx_post_gpnid_work(sp->vha, &ea.id);
-			sp->free(sp);
+			/* ref: INIT */
+			kref_put(&sp->cmd_kref, qla2x00_sp_release);
 			return;
 		}
 	} else if (sp->gen1) {
 		/* There was another RSCN for this Nport ID */
 		qla24xx_post_gpnid_work(sp->vha, &ea.id);
-		sp->free(sp);
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 		return;
 	}
 
@@ -3153,7 +3166,8 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
 				  sp->u.iocb_cmd.u.ctarg.rsp_dma);
 		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 
-		sp->free(sp);
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 		return;
 	}
 
@@ -3173,6 +3187,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
 	if (!vha->flags.online)
 		goto done;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -3189,7 +3204,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
 		if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
 			tsp->gen1++;
 			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
-			sp->free(sp);
+			/* ref: INIT */
+			kref_put(&sp->cmd_kref, qla2x00_sp_release);
 			goto done;
 		}
 	}
@@ -3259,8 +3275,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
 			sp->u.iocb_cmd.u.ctarg.rsp_dma);
 		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 	}
-
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
@@ -3315,7 +3331,8 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
 	ea.rc = res;
 
 	qla24xx_handle_gffid_event(vha, &ea);
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 /* Get FC4 Feature with Nport ID. */
@@ -3328,6 +3345,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
 		return rval;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		return rval;
@@ -3366,7 +3384,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 
 	return rval;
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	fcport->flags &= ~FCF_ASYNC_SENT;
 	return rval;
 }
@@ -3753,7 +3772,6 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
 	    "Async done-%s res %x FC4Type %x\n",
 	    sp->name, res, sp->gen2);
 
-	del_timer(&sp->u.iocb_cmd.timer);
 	sp->rc = res;
 	if (res) {
 		unsigned long flags;
@@ -3921,8 +3939,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
 		    sp->u.iocb_cmd.u.ctarg.rsp_dma);
 		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 	}
-
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 
 	spin_lock_irqsave(&vha->work_lock, flags);
 	vha->scan.scan_flags &= ~SF_SCANNING;
@@ -3974,9 +3992,12 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
 		ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
 		    "%s: Performing FCP Scan\n", __func__);
 
-		if (sp)
-			sp->free(sp); /* should not happen */
+		if (sp) {
+			/* ref: INIT */
+			kref_put(&sp->cmd_kref, qla2x00_sp_release);
+		}
 
+		/* ref: INIT */
 		sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 		if (!sp) {
 			spin_lock_irqsave(&vha->work_lock, flags);
@@ -4021,6 +4042,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
 			    sp->u.iocb_cmd.u.ctarg.req,
 			    sp->u.iocb_cmd.u.ctarg.req_dma);
 			sp->u.iocb_cmd.u.ctarg.req = NULL;
+			/* ref: INIT */
 			qla2x00_rel_sp(sp);
 			return rval;
 		}
@@ -4083,7 +4105,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
 		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 	}
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 
 	spin_lock_irqsave(&vha->work_lock, flags);
 	vha->scan.scan_flags &= ~SF_SCANNING;
@@ -4147,7 +4170,8 @@ static void qla2x00_async_gnnid_sp_done(srb_t *sp, int res)
 
 	qla24xx_handle_gnnid_event(vha, &ea);
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
@@ -4160,6 +4184,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 		return rval;
 
 	qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
 	if (!sp)
 		goto done;
@@ -4200,7 +4225,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	fcport->flags &= ~FCF_ASYNC_SENT;
 done:
 	return rval;
@@ -4274,7 +4300,8 @@ static void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res)
 
 	qla24xx_handle_gfpnid_event(vha, &ea);
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
@@ -4286,6 +4313,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
 		return rval;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
 	if (!sp)
 		goto done;
@@ -4326,7 +4354,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e6f13cb6fa28..38c11b75f644 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -51,6 +51,9 @@ qla2x00_sp_timeout(struct timer_list *t)
 	WARN_ON(irqs_disabled());
 	iocb = &sp->u.iocb_cmd;
 	iocb->timeout(sp);
+
+	/* ref: TMR */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 void qla2x00_sp_free(srb_t *sp)
@@ -125,8 +128,13 @@ static void qla24xx_abort_iocb_timeout(void *data)
 	}
 	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
 
-	if (sp->cmd_sp)
+	if (sp->cmd_sp) {
+		/*
+		 * This done function should take care of
+		 * original command ref: INIT
+		 */
 		sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
+	}
 
 	abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
 	sp->done(sp, QLA_OS_TIMER_EXPIRED);
@@ -140,11 +148,11 @@ static void qla24xx_abort_sp_done(srb_t *sp, int res)
 	if (orig_sp)
 		qla_wait_nvme_release_cmd_kref(orig_sp);
 
-	del_timer(&sp->u.iocb_cmd.timer);
 	if (sp->flags & SRB_WAKEUP_ON_COMP)
 		complete(&abt->u.abt.comp);
 	else
-		sp->free(sp);
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
@@ -154,6 +162,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
 	srb_t *sp;
 	int rval = QLA_FUNCTION_FAILED;
 
+	/* ref: INIT for ABTS command */
 	sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
 				  GFP_ATOMIC);
 	if (!sp)
@@ -181,7 +190,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
 
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
-		sp->free(sp);
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 		return rval;
 	}
 
@@ -189,7 +199,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
 		wait_for_completion(&abt_iocb->u.abt.comp);
 		rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
 			QLA_SUCCESS : QLA_ERR_FROM_FW;
-		sp->free(sp);
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	}
 
 	return rval;
@@ -287,7 +298,8 @@ static void qla2x00_async_login_sp_done(srb_t *sp, int res)
 		qla24xx_handle_plogi_done_event(vha, &ea);
 	}
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int
@@ -306,6 +318,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 		return rval;
 	}
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -354,7 +367,8 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	fcport->flags &= ~FCF_ASYNC_SENT;
 done:
 	fcport->flags &= ~FCF_ASYNC_ACTIVE;
@@ -366,7 +380,8 @@ static void qla2x00_async_logout_sp_done(srb_t *sp, int res)
 	sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 	sp->fcport->login_gen++;
 	qlt_logo_completion_handler(sp->fcport, sp->u.iocb_cmd.u.logio.data[0]);
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int
@@ -376,6 +391,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 	int rval = QLA_FUNCTION_FAILED;
 
 	fcport->flags |= FCF_ASYNC_SENT;
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -397,7 +413,8 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 	return rval;
@@ -423,7 +440,8 @@ static void qla2x00_async_prlo_sp_done(srb_t *sp, int res)
 	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);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int
@@ -433,6 +451,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
 	int rval;
 
 	rval = QLA_FUNCTION_FAILED;
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -454,7 +473,8 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	fcport->flags &= ~FCF_ASYNC_ACTIVE;
 	return rval;
@@ -539,8 +559,8 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp, int res)
 	ea.sp = sp;
 
 	qla24xx_handle_adisc_event(vha, &ea);
-
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int
@@ -555,6 +575,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 		return rval;
 
 	fcport->flags |= FCF_ASYNC_SENT;
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -582,7 +603,8 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 	qla2x00_post_async_adisc_work(vha, fcport, data);
@@ -1063,7 +1085,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
 	}
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
@@ -1093,6 +1116,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	vha->gnl.sent = 1;
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -1125,7 +1149,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
 	return rval;
@@ -1171,7 +1196,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res)
 	dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
 		sp->u.iocb_cmd.u.mbx.in_dma);
 
-	sp->free(sp);
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
@@ -1216,7 +1241,7 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
 		qla24xx_handle_prli_done_event(vha, &ea);
 	}
 
-	sp->free(sp);
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int
@@ -1274,7 +1299,8 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	fcport->flags &= ~FCF_ASYNC_SENT;
 	return rval;
 }
@@ -1359,7 +1385,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 	if (pd)
 		dma_pool_free(ha->s_dma_pool, pd, pd_dma);
 
-	sp->free(sp);
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	fcport->flags &= ~FCF_ASYNC_SENT;
 done:
 	fcport->flags &= ~FCF_ASYNC_ACTIVE;
@@ -1945,6 +1971,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 	srb_t *sp;
 	int rval = QLA_FUNCTION_FAILED;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -1988,7 +2015,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 	}
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	fcport->flags &= ~FCF_ASYNC_SENT;
 done:
 	return rval;
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 5f3b7995cc8f..db17f7f410cd 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -184,6 +184,8 @@ static void qla2xxx_init_sp(srb_t *sp, scsi_qla_host_t *vha,
 	sp->vha = vha;
 	sp->qpair = qpair;
 	sp->cmd_type = TYPE_SRB;
+	/* ref : INIT - normal flow */
+	kref_init(&sp->cmd_kref);
 	INIT_LIST_HEAD(&sp->elem);
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 95aae9a9631e..7dd82214d59f 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2560,6 +2560,14 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
 	}
 }
 
+void
+qla2x00_sp_release(struct kref *kref)
+{
+	struct srb *sp = container_of(kref, struct srb, cmd_kref);
+
+	sp->free(sp);
+}
+
 void
 qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
 		     void (*done)(struct srb *sp, int res))
@@ -2655,7 +2663,9 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 	       return -ENOMEM;
 	}
 
-	/* Alloc SRB structure */
+	/* Alloc SRB structure
+	 * ref: INIT
+	 */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp) {
 		kfree(fcport);
@@ -2687,7 +2697,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 			    GFP_KERNEL);
 
 	if (!elsio->u.els_logo.els_logo_pyld) {
-		sp->free(sp);
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 		return QLA_FUNCTION_FAILED;
 	}
 
@@ -2710,7 +2721,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
-		sp->free(sp);
+		/* ref: INIT */
+		kref_put(&sp->cmd_kref, qla2x00_sp_release);
 		return QLA_FUNCTION_FAILED;
 	}
 
@@ -2721,7 +2733,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 
 	wait_for_completion(&elsio->u.els_logo.comp);
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	return rval;
 }
 
@@ -2854,7 +2867,6 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
 	    sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
 
 	fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
-	del_timer(&sp->u.iocb_cmd.timer);
 
 	if (sp->flags & SRB_WAKEUP_ON_COMP)
 		complete(&lio->u.els_plogi.comp);
@@ -2964,7 +2976,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
 			struct srb_iocb *elsio = &sp->u.iocb_cmd;
 
 			qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
-			sp->free(sp);
+			/* ref: INIT */
+			kref_put(&sp->cmd_kref, qla2x00_sp_release);
 			return;
 		}
 		e->u.iosb.sp = sp;
@@ -2982,7 +2995,9 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 	int rval = QLA_SUCCESS;
 	void	*ptr, *resp_ptr;
 
-	/* Alloc SRB structure */
+	/* Alloc SRB structure
+	 * ref: INIT
+	 */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp) {
 		ql_log(ql_log_info, vha, 0x70e6,
@@ -3071,7 +3086,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 out:
 	fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 	qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
@@ -3882,8 +3898,15 @@ qla2x00_start_sp(srb_t *sp)
 		break;
 	}
 
-	if (sp->start_timer)
+	if (sp->start_timer) {
+		/* ref: TMR timer ref
+		 * this code should be just before start_iocbs function
+		 * This will make sure that caller function don't to do
+		 * kref_put even on failure
+		 */
+		kref_get(&sp->cmd_kref);
 		add_timer(&sp->u.iocb_cmd.timer);
+	}
 
 	wmb();
 	qla2x00_start_iocbs(vha, qp->req);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 2aacd3653245..38e0f02c75e1 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -6479,6 +6479,7 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
 	if (!vha->hw->flags.fw_started)
 		goto done;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -6524,7 +6525,8 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
 	}
 
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index c4a967c96fd6..e6b5c4ccce97 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -965,6 +965,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
 	if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
 		return QLA_PARAMETER_ERROR;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
 	if (!sp)
 		return rval;
@@ -1007,6 +1008,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
 		break;
 	}
 done:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	return rval;
 }
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index e3ae0894c7a8..f726eb8449c5 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1787,6 +1787,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
 	struct register_host_info *preg_hsi;
 	struct new_utsname *p_sysid = NULL;
 
+	/* ref: INIT */
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 	if (!sp)
 		goto done;
@@ -1973,7 +1974,8 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
 		dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
 		    fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
 done_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	return rval;
 }
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index abcd30917263..0a7b00d165c7 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -728,7 +728,8 @@ void qla2x00_sp_compl(srb_t *sp, int res)
 	struct scsi_cmnd *cmd = GET_CMD_SP(sp);
 	struct completion *comp = sp->comp;
 
-	sp->free(sp);
+	/* kref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	cmd->result = res;
 	CMD_SP(cmd) = NULL;
 	scsi_done(cmd);
@@ -819,7 +820,8 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
 	struct scsi_cmnd *cmd = GET_CMD_SP(sp);
 	struct completion *comp = sp->comp;
 
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 	cmd->result = res;
 	CMD_SP(cmd) = NULL;
 	scsi_done(cmd);
@@ -919,6 +921,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 		goto qc24_target_busy;
 
 	sp = scsi_cmd_priv(cmd);
+	/* ref: INIT */
 	qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
 
 	sp->u.scmd.cmd = cmd;
@@ -938,7 +941,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 	return 0;
 
 qc24_host_busy_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 
 qc24_target_busy:
 	return SCSI_MLQUEUE_TARGET_BUSY;
@@ -1008,6 +1012,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
 		goto qc24_target_busy;
 
 	sp = scsi_cmd_priv(cmd);
+	/* ref: INIT */
 	qla2xxx_init_sp(sp, vha, qpair, fcport);
 
 	sp->u.scmd.cmd = cmd;
@@ -1026,7 +1031,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
 	return 0;
 
 qc24_host_busy_free_sp:
-	sp->free(sp);
+	/* ref: INIT */
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 
 qc24_target_busy:
 	return SCSI_MLQUEUE_TARGET_BUSY;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 83c8c55017d1..b0990f2ee91c 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -620,7 +620,7 @@ static void qla2x00_async_nack_sp_done(srb_t *sp, int res)
 	}
 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
-	sp->free(sp);
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 }
 
 int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
@@ -672,7 +672,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
 	return rval;
 
 done_free_sp:
-	sp->free(sp);
+	kref_put(&sp->cmd_kref, qla2x00_sp_release);
 done:
 	fcport->flags &= ~FCF_ASYNC_SENT;
 	return rval;
-- 
2.23.1


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

* [PATCH v2 03/17] qla2xxx: fix stuck session in gpdb
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 01/17] qla2xxx: Refactor asynchronous command initialization Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 02/17] qla2xxx: Implement ref count for srb Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 04/17] qla2xxx: Fix warning message due to adisc is being flush Nilesh Javali
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Quinn Tran <qutran@marvell.com>

Fix stuck sessions in get port database. When a thread is in the process
of re-establishing a session, a flag is set to prevent multiple threads /
triggers from doing the same task. This flag was left on, where any attempt to
relogin was locked out. Clear this flag, if the attempt has failed.

Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 38c11b75f644..0b641a803f7c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1332,9 +1332,9 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) ||
 	    fcport->loop_id == FC_NO_LOOP_ID) {
 		ql_log(ql_log_warn, vha, 0xffff,
-		    "%s: %8phC - not sending command.\n",
-		    __func__, fcport->port_name);
-		return rval;
+		    "%s: %8phC online %d flags %x - not sending command.\n",
+		    __func__, fcport->port_name, vha->flags.online, fcport->flags);
+		goto done;
 	}
 
 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
-- 
2.23.1


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

* [PATCH v2 04/17] qla2xxx: Fix warning message due to adisc is being flush
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (2 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 03/17] qla2xxx: fix stuck session in gpdb Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 05/17] qla2xxx: Fix premature hw access after pci error Nilesh Javali
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Quinn Tran <qutran@marvell.com>

Fix warning message due to adisc is being flush.
Linux kernel triggered a warning message where a different
error code type is not matching up with the expected type. This
patch adds additional translation of one error code type to another.

WARNING: CPU: 2 PID: 1131623 at drivers/scsi/qla2xxx/qla_init.c:498
qla2x00_async_adisc_sp_done+0x294/0x2b0 [qla2xxx]
CPU: 2 PID: 1131623 Comm: drmgr Not tainted 5.13.0-rc1-autotest #1
..
GPR28: c000000aaa9c8890 c0080000079ab678 c00000140a104800 c00000002bd19000
NIP [c00800000790857c] qla2x00_async_adisc_sp_done+0x294/0x2b0 [qla2xxx]
LR [c008000007908578] qla2x00_async_adisc_sp_done+0x290/0x2b0 [qla2xxx]
Call Trace:
[c00000001cdc3620] [c008000007908578] qla2x00_async_adisc_sp_done+0x290/0x2b0 [qla2xxx] (unreliable)
[c00000001cdc3710] [c0080000078f3080] __qla2x00_abort_all_cmds+0x1b8/0x580 [qla2xxx]
[c00000001cdc3840] [c0080000078f589c] qla2x00_abort_all_cmds+0x34/0xd0 [qla2xxx]
[c00000001cdc3880] [c0080000079153d8] qla2x00_abort_isp_cleanup+0x3f0/0x570 [qla2xxx]
[c00000001cdc3920] [c0080000078fb7e8] qla2x00_remove_one+0x3d0/0x480 [qla2xxx]
[c00000001cdc39b0] [c00000000071c274] pci_device_remove+0x64/0x120
[c00000001cdc39f0] [c0000000007fb818] device_release_driver_internal+0x168/0x2a0
[c00000001cdc3a30] [c00000000070e304] pci_stop_bus_device+0xb4/0x100
[c00000001cdc3a70] [c00000000070e4f0] pci_stop_and_remove_bus_device+0x20/0x40
[c00000001cdc3aa0] [c000000000073940] pci_hp_remove_devices+0x90/0x130
[c00000001cdc3b30] [c0080000070704d0] disable_slot+0x38/0x90 [rpaphp] [
c00000001cdc3b60] [c00000000073eb4c] power_write_file+0xcc/0x180
[c00000001cdc3be0] [c0000000007354bc] pci_slot_attr_store+0x3c/0x60
[c00000001cdc3c00] [c00000000055f820] sysfs_kf_write+0x60/0x80 [c00000001cdc3c20]
[c00000000055df10] kernfs_fop_write_iter+0x1a0/0x290
[c00000001cdc3c70] [c000000000447c4c] new_sync_write+0x14c/0x1d0
[c00000001cdc3d10] [c00000000044b134] vfs_write+0x224/0x330
[c00000001cdc3d60] [c00000000044b3f4] ksys_write+0x74/0x130
[c00000001cdc3db0] [c00000000002df70] system_call_exception+0x150/0x2d0
[c00000001cdc3e10] [c00000000000d45c] system_call_common+0xec/0x278

Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 0b641a803f7c..e54c31296fab 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -295,6 +295,8 @@ static void qla2x00_async_login_sp_done(srb_t *sp, int res)
 		ea.iop[0] = lio->u.logio.iop[0];
 		ea.iop[1] = lio->u.logio.iop[1];
 		ea.sp = sp;
+		if (res)
+			ea.data[0] = MBS_COMMAND_ERROR;
 		qla24xx_handle_plogi_done_event(vha, &ea);
 	}
 
@@ -557,6 +559,8 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp, int res)
 	ea.iop[1] = lio->u.logio.iop[1];
 	ea.fcport = sp->fcport;
 	ea.sp = sp;
+	if (res)
+		ea.data[0] = MBS_COMMAND_ERROR;
 
 	qla24xx_handle_adisc_event(vha, &ea);
 	/* ref: INIT */
@@ -1237,6 +1241,8 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
 		ea.sp = sp;
 		if (res == QLA_OS_TIMER_EXPIRED)
 			ea.data[0] = QLA_OS_TIMER_EXPIRED;
+		else if (res)
+			ea.data[0] = MBS_COMMAND_ERROR;
 
 		qla24xx_handle_prli_done_event(vha, &ea);
 	}
-- 
2.23.1


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

* [PATCH v2 05/17] qla2xxx: Fix premature hw access after pci error
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (3 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 04/17] qla2xxx: Fix warning message due to adisc is being flush Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 06/17] qla2xxx: Fix scheduling while atomic Nilesh Javali
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Quinn Tran <qutran@marvell.com>

Fix premature hw access after pci error.
After a recoverable PCI error has been detected and recovered, qla driver
needs to check to see if the error condition still persist and/or wait until
the OS to give the resume signal.

Sep  8 22:26:03 localhost kernel: WARNING: CPU: 9 PID: 124606 at qla_tmpl.c:440
qla27xx_fwdt_entry_t266+0x55/0x60 [qla2xxx]
Sep  8 22:26:03 localhost kernel: RIP: 0010:qla27xx_fwdt_entry_t266+0x55/0x60
[qla2xxx]
Sep  8 22:26:03 localhost kernel: Call Trace:
Sep  8 22:26:03 localhost kernel: ? qla27xx_walk_template+0xb1/0x1b0 [qla2xxx]
Sep  8 22:26:03 localhost kernel: ? qla27xx_execute_fwdt_template+0x12a/0x160
[qla2xxx]
Sep  8 22:26:03 localhost kernel: ? qla27xx_fwdump+0xa0/0x1c0 [qla2xxx]
Sep  8 22:26:03 localhost kernel: ? qla2xxx_pci_mmio_enabled+0xfb/0x120
[qla2xxx]
Sep  8 22:26:03 localhost kernel: ? report_mmio_enabled+0x44/0x80
Sep  8 22:26:03 localhost kernel: ? report_slot_reset+0x80/0x80
Sep  8 22:26:03 localhost kernel: ? pci_walk_bus+0x70/0x90
Sep  8 22:26:03 localhost kernel: ? aer_dev_correctable_show+0xc0/0xc0
Sep  8 22:26:03 localhost kernel: ? pcie_do_recovery+0x1bb/0x240
Sep  8 22:26:03 localhost kernel: ? aer_recover_work_func+0xaa/0xd0
Sep  8 22:26:03 localhost kernel: ? process_one_work+0x1a7/0x360
..
Sep  8 22:26:03 localhost kernel: qla2xxx [0000:42:00.2]-8041:22: detected PCI
disconnect.
Sep  8 22:26:03 localhost kernel: qla2xxx [0000:42:00.2]-107ff:22:
qla27xx_fwdt_entry_t262: dump ram MB failed. Area 5h start 198013h end 198013h
Sep  8 22:26:03 localhost kernel: qla2xxx [0000:42:00.2]-107ff:22: Unable to
capture FW dump
Sep  8 22:26:03 localhost kernel: qla2xxx [0000:42:00.2]-1015:22: cmd=0x0,
waited 5221 msecs
Sep  8 22:26:03 localhost kernel: qla2xxx [0000:42:00.2]-680d:22: mmio
enabled returning.
Sep  8 22:26:03 localhost kernel: qla2xxx [0000:42:00.2]-d04c:22: MBX
Command timeout for cmd 0, iocontrol=ffffffff jiffies=10140f2e5
mb[0-3]=[0xffff 0xffff 0xffff 0xffff]

Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_os.c   | 10 +++++++++-
 drivers/scsi/qla2xxx/qla_tmpl.c |  9 +++++++--
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 0a7b00d165c7..c4b4b4496399 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -7639,7 +7639,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 
 	switch (state) {
 	case pci_channel_io_normal:
-		ha->flags.eeh_busy = 0;
+		qla_pci_set_eeh_busy(vha);
 		if (ql2xmqsupport || ql2xnvmeenable) {
 			set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags);
 			qla2xxx_wake_dpc(vha);
@@ -7680,9 +7680,16 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
 	       "mmio enabled\n");
 
 	ha->pci_error_state = QLA_PCI_MMIO_ENABLED;
+
 	if (IS_QLA82XX(ha))
 		return PCI_ERS_RESULT_RECOVERED;
 
+	if (qla2x00_isp_reg_stat(ha)) {
+		ql_log(ql_log_info, base_vha, 0x803f,
+		    "During mmio enabled, PCI/Register disconnect still detected.\n");
+		goto out;
+	}
+
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	if (IS_QLA2100(ha) || IS_QLA2200(ha)){
 		stat = rd_reg_word(&reg->hccr);
@@ -7704,6 +7711,7 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
 		    "RISC paused -- mmio_enabled, Dumping firmware.\n");
 		qla2xxx_dump_fw(base_vha);
 	}
+out:
 	/* set PCI_ERS_RESULT_NEED_RESET to trigger call to qla2xxx_pci_slot_reset */
 	ql_dbg(ql_dbg_aer, base_vha, 0x600d,
 	       "mmio enabled returning.\n");
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index 26c13a953b97..b0a74b036cf4 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -435,8 +435,13 @@ qla27xx_fwdt_entry_t266(struct scsi_qla_host *vha,
 {
 	ql_dbg(ql_dbg_misc, vha, 0xd20a,
 	    "%s: reset risc [%lx]\n", __func__, *len);
-	if (buf)
-		WARN_ON_ONCE(qla24xx_soft_reset(vha->hw) != QLA_SUCCESS);
+	if (buf) {
+		if (qla24xx_soft_reset(vha->hw) != QLA_SUCCESS) {
+			ql_dbg(ql_dbg_async, vha, 0x5001,
+			    "%s: unable to soft reset\n", __func__);
+			return INVALID_ENTRY;
+		}
+	}
 
 	return qla27xx_next_entry(ent);
 }
-- 
2.23.1


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

* [PATCH v2 06/17] qla2xxx: Fix scheduling while atomic
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (4 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 05/17] qla2xxx: Fix premature hw access after pci error Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 07/17] qla2xxx: add retry for exec fw Nilesh Javali
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Quinn Tran <qutran@marvell.com>

QLA makes a call into midlayer (fc_remote_port_delete) which
can put the thread to sleep. The thread that originate the call
is in interrupt context. The combination of the 2 trigger a
crash. This patch schedule the call in non-interrupt context
where it is more safe.

kernel: BUG: scheduling while atomic: swapper/7/0/0x00010000
kernel: Call Trace:
kernel:  <IRQ>
kernel:  dump_stack+0x66/0x81
kernel:  __schedule_bug.cold.90+0x5/0x1d
kernel:  __schedule+0x7af/0x960
kernel:  schedule+0x28/0x80
kernel:  schedule_timeout+0x26d/0x3b0
kernel:  wait_for_completion+0xb4/0x140
kernel:  ? wake_up_q+0x70/0x70
kernel:  __wait_rcu_gp+0x12c/0x160
kernel:  ? sdev_evt_alloc+0xc0/0x180 [scsi_mod]
kernel:  synchronize_sched+0x6c/0x80
kernel:  ? call_rcu_bh+0x20/0x20
kernel:  ? __bpf_trace_rcu_invoke_callback+0x10/0x10
kernel:  sdev_evt_alloc+0xfd/0x180 [scsi_mod]
kernel:  starget_for_each_device+0x85/0xb0 [scsi_mod]
kernel:  ? scsi_init_io+0x360/0x3d0 [scsi_mod]
kernel:  scsi_init_io+0x388/0x3d0 [scsi_mod]
kernel:  device_for_each_child+0x54/0x90
kernel:  fc_remote_port_delete+0x70/0xe0 [scsi_transport_fc]
kernel:  qla2x00_schedule_rport_del+0x62/0xf0 [qla2xxx]
kernel:  qla2x00_mark_device_lost+0x9c/0xd0 [qla2xxx]
kernel:  qla24xx_handle_plogi_done_event+0x55f/0x570 [qla2xxx]
kernel:  qla2x00_async_login_sp_done+0xd2/0x100 [qla2xxx]
kernel:  qla24xx_logio_entry+0x13a/0x3c0 [qla2xxx]
kernel:  qla24xx_process_response_queue+0x306/0x400 [qla2xxx]
kernel:  qla24xx_msix_rsp_q+0x3f/0xb0 [qla2xxx]
kernel:  __handle_irq_event_percpu+0x40/0x180
kernel:  handle_irq_event_percpu+0x30/0x80
kernel:  handle_irq_event+0x36/0x60

Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e54c31296fab..ac25d2bfa90b 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2231,12 +2231,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 		ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %d %8phC cmd error %x\n",
 		    __func__, __LINE__, ea->fcport->port_name, ea->data[1]);
 
-		ea->fcport->flags &= ~FCF_ASYNC_SENT;
-		qla2x00_set_fcport_disc_state(ea->fcport, DSC_LOGIN_FAILED);
-		if (ea->data[1] & QLA_LOGIO_LOGIN_RETRIED)
-			set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
-		else
-			qla2x00_mark_device_lost(vha, ea->fcport, 1);
+		qlt_schedule_sess_for_deletion(ea->fcport);
 		break;
 	case MBS_LOOP_ID_USED:
 		/* data[1] = IO PARAM 1 = nport ID  */
-- 
2.23.1


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

* [PATCH v2 07/17] qla2xxx: add retry for exec fw
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (5 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 06/17] qla2xxx: Fix scheduling while atomic Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 08/17] qla2xxx: Show wrong FDMI data for 64G adaptor Nilesh Javali
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Quinn Tran <qutran@marvell.com>

Per FW request, Exec FW can fail due to temp error resulting in driver not
attaching to the adapter. Add retry of this command up to 4 retries.

Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_mbx.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 38e0f02c75e1..c4bd8a16d78c 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -689,7 +689,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
 	mbx_cmd_t *mcp = &mc;
 	u8 semaphore = 0;
 #define EXE_FW_FORCE_SEMAPHORE BIT_7
-	u8 retry = 3;
+	u8 retry = 5;
 
 	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025,
 	    "Entered %s.\n", __func__);
@@ -764,6 +764,12 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
 			goto again;
 		}
 
+		if (retry) {
+			retry--;
+			ql_dbg(ql_dbg_async, vha, 0x509d,
+			    "Exe FW retry: mb[0]=%x retry[%d]\n", mcp->mb[0], retry);
+			goto again;
+		}
 		ql_dbg(ql_dbg_mbx, vha, 0x1026,
 		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
 		vha->hw_err_cnt++;
-- 
2.23.1


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

* [PATCH v2 08/17] qla2xxx: Show wrong FDMI data for 64G adaptor
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (6 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 07/17] qla2xxx: add retry for exec fw Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 09/17] qla2xxx: Add ql2xnvme_queues module param to configure number of NVME queues Nilesh Javali
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Bikash Hazarika <bhazarika@marvell.com>

Corrected transmission speed mask values for FC.
Supported Speed: 16 32 20 Gb/s   ===> It should be 64 instead of 20
Supported Speed: 16G 32G 48G  ===>  It should be 64G instead of 48G

Cc: stable@vger.kernel.org
Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_def.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a5fc01b4fa96..bc0c5df77801 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2891,7 +2891,11 @@ struct ct_fdmi2_hba_attributes {
 #define FDMI_PORT_SPEED_8GB		0x10
 #define FDMI_PORT_SPEED_16GB		0x20
 #define FDMI_PORT_SPEED_32GB		0x40
-#define FDMI_PORT_SPEED_64GB		0x80
+#define FDMI_PORT_SPEED_20GB		0x80
+#define FDMI_PORT_SPEED_40GB		0x100
+#define FDMI_PORT_SPEED_128GB		0x200
+#define FDMI_PORT_SPEED_64GB		0x400
+#define FDMI_PORT_SPEED_256GB		0x800
 #define FDMI_PORT_SPEED_UNKNOWN		0x8000
 
 #define FC_CLASS_2	0x04
-- 
2.23.1


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

* [PATCH v2 09/17] qla2xxx: Add ql2xnvme_queues module param to configure number of NVME queues
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (7 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 08/17] qla2xxx: Show wrong FDMI data for 64G adaptor Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 10/17] qla2xxx: Fix device reconnect in loop topology Nilesh Javali
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Shreyas Deodhar <sdeodhar@marvell.com>

Add ql2xnvme_queues module parameter to configure number of NVME queues

Usage:
Number of NVMe Queues that can be configured.
Final value will be min(ql2xnvme_queues, num_cpus, num_chip_queues),
1 - Minimum number of queues supported
128 - Maximum number of queues supported
8 - Default value

Signed-off-by: Shreyas Deodhar <sdeodhar@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h  |  1 +
 drivers/scsi/qla2xxx/qla_nvme.c | 16 ++++++++++++++--
 drivers/scsi/qla2xxx/qla_nvme.h |  4 ++++
 drivers/scsi/qla2xxx/qla_os.c   |  8 ++++++++
 4 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3f8b8bbabe6d..cedc347e3c33 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -192,6 +192,7 @@ extern int ql2xfulldump_on_mpifail;
 extern int ql2xsecenable;
 extern int ql2xenforce_iocb_limit;
 extern int ql2xabts_wait_nvme;
+extern u32 ql2xnvme_queues;
 
 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_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index e22ec7cb65db..718c761ff5f8 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -710,7 +710,7 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = {
 	.fcp_io		= qla_nvme_post_cmd,
 	.fcp_abort	= qla_nvme_fcp_abort,
 	.map_queues	= qla_nvme_map_queues,
-	.max_hw_queues  = 8,
+	.max_hw_queues  = DEF_NVME_HW_QUEUES,
 	.max_sgl_segments = 1024,
 	.max_dif_sgl_segments = 64,
 	.dma_boundary = 0xFFFFFFFF,
@@ -779,10 +779,22 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha)
 
 	WARN_ON(vha->nvme_local_port);
 
+	if (ql2xnvme_queues < MIN_NVME_HW_QUEUES || ql2xnvme_queues > MAX_NVME_HW_QUEUES) {
+		ql_log(ql_log_warn, vha, 0xfffd,
+		    "ql2xnvme_queues=%d is out of range(MIN:%d - MAX:%d). Resetting ql2xnvme_queues to:%d\n",
+		    ql2xnvme_queues, MIN_NVME_HW_QUEUES, MAX_NVME_HW_QUEUES,
+		    DEF_NVME_HW_QUEUES);
+		ql2xnvme_queues = DEF_NVME_HW_QUEUES;
+	}
+
 	qla_nvme_fc_transport.max_hw_queues =
-	    min((uint8_t)(qla_nvme_fc_transport.max_hw_queues),
+	    min((uint8_t)(ql2xnvme_queues),
 		(uint8_t)(ha->max_qpairs ? ha->max_qpairs : 1));
 
+	ql_log(ql_log_info, vha, 0xfffb,
+	    "Number of NVME queues used for this port: %d\n",
+	    qla_nvme_fc_transport.max_hw_queues);
+
 	pinfo.node_name = wwn_to_u64(vha->node_name);
 	pinfo.port_name = wwn_to_u64(vha->port_name);
 	pinfo.port_role = FC_PORT_ROLE_NVME_INITIATOR;
diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h
index f81f219c7c7d..d0e3c0e07baa 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.h
+++ b/drivers/scsi/qla2xxx/qla_nvme.h
@@ -13,6 +13,10 @@
 #include "qla_def.h"
 #include "qla_dsd.h"
 
+#define MIN_NVME_HW_QUEUES 1
+#define MAX_NVME_HW_QUEUES 128
+#define DEF_NVME_HW_QUEUES 8
+
 #define NVME_ATIO_CMD_OFF 32
 #define NVME_FIRST_PACKET_CMDLEN (64 - NVME_ATIO_CMD_OFF)
 #define Q2T_NVME_NUM_TAGS 2048
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index c4b4b4496399..7d5159306112 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -338,6 +338,14 @@ static void qla2x00_free_device(scsi_qla_host_t *);
 static int qla2xxx_map_queues(struct Scsi_Host *shost);
 static void qla2x00_destroy_deferred_work(struct qla_hw_data *);
 
+u32 ql2xnvme_queues = DEF_NVME_HW_QUEUES;
+module_param(ql2xnvme_queues, uint, S_IRUGO);
+MODULE_PARM_DESC(ql2xnvme_queues,
+	"Number of NVMe Queues that can be configured.\n"
+	"Final value will be min(ql2xnvme_queues, num_cpus,num_chip_queues)\n"
+	"1 - Minimum number of queues supported\n"
+	"128 - Maximum number of queues supported\n"
+	"8 - Default value");
 
 static struct scsi_transport_template *qla2xxx_transport_template = NULL;
 struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
-- 
2.23.1


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

* [PATCH v2 10/17] qla2xxx: Fix device reconnect in loop topology
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (8 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 09/17] qla2xxx: Add ql2xnvme_queues module param to configure number of NVME queues Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 11/17] qla2xxx: fix warning for missing error code Nilesh Javali
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Arun Easi <aeasi@marvell.com>

A device logout in loop topology initiates a device connection teardown
which looses the FW device handle. In loop topo, the device handle is not
regrabbed leading to device login failures and eventually to loss of the
device. Fix this by taking the main login path that does it.

Cc: stable@vger.kernel.org
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 15 +++++++++++++++
 drivers/scsi/qla2xxx/qla_os.c   |  5 +++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index ac25d2bfa90b..24322eb01571 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -974,6 +974,9 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 				set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 			}
 			break;
+		case ISP_CFG_NL:
+			qla24xx_fcport_handle_login(vha, fcport);
+			break;
 		default:
 			break;
 		}
@@ -1563,6 +1566,11 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 	u8 login = 0;
 	int rc;
 
+	ql_dbg(ql_dbg_disc, vha, 0x307b,
+	    "%s %8phC DS %d LS %d lid %d retries=%d\n",
+	    __func__, fcport->port_name, fcport->disc_state,
+	    fcport->fw_login_state, fcport->loop_id, fcport->login_retry);
+
 	if (qla_tgt_mode_enabled(vha))
 		return;
 
@@ -5604,6 +5612,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 			memcpy(fcport->node_name, new_fcport->node_name,
 			    WWN_SIZE);
 			fcport->scan_state = QLA_FCPORT_FOUND;
+			if (fcport->login_retry == 0) {
+				fcport->login_retry = vha->hw->login_retry_count;
+				ql_dbg(ql_dbg_disc, vha, 0x2135,
+				    "Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
+				    fcport->port_name, fcport->loop_id,
+				    fcport->login_retry);
+			}
 			found++;
 			break;
 		}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7d5159306112..88bff825aa5e 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5540,6 +5540,11 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 					memset(&ea, 0, sizeof(ea));
 					ea.fcport = fcport;
 					qla24xx_handle_relogin_event(vha, &ea);
+				} else if (vha->hw->current_topology ==
+					 ISP_CFG_NL &&
+					IS_QLA2XXX_MIDTYPE(vha->hw)) {
+					(void)qla24xx_fcport_handle_login(vha,
+									fcport);
 				} else if (vha->hw->current_topology ==
 				    ISP_CFG_NL) {
 					fcport->login_retry--;
-- 
2.23.1


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

* [PATCH v2 11/17] qla2xxx: fix warning for missing error code
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (9 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 10/17] qla2xxx: Fix device reconnect in loop topology Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 12/17] qla2xxx: edif: Fix clang warning Nilesh Javali
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

The smatch reports warning message,
drivers/scsi/qla2xxx/qla_target.c:3324 qlt_xmit_response() warn: missing error
code 'res'

Cc: stable@vger.kernel.org
Fixes: 4a8f71014b4d ("scsi: qla2xxx: Fix unmap of already freed sgl")
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_target.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index b0990f2ee91c..feb054c688a3 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -3318,6 +3318,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
 			"RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n",
 			vha->flags.online, qla2x00_reset_active(vha),
 			cmd->reset_count, qpair->chip_reset);
+		res = 0;
 		goto out_unmap_unlock;
 	}
 
-- 
2.23.1


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

* [PATCH v2 12/17] qla2xxx: edif: Fix clang warning
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (10 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 11/17] qla2xxx: fix warning for missing error code Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 13/17] qla2xxx: Fix T10 PI tag escape and IP guard options for 28XX adapters Nilesh Javali
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Quinn Tran <qutran@marvell.com>

Silent compile warning due to unaligned memory access.

qla_edif.c:713:45: warning: taking address of packed member 'u' of class or
   structure 'auth_complete_cmd' may result in an unaligned pointer value
   [-Waddress-of-packed-member]
    fcport = qla2x00_find_fcport_by_pid(vha, &appplogiok.u.d_id);

Cc: stable@vger.kernel.org
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_edif.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
index c04957c363d8..0628633c7c7e 100644
--- a/drivers/scsi/qla2xxx/qla_edif.c
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -668,6 +668,11 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
 	    bsg_job->request_payload.sg_cnt, &appplogiok,
 	    sizeof(struct auth_complete_cmd));
 
+	/* silent unaligned access warning */
+	portid.b.domain = appplogiok.u.d_id.b.domain;
+	portid.b.area   = appplogiok.u.d_id.b.area;
+	portid.b.al_pa  = appplogiok.u.d_id.b.al_pa;
+
 	switch (appplogiok.type) {
 	case PL_TYPE_WWPN:
 		fcport = qla2x00_find_fcport_by_wwpn(vha,
@@ -678,7 +683,7 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
 			    __func__, appplogiok.u.wwpn);
 		break;
 	case PL_TYPE_DID:
-		fcport = qla2x00_find_fcport_by_pid(vha, &appplogiok.u.d_id);
+		fcport = qla2x00_find_fcport_by_pid(vha, &portid);
 		if (!fcport)
 			ql_dbg(ql_dbg_edif, vha, 0x911d,
 			    "%s d_id lookup failed: %x\n", __func__,
@@ -777,6 +782,11 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
 	    bsg_job->request_payload.sg_cnt, &appplogifail,
 	    sizeof(struct auth_complete_cmd));
 
+	/* silent unaligned access warning */
+	portid.b.domain = appplogifail.u.d_id.b.domain;
+	portid.b.area   = appplogifail.u.d_id.b.area;
+	portid.b.al_pa  = appplogifail.u.d_id.b.al_pa;
+
 	/*
 	 * TODO: edif: app has failed this plogi. Inform driver to
 	 * take any action (if any).
@@ -788,7 +798,7 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
 		SET_DID_STATUS(bsg_reply->result, DID_OK);
 		break;
 	case PL_TYPE_DID:
-		fcport = qla2x00_find_fcport_by_pid(vha, &appplogifail.u.d_id);
+		fcport = qla2x00_find_fcport_by_pid(vha, &portid);
 		if (!fcport)
 			ql_dbg(ql_dbg_edif, vha, 0x911d,
 			    "%s d_id lookup failed: %x\n", __func__,
@@ -1253,6 +1263,7 @@ qla24xx_sadb_update(struct bsg_job *bsg_job)
 	int result = 0;
 	struct qla_sa_update_frame sa_frame;
 	struct srb_iocb *iocb_cmd;
+	port_id_t portid;
 
 	ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d,
 	    "%s entered, vha: 0x%p\n", __func__, vha);
@@ -1276,7 +1287,12 @@ qla24xx_sadb_update(struct bsg_job *bsg_job)
 		goto done;
 	}
 
-	fcport = qla2x00_find_fcport_by_pid(vha, &sa_frame.port_id);
+	/* silent unaligned access warning */
+	portid.b.domain = sa_frame.port_id.b.domain;
+	portid.b.area   = sa_frame.port_id.b.area;
+	portid.b.al_pa  = sa_frame.port_id.b.al_pa;
+
+	fcport = qla2x00_find_fcport_by_pid(vha, &portid);
 	if (fcport) {
 		found = 1;
 		if (sa_frame.flags == QLA_SA_UPDATE_FLAGS_TX_KEY)
-- 
2.23.1


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

* [PATCH v2 13/17] qla2xxx: Fix T10 PI tag escape and IP guard options for 28XX adapters
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (11 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 12/17] qla2xxx: edif: Fix clang warning Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 14/17] qla2xxx: Suppress a kernel complaint in qla_create_qpair() Nilesh Javali
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

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

28XX adapters are capable of detecting both T10 PI tag escape values
as well as IP guard. This was missed due to the adapter type missed
in the corresponding macros. Fix this by adding support for 28xx in
those macros.

Cc: stable@vger.kernel.org
Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_def.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index bc0c5df77801..81ca0cba9055 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -4271,8 +4271,10 @@ struct qla_hw_data {
 #define QLA_ABTS_WAIT_ENABLED(_sp) \
 	(QLA_NVME_IOS(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
 
-#define IS_PI_UNINIT_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
-#define IS_PI_IPGUARD_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_PI_UNINIT_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+					 IS_QLA28XX(ha))
+#define IS_PI_IPGUARD_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+					 IS_QLA28XX(ha))
 #define IS_PI_DIFB_DIX0_CAPABLE(ha)	(0)
 #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
 					IS_QLA28XX(ha))
-- 
2.23.1


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

* [PATCH v2 14/17] qla2xxx: Suppress a kernel complaint in qla_create_qpair()
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (12 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 13/17] qla2xxx: Fix T10 PI tag escape and IP guard options for 28XX adapters Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 15/17] qla2xxx: Add devid's and conditionals for 28xx Nilesh Javali
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Saurav Kashyap <skashyap@marvell.com>

[   12.323788] BUG: using smp_processor_id() in preemptible [00000000] code: systemd-udevd/1020
[   12.332297] caller is qla2xxx_create_qpair+0x32a/0x5d0 [qla2xxx]
[   12.338417] CPU: 7 PID: 1020 Comm: systemd-udevd Tainted: G          I      --------- ---  5.14.0-29.el9.x86_64 #1
[   12.348827] Hardware name: Dell Inc. PowerEdge R610/0F0XJ6, BIOS 6.6.0 05/22/2018
[   12.356356] Call Trace:
[   12.358821]  dump_stack_lvl+0x34/0x44
[   12.362514]  check_preemption_disabled+0xd9/0xe0
[   12.367164]  qla2xxx_create_qpair+0x32a/0x5d0 [qla2xxx]
[   12.372481]  qla2x00_probe_one+0xa3a/0x1b80 [qla2xxx]
[   12.377617]  ? _raw_spin_lock_irqsave+0x19/0x40
[   12.384284]  local_pci_probe+0x42/0x80
[   12.390162]  ? pci_match_device+0xd7/0x110
[   12.396366]  pci_device_probe+0xfd/0x1b0
[   12.402372]  really_probe+0x1e7/0x3e0
[   12.408114]  __driver_probe_device+0xfe/0x180
[   12.414544]  driver_probe_device+0x1e/0x90
[   12.420685]  __driver_attach+0xc0/0x1c0
[   12.426536]  ? __device_attach_driver+0xe0/0xe0
[   12.433061]  ? __device_attach_driver+0xe0/0xe0
[   12.439538]  bus_for_each_dev+0x78/0xc0
[   12.445294]  bus_add_driver+0x12b/0x1e0
[   12.451021]  driver_register+0x8f/0xe0
[   12.456631]  ? 0xffffffffc07bc000
[   12.461773]  qla2x00_module_init+0x1be/0x229 [qla2xxx]
[   12.468776]  do_one_initcall+0x44/0x200
[   12.474401]  ? load_module+0xad3/0xba0
[   12.479908]  ? kmem_cache_alloc_trace+0x45/0x410
[   12.486268]  do_init_module+0x5c/0x280
[   12.491730]  __do_sys_init_module+0x12e/0x1b0
[   12.497785]  do_syscall_64+0x3b/0x90
[   12.503029]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[   12.509764] RIP: 0033:0x7f554f73ab2e

Cc: stable@vger.kernel.org
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 24322eb01571..71e31e4bfa61 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -9407,7 +9407,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
 		qpair->rsp->req = qpair->req;
 		qpair->rsp->qpair = qpair;
 		/* init qpair to this cpu. Will adjust at run time. */
-		qla_cpu_update(qpair, smp_processor_id());
+		qla_cpu_update(qpair, raw_smp_processor_id());
 
 		if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
 			if (ha->fw_attributes & BIT_4)
-- 
2.23.1


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

* [PATCH v2 15/17] qla2xxx: Add devid's and conditionals for 28xx
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (13 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 14/17] qla2xxx: Suppress a kernel complaint in qla_create_qpair() Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 16/17] qla2xxx: check for firmware dump already collected Nilesh Javali
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

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

This is an update to the original 28xx adapter enablement. This patch
adds a bunch of conditionals that is applicable for 28xx.

Cc: stable@vger.kernel.org
Fixes: ecc89f25e225 ("scsi: qla2xxx: Add Device ID for ISP28XX")
Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
v1->v2:
- update author of patch
- add Fixes tag
- separate out few hunk as a separate commit
- update description of the commit

 drivers/scsi/qla2xxx/qla_attr.c   |  7 ++-----
 drivers/scsi/qla2xxx/qla_init.c   |  8 +++-----
 drivers/scsi/qla2xxx/qla_mbx.c    | 14 +++++++++++---
 drivers/scsi/qla2xxx/qla_os.c     |  3 +--
 drivers/scsi/qla2xxx/qla_sup.c    |  4 ++--
 drivers/scsi/qla2xxx/qla_target.c |  3 +--
 6 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index db55737000ab..3b3e4234f37a 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -555,7 +555,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EINVAL;
 
-	if (IS_NOCACHE_VPD_TYPE(ha))
+	if (!IS_NOCACHE_VPD_TYPE(ha))
 		goto skip;
 
 	faddr = ha->flt_region_vpd << 2;
@@ -745,7 +745,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
 		ql_log(ql_log_info, vha, 0x706f,
 		    "Issuing MPI reset.\n");
 
-		if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+		if (IS_QLA83XX(ha)) {
 			uint32_t idc_control;
 
 			qla83xx_idc_lock(vha, 0);
@@ -1056,9 +1056,6 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
 			continue;
 		if (iter->type == 3 && !(IS_CNA_CAPABLE(ha)))
 			continue;
-		if (iter->type == 0x27 &&
-		    (!IS_QLA27XX(ha) || !IS_QLA28XX(ha)))
-			continue;
 
 		sysfs_remove_bin_file(&host->shost_gendev.kobj,
 		    iter->attr);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 71e31e4bfa61..acc39a08454c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3492,7 +3492,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 		mem_size = (ha->fw_memory_size - 0x11000 + 1) *
 		    sizeof(uint16_t);
 	} else if (IS_FWI2_CAPABLE(ha)) {
-		if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
+		if (IS_QLA83XX(ha))
 			fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
 		else if (IS_QLA81XX(ha))
 			fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
@@ -3504,8 +3504,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 		mem_size = (ha->fw_memory_size - 0x100000 + 1) *
 		    sizeof(uint32_t);
 		if (ha->mqenable) {
-			if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) &&
-			    !IS_QLA28XX(ha))
+			if (!IS_QLA83XX(ha))
 				mq_size = sizeof(struct qla2xxx_mq_chain);
 			/*
 			 * Allocate maximum buffer size for all queues - Q0.
@@ -4066,8 +4065,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
 			    ha->fw_major_version, ha->fw_minor_version,
 			    ha->fw_subminor_version);
 
-			if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
-			    IS_QLA28XX(ha)) {
+			if (IS_QLA83XX(ha)) {
 				ha->flags.fac_supported = 0;
 				rval = QLA_SUCCESS;
 			}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index c4bd8a16d78c..892caf2475df 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -9,6 +9,12 @@
 #include <linux/delay.h>
 #include <linux/gfp.h>
 
+#ifdef CONFIG_PPC
+#define IS_PPCARCH      true
+#else
+#define IS_PPCARCH      false
+#endif
+
 static struct mb_cmd_name {
 	uint16_t cmd;
 	const char *str;
@@ -728,6 +734,9 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
 				vha->min_supported_speed =
 				    nv->min_supported_speed;
 			}
+
+			if (IS_PPCARCH)
+				mcp->mb[11] |= BIT_4;
 		}
 
 		if (ha->flags.exlogins_enabled)
@@ -3035,8 +3044,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
 		ha->orig_fw_iocb_count = mcp->mb[10];
 		if (ha->flags.npiv_supported)
 			ha->max_npiv_vports = mcp->mb[11];
-		if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
-		    IS_QLA28XX(ha))
+		if (IS_QLA81XX(ha) || IS_QLA83XX(ha))
 			ha->fw_max_fcf_count = mcp->mb[12];
 	}
 
@@ -5627,7 +5635,7 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
 	mcp->out_mb = MBX_1|MBX_0;
 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
 	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
-		mcp->in_mb |= MBX_3;
+		mcp->in_mb |= MBX_4|MBX_3;
 	mcp->tov = MBX_TOV_SECONDS;
 	mcp->flags = 0;
 	rval = qla2x00_mailbox_command(vha, mcp);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 88bff825aa5e..cff5e4a710d1 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3762,8 +3762,7 @@ qla2x00_unmap_iobases(struct qla_hw_data *ha)
 		if (ha->mqiobase)
 			iounmap(ha->mqiobase);
 
-		if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
-		    ha->msixbase)
+		if (ha->msixbase)
 			iounmap(ha->msixbase);
 	}
 }
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index a0aeba69513d..c092a6b1ced4 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -844,7 +844,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
 				ha->flt_region_nvram = start;
 			break;
 		case FLT_REG_IMG_PRI_27XX:
-			if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
 				ha->flt_region_img_status_pri = start;
 			break;
 		case FLT_REG_IMG_SEC_27XX:
@@ -1356,7 +1356,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, __le32 *dwptr, uint32_t faddr,
 		    flash_data_addr(ha, faddr), le32_to_cpu(*dwptr));
 		if (ret) {
 			ql_dbg(ql_dbg_user, vha, 0x7006,
-			    "Failed slopw write %x (%x)\n", faddr, *dwptr);
+			    "Failed slow write %x (%x)\n", faddr, *dwptr);
 			break;
 		}
 	}
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index feb054c688a3..b109716d44fb 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -7220,8 +7220,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
 	if (!QLA_TGT_MODE_ENABLED())
 		return;
 
-	if  ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
-	    IS_QLA28XX(ha)) {
+	if  (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
 		ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
 		ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
 	} else {
-- 
2.23.1


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

* [PATCH v2 16/17] qla2xxx: check for firmware dump already collected
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (14 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 15/17] qla2xxx: Add devid's and conditionals for 28xx Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-10  5:02 ` [PATCH v2 17/17] qla2xxx: Update version to 10.02.07.300-k Nilesh Javali
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

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

While allocating firmware dump, check if dump is already
collected and do not re-allocate the buffer.

Cc: stable@vger.kernel.org
Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
v1->v2:
- update author of patch
- commit this patch as a separate fix

 drivers/scsi/qla2xxx/qla_init.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index acc39a08454c..835ed4179887 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3482,6 +3482,14 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 	struct rsp_que *rsp = ha->rsp_q_map[0];
 	struct qla2xxx_fw_dump *fw_dump;
 
+	if (ha->fw_dump) {
+		ql_dbg(ql_dbg_init, vha, 0x00bd,
+		    "Firmware dump already allocated.\n");
+		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;
 
-- 
2.23.1


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

* [PATCH v2 17/17] qla2xxx: Update version to 10.02.07.300-k
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (15 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 16/17] qla2xxx: check for firmware dump already collected Nilesh Javali
@ 2022-01-10  5:02 ` Nilesh Javali
  2022-01-25  5:00 ` [PATCH v2 00/17] qla2xxx misc bug fixes and features Martin K. Petersen
  2022-02-01  2:04 ` Martin K. Petersen
  18 siblings, 0 replies; 24+ messages in thread
From: Nilesh Javali @ 2022-01-10  5:02 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
---
 drivers/scsi/qla2xxx/qla_version.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 27e440f8a702..913d454f4949 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -6,9 +6,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "10.02.07.200-k"
+#define QLA2XXX_VERSION      "10.02.07.300-k"
 
 #define QLA_DRIVER_MAJOR_VER	10
 #define QLA_DRIVER_MINOR_VER	2
 #define QLA_DRIVER_PATCH_VER	7
-#define QLA_DRIVER_BETA_VER	200
+#define QLA_DRIVER_BETA_VER	300
-- 
2.23.1


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

* Re: [PATCH v2 00/17] qla2xxx misc bug fixes and features
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (16 preceding siblings ...)
  2022-01-10  5:02 ` [PATCH v2 17/17] qla2xxx: Update version to 10.02.07.300-k Nilesh Javali
@ 2022-01-25  5:00 ` Martin K. Petersen
  2022-02-01  2:04 ` Martin K. Petersen
  18 siblings, 0 replies; 24+ messages in thread
From: Martin K. Petersen @ 2022-01-25  5:00 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: martin.petersen, linux-scsi, GR-QLogic-Storage-Upstream


Nilesh,

> Please apply the qla2xxx driver misc bug fixes and features to the
> scsi tree at your earliest convenience.

Applied to 5.18/scsi-staging, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH v2 00/17] qla2xxx misc bug fixes and features
  2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
                   ` (17 preceding siblings ...)
  2022-01-25  5:00 ` [PATCH v2 00/17] qla2xxx misc bug fixes and features Martin K. Petersen
@ 2022-02-01  2:04 ` Martin K. Petersen
  18 siblings, 0 replies; 24+ messages in thread
From: Martin K. Petersen @ 2022-02-01  2:04 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: Martin K . Petersen, linux-scsi, GR-QLogic-Storage-Upstream

On Sun, 9 Jan 2022 21:02:01 -0800, Nilesh Javali wrote:

> Martin,
> 
> Please apply the qla2xxx driver misc bug fixes and features to the scsi
> tree at your earliest convenience.
> 
> Thanks,
> Nilesh
> 
> [...]

Applied to 5.18/scsi-queue, thanks!

[01/17] qla2xxx: Refactor asynchronous command initialization
        https://git.kernel.org/mkp/scsi/c/d4523bd6fd5d
[02/17] qla2xxx: Implement ref count for srb
        https://git.kernel.org/mkp/scsi/c/31e6cdbe0eae
[03/17] qla2xxx: fix stuck session in gpdb
        https://git.kernel.org/mkp/scsi/c/725d3a0d31a5
[04/17] qla2xxx: Fix warning message due to adisc is being flush
        https://git.kernel.org/mkp/scsi/c/64f24af75b79
[05/17] qla2xxx: Fix premature hw access after pci error
        https://git.kernel.org/mkp/scsi/c/e35920ab7874
[06/17] qla2xxx: Fix scheduling while atomic
        https://git.kernel.org/mkp/scsi/c/afd438ff874c
[07/17] qla2xxx: add retry for exec fw
        https://git.kernel.org/mkp/scsi/c/355f5ffe840a
[08/17] qla2xxx: Show wrong FDMI data for 64G adaptor
        https://git.kernel.org/mkp/scsi/c/1cfbbacbee2d
[09/17] qla2xxx: Add ql2xnvme_queues module param to configure number of NVME queues
        https://git.kernel.org/mkp/scsi/c/65120de26a54
[10/17] qla2xxx: Fix device reconnect in loop topology
        https://git.kernel.org/mkp/scsi/c/8ad4be3d15cf
[11/17] qla2xxx: fix warning for missing error code
        https://git.kernel.org/mkp/scsi/c/14cb838d245a
[12/17] qla2xxx: edif: Fix clang warning
        https://git.kernel.org/mkp/scsi/c/73825fd7a37c
[13/17] qla2xxx: Fix T10 PI tag escape and IP guard options for 28XX adapters
        https://git.kernel.org/mkp/scsi/c/4c103a802c69
[14/17] qla2xxx: Suppress a kernel complaint in qla_create_qpair()
        https://git.kernel.org/mkp/scsi/c/a60447e7d451
[15/17] qla2xxx: Add devid's and conditionals for 28xx
        https://git.kernel.org/mkp/scsi/c/0d6a536cb1fc
[16/17] qla2xxx: check for firmware dump already collected
        https://git.kernel.org/mkp/scsi/c/cfbafad7c603
[17/17] qla2xxx: Update version to 10.02.07.300-k
        https://git.kernel.org/mkp/scsi/c/0dd392d16db4

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
  2022-01-10  5:02 ` [PATCH v2 02/17] qla2xxx: Implement ref count for srb Nilesh Javali
@ 2022-02-03 14:44   ` Ewan Milne
  2022-02-04  7:16     ` Saurav Kashyap
  0 siblings, 1 reply; 24+ messages in thread
From: Ewan Milne @ 2022-02-03 14:44 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream

This commit causes at least 2 of our systems with Qlogic HBAs to panic on boot:
From the look of it, it is possible that a timer was left active on a
freed object or something.

[   44.232603] general protection fault, probably for non-canonical
address 0xdead00000000012a: 0000 [#1] PR
[   44.247211] CPU: 9 PID: 0 Comm: swapper/9 Tainted: G          I
  5.17.0-rc1 #4
[   44.254870] Hardware name: Dell Inc. PowerEdge R440/0WKGTH, BIOS
1.4.8 05/22/2018
[   44.262349] RIP: 0010:__run_timers.part.0+0x19c/0x260
[   44.267411] Code: 00 48 8b 03 49 c7 47 08 00 00 00 00 48 85 c0 74
61 48 8b 2b 49 89 6f 08 66 90 48 8b 45
[   44.286156] RSP: 0018:ffffb0a7803ecef0 EFLAGS: 00010086
[   44.291383] RAX: dead000000000122 RBX: ffffb0a7803ecf00 RCX: 0000000000000009
[   44.298515] RDX: ffffb0a7803ecf00 RSI: ffff91dad1060380 RDI: ffff91dad10603a8
[   44.305646] RBP: ffff91cfe34c8c10 R08: 0000000000000000 R09: 0000000000000000
[   44.312780] R10: 0000000000000002 R11: 00000000000000ca R12: 00000000fffc1200
[   44.319911] R13: dead000000000122 R14: 0000000000000001 R15: ffff91dad1060380
[   44.327045] FS:  0000000000000000(0000) GS:ffff91dad1040000(0000)
knlGS:0000000000000000
[   44.335131] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   44.340877] CR2: 00007ff966417870 CR3: 00000002db010004 CR4: 00000000007706e0
[   44.348010] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   44.355143] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   44.362274] PKRU: 55555554
[   44.364987] Call Trace:
[   44.367442]  <IRQ>
[   44.369460]  ? tick_sched_timer+0x6d/0x80
[   44.373472]  ? _raw_spin_lock_irq+0x14/0x40
[   44.377658]  ? __hrtimer_run_queues+0x139/0x2c0
[   44.382190]  ? recalibrate_cpu_khz+0x10/0x10
[   44.386464]  run_timer_softirq+0x31/0x60
[   44.390391]  __do_softirq+0xf6/0x2fb
[   44.393968]  __irq_exit_rcu+0xe2/0x130
[   44.397720]  sysvec_apic_timer_interrupt+0xa2/0xd0
[   44.402514]  </IRQ>
[   44.404619]  <TASK>
[   44.406725]  asm_sysvec_apic_timer_interrupt+0x12/0x20


-Ewan

On Mon, Jan 10, 2022 at 12:03 AM Nilesh Javali <njavali@marvell.com> wrote:
>
> From: Saurav Kashyap <skashyap@marvell.com>
>
> The timeout handler and done function are racing. When
> qla2x00_async_iocb_timeout() starts to run it can be preempted by the
> normal response path (via the firmware?). qla24xx_async_gpsc_sp_done()
> releases the SRB unconditionally. When scheduling back to
> qla2x00_async_iocb_timeout() qla24xx_async_abort_cmd() will access an
> freed sp->qpair pointer:
>
>   qla2xxx [0000:83:00.0]-2871:0: Async-gpsc timeout - hdl=63d portid=234500 50:06:0e:80:08:77:b6:21.
>   qla2xxx [0000:83:00.0]-2853:0: Async done-gpsc res 0, WWPN 50:06:0e:80:08:77:b6:21
>   qla2xxx [0000:83:00.0]-2854:0: Async-gpsc OUT WWPN 20:45:00:27:f8:75:33:00 speeds=2c00 speed=0400.
>   qla2xxx [0000:83:00.0]-28d8:0: qla24xx_handle_gpsc_event 50:06:0e:80:08:77:b6:21 DS 7 LS 6 rc 0 login 1|1 rscn 1|0 lid 5
>   BUG: unable to handle kernel NULL pointer dereference at 0000000000000004
>   IP: qla24xx_async_abort_cmd+0x1b/0x1c0 [qla2xxx]
>
> Obvious solution to this is to introduce a reference counter. One
> reference is taken for the normal code path (the 'good case') and one
> for the timeout path. As we always race between the normal good case
> and the timeout/abort handler we need to serialize it. Also we cannot
> assume any order between the handlers. Since this is slow path we can
> use proper synchronization via locks.
>
> When we are able to cancel a timer (del_timer returns 1) we know there
> can't be any error handling in progress because the timeout handler
> hasn't expired yet, thus we can safely decrement the refcounter by one.
>
> If we are not able to cancel the timer, we know an abort handler is
> running. We have to make sure we call sp->done() in the abort handlers
> before calling kref_put().
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
> ---
> v1->v2:
> - update detailed issue description and the solution
>
>  drivers/scsi/qla2xxx/qla_bsg.c    |  6 ++-
>  drivers/scsi/qla2xxx/qla_def.h    |  5 ++
>  drivers/scsi/qla2xxx/qla_edif.c   |  3 +-
>  drivers/scsi/qla2xxx/qla_gbl.h    |  1 +
>  drivers/scsi/qla2xxx/qla_gs.c     | 85 +++++++++++++++++++++----------
>  drivers/scsi/qla2xxx/qla_init.c   | 70 +++++++++++++++++--------
>  drivers/scsi/qla2xxx/qla_inline.h |  2 +
>  drivers/scsi/qla2xxx/qla_iocb.c   | 41 +++++++++++----
>  drivers/scsi/qla2xxx/qla_mbx.c    |  4 +-
>  drivers/scsi/qla2xxx/qla_mid.c    |  4 +-
>  drivers/scsi/qla2xxx/qla_mr.c     |  4 +-
>  drivers/scsi/qla2xxx/qla_os.c     | 14 +++--
>  drivers/scsi/qla2xxx/qla_target.c |  4 +-
>  13 files changed, 173 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> index 9da8034ccad4..c2f00f076f79 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.c
> +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> @@ -29,7 +29,8 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
>             "%s: sp hdl %x, result=%x bsg ptr %p\n",
>             __func__, sp->handle, res, bsg_job);
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>
>         bsg_reply->result = res;
>         bsg_job_done(bsg_job, bsg_reply->result,
> @@ -3013,7 +3014,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
>
>  done:
>         spin_unlock_irqrestore(&ha->hardware_lock, flags);
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         return 0;
>  }
>
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index 9ebf4a234d9a..a5fc01b4fa96 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -726,6 +726,11 @@ typedef struct srb {
>          * code.
>          */
>         void (*put_fn)(struct kref *kref);
> +
> +       /*
> +        * Report completion for asynchronous commands.
> +        */
> +       void (*async_done)(struct srb *sp, int res);
>  } srb_t;
>
>  #define GET_CMD_SP(sp) (sp->u.scmd.cmd)
> diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
> index 53d2b8562027..c04957c363d8 100644
> --- a/drivers/scsi/qla2xxx/qla_edif.c
> +++ b/drivers/scsi/qla2xxx/qla_edif.c
> @@ -2146,7 +2146,8 @@ edif_doorbell_show(struct device *dev, struct device_attribute *attr,
>
>  static void qla_noop_sp_done(srb_t *sp, int res)
>  {
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  /*
> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> index 5056564f0d0c..3f8b8bbabe6d 100644
> --- a/drivers/scsi/qla2xxx/qla_gbl.h
> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> @@ -333,6 +333,7 @@ extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
>  extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
>  extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
>         struct qla_work_evt *e);
> +void qla2x00_sp_release(struct kref *kref);
>
>  /*
>   * Global Function Prototypes in qla_mbx.c source file.
> diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> index 744eb3192056..a812f4a45232 100644
> --- a/drivers/scsi/qla2xxx/qla_gs.c
> +++ b/drivers/scsi/qla2xxx/qla_gs.c
> @@ -529,7 +529,6 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
>                 if (!e)
>                         goto err2;
>
> -               del_timer(&sp->u.iocb_cmd.timer);
>                 e->u.iosb.sp = sp;
>                 qla2x00_post_work(vha, e);
>                 return;
> @@ -556,8 +555,8 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
>                         sp->u.iocb_cmd.u.ctarg.rsp = NULL;
>                 }
>
> -               sp->free(sp);
> -
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                 return;
>         }
>
> @@ -592,6 +591,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
>         if (!vha->flags.online)
>                 goto done;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -652,7 +652,8 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
>         }
>         return rval;
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> @@ -687,6 +688,7 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
>         srb_t *sp;
>         struct ct_sns_pkt *ct_sns;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -747,7 +749,8 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> @@ -777,6 +780,7 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
>         srb_t *sp;
>         struct ct_sns_pkt *ct_sns;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -836,7 +840,8 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> @@ -882,6 +887,7 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
>         srb_t *sp;
>         struct ct_sns_pkt *ct_sns;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -947,7 +953,8 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> @@ -2887,7 +2894,8 @@ static void qla24xx_async_gpsc_sp_done(srb_t *sp, int res)
>         qla24xx_handle_gpsc_event(vha, &ea);
>
>  done:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
> @@ -2899,6 +2907,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
>         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
>                 return rval;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -2938,7 +2947,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> @@ -2987,7 +2997,8 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
>                 break;
>         }
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
> @@ -3126,13 +3137,15 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
>         if (res) {
>                 if (res == QLA_FUNCTION_TIMEOUT) {
>                         qla24xx_post_gpnid_work(sp->vha, &ea.id);
> -                       sp->free(sp);
> +                       /* ref: INIT */
> +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                         return;
>                 }
>         } else if (sp->gen1) {
>                 /* There was another RSCN for this Nport ID */
>                 qla24xx_post_gpnid_work(sp->vha, &ea.id);
> -               sp->free(sp);
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                 return;
>         }
>
> @@ -3153,7 +3166,8 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
>                                   sp->u.iocb_cmd.u.ctarg.rsp_dma);
>                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
>
> -               sp->free(sp);
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                 return;
>         }
>
> @@ -3173,6 +3187,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
>         if (!vha->flags.online)
>                 goto done;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -3189,7 +3204,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
>                 if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
>                         tsp->gen1++;
>                         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> -                       sp->free(sp);
> +                       /* ref: INIT */
> +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                         goto done;
>                 }
>         }
> @@ -3259,8 +3275,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
>                         sp->u.iocb_cmd.u.ctarg.rsp_dma);
>                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
>         }
> -
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> @@ -3315,7 +3331,8 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
>         ea.rc = res;
>
>         qla24xx_handle_gffid_event(vha, &ea);
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  /* Get FC4 Feature with Nport ID. */
> @@ -3328,6 +3345,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
>         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
>                 return rval;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 return rval;
> @@ -3366,7 +3384,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
>
>         return rval;
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         fcport->flags &= ~FCF_ASYNC_SENT;
>         return rval;
>  }
> @@ -3753,7 +3772,6 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
>             "Async done-%s res %x FC4Type %x\n",
>             sp->name, res, sp->gen2);
>
> -       del_timer(&sp->u.iocb_cmd.timer);
>         sp->rc = res;
>         if (res) {
>                 unsigned long flags;
> @@ -3921,8 +3939,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
>                     sp->u.iocb_cmd.u.ctarg.rsp_dma);
>                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
>         }
> -
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>
>         spin_lock_irqsave(&vha->work_lock, flags);
>         vha->scan.scan_flags &= ~SF_SCANNING;
> @@ -3974,9 +3992,12 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
>                 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
>                     "%s: Performing FCP Scan\n", __func__);
>
> -               if (sp)
> -                       sp->free(sp); /* should not happen */
> +               if (sp) {
> +                       /* ref: INIT */
> +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> +               }
>
> +               /* ref: INIT */
>                 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
>                 if (!sp) {
>                         spin_lock_irqsave(&vha->work_lock, flags);
> @@ -4021,6 +4042,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
>                             sp->u.iocb_cmd.u.ctarg.req,
>                             sp->u.iocb_cmd.u.ctarg.req_dma);
>                         sp->u.iocb_cmd.u.ctarg.req = NULL;
> +                       /* ref: INIT */
>                         qla2x00_rel_sp(sp);
>                         return rval;
>                 }
> @@ -4083,7 +4105,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
>                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
>         }
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>
>         spin_lock_irqsave(&vha->work_lock, flags);
>         vha->scan.scan_flags &= ~SF_SCANNING;
> @@ -4147,7 +4170,8 @@ static void qla2x00_async_gnnid_sp_done(srb_t *sp, int res)
>
>         qla24xx_handle_gnnid_event(vha, &ea);
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> @@ -4160,6 +4184,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
>                 return rval;
>
>         qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
>         if (!sp)
>                 goto done;
> @@ -4200,7 +4225,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         fcport->flags &= ~FCF_ASYNC_SENT;
>  done:
>         return rval;
> @@ -4274,7 +4300,8 @@ static void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res)
>
>         qla24xx_handle_gfpnid_event(vha, &ea);
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> @@ -4286,6 +4313,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
>         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
>                 return rval;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
>         if (!sp)
>                 goto done;
> @@ -4326,7 +4354,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index e6f13cb6fa28..38c11b75f644 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -51,6 +51,9 @@ qla2x00_sp_timeout(struct timer_list *t)
>         WARN_ON(irqs_disabled());
>         iocb = &sp->u.iocb_cmd;
>         iocb->timeout(sp);
> +
> +       /* ref: TMR */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  void qla2x00_sp_free(srb_t *sp)
> @@ -125,8 +128,13 @@ static void qla24xx_abort_iocb_timeout(void *data)
>         }
>         spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
>
> -       if (sp->cmd_sp)
> +       if (sp->cmd_sp) {
> +               /*
> +                * This done function should take care of
> +                * original command ref: INIT
> +                */
>                 sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
> +       }
>
>         abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
>         sp->done(sp, QLA_OS_TIMER_EXPIRED);
> @@ -140,11 +148,11 @@ static void qla24xx_abort_sp_done(srb_t *sp, int res)
>         if (orig_sp)
>                 qla_wait_nvme_release_cmd_kref(orig_sp);
>
> -       del_timer(&sp->u.iocb_cmd.timer);
>         if (sp->flags & SRB_WAKEUP_ON_COMP)
>                 complete(&abt->u.abt.comp);
>         else
> -               sp->free(sp);
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
> @@ -154,6 +162,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
>         srb_t *sp;
>         int rval = QLA_FUNCTION_FAILED;
>
> +       /* ref: INIT for ABTS command */
>         sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
>                                   GFP_ATOMIC);
>         if (!sp)
> @@ -181,7 +190,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
>
>         rval = qla2x00_start_sp(sp);
>         if (rval != QLA_SUCCESS) {
> -               sp->free(sp);
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                 return rval;
>         }
>
> @@ -189,7 +199,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
>                 wait_for_completion(&abt_iocb->u.abt.comp);
>                 rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
>                         QLA_SUCCESS : QLA_ERR_FROM_FW;
> -               sp->free(sp);
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         }
>
>         return rval;
> @@ -287,7 +298,8 @@ static void qla2x00_async_login_sp_done(srb_t *sp, int res)
>                 qla24xx_handle_plogi_done_event(vha, &ea);
>         }
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int
> @@ -306,6 +318,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
>                 return rval;
>         }
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -354,7 +367,8 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         fcport->flags &= ~FCF_ASYNC_SENT;
>  done:
>         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> @@ -366,7 +380,8 @@ static void qla2x00_async_logout_sp_done(srb_t *sp, int res)
>         sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
>         sp->fcport->login_gen++;
>         qlt_logo_completion_handler(sp->fcport, sp->u.iocb_cmd.u.logio.data[0]);
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int
> @@ -376,6 +391,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
>         int rval = QLA_FUNCTION_FAILED;
>
>         fcport->flags |= FCF_ASYNC_SENT;
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -397,7 +413,8 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
>         return rval;
> @@ -423,7 +440,8 @@ static void qla2x00_async_prlo_sp_done(srb_t *sp, int res)
>         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);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int
> @@ -433,6 +451,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
>         int rval;
>
>         rval = QLA_FUNCTION_FAILED;
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -454,7 +473,8 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         fcport->flags &= ~FCF_ASYNC_ACTIVE;
>         return rval;
> @@ -539,8 +559,8 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp, int res)
>         ea.sp = sp;
>
>         qla24xx_handle_adisc_event(vha, &ea);
> -
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int
> @@ -555,6 +575,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
>                 return rval;
>
>         fcport->flags |= FCF_ASYNC_SENT;
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -582,7 +603,8 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
>         qla2x00_post_async_adisc_work(vha, fcport, data);
> @@ -1063,7 +1085,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
>         }
>         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
> @@ -1093,6 +1116,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
>         vha->gnl.sent = 1;
>         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -1125,7 +1149,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
>         return rval;
> @@ -1171,7 +1196,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res)
>         dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
>                 sp->u.iocb_cmd.u.mbx.in_dma);
>
> -       sp->free(sp);
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
> @@ -1216,7 +1241,7 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
>                 qla24xx_handle_prli_done_event(vha, &ea);
>         }
>
> -       sp->free(sp);
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int
> @@ -1274,7 +1299,8 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         fcport->flags &= ~FCF_ASYNC_SENT;
>         return rval;
>  }
> @@ -1359,7 +1385,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
>         if (pd)
>                 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
>
> -       sp->free(sp);
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         fcport->flags &= ~FCF_ASYNC_SENT;
>  done:
>         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> @@ -1945,6 +1971,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
>         srb_t *sp;
>         int rval = QLA_FUNCTION_FAILED;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -1988,7 +2015,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
>         }
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         fcport->flags &= ~FCF_ASYNC_SENT;
>  done:
>         return rval;
> diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
> index 5f3b7995cc8f..db17f7f410cd 100644
> --- a/drivers/scsi/qla2xxx/qla_inline.h
> +++ b/drivers/scsi/qla2xxx/qla_inline.h
> @@ -184,6 +184,8 @@ static void qla2xxx_init_sp(srb_t *sp, scsi_qla_host_t *vha,
>         sp->vha = vha;
>         sp->qpair = qpair;
>         sp->cmd_type = TYPE_SRB;
> +       /* ref : INIT - normal flow */
> +       kref_init(&sp->cmd_kref);
>         INIT_LIST_HEAD(&sp->elem);
>  }
>
> diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> index 95aae9a9631e..7dd82214d59f 100644
> --- a/drivers/scsi/qla2xxx/qla_iocb.c
> +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> @@ -2560,6 +2560,14 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
>         }
>  }
>
> +void
> +qla2x00_sp_release(struct kref *kref)
> +{
> +       struct srb *sp = container_of(kref, struct srb, cmd_kref);
> +
> +       sp->free(sp);
> +}
> +
>  void
>  qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
>                      void (*done)(struct srb *sp, int res))
> @@ -2655,7 +2663,9 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
>                return -ENOMEM;
>         }
>
> -       /* Alloc SRB structure */
> +       /* Alloc SRB structure
> +        * ref: INIT
> +        */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp) {
>                 kfree(fcport);
> @@ -2687,7 +2697,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
>                             GFP_KERNEL);
>
>         if (!elsio->u.els_logo.els_logo_pyld) {
> -               sp->free(sp);
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                 return QLA_FUNCTION_FAILED;
>         }
>
> @@ -2710,7 +2721,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
>
>         rval = qla2x00_start_sp(sp);
>         if (rval != QLA_SUCCESS) {
> -               sp->free(sp);
> +               /* ref: INIT */
> +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                 return QLA_FUNCTION_FAILED;
>         }
>
> @@ -2721,7 +2733,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
>
>         wait_for_completion(&elsio->u.els_logo.comp);
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         return rval;
>  }
>
> @@ -2854,7 +2867,6 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
>             sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
>
>         fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
> -       del_timer(&sp->u.iocb_cmd.timer);
>
>         if (sp->flags & SRB_WAKEUP_ON_COMP)
>                 complete(&lio->u.els_plogi.comp);
> @@ -2964,7 +2976,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
>                         struct srb_iocb *elsio = &sp->u.iocb_cmd;
>
>                         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> -                       sp->free(sp);
> +                       /* ref: INIT */
> +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>                         return;
>                 }
>                 e->u.iosb.sp = sp;
> @@ -2982,7 +2995,9 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
>         int rval = QLA_SUCCESS;
>         void    *ptr, *resp_ptr;
>
> -       /* Alloc SRB structure */
> +       /* Alloc SRB structure
> +        * ref: INIT
> +        */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp) {
>                 ql_log(ql_log_info, vha, 0x70e6,
> @@ -3071,7 +3086,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
>  out:
>         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
>         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> @@ -3882,8 +3898,15 @@ qla2x00_start_sp(srb_t *sp)
>                 break;
>         }
>
> -       if (sp->start_timer)
> +       if (sp->start_timer) {
> +               /* ref: TMR timer ref
> +                * this code should be just before start_iocbs function
> +                * This will make sure that caller function don't to do
> +                * kref_put even on failure
> +                */
> +               kref_get(&sp->cmd_kref);
>                 add_timer(&sp->u.iocb_cmd.timer);
> +       }
>
>         wmb();
>         qla2x00_start_iocbs(vha, qp->req);
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index 2aacd3653245..38e0f02c75e1 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -6479,6 +6479,7 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
>         if (!vha->hw->flags.fw_started)
>                 goto done;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -6524,7 +6525,8 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
>         }
>
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
> index c4a967c96fd6..e6b5c4ccce97 100644
> --- a/drivers/scsi/qla2xxx/qla_mid.c
> +++ b/drivers/scsi/qla2xxx/qla_mid.c
> @@ -965,6 +965,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
>         if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
>                 return QLA_PARAMETER_ERROR;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
>         if (!sp)
>                 return rval;
> @@ -1007,6 +1008,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
>                 break;
>         }
>  done:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         return rval;
>  }
> diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
> index e3ae0894c7a8..f726eb8449c5 100644
> --- a/drivers/scsi/qla2xxx/qla_mr.c
> +++ b/drivers/scsi/qla2xxx/qla_mr.c
> @@ -1787,6 +1787,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
>         struct register_host_info *preg_hsi;
>         struct new_utsname *p_sysid = NULL;
>
> +       /* ref: INIT */
>         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>         if (!sp)
>                 goto done;
> @@ -1973,7 +1974,8 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
>                 dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
>                     fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
>  done_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         return rval;
>  }
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index abcd30917263..0a7b00d165c7 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -728,7 +728,8 @@ void qla2x00_sp_compl(srb_t *sp, int res)
>         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
>         struct completion *comp = sp->comp;
>
> -       sp->free(sp);
> +       /* kref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         cmd->result = res;
>         CMD_SP(cmd) = NULL;
>         scsi_done(cmd);
> @@ -819,7 +820,8 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
>         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
>         struct completion *comp = sp->comp;
>
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>         cmd->result = res;
>         CMD_SP(cmd) = NULL;
>         scsi_done(cmd);
> @@ -919,6 +921,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
>                 goto qc24_target_busy;
>
>         sp = scsi_cmd_priv(cmd);
> +       /* ref: INIT */
>         qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
>
>         sp->u.scmd.cmd = cmd;
> @@ -938,7 +941,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
>         return 0;
>
>  qc24_host_busy_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>
>  qc24_target_busy:
>         return SCSI_MLQUEUE_TARGET_BUSY;
> @@ -1008,6 +1012,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
>                 goto qc24_target_busy;
>
>         sp = scsi_cmd_priv(cmd);
> +       /* ref: INIT */
>         qla2xxx_init_sp(sp, vha, qpair, fcport);
>
>         sp->u.scmd.cmd = cmd;
> @@ -1026,7 +1031,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
>         return 0;
>
>  qc24_host_busy_free_sp:
> -       sp->free(sp);
> +       /* ref: INIT */
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>
>  qc24_target_busy:
>         return SCSI_MLQUEUE_TARGET_BUSY;
> diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
> index 83c8c55017d1..b0990f2ee91c 100644
> --- a/drivers/scsi/qla2xxx/qla_target.c
> +++ b/drivers/scsi/qla2xxx/qla_target.c
> @@ -620,7 +620,7 @@ static void qla2x00_async_nack_sp_done(srb_t *sp, int res)
>         }
>         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
>
> -       sp->free(sp);
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  }
>
>  int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
> @@ -672,7 +672,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
>         return rval;
>
>  done_free_sp:
> -       sp->free(sp);
> +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
>  done:
>         fcport->flags &= ~FCF_ASYNC_SENT;
>         return rval;
> --
> 2.23.1
>


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

* RE: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
  2022-02-03 14:44   ` Ewan Milne
@ 2022-02-04  7:16     ` Saurav Kashyap
  2022-02-08 10:59       ` Saurav Kashyap
  0 siblings, 1 reply; 24+ messages in thread
From: Saurav Kashyap @ 2022-02-04  7:16 UTC (permalink / raw)
  To: Ewan Milne, Nilesh Javali
  Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream

Hi Ewan,
This patch have undergone extensive testing from our side and we didn't hit any of the issues. Can you share the test case? So that we can try to reproduce this? 

Thanks,
~Saurav

> -----Original Message-----
> From: Ewan Milne <emilne@redhat.com>
> Sent: Thursday, February 3, 2022 8:15 PM
> To: Nilesh Javali <njavali@marvell.com>
> Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> Upstream@marvell.com>
> Subject: Re: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
> 
> This commit causes at least 2 of our systems with Qlogic HBAs to panic on
> boot:
> From the look of it, it is possible that a timer was left active on a
> freed object or something.
> 
> [   44.232603] general protection fault, probably for non-canonical
> address 0xdead00000000012a: 0000 [#1] PR
> [   44.247211] CPU: 9 PID: 0 Comm: swapper/9 Tainted: G          I
>   5.17.0-rc1 #4
> [   44.254870] Hardware name: Dell Inc. PowerEdge R440/0WKGTH, BIOS
> 1.4.8 05/22/2018
> [   44.262349] RIP: 0010:__run_timers.part.0+0x19c/0x260
> [   44.267411] Code: 00 48 8b 03 49 c7 47 08 00 00 00 00 48 85 c0 74
> 61 48 8b 2b 49 89 6f 08 66 90 48 8b 45
> [   44.286156] RSP: 0018:ffffb0a7803ecef0 EFLAGS: 00010086
> [   44.291383] RAX: dead000000000122 RBX: ffffb0a7803ecf00 RCX:
> 0000000000000009
> [   44.298515] RDX: ffffb0a7803ecf00 RSI: ffff91dad1060380 RDI:
> ffff91dad10603a8
> [   44.305646] RBP: ffff91cfe34c8c10 R08: 0000000000000000 R09:
> 0000000000000000
> [   44.312780] R10: 0000000000000002 R11: 00000000000000ca R12:
> 00000000fffc1200
> [   44.319911] R13: dead000000000122 R14: 0000000000000001 R15:
> ffff91dad1060380
> [   44.327045] FS:  0000000000000000(0000) GS:ffff91dad1040000(0000)
> knlGS:0000000000000000
> [   44.335131] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   44.340877] CR2: 00007ff966417870 CR3: 00000002db010004 CR4:
> 00000000007706e0
> [   44.348010] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> 0000000000000000
> [   44.355143] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7:
> 0000000000000400
> [   44.362274] PKRU: 55555554
> [   44.364987] Call Trace:
> [   44.367442]  <IRQ>
> [   44.369460]  ? tick_sched_timer+0x6d/0x80
> [   44.373472]  ? _raw_spin_lock_irq+0x14/0x40
> [   44.377658]  ? __hrtimer_run_queues+0x139/0x2c0
> [   44.382190]  ? recalibrate_cpu_khz+0x10/0x10
> [   44.386464]  run_timer_softirq+0x31/0x60
> [   44.390391]  __do_softirq+0xf6/0x2fb
> [   44.393968]  __irq_exit_rcu+0xe2/0x130
> [   44.397720]  sysvec_apic_timer_interrupt+0xa2/0xd0
> [   44.402514]  </IRQ>
> [   44.404619]  <TASK>
> [   44.406725]  asm_sysvec_apic_timer_interrupt+0x12/0x20
> 
> 
> -Ewan
> 
> On Mon, Jan 10, 2022 at 12:03 AM Nilesh Javali <njavali@marvell.com> wrote:
> >
> > From: Saurav Kashyap <skashyap@marvell.com>
> >
> > The timeout handler and done function are racing. When
> > qla2x00_async_iocb_timeout() starts to run it can be preempted by the
> > normal response path (via the firmware?). qla24xx_async_gpsc_sp_done()
> > releases the SRB unconditionally. When scheduling back to
> > qla2x00_async_iocb_timeout() qla24xx_async_abort_cmd() will access an
> > freed sp->qpair pointer:
> >
> >   qla2xxx [0000:83:00.0]-2871:0: Async-gpsc timeout - hdl=63d
> portid=234500 50:06:0e:80:08:77:b6:21.
> >   qla2xxx [0000:83:00.0]-2853:0: Async done-gpsc res 0, WWPN
> 50:06:0e:80:08:77:b6:21
> >   qla2xxx [0000:83:00.0]-2854:0: Async-gpsc OUT WWPN
> 20:45:00:27:f8:75:33:00 speeds=2c00 speed=0400.
> >   qla2xxx [0000:83:00.0]-28d8:0: qla24xx_handle_gpsc_event
> 50:06:0e:80:08:77:b6:21 DS 7 LS 6 rc 0 login 1|1 rscn 1|0 lid 5
> >   BUG: unable to handle kernel NULL pointer dereference at
> 0000000000000004
> >   IP: qla24xx_async_abort_cmd+0x1b/0x1c0 [qla2xxx]
> >
> > Obvious solution to this is to introduce a reference counter. One
> > reference is taken for the normal code path (the 'good case') and one
> > for the timeout path. As we always race between the normal good case
> > and the timeout/abort handler we need to serialize it. Also we cannot
> > assume any order between the handlers. Since this is slow path we can
> > use proper synchronization via locks.
> >
> > When we are able to cancel a timer (del_timer returns 1) we know there
> > can't be any error handling in progress because the timeout handler
> > hasn't expired yet, thus we can safely decrement the refcounter by one.
> >
> > If we are not able to cancel the timer, we know an abort handler is
> > running. We have to make sure we call sp->done() in the abort handlers
> > before calling kref_put().
> >
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Daniel Wagner <dwagner@suse.de>
> > Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> > Signed-off-by: Nilesh Javali <njavali@marvell.com>
> > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
> > ---
> > v1->v2:
> > - update detailed issue description and the solution
> >
> >  drivers/scsi/qla2xxx/qla_bsg.c    |  6 ++-
> >  drivers/scsi/qla2xxx/qla_def.h    |  5 ++
> >  drivers/scsi/qla2xxx/qla_edif.c   |  3 +-
> >  drivers/scsi/qla2xxx/qla_gbl.h    |  1 +
> >  drivers/scsi/qla2xxx/qla_gs.c     | 85 +++++++++++++++++++++----------
> >  drivers/scsi/qla2xxx/qla_init.c   | 70 +++++++++++++++++--------
> >  drivers/scsi/qla2xxx/qla_inline.h |  2 +
> >  drivers/scsi/qla2xxx/qla_iocb.c   | 41 +++++++++++----
> >  drivers/scsi/qla2xxx/qla_mbx.c    |  4 +-
> >  drivers/scsi/qla2xxx/qla_mid.c    |  4 +-
> >  drivers/scsi/qla2xxx/qla_mr.c     |  4 +-
> >  drivers/scsi/qla2xxx/qla_os.c     | 14 +++--
> >  drivers/scsi/qla2xxx/qla_target.c |  4 +-
> >  13 files changed, 173 insertions(+), 70 deletions(-)
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> > index 9da8034ccad4..c2f00f076f79 100644
> > --- a/drivers/scsi/qla2xxx/qla_bsg.c
> > +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> > @@ -29,7 +29,8 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
> >             "%s: sp hdl %x, result=%x bsg ptr %p\n",
> >             __func__, sp->handle, res, bsg_job);
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >
> >         bsg_reply->result = res;
> >         bsg_job_done(bsg_job, bsg_reply->result,
> > @@ -3013,7 +3014,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
> >
> >  done:
> >         spin_unlock_irqrestore(&ha->hardware_lock, flags);
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         return 0;
> >  }
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> > index 9ebf4a234d9a..a5fc01b4fa96 100644
> > --- a/drivers/scsi/qla2xxx/qla_def.h
> > +++ b/drivers/scsi/qla2xxx/qla_def.h
> > @@ -726,6 +726,11 @@ typedef struct srb {
> >          * code.
> >          */
> >         void (*put_fn)(struct kref *kref);
> > +
> > +       /*
> > +        * Report completion for asynchronous commands.
> > +        */
> > +       void (*async_done)(struct srb *sp, int res);
> >  } srb_t;
> >
> >  #define GET_CMD_SP(sp) (sp->u.scmd.cmd)
> > diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
> > index 53d2b8562027..c04957c363d8 100644
> > --- a/drivers/scsi/qla2xxx/qla_edif.c
> > +++ b/drivers/scsi/qla2xxx/qla_edif.c
> > @@ -2146,7 +2146,8 @@ edif_doorbell_show(struct device *dev, struct
> device_attribute *attr,
> >
> >  static void qla_noop_sp_done(srb_t *sp, int res)
> >  {
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  /*
> > diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> > index 5056564f0d0c..3f8b8bbabe6d 100644
> > --- a/drivers/scsi/qla2xxx/qla_gbl.h
> > +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> > @@ -333,6 +333,7 @@ extern int qla24xx_get_one_block_sg(uint32_t,
> struct qla2_sgx *, uint32_t *);
> >  extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
> >  extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
> >         struct qla_work_evt *e);
> > +void qla2x00_sp_release(struct kref *kref);
> >
> >  /*
> >   * Global Function Prototypes in qla_mbx.c source file.
> > diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> > index 744eb3192056..a812f4a45232 100644
> > --- a/drivers/scsi/qla2xxx/qla_gs.c
> > +++ b/drivers/scsi/qla2xxx/qla_gs.c
> > @@ -529,7 +529,6 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int
> rc)
> >                 if (!e)
> >                         goto err2;
> >
> > -               del_timer(&sp->u.iocb_cmd.timer);
> >                 e->u.iosb.sp = sp;
> >                 qla2x00_post_work(vha, e);
> >                 return;
> > @@ -556,8 +555,8 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int
> rc)
> >                         sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> >                 }
> >
> > -               sp->free(sp);
> > -
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                 return;
> >         }
> >
> > @@ -592,6 +591,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha,
> port_id_t *d_id)
> >         if (!vha->flags.online)
> >                 goto done;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -652,7 +652,8 @@ static int qla_async_rftid(scsi_qla_host_t *vha,
> port_id_t *d_id)
> >         }
> >         return rval;
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > @@ -687,6 +688,7 @@ static int qla_async_rffid(scsi_qla_host_t *vha,
> port_id_t *d_id,
> >         srb_t *sp;
> >         struct ct_sns_pkt *ct_sns;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -747,7 +749,8 @@ static int qla_async_rffid(scsi_qla_host_t *vha,
> port_id_t *d_id,
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > @@ -777,6 +780,7 @@ static int qla_async_rnnid(scsi_qla_host_t *vha,
> port_id_t *d_id,
> >         srb_t *sp;
> >         struct ct_sns_pkt *ct_sns;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -836,7 +840,8 @@ static int qla_async_rnnid(scsi_qla_host_t *vha,
> port_id_t *d_id,
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > @@ -882,6 +887,7 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
> >         srb_t *sp;
> >         struct ct_sns_pkt *ct_sns;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -947,7 +953,8 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > @@ -2887,7 +2894,8 @@ static void qla24xx_async_gpsc_sp_done(srb_t
> *sp, int res)
> >         qla24xx_handle_gpsc_event(vha, &ea);
> >
> >  done:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
> > @@ -2899,6 +2907,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> >                 return rval;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -2938,7 +2947,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > @@ -2987,7 +2997,8 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha,
> srb_t *sp)
> >                 break;
> >         }
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg
> *ea)
> > @@ -3126,13 +3137,15 @@ static void qla2x00_async_gpnid_sp_done(srb_t
> *sp, int res)
> >         if (res) {
> >                 if (res == QLA_FUNCTION_TIMEOUT) {
> >                         qla24xx_post_gpnid_work(sp->vha, &ea.id);
> > -                       sp->free(sp);
> > +                       /* ref: INIT */
> > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                         return;
> >                 }
> >         } else if (sp->gen1) {
> >                 /* There was another RSCN for this Nport ID */
> >                 qla24xx_post_gpnid_work(sp->vha, &ea.id);
> > -               sp->free(sp);
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                 return;
> >         }
> >
> > @@ -3153,7 +3166,8 @@ static void qla2x00_async_gpnid_sp_done(srb_t
> *sp, int res)
> >                                   sp->u.iocb_cmd.u.ctarg.rsp_dma);
> >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> >
> > -               sp->free(sp);
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                 return;
> >         }
> >
> > @@ -3173,6 +3187,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> port_id_t *id)
> >         if (!vha->flags.online)
> >                 goto done;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -3189,7 +3204,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> port_id_t *id)
> >                 if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
> >                         tsp->gen1++;
> >                         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > -                       sp->free(sp);
> > +                       /* ref: INIT */
> > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                         goto done;
> >                 }
> >         }
> > @@ -3259,8 +3275,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> port_id_t *id)
> >                         sp->u.iocb_cmd.u.ctarg.rsp_dma);
> >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> >         }
> > -
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > @@ -3315,7 +3331,8 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int
> res)
> >         ea.rc = res;
> >
> >         qla24xx_handle_gffid_event(vha, &ea);
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  /* Get FC4 Feature with Nport ID. */
> > @@ -3328,6 +3345,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> >                 return rval;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 return rval;
> > @@ -3366,7 +3384,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >
> >         return rval;
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         fcport->flags &= ~FCF_ASYNC_SENT;
> >         return rval;
> >  }
> > @@ -3753,7 +3772,6 @@ static void
> qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
> >             "Async done-%s res %x FC4Type %x\n",
> >             sp->name, res, sp->gen2);
> >
> > -       del_timer(&sp->u.iocb_cmd.timer);
> >         sp->rc = res;
> >         if (res) {
> >                 unsigned long flags;
> > @@ -3921,8 +3939,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t
> *vha, struct srb *sp,
> >                     sp->u.iocb_cmd.u.ctarg.rsp_dma);
> >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> >         }
> > -
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >
> >         spin_lock_irqsave(&vha->work_lock, flags);
> >         vha->scan.scan_flags &= ~SF_SCANNING;
> > @@ -3974,9 +3992,12 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8
> fc4_type, srb_t *sp)
> >                 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
> >                     "%s: Performing FCP Scan\n", __func__);
> >
> > -               if (sp)
> > -                       sp->free(sp); /* should not happen */
> > +               if (sp) {
> > +                       /* ref: INIT */
> > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > +               }
> >
> > +               /* ref: INIT */
> >                 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> >                 if (!sp) {
> >                         spin_lock_irqsave(&vha->work_lock, flags);
> > @@ -4021,6 +4042,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8
> fc4_type, srb_t *sp)
> >                             sp->u.iocb_cmd.u.ctarg.req,
> >                             sp->u.iocb_cmd.u.ctarg.req_dma);
> >                         sp->u.iocb_cmd.u.ctarg.req = NULL;
> > +                       /* ref: INIT */
> >                         qla2x00_rel_sp(sp);
> >                         return rval;
> >                 }
> > @@ -4083,7 +4105,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8
> fc4_type, srb_t *sp)
> >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> >         }
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >
> >         spin_lock_irqsave(&vha->work_lock, flags);
> >         vha->scan.scan_flags &= ~SF_SCANNING;
> > @@ -4147,7 +4170,8 @@ static void qla2x00_async_gnnid_sp_done(srb_t
> *sp, int res)
> >
> >         qla24xx_handle_gnnid_event(vha, &ea);
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> > @@ -4160,6 +4184,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >                 return rval;
> >
> >         qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
> >         if (!sp)
> >                 goto done;
> > @@ -4200,7 +4225,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         fcport->flags &= ~FCF_ASYNC_SENT;
> >  done:
> >         return rval;
> > @@ -4274,7 +4300,8 @@ static void qla2x00_async_gfpnid_sp_done(srb_t
> *sp, int res)
> >
> >         qla24xx_handle_gfpnid_event(vha, &ea);
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> > @@ -4286,6 +4313,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> >                 return rval;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
> >         if (!sp)
> >                 goto done;
> > @@ -4326,7 +4354,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> > index e6f13cb6fa28..38c11b75f644 100644
> > --- a/drivers/scsi/qla2xxx/qla_init.c
> > +++ b/drivers/scsi/qla2xxx/qla_init.c
> > @@ -51,6 +51,9 @@ qla2x00_sp_timeout(struct timer_list *t)
> >         WARN_ON(irqs_disabled());
> >         iocb = &sp->u.iocb_cmd;
> >         iocb->timeout(sp);
> > +
> > +       /* ref: TMR */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  void qla2x00_sp_free(srb_t *sp)
> > @@ -125,8 +128,13 @@ static void qla24xx_abort_iocb_timeout(void *data)
> >         }
> >         spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
> >
> > -       if (sp->cmd_sp)
> > +       if (sp->cmd_sp) {
> > +               /*
> > +                * This done function should take care of
> > +                * original command ref: INIT
> > +                */
> >                 sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
> > +       }
> >
> >         abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
> >         sp->done(sp, QLA_OS_TIMER_EXPIRED);
> > @@ -140,11 +148,11 @@ static void qla24xx_abort_sp_done(srb_t *sp, int
> res)
> >         if (orig_sp)
> >                 qla_wait_nvme_release_cmd_kref(orig_sp);
> >
> > -       del_timer(&sp->u.iocb_cmd.timer);
> >         if (sp->flags & SRB_WAKEUP_ON_COMP)
> >                 complete(&abt->u.abt.comp);
> >         else
> > -               sp->free(sp);
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
> > @@ -154,6 +162,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> wait)
> >         srb_t *sp;
> >         int rval = QLA_FUNCTION_FAILED;
> >
> > +       /* ref: INIT for ABTS command */
> >         sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp-
> >fcport,
> >                                   GFP_ATOMIC);
> >         if (!sp)
> > @@ -181,7 +190,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> wait)
> >
> >         rval = qla2x00_start_sp(sp);
> >         if (rval != QLA_SUCCESS) {
> > -               sp->free(sp);
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                 return rval;
> >         }
> >
> > @@ -189,7 +199,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> wait)
> >                 wait_for_completion(&abt_iocb->u.abt.comp);
> >                 rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
> >                         QLA_SUCCESS : QLA_ERR_FROM_FW;
> > -               sp->free(sp);
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         }
> >
> >         return rval;
> > @@ -287,7 +298,8 @@ static void qla2x00_async_login_sp_done(srb_t *sp,
> int res)
> >                 qla24xx_handle_plogi_done_event(vha, &ea);
> >         }
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int
> > @@ -306,6 +318,7 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> fc_port_t *fcport,
> >                 return rval;
> >         }
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -354,7 +367,8 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> fc_port_t *fcport,
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         fcport->flags &= ~FCF_ASYNC_SENT;
> >  done:
> >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > @@ -366,7 +380,8 @@ static void qla2x00_async_logout_sp_done(srb_t *sp,
> int res)
> >         sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> >         sp->fcport->login_gen++;
> >         qlt_logo_completion_handler(sp->fcport, sp-
> >u.iocb_cmd.u.logio.data[0]);
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int
> > @@ -376,6 +391,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha,
> fc_port_t *fcport)
> >         int rval = QLA_FUNCTION_FAILED;
> >
> >         fcport->flags |= FCF_ASYNC_SENT;
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -397,7 +413,8 @@ qla2x00_async_logout(struct scsi_qla_host *vha,
> fc_port_t *fcport)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> >         return rval;
> > @@ -423,7 +440,8 @@ static void qla2x00_async_prlo_sp_done(srb_t *sp,
> int res)
> >         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);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int
> > @@ -433,6 +451,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha,
> fc_port_t *fcport)
> >         int rval;
> >
> >         rval = QLA_FUNCTION_FAILED;
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -454,7 +473,8 @@ qla2x00_async_prlo(struct scsi_qla_host *vha,
> fc_port_t *fcport)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> >         return rval;
> > @@ -539,8 +559,8 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp,
> int res)
> >         ea.sp = sp;
> >
> >         qla24xx_handle_adisc_event(vha, &ea);
> > -
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int
> > @@ -555,6 +575,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha,
> fc_port_t *fcport,
> >                 return rval;
> >
> >         fcport->flags |= FCF_ASYNC_SENT;
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -582,7 +603,8 @@ qla2x00_async_adisc(struct scsi_qla_host *vha,
> fc_port_t *fcport,
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> >         qla2x00_post_async_adisc_work(vha, fcport, data);
> > @@ -1063,7 +1085,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp,
> int res)
> >         }
> >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
> > @@ -1093,6 +1116,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha,
> fc_port_t *fcport)
> >         vha->gnl.sent = 1;
> >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -1125,7 +1149,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha,
> fc_port_t *fcport)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
> >         return rval;
> > @@ -1171,7 +1196,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t
> *sp, int res)
> >         dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
> >                 sp->u.iocb_cmd.u.mbx.in_dma);
> >
> > -       sp->free(sp);
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
> > @@ -1216,7 +1241,7 @@ static void qla2x00_async_prli_sp_done(srb_t *sp,
> int res)
> >                 qla24xx_handle_prli_done_event(vha, &ea);
> >         }
> >
> > -       sp->free(sp);
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int
> > @@ -1274,7 +1299,8 @@ qla24xx_async_prli(struct scsi_qla_host *vha,
> fc_port_t *fcport)
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         fcport->flags &= ~FCF_ASYNC_SENT;
> >         return rval;
> >  }
> > @@ -1359,7 +1385,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha,
> fc_port_t *fcport, u8 opt)
> >         if (pd)
> >                 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
> >
> > -       sp->free(sp);
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         fcport->flags &= ~FCF_ASYNC_SENT;
> >  done:
> >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > @@ -1945,6 +1971,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
> uint32_t flags, uint32_t lun,
> >         srb_t *sp;
> >         int rval = QLA_FUNCTION_FAILED;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -1988,7 +2015,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
> uint32_t flags, uint32_t lun,
> >         }
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         fcport->flags &= ~FCF_ASYNC_SENT;
> >  done:
> >         return rval;
> > diff --git a/drivers/scsi/qla2xxx/qla_inline.h
> b/drivers/scsi/qla2xxx/qla_inline.h
> > index 5f3b7995cc8f..db17f7f410cd 100644
> > --- a/drivers/scsi/qla2xxx/qla_inline.h
> > +++ b/drivers/scsi/qla2xxx/qla_inline.h
> > @@ -184,6 +184,8 @@ static void qla2xxx_init_sp(srb_t *sp, scsi_qla_host_t
> *vha,
> >         sp->vha = vha;
> >         sp->qpair = qpair;
> >         sp->cmd_type = TYPE_SRB;
> > +       /* ref : INIT - normal flow */
> > +       kref_init(&sp->cmd_kref);
> >         INIT_LIST_HEAD(&sp->elem);
> >  }
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> > index 95aae9a9631e..7dd82214d59f 100644
> > --- a/drivers/scsi/qla2xxx/qla_iocb.c
> > +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> > @@ -2560,6 +2560,14 @@ qla24xx_tm_iocb(srb_t *sp, struct
> tsk_mgmt_entry *tsk)
> >         }
> >  }
> >
> > +void
> > +qla2x00_sp_release(struct kref *kref)
> > +{
> > +       struct srb *sp = container_of(kref, struct srb, cmd_kref);
> > +
> > +       sp->free(sp);
> > +}
> > +
> >  void
> >  qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
> >                      void (*done)(struct srb *sp, int res))
> > @@ -2655,7 +2663,9 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> els_opcode,
> >                return -ENOMEM;
> >         }
> >
> > -       /* Alloc SRB structure */
> > +       /* Alloc SRB structure
> > +        * ref: INIT
> > +        */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp) {
> >                 kfree(fcport);
> > @@ -2687,7 +2697,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> els_opcode,
> >                             GFP_KERNEL);
> >
> >         if (!elsio->u.els_logo.els_logo_pyld) {
> > -               sp->free(sp);
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                 return QLA_FUNCTION_FAILED;
> >         }
> >
> > @@ -2710,7 +2721,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> els_opcode,
> >
> >         rval = qla2x00_start_sp(sp);
> >         if (rval != QLA_SUCCESS) {
> > -               sp->free(sp);
> > +               /* ref: INIT */
> > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                 return QLA_FUNCTION_FAILED;
> >         }
> >
> > @@ -2721,7 +2733,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> els_opcode,
> >
> >         wait_for_completion(&elsio->u.els_logo.comp);
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         return rval;
> >  }
> >
> > @@ -2854,7 +2867,6 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp,
> int res)
> >             sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
> >
> >         fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
> > -       del_timer(&sp->u.iocb_cmd.timer);
> >
> >         if (sp->flags & SRB_WAKEUP_ON_COMP)
> >                 complete(&lio->u.els_plogi.comp);
> > @@ -2964,7 +2976,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp,
> int res)
> >                         struct srb_iocb *elsio = &sp->u.iocb_cmd;
> >
> >                         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> > -                       sp->free(sp);
> > +                       /* ref: INIT */
> > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >                         return;
> >                 }
> >                 e->u.iosb.sp = sp;
> > @@ -2982,7 +2995,9 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int
> els_opcode,
> >         int rval = QLA_SUCCESS;
> >         void    *ptr, *resp_ptr;
> >
> > -       /* Alloc SRB structure */
> > +       /* Alloc SRB structure
> > +        * ref: INIT
> > +        */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp) {
> >                 ql_log(ql_log_info, vha, 0x70e6,
> > @@ -3071,7 +3086,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int
> els_opcode,
> >  out:
> >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> >         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > @@ -3882,8 +3898,15 @@ qla2x00_start_sp(srb_t *sp)
> >                 break;
> >         }
> >
> > -       if (sp->start_timer)
> > +       if (sp->start_timer) {
> > +               /* ref: TMR timer ref
> > +                * this code should be just before start_iocbs function
> > +                * This will make sure that caller function don't to do
> > +                * kref_put even on failure
> > +                */
> > +               kref_get(&sp->cmd_kref);
> >                 add_timer(&sp->u.iocb_cmd.timer);
> > +       }
> >
> >         wmb();
> >         qla2x00_start_iocbs(vha, qp->req);
> > diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> > index 2aacd3653245..38e0f02c75e1 100644
> > --- a/drivers/scsi/qla2xxx/qla_mbx.c
> > +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> > @@ -6479,6 +6479,7 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host
> *vha, mbx_cmd_t *mcp)
> >         if (!vha->hw->flags.fw_started)
> >                 goto done;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -6524,7 +6525,8 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host
> *vha, mbx_cmd_t *mcp)
> >         }
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
> > index c4a967c96fd6..e6b5c4ccce97 100644
> > --- a/drivers/scsi/qla2xxx/qla_mid.c
> > +++ b/drivers/scsi/qla2xxx/qla_mid.c
> > @@ -965,6 +965,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int
> cmd)
> >         if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
> >                 return QLA_PARAMETER_ERROR;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
> >         if (!sp)
> >                 return rval;
> > @@ -1007,6 +1008,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int
> cmd)
> >                 break;
> >         }
> >  done:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         return rval;
> >  }
> > diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
> > index e3ae0894c7a8..f726eb8449c5 100644
> > --- a/drivers/scsi/qla2xxx/qla_mr.c
> > +++ b/drivers/scsi/qla2xxx/qla_mr.c
> > @@ -1787,6 +1787,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t
> *fcport, uint16_t fx_type)
> >         struct register_host_info *preg_hsi;
> >         struct new_utsname *p_sysid = NULL;
> >
> > +       /* ref: INIT */
> >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> >         if (!sp)
> >                 goto done;
> > @@ -1973,7 +1974,8 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t
> *fcport, uint16_t fx_type)
> >                 dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
> >                     fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
> >  done_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         return rval;
> >  }
> > diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> > index abcd30917263..0a7b00d165c7 100644
> > --- a/drivers/scsi/qla2xxx/qla_os.c
> > +++ b/drivers/scsi/qla2xxx/qla_os.c
> > @@ -728,7 +728,8 @@ void qla2x00_sp_compl(srb_t *sp, int res)
> >         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
> >         struct completion *comp = sp->comp;
> >
> > -       sp->free(sp);
> > +       /* kref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         cmd->result = res;
> >         CMD_SP(cmd) = NULL;
> >         scsi_done(cmd);
> > @@ -819,7 +820,8 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
> >         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
> >         struct completion *comp = sp->comp;
> >
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >         cmd->result = res;
> >         CMD_SP(cmd) = NULL;
> >         scsi_done(cmd);
> > @@ -919,6 +921,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host,
> struct scsi_cmnd *cmd)
> >                 goto qc24_target_busy;
> >
> >         sp = scsi_cmd_priv(cmd);
> > +       /* ref: INIT */
> >         qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
> >
> >         sp->u.scmd.cmd = cmd;
> > @@ -938,7 +941,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host,
> struct scsi_cmnd *cmd)
> >         return 0;
> >
> >  qc24_host_busy_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >
> >  qc24_target_busy:
> >         return SCSI_MLQUEUE_TARGET_BUSY;
> > @@ -1008,6 +1012,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host,
> struct scsi_cmnd *cmd,
> >                 goto qc24_target_busy;
> >
> >         sp = scsi_cmd_priv(cmd);
> > +       /* ref: INIT */
> >         qla2xxx_init_sp(sp, vha, qpair, fcport);
> >
> >         sp->u.scmd.cmd = cmd;
> > @@ -1026,7 +1031,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host,
> struct scsi_cmnd *cmd,
> >         return 0;
> >
> >  qc24_host_busy_free_sp:
> > -       sp->free(sp);
> > +       /* ref: INIT */
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >
> >  qc24_target_busy:
> >         return SCSI_MLQUEUE_TARGET_BUSY;
> > diff --git a/drivers/scsi/qla2xxx/qla_target.c
> b/drivers/scsi/qla2xxx/qla_target.c
> > index 83c8c55017d1..b0990f2ee91c 100644
> > --- a/drivers/scsi/qla2xxx/qla_target.c
> > +++ b/drivers/scsi/qla2xxx/qla_target.c
> > @@ -620,7 +620,7 @@ static void qla2x00_async_nack_sp_done(srb_t *sp,
> int res)
> >         }
> >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> >
> > -       sp->free(sp);
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  }
> >
> >  int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
> > @@ -672,7 +672,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha,
> fc_port_t *fcport,
> >         return rval;
> >
> >  done_free_sp:
> > -       sp->free(sp);
> > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> >  done:
> >         fcport->flags &= ~FCF_ASYNC_SENT;
> >         return rval;
> > --
> > 2.23.1
> >


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

* RE: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
  2022-02-04  7:16     ` Saurav Kashyap
@ 2022-02-08 10:59       ` Saurav Kashyap
  2022-02-09 20:09         ` Ewan Milne
  0 siblings, 1 reply; 24+ messages in thread
From: Saurav Kashyap @ 2022-02-08 10:59 UTC (permalink / raw)
  To: Ewan Milne, Nilesh Javali
  Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream

Hi Ewan,
Thanks for reporting this, the patch, "qla2xxx: Add qla2x00_async_done routine for async routines", fixes this issue and is submitted upstream. 
Can you test it out and let us know the results?

Thanks,
~Saurav

> -----Original Message-----
> From: Saurav Kashyap
> Sent: Friday, February 4, 2022 12:47 PM
> To: Ewan Milne <emilne@redhat.com>; Nilesh Javali <njavali@marvell.com>
> Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> Upstream@marvell.com>
> Subject: RE: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
> 
> Hi Ewan,
> This patch have undergone extensive testing from our side and we didn't hit
> any of the issues. Can you share the test case? So that we can try to reproduce
> this?
> 
> Thanks,
> ~Saurav
> 
> > -----Original Message-----
> > From: Ewan Milne <emilne@redhat.com>
> > Sent: Thursday, February 3, 2022 8:15 PM
> > To: Nilesh Javali <njavali@marvell.com>
> > Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> > scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> > Upstream@marvell.com>
> > Subject: Re: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
> >
> > This commit causes at least 2 of our systems with Qlogic HBAs to panic on
> > boot:
> > From the look of it, it is possible that a timer was left active on a
> > freed object or something.
> >
> > [   44.232603] general protection fault, probably for non-canonical
> > address 0xdead00000000012a: 0000 [#1] PR
> > [   44.247211] CPU: 9 PID: 0 Comm: swapper/9 Tainted: G          I
> >   5.17.0-rc1 #4
> > [   44.254870] Hardware name: Dell Inc. PowerEdge R440/0WKGTH, BIOS
> > 1.4.8 05/22/2018
> > [   44.262349] RIP: 0010:__run_timers.part.0+0x19c/0x260
> > [   44.267411] Code: 00 48 8b 03 49 c7 47 08 00 00 00 00 48 85 c0 74
> > 61 48 8b 2b 49 89 6f 08 66 90 48 8b 45
> > [   44.286156] RSP: 0018:ffffb0a7803ecef0 EFLAGS: 00010086
> > [   44.291383] RAX: dead000000000122 RBX: ffffb0a7803ecf00 RCX:
> > 0000000000000009
> > [   44.298515] RDX: ffffb0a7803ecf00 RSI: ffff91dad1060380 RDI:
> > ffff91dad10603a8
> > [   44.305646] RBP: ffff91cfe34c8c10 R08: 0000000000000000 R09:
> > 0000000000000000
> > [   44.312780] R10: 0000000000000002 R11: 00000000000000ca R12:
> > 00000000fffc1200
> > [   44.319911] R13: dead000000000122 R14: 0000000000000001 R15:
> > ffff91dad1060380
> > [   44.327045] FS:  0000000000000000(0000) GS:ffff91dad1040000(0000)
> > knlGS:0000000000000000
> > [   44.335131] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [   44.340877] CR2: 00007ff966417870 CR3: 00000002db010004 CR4:
> > 00000000007706e0
> > [   44.348010] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> > 0000000000000000
> > [   44.355143] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7:
> > 0000000000000400
> > [   44.362274] PKRU: 55555554
> > [   44.364987] Call Trace:
> > [   44.367442]  <IRQ>
> > [   44.369460]  ? tick_sched_timer+0x6d/0x80
> > [   44.373472]  ? _raw_spin_lock_irq+0x14/0x40
> > [   44.377658]  ? __hrtimer_run_queues+0x139/0x2c0
> > [   44.382190]  ? recalibrate_cpu_khz+0x10/0x10
> > [   44.386464]  run_timer_softirq+0x31/0x60
> > [   44.390391]  __do_softirq+0xf6/0x2fb
> > [   44.393968]  __irq_exit_rcu+0xe2/0x130
> > [   44.397720]  sysvec_apic_timer_interrupt+0xa2/0xd0
> > [   44.402514]  </IRQ>
> > [   44.404619]  <TASK>
> > [   44.406725]  asm_sysvec_apic_timer_interrupt+0x12/0x20
> >
> >
> > -Ewan
> >
> > On Mon, Jan 10, 2022 at 12:03 AM Nilesh Javali <njavali@marvell.com>
> wrote:
> > >
> > > From: Saurav Kashyap <skashyap@marvell.com>
> > >
> > > The timeout handler and done function are racing. When
> > > qla2x00_async_iocb_timeout() starts to run it can be preempted by the
> > > normal response path (via the firmware?). qla24xx_async_gpsc_sp_done()
> > > releases the SRB unconditionally. When scheduling back to
> > > qla2x00_async_iocb_timeout() qla24xx_async_abort_cmd() will access an
> > > freed sp->qpair pointer:
> > >
> > >   qla2xxx [0000:83:00.0]-2871:0: Async-gpsc timeout - hdl=63d
> > portid=234500 50:06:0e:80:08:77:b6:21.
> > >   qla2xxx [0000:83:00.0]-2853:0: Async done-gpsc res 0, WWPN
> > 50:06:0e:80:08:77:b6:21
> > >   qla2xxx [0000:83:00.0]-2854:0: Async-gpsc OUT WWPN
> > 20:45:00:27:f8:75:33:00 speeds=2c00 speed=0400.
> > >   qla2xxx [0000:83:00.0]-28d8:0: qla24xx_handle_gpsc_event
> > 50:06:0e:80:08:77:b6:21 DS 7 LS 6 rc 0 login 1|1 rscn 1|0 lid 5
> > >   BUG: unable to handle kernel NULL pointer dereference at
> > 0000000000000004
> > >   IP: qla24xx_async_abort_cmd+0x1b/0x1c0 [qla2xxx]
> > >
> > > Obvious solution to this is to introduce a reference counter. One
> > > reference is taken for the normal code path (the 'good case') and one
> > > for the timeout path. As we always race between the normal good case
> > > and the timeout/abort handler we need to serialize it. Also we cannot
> > > assume any order between the handlers. Since this is slow path we can
> > > use proper synchronization via locks.
> > >
> > > When we are able to cancel a timer (del_timer returns 1) we know there
> > > can't be any error handling in progress because the timeout handler
> > > hasn't expired yet, thus we can safely decrement the refcounter by one.
> > >
> > > If we are not able to cancel the timer, we know an abort handler is
> > > running. We have to make sure we call sp->done() in the abort handlers
> > > before calling kref_put().
> > >
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Daniel Wagner <dwagner@suse.de>
> > > Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> > > Signed-off-by: Nilesh Javali <njavali@marvell.com>
> > > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
> > > ---
> > > v1->v2:
> > > - update detailed issue description and the solution
> > >
> > >  drivers/scsi/qla2xxx/qla_bsg.c    |  6 ++-
> > >  drivers/scsi/qla2xxx/qla_def.h    |  5 ++
> > >  drivers/scsi/qla2xxx/qla_edif.c   |  3 +-
> > >  drivers/scsi/qla2xxx/qla_gbl.h    |  1 +
> > >  drivers/scsi/qla2xxx/qla_gs.c     | 85 +++++++++++++++++++++----------
> > >  drivers/scsi/qla2xxx/qla_init.c   | 70 +++++++++++++++++--------
> > >  drivers/scsi/qla2xxx/qla_inline.h |  2 +
> > >  drivers/scsi/qla2xxx/qla_iocb.c   | 41 +++++++++++----
> > >  drivers/scsi/qla2xxx/qla_mbx.c    |  4 +-
> > >  drivers/scsi/qla2xxx/qla_mid.c    |  4 +-
> > >  drivers/scsi/qla2xxx/qla_mr.c     |  4 +-
> > >  drivers/scsi/qla2xxx/qla_os.c     | 14 +++--
> > >  drivers/scsi/qla2xxx/qla_target.c |  4 +-
> > >  13 files changed, 173 insertions(+), 70 deletions(-)
> > >
> > > diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> > > index 9da8034ccad4..c2f00f076f79 100644
> > > --- a/drivers/scsi/qla2xxx/qla_bsg.c
> > > +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> > > @@ -29,7 +29,8 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
> > >             "%s: sp hdl %x, result=%x bsg ptr %p\n",
> > >             __func__, sp->handle, res, bsg_job);
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >
> > >         bsg_reply->result = res;
> > >         bsg_job_done(bsg_job, bsg_reply->result,
> > > @@ -3013,7 +3014,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
> > >
> > >  done:
> > >         spin_unlock_irqrestore(&ha->hardware_lock, flags);
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         return 0;
> > >  }
> > >
> > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> > > index 9ebf4a234d9a..a5fc01b4fa96 100644
> > > --- a/drivers/scsi/qla2xxx/qla_def.h
> > > +++ b/drivers/scsi/qla2xxx/qla_def.h
> > > @@ -726,6 +726,11 @@ typedef struct srb {
> > >          * code.
> > >          */
> > >         void (*put_fn)(struct kref *kref);
> > > +
> > > +       /*
> > > +        * Report completion for asynchronous commands.
> > > +        */
> > > +       void (*async_done)(struct srb *sp, int res);
> > >  } srb_t;
> > >
> > >  #define GET_CMD_SP(sp) (sp->u.scmd.cmd)
> > > diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
> > > index 53d2b8562027..c04957c363d8 100644
> > > --- a/drivers/scsi/qla2xxx/qla_edif.c
> > > +++ b/drivers/scsi/qla2xxx/qla_edif.c
> > > @@ -2146,7 +2146,8 @@ edif_doorbell_show(struct device *dev, struct
> > device_attribute *attr,
> > >
> > >  static void qla_noop_sp_done(srb_t *sp, int res)
> > >  {
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  /*
> > > diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> > > index 5056564f0d0c..3f8b8bbabe6d 100644
> > > --- a/drivers/scsi/qla2xxx/qla_gbl.h
> > > +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> > > @@ -333,6 +333,7 @@ extern int qla24xx_get_one_block_sg(uint32_t,
> > struct qla2_sgx *, uint32_t *);
> > >  extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
> > >  extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
> > >         struct qla_work_evt *e);
> > > +void qla2x00_sp_release(struct kref *kref);
> > >
> > >  /*
> > >   * Global Function Prototypes in qla_mbx.c source file.
> > > diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> > > index 744eb3192056..a812f4a45232 100644
> > > --- a/drivers/scsi/qla2xxx/qla_gs.c
> > > +++ b/drivers/scsi/qla2xxx/qla_gs.c
> > > @@ -529,7 +529,6 @@ static void qla2x00_async_sns_sp_done(srb_t *sp,
> int
> > rc)
> > >                 if (!e)
> > >                         goto err2;
> > >
> > > -               del_timer(&sp->u.iocb_cmd.timer);
> > >                 e->u.iosb.sp = sp;
> > >                 qla2x00_post_work(vha, e);
> > >                 return;
> > > @@ -556,8 +555,8 @@ static void qla2x00_async_sns_sp_done(srb_t *sp,
> int
> > rc)
> > >                         sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > >                 }
> > >
> > > -               sp->free(sp);
> > > -
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                 return;
> > >         }
> > >
> > > @@ -592,6 +591,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha,
> > port_id_t *d_id)
> > >         if (!vha->flags.online)
> > >                 goto done;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -652,7 +652,8 @@ static int qla_async_rftid(scsi_qla_host_t *vha,
> > port_id_t *d_id)
> > >         }
> > >         return rval;
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > @@ -687,6 +688,7 @@ static int qla_async_rffid(scsi_qla_host_t *vha,
> > port_id_t *d_id,
> > >         srb_t *sp;
> > >         struct ct_sns_pkt *ct_sns;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -747,7 +749,8 @@ static int qla_async_rffid(scsi_qla_host_t *vha,
> > port_id_t *d_id,
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > @@ -777,6 +780,7 @@ static int qla_async_rnnid(scsi_qla_host_t *vha,
> > port_id_t *d_id,
> > >         srb_t *sp;
> > >         struct ct_sns_pkt *ct_sns;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -836,7 +840,8 @@ static int qla_async_rnnid(scsi_qla_host_t *vha,
> > port_id_t *d_id,
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > @@ -882,6 +887,7 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
> > >         srb_t *sp;
> > >         struct ct_sns_pkt *ct_sns;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -947,7 +953,8 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > @@ -2887,7 +2894,8 @@ static void qla24xx_async_gpsc_sp_done(srb_t
> > *sp, int res)
> > >         qla24xx_handle_gpsc_event(vha, &ea);
> > >
> > >  done:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
> > > @@ -2899,6 +2907,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> > >                 return rval;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -2938,7 +2947,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > @@ -2987,7 +2997,8 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha,
> > srb_t *sp)
> > >                 break;
> > >         }
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg
> > *ea)
> > > @@ -3126,13 +3137,15 @@ static void
> qla2x00_async_gpnid_sp_done(srb_t
> > *sp, int res)
> > >         if (res) {
> > >                 if (res == QLA_FUNCTION_TIMEOUT) {
> > >                         qla24xx_post_gpnid_work(sp->vha, &ea.id);
> > > -                       sp->free(sp);
> > > +                       /* ref: INIT */
> > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                         return;
> > >                 }
> > >         } else if (sp->gen1) {
> > >                 /* There was another RSCN for this Nport ID */
> > >                 qla24xx_post_gpnid_work(sp->vha, &ea.id);
> > > -               sp->free(sp);
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                 return;
> > >         }
> > >
> > > @@ -3153,7 +3166,8 @@ static void qla2x00_async_gpnid_sp_done(srb_t
> > *sp, int res)
> > >                                   sp->u.iocb_cmd.u.ctarg.rsp_dma);
> > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > >
> > > -               sp->free(sp);
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                 return;
> > >         }
> > >
> > > @@ -3173,6 +3187,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> > port_id_t *id)
> > >         if (!vha->flags.online)
> > >                 goto done;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -3189,7 +3204,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> > port_id_t *id)
> > >                 if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
> > >                         tsp->gen1++;
> > >                         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > > -                       sp->free(sp);
> > > +                       /* ref: INIT */
> > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                         goto done;
> > >                 }
> > >         }
> > > @@ -3259,8 +3275,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> > port_id_t *id)
> > >                         sp->u.iocb_cmd.u.ctarg.rsp_dma);
> > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > >         }
> > > -
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > @@ -3315,7 +3331,8 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int
> > res)
> > >         ea.rc = res;
> > >
> > >         qla24xx_handle_gffid_event(vha, &ea);
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  /* Get FC4 Feature with Nport ID. */
> > > @@ -3328,6 +3345,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> > >                 return rval;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 return rval;
> > > @@ -3366,7 +3384,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >
> > >         return rval;
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > >         return rval;
> > >  }
> > > @@ -3753,7 +3772,6 @@ static void
> > qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
> > >             "Async done-%s res %x FC4Type %x\n",
> > >             sp->name, res, sp->gen2);
> > >
> > > -       del_timer(&sp->u.iocb_cmd.timer);
> > >         sp->rc = res;
> > >         if (res) {
> > >                 unsigned long flags;
> > > @@ -3921,8 +3939,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t
> > *vha, struct srb *sp,
> > >                     sp->u.iocb_cmd.u.ctarg.rsp_dma);
> > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > >         }
> > > -
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >
> > >         spin_lock_irqsave(&vha->work_lock, flags);
> > >         vha->scan.scan_flags &= ~SF_SCANNING;
> > > @@ -3974,9 +3992,12 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha,
> u8
> > fc4_type, srb_t *sp)
> > >                 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
> > >                     "%s: Performing FCP Scan\n", __func__);
> > >
> > > -               if (sp)
> > > -                       sp->free(sp); /* should not happen */
> > > +               if (sp) {
> > > +                       /* ref: INIT */
> > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > +               }
> > >
> > > +               /* ref: INIT */
> > >                 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > >                 if (!sp) {
> > >                         spin_lock_irqsave(&vha->work_lock, flags);
> > > @@ -4021,6 +4042,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha,
> u8
> > fc4_type, srb_t *sp)
> > >                             sp->u.iocb_cmd.u.ctarg.req,
> > >                             sp->u.iocb_cmd.u.ctarg.req_dma);
> > >                         sp->u.iocb_cmd.u.ctarg.req = NULL;
> > > +                       /* ref: INIT */
> > >                         qla2x00_rel_sp(sp);
> > >                         return rval;
> > >                 }
> > > @@ -4083,7 +4105,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha,
> u8
> > fc4_type, srb_t *sp)
> > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > >         }
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >
> > >         spin_lock_irqsave(&vha->work_lock, flags);
> > >         vha->scan.scan_flags &= ~SF_SCANNING;
> > > @@ -4147,7 +4170,8 @@ static void qla2x00_async_gnnid_sp_done(srb_t
> > *sp, int res)
> > >
> > >         qla24xx_handle_gnnid_event(vha, &ea);
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> > > @@ -4160,6 +4184,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >                 return rval;
> > >
> > >         qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -4200,7 +4225,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > >  done:
> > >         return rval;
> > > @@ -4274,7 +4300,8 @@ static void qla2x00_async_gfpnid_sp_done(srb_t
> > *sp, int res)
> > >
> > >         qla24xx_handle_gfpnid_event(vha, &ea);
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> > > @@ -4286,6 +4313,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> > >                 return rval;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -4326,7 +4354,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha,
> > fc_port_t *fcport)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> > > index e6f13cb6fa28..38c11b75f644 100644
> > > --- a/drivers/scsi/qla2xxx/qla_init.c
> > > +++ b/drivers/scsi/qla2xxx/qla_init.c
> > > @@ -51,6 +51,9 @@ qla2x00_sp_timeout(struct timer_list *t)
> > >         WARN_ON(irqs_disabled());
> > >         iocb = &sp->u.iocb_cmd;
> > >         iocb->timeout(sp);
> > > +
> > > +       /* ref: TMR */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  void qla2x00_sp_free(srb_t *sp)
> > > @@ -125,8 +128,13 @@ static void qla24xx_abort_iocb_timeout(void
> *data)
> > >         }
> > >         spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
> > >
> > > -       if (sp->cmd_sp)
> > > +       if (sp->cmd_sp) {
> > > +               /*
> > > +                * This done function should take care of
> > > +                * original command ref: INIT
> > > +                */
> > >                 sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
> > > +       }
> > >
> > >         abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
> > >         sp->done(sp, QLA_OS_TIMER_EXPIRED);
> > > @@ -140,11 +148,11 @@ static void qla24xx_abort_sp_done(srb_t *sp, int
> > res)
> > >         if (orig_sp)
> > >                 qla_wait_nvme_release_cmd_kref(orig_sp);
> > >
> > > -       del_timer(&sp->u.iocb_cmd.timer);
> > >         if (sp->flags & SRB_WAKEUP_ON_COMP)
> > >                 complete(&abt->u.abt.comp);
> > >         else
> > > -               sp->free(sp);
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
> > > @@ -154,6 +162,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> > wait)
> > >         srb_t *sp;
> > >         int rval = QLA_FUNCTION_FAILED;
> > >
> > > +       /* ref: INIT for ABTS command */
> > >         sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp-
> > >fcport,
> > >                                   GFP_ATOMIC);
> > >         if (!sp)
> > > @@ -181,7 +190,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> > wait)
> > >
> > >         rval = qla2x00_start_sp(sp);
> > >         if (rval != QLA_SUCCESS) {
> > > -               sp->free(sp);
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                 return rval;
> > >         }
> > >
> > > @@ -189,7 +199,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> > wait)
> > >                 wait_for_completion(&abt_iocb->u.abt.comp);
> > >                 rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
> > >                         QLA_SUCCESS : QLA_ERR_FROM_FW;
> > > -               sp->free(sp);
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         }
> > >
> > >         return rval;
> > > @@ -287,7 +298,8 @@ static void qla2x00_async_login_sp_done(srb_t *sp,
> > int res)
> > >                 qla24xx_handle_plogi_done_event(vha, &ea);
> > >         }
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int
> > > @@ -306,6 +318,7 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> > fc_port_t *fcport,
> > >                 return rval;
> > >         }
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -354,7 +367,8 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> > fc_port_t *fcport,
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > >  done:
> > >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > > @@ -366,7 +380,8 @@ static void qla2x00_async_logout_sp_done(srb_t
> *sp,
> > int res)
> > >         sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > >         sp->fcport->login_gen++;
> > >         qlt_logo_completion_handler(sp->fcport, sp-
> > >u.iocb_cmd.u.logio.data[0]);
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int
> > > @@ -376,6 +391,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha,
> > fc_port_t *fcport)
> > >         int rval = QLA_FUNCTION_FAILED;
> > >
> > >         fcport->flags |= FCF_ASYNC_SENT;
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -397,7 +413,8 @@ qla2x00_async_logout(struct scsi_qla_host *vha,
> > fc_port_t *fcport)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > >         return rval;
> > > @@ -423,7 +440,8 @@ static void qla2x00_async_prlo_sp_done(srb_t *sp,
> > int res)
> > >         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);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int
> > > @@ -433,6 +451,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha,
> > fc_port_t *fcport)
> > >         int rval;
> > >
> > >         rval = QLA_FUNCTION_FAILED;
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -454,7 +473,8 @@ qla2x00_async_prlo(struct scsi_qla_host *vha,
> > fc_port_t *fcport)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > >         return rval;
> > > @@ -539,8 +559,8 @@ static void qla2x00_async_adisc_sp_done(srb_t
> *sp,
> > int res)
> > >         ea.sp = sp;
> > >
> > >         qla24xx_handle_adisc_event(vha, &ea);
> > > -
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int
> > > @@ -555,6 +575,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha,
> > fc_port_t *fcport,
> > >                 return rval;
> > >
> > >         fcport->flags |= FCF_ASYNC_SENT;
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -582,7 +603,8 @@ qla2x00_async_adisc(struct scsi_qla_host *vha,
> > fc_port_t *fcport,
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > >         qla2x00_post_async_adisc_work(vha, fcport, data);
> > > @@ -1063,7 +1085,8 @@ static void qla24xx_async_gnl_sp_done(srb_t
> *sp,
> > int res)
> > >         }
> > >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
> > > @@ -1093,6 +1116,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha,
> > fc_port_t *fcport)
> > >         vha->gnl.sent = 1;
> > >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -1125,7 +1149,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha,
> > fc_port_t *fcport)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
> > >         return rval;
> > > @@ -1171,7 +1196,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t
> > *sp, int res)
> > >         dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
> > >                 sp->u.iocb_cmd.u.mbx.in_dma);
> > >
> > > -       sp->free(sp);
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
> > > @@ -1216,7 +1241,7 @@ static void qla2x00_async_prli_sp_done(srb_t
> *sp,
> > int res)
> > >                 qla24xx_handle_prli_done_event(vha, &ea);
> > >         }
> > >
> > > -       sp->free(sp);
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int
> > > @@ -1274,7 +1299,8 @@ qla24xx_async_prli(struct scsi_qla_host *vha,
> > fc_port_t *fcport)
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > >         return rval;
> > >  }
> > > @@ -1359,7 +1385,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host
> *vha,
> > fc_port_t *fcport, u8 opt)
> > >         if (pd)
> > >                 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
> > >
> > > -       sp->free(sp);
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > >  done:
> > >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > > @@ -1945,6 +1971,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
> > uint32_t flags, uint32_t lun,
> > >         srb_t *sp;
> > >         int rval = QLA_FUNCTION_FAILED;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -1988,7 +2015,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
> > uint32_t flags, uint32_t lun,
> > >         }
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > >  done:
> > >         return rval;
> > > diff --git a/drivers/scsi/qla2xxx/qla_inline.h
> > b/drivers/scsi/qla2xxx/qla_inline.h
> > > index 5f3b7995cc8f..db17f7f410cd 100644
> > > --- a/drivers/scsi/qla2xxx/qla_inline.h
> > > +++ b/drivers/scsi/qla2xxx/qla_inline.h
> > > @@ -184,6 +184,8 @@ static void qla2xxx_init_sp(srb_t *sp,
> scsi_qla_host_t
> > *vha,
> > >         sp->vha = vha;
> > >         sp->qpair = qpair;
> > >         sp->cmd_type = TYPE_SRB;
> > > +       /* ref : INIT - normal flow */
> > > +       kref_init(&sp->cmd_kref);
> > >         INIT_LIST_HEAD(&sp->elem);
> > >  }
> > >
> > > diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> > > index 95aae9a9631e..7dd82214d59f 100644
> > > --- a/drivers/scsi/qla2xxx/qla_iocb.c
> > > +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> > > @@ -2560,6 +2560,14 @@ qla24xx_tm_iocb(srb_t *sp, struct
> > tsk_mgmt_entry *tsk)
> > >         }
> > >  }
> > >
> > > +void
> > > +qla2x00_sp_release(struct kref *kref)
> > > +{
> > > +       struct srb *sp = container_of(kref, struct srb, cmd_kref);
> > > +
> > > +       sp->free(sp);
> > > +}
> > > +
> > >  void
> > >  qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
> > >                      void (*done)(struct srb *sp, int res))
> > > @@ -2655,7 +2663,9 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > els_opcode,
> > >                return -ENOMEM;
> > >         }
> > >
> > > -       /* Alloc SRB structure */
> > > +       /* Alloc SRB structure
> > > +        * ref: INIT
> > > +        */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp) {
> > >                 kfree(fcport);
> > > @@ -2687,7 +2697,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > els_opcode,
> > >                             GFP_KERNEL);
> > >
> > >         if (!elsio->u.els_logo.els_logo_pyld) {
> > > -               sp->free(sp);
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                 return QLA_FUNCTION_FAILED;
> > >         }
> > >
> > > @@ -2710,7 +2721,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > els_opcode,
> > >
> > >         rval = qla2x00_start_sp(sp);
> > >         if (rval != QLA_SUCCESS) {
> > > -               sp->free(sp);
> > > +               /* ref: INIT */
> > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                 return QLA_FUNCTION_FAILED;
> > >         }
> > >
> > > @@ -2721,7 +2733,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > els_opcode,
> > >
> > >         wait_for_completion(&elsio->u.els_logo.comp);
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         return rval;
> > >  }
> > >
> > > @@ -2854,7 +2867,6 @@ static void qla2x00_els_dcmd2_sp_done(srb_t
> *sp,
> > int res)
> > >             sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
> > >
> > >         fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
> > > -       del_timer(&sp->u.iocb_cmd.timer);
> > >
> > >         if (sp->flags & SRB_WAKEUP_ON_COMP)
> > >                 complete(&lio->u.els_plogi.comp);
> > > @@ -2964,7 +2976,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t
> *sp,
> > int res)
> > >                         struct srb_iocb *elsio = &sp->u.iocb_cmd;
> > >
> > >                         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> > > -                       sp->free(sp);
> > > +                       /* ref: INIT */
> > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >                         return;
> > >                 }
> > >                 e->u.iosb.sp = sp;
> > > @@ -2982,7 +2995,9 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha,
> int
> > els_opcode,
> > >         int rval = QLA_SUCCESS;
> > >         void    *ptr, *resp_ptr;
> > >
> > > -       /* Alloc SRB structure */
> > > +       /* Alloc SRB structure
> > > +        * ref: INIT
> > > +        */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp) {
> > >                 ql_log(ql_log_info, vha, 0x70e6,
> > > @@ -3071,7 +3086,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha,
> int
> > els_opcode,
> > >  out:
> > >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > >         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > @@ -3882,8 +3898,15 @@ qla2x00_start_sp(srb_t *sp)
> > >                 break;
> > >         }
> > >
> > > -       if (sp->start_timer)
> > > +       if (sp->start_timer) {
> > > +               /* ref: TMR timer ref
> > > +                * this code should be just before start_iocbs function
> > > +                * This will make sure that caller function don't to do
> > > +                * kref_put even on failure
> > > +                */
> > > +               kref_get(&sp->cmd_kref);
> > >                 add_timer(&sp->u.iocb_cmd.timer);
> > > +       }
> > >
> > >         wmb();
> > >         qla2x00_start_iocbs(vha, qp->req);
> > > diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> > > index 2aacd3653245..38e0f02c75e1 100644
> > > --- a/drivers/scsi/qla2xxx/qla_mbx.c
> > > +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> > > @@ -6479,6 +6479,7 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host
> > *vha, mbx_cmd_t *mcp)
> > >         if (!vha->hw->flags.fw_started)
> > >                 goto done;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -6524,7 +6525,8 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host
> > *vha, mbx_cmd_t *mcp)
> > >         }
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
> > > index c4a967c96fd6..e6b5c4ccce97 100644
> > > --- a/drivers/scsi/qla2xxx/qla_mid.c
> > > +++ b/drivers/scsi/qla2xxx/qla_mid.c
> > > @@ -965,6 +965,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int
> > cmd)
> > >         if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
> > >                 return QLA_PARAMETER_ERROR;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
> > >         if (!sp)
> > >                 return rval;
> > > @@ -1007,6 +1008,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int
> > cmd)
> > >                 break;
> > >         }
> > >  done:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         return rval;
> > >  }
> > > diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
> > > index e3ae0894c7a8..f726eb8449c5 100644
> > > --- a/drivers/scsi/qla2xxx/qla_mr.c
> > > +++ b/drivers/scsi/qla2xxx/qla_mr.c
> > > @@ -1787,6 +1787,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t
> > *fcport, uint16_t fx_type)
> > >         struct register_host_info *preg_hsi;
> > >         struct new_utsname *p_sysid = NULL;
> > >
> > > +       /* ref: INIT */
> > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > >         if (!sp)
> > >                 goto done;
> > > @@ -1973,7 +1974,8 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t
> > *fcport, uint16_t fx_type)
> > >                 dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
> > >                     fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         return rval;
> > >  }
> > > diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> > > index abcd30917263..0a7b00d165c7 100644
> > > --- a/drivers/scsi/qla2xxx/qla_os.c
> > > +++ b/drivers/scsi/qla2xxx/qla_os.c
> > > @@ -728,7 +728,8 @@ void qla2x00_sp_compl(srb_t *sp, int res)
> > >         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
> > >         struct completion *comp = sp->comp;
> > >
> > > -       sp->free(sp);
> > > +       /* kref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         cmd->result = res;
> > >         CMD_SP(cmd) = NULL;
> > >         scsi_done(cmd);
> > > @@ -819,7 +820,8 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
> > >         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
> > >         struct completion *comp = sp->comp;
> > >
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >         cmd->result = res;
> > >         CMD_SP(cmd) = NULL;
> > >         scsi_done(cmd);
> > > @@ -919,6 +921,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host,
> > struct scsi_cmnd *cmd)
> > >                 goto qc24_target_busy;
> > >
> > >         sp = scsi_cmd_priv(cmd);
> > > +       /* ref: INIT */
> > >         qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
> > >
> > >         sp->u.scmd.cmd = cmd;
> > > @@ -938,7 +941,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host,
> > struct scsi_cmnd *cmd)
> > >         return 0;
> > >
> > >  qc24_host_busy_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >
> > >  qc24_target_busy:
> > >         return SCSI_MLQUEUE_TARGET_BUSY;
> > > @@ -1008,6 +1012,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host
> *host,
> > struct scsi_cmnd *cmd,
> > >                 goto qc24_target_busy;
> > >
> > >         sp = scsi_cmd_priv(cmd);
> > > +       /* ref: INIT */
> > >         qla2xxx_init_sp(sp, vha, qpair, fcport);
> > >
> > >         sp->u.scmd.cmd = cmd;
> > > @@ -1026,7 +1031,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host
> *host,
> > struct scsi_cmnd *cmd,
> > >         return 0;
> > >
> > >  qc24_host_busy_free_sp:
> > > -       sp->free(sp);
> > > +       /* ref: INIT */
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >
> > >  qc24_target_busy:
> > >         return SCSI_MLQUEUE_TARGET_BUSY;
> > > diff --git a/drivers/scsi/qla2xxx/qla_target.c
> > b/drivers/scsi/qla2xxx/qla_target.c
> > > index 83c8c55017d1..b0990f2ee91c 100644
> > > --- a/drivers/scsi/qla2xxx/qla_target.c
> > > +++ b/drivers/scsi/qla2xxx/qla_target.c
> > > @@ -620,7 +620,7 @@ static void qla2x00_async_nack_sp_done(srb_t *sp,
> > int res)
> > >         }
> > >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > >
> > > -       sp->free(sp);
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  }
> > >
> > >  int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
> > > @@ -672,7 +672,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha,
> > fc_port_t *fcport,
> > >         return rval;
> > >
> > >  done_free_sp:
> > > -       sp->free(sp);
> > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > >  done:
> > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > >         return rval;
> > > --
> > > 2.23.1
> > >


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

* Re: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
  2022-02-08 10:59       ` Saurav Kashyap
@ 2022-02-09 20:09         ` Ewan Milne
  0 siblings, 0 replies; 24+ messages in thread
From: Ewan Milne @ 2022-02-09 20:09 UTC (permalink / raw)
  To: Saurav Kashyap
  Cc: Nilesh Javali, Martin K. Petersen, linux-scsi,
	GR-QLogic-Storage-Upstream

Thanks, that appears to have resolved the crash on boot I was seeing.

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

On Tue, Feb 8, 2022 at 5:59 AM Saurav Kashyap <skashyap@marvell.com> wrote:
>
> Hi Ewan,
> Thanks for reporting this, the patch, "qla2xxx: Add qla2x00_async_done routine for async routines", fixes this issue and is submitted upstream.
> Can you test it out and let us know the results?
>
> Thanks,
> ~Saurav
>
> > -----Original Message-----
> > From: Saurav Kashyap
> > Sent: Friday, February 4, 2022 12:47 PM
> > To: Ewan Milne <emilne@redhat.com>; Nilesh Javali <njavali@marvell.com>
> > Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> > scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> > Upstream@marvell.com>
> > Subject: RE: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
> >
> > Hi Ewan,
> > This patch have undergone extensive testing from our side and we didn't hit
> > any of the issues. Can you share the test case? So that we can try to reproduce
> > this?
> >
> > Thanks,
> > ~Saurav
> >
> > > -----Original Message-----
> > > From: Ewan Milne <emilne@redhat.com>
> > > Sent: Thursday, February 3, 2022 8:15 PM
> > > To: Nilesh Javali <njavali@marvell.com>
> > > Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> > > scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> > > Upstream@marvell.com>
> > > Subject: Re: [PATCH v2 02/17] qla2xxx: Implement ref count for srb
> > >
> > > This commit causes at least 2 of our systems with Qlogic HBAs to panic on
> > > boot:
> > > From the look of it, it is possible that a timer was left active on a
> > > freed object or something.
> > >
> > > [   44.232603] general protection fault, probably for non-canonical
> > > address 0xdead00000000012a: 0000 [#1] PR
> > > [   44.247211] CPU: 9 PID: 0 Comm: swapper/9 Tainted: G          I
> > >   5.17.0-rc1 #4
> > > [   44.254870] Hardware name: Dell Inc. PowerEdge R440/0WKGTH, BIOS
> > > 1.4.8 05/22/2018
> > > [   44.262349] RIP: 0010:__run_timers.part.0+0x19c/0x260
> > > [   44.267411] Code: 00 48 8b 03 49 c7 47 08 00 00 00 00 48 85 c0 74
> > > 61 48 8b 2b 49 89 6f 08 66 90 48 8b 45
> > > [   44.286156] RSP: 0018:ffffb0a7803ecef0 EFLAGS: 00010086
> > > [   44.291383] RAX: dead000000000122 RBX: ffffb0a7803ecf00 RCX:
> > > 0000000000000009
> > > [   44.298515] RDX: ffffb0a7803ecf00 RSI: ffff91dad1060380 RDI:
> > > ffff91dad10603a8
> > > [   44.305646] RBP: ffff91cfe34c8c10 R08: 0000000000000000 R09:
> > > 0000000000000000
> > > [   44.312780] R10: 0000000000000002 R11: 00000000000000ca R12:
> > > 00000000fffc1200
> > > [   44.319911] R13: dead000000000122 R14: 0000000000000001 R15:
> > > ffff91dad1060380
> > > [   44.327045] FS:  0000000000000000(0000) GS:ffff91dad1040000(0000)
> > > knlGS:0000000000000000
> > > [   44.335131] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > > [   44.340877] CR2: 00007ff966417870 CR3: 00000002db010004 CR4:
> > > 00000000007706e0
> > > [   44.348010] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> > > 0000000000000000
> > > [   44.355143] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7:
> > > 0000000000000400
> > > [   44.362274] PKRU: 55555554
> > > [   44.364987] Call Trace:
> > > [   44.367442]  <IRQ>
> > > [   44.369460]  ? tick_sched_timer+0x6d/0x80
> > > [   44.373472]  ? _raw_spin_lock_irq+0x14/0x40
> > > [   44.377658]  ? __hrtimer_run_queues+0x139/0x2c0
> > > [   44.382190]  ? recalibrate_cpu_khz+0x10/0x10
> > > [   44.386464]  run_timer_softirq+0x31/0x60
> > > [   44.390391]  __do_softirq+0xf6/0x2fb
> > > [   44.393968]  __irq_exit_rcu+0xe2/0x130
> > > [   44.397720]  sysvec_apic_timer_interrupt+0xa2/0xd0
> > > [   44.402514]  </IRQ>
> > > [   44.404619]  <TASK>
> > > [   44.406725]  asm_sysvec_apic_timer_interrupt+0x12/0x20
> > >
> > >
> > > -Ewan
> > >
> > > On Mon, Jan 10, 2022 at 12:03 AM Nilesh Javali <njavali@marvell.com>
> > wrote:
> > > >
> > > > From: Saurav Kashyap <skashyap@marvell.com>
> > > >
> > > > The timeout handler and done function are racing. When
> > > > qla2x00_async_iocb_timeout() starts to run it can be preempted by the
> > > > normal response path (via the firmware?). qla24xx_async_gpsc_sp_done()
> > > > releases the SRB unconditionally. When scheduling back to
> > > > qla2x00_async_iocb_timeout() qla24xx_async_abort_cmd() will access an
> > > > freed sp->qpair pointer:
> > > >
> > > >   qla2xxx [0000:83:00.0]-2871:0: Async-gpsc timeout - hdl=63d
> > > portid=234500 50:06:0e:80:08:77:b6:21.
> > > >   qla2xxx [0000:83:00.0]-2853:0: Async done-gpsc res 0, WWPN
> > > 50:06:0e:80:08:77:b6:21
> > > >   qla2xxx [0000:83:00.0]-2854:0: Async-gpsc OUT WWPN
> > > 20:45:00:27:f8:75:33:00 speeds=2c00 speed=0400.
> > > >   qla2xxx [0000:83:00.0]-28d8:0: qla24xx_handle_gpsc_event
> > > 50:06:0e:80:08:77:b6:21 DS 7 LS 6 rc 0 login 1|1 rscn 1|0 lid 5
> > > >   BUG: unable to handle kernel NULL pointer dereference at
> > > 0000000000000004
> > > >   IP: qla24xx_async_abort_cmd+0x1b/0x1c0 [qla2xxx]
> > > >
> > > > Obvious solution to this is to introduce a reference counter. One
> > > > reference is taken for the normal code path (the 'good case') and one
> > > > for the timeout path. As we always race between the normal good case
> > > > and the timeout/abort handler we need to serialize it. Also we cannot
> > > > assume any order between the handlers. Since this is slow path we can
> > > > use proper synchronization via locks.
> > > >
> > > > When we are able to cancel a timer (del_timer returns 1) we know there
> > > > can't be any error handling in progress because the timeout handler
> > > > hasn't expired yet, thus we can safely decrement the refcounter by one.
> > > >
> > > > If we are not able to cancel the timer, we know an abort handler is
> > > > running. We have to make sure we call sp->done() in the abort handlers
> > > > before calling kref_put().
> > > >
> > > > Cc: stable@vger.kernel.org
> > > > Signed-off-by: Daniel Wagner <dwagner@suse.de>
> > > > Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> > > > Signed-off-by: Nilesh Javali <njavali@marvell.com>
> > > > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
> > > > ---
> > > > v1->v2:
> > > > - update detailed issue description and the solution
> > > >
> > > >  drivers/scsi/qla2xxx/qla_bsg.c    |  6 ++-
> > > >  drivers/scsi/qla2xxx/qla_def.h    |  5 ++
> > > >  drivers/scsi/qla2xxx/qla_edif.c   |  3 +-
> > > >  drivers/scsi/qla2xxx/qla_gbl.h    |  1 +
> > > >  drivers/scsi/qla2xxx/qla_gs.c     | 85 +++++++++++++++++++++----------
> > > >  drivers/scsi/qla2xxx/qla_init.c   | 70 +++++++++++++++++--------
> > > >  drivers/scsi/qla2xxx/qla_inline.h |  2 +
> > > >  drivers/scsi/qla2xxx/qla_iocb.c   | 41 +++++++++++----
> > > >  drivers/scsi/qla2xxx/qla_mbx.c    |  4 +-
> > > >  drivers/scsi/qla2xxx/qla_mid.c    |  4 +-
> > > >  drivers/scsi/qla2xxx/qla_mr.c     |  4 +-
> > > >  drivers/scsi/qla2xxx/qla_os.c     | 14 +++--
> > > >  drivers/scsi/qla2xxx/qla_target.c |  4 +-
> > > >  13 files changed, 173 insertions(+), 70 deletions(-)
> > > >
> > > > diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> > > > index 9da8034ccad4..c2f00f076f79 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_bsg.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> > > > @@ -29,7 +29,8 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
> > > >             "%s: sp hdl %x, result=%x bsg ptr %p\n",
> > > >             __func__, sp->handle, res, bsg_job);
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >
> > > >         bsg_reply->result = res;
> > > >         bsg_job_done(bsg_job, bsg_reply->result,
> > > > @@ -3013,7 +3014,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
> > > >
> > > >  done:
> > > >         spin_unlock_irqrestore(&ha->hardware_lock, flags);
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         return 0;
> > > >  }
> > > >
> > > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> > > > index 9ebf4a234d9a..a5fc01b4fa96 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_def.h
> > > > +++ b/drivers/scsi/qla2xxx/qla_def.h
> > > > @@ -726,6 +726,11 @@ typedef struct srb {
> > > >          * code.
> > > >          */
> > > >         void (*put_fn)(struct kref *kref);
> > > > +
> > > > +       /*
> > > > +        * Report completion for asynchronous commands.
> > > > +        */
> > > > +       void (*async_done)(struct srb *sp, int res);
> > > >  } srb_t;
> > > >
> > > >  #define GET_CMD_SP(sp) (sp->u.scmd.cmd)
> > > > diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
> > > > index 53d2b8562027..c04957c363d8 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_edif.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_edif.c
> > > > @@ -2146,7 +2146,8 @@ edif_doorbell_show(struct device *dev, struct
> > > device_attribute *attr,
> > > >
> > > >  static void qla_noop_sp_done(srb_t *sp, int res)
> > > >  {
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  /*
> > > > diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> > > > index 5056564f0d0c..3f8b8bbabe6d 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_gbl.h
> > > > +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> > > > @@ -333,6 +333,7 @@ extern int qla24xx_get_one_block_sg(uint32_t,
> > > struct qla2_sgx *, uint32_t *);
> > > >  extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
> > > >  extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
> > > >         struct qla_work_evt *e);
> > > > +void qla2x00_sp_release(struct kref *kref);
> > > >
> > > >  /*
> > > >   * Global Function Prototypes in qla_mbx.c source file.
> > > > diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> > > > index 744eb3192056..a812f4a45232 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_gs.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_gs.c
> > > > @@ -529,7 +529,6 @@ static void qla2x00_async_sns_sp_done(srb_t *sp,
> > int
> > > rc)
> > > >                 if (!e)
> > > >                         goto err2;
> > > >
> > > > -               del_timer(&sp->u.iocb_cmd.timer);
> > > >                 e->u.iosb.sp = sp;
> > > >                 qla2x00_post_work(vha, e);
> > > >                 return;
> > > > @@ -556,8 +555,8 @@ static void qla2x00_async_sns_sp_done(srb_t *sp,
> > int
> > > rc)
> > > >                         sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > > >                 }
> > > >
> > > > -               sp->free(sp);
> > > > -
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                 return;
> > > >         }
> > > >
> > > > @@ -592,6 +591,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha,
> > > port_id_t *d_id)
> > > >         if (!vha->flags.online)
> > > >                 goto done;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -652,7 +652,8 @@ static int qla_async_rftid(scsi_qla_host_t *vha,
> > > port_id_t *d_id)
> > > >         }
> > > >         return rval;
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > @@ -687,6 +688,7 @@ static int qla_async_rffid(scsi_qla_host_t *vha,
> > > port_id_t *d_id,
> > > >         srb_t *sp;
> > > >         struct ct_sns_pkt *ct_sns;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -747,7 +749,8 @@ static int qla_async_rffid(scsi_qla_host_t *vha,
> > > port_id_t *d_id,
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > @@ -777,6 +780,7 @@ static int qla_async_rnnid(scsi_qla_host_t *vha,
> > > port_id_t *d_id,
> > > >         srb_t *sp;
> > > >         struct ct_sns_pkt *ct_sns;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -836,7 +840,8 @@ static int qla_async_rnnid(scsi_qla_host_t *vha,
> > > port_id_t *d_id,
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > @@ -882,6 +887,7 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
> > > >         srb_t *sp;
> > > >         struct ct_sns_pkt *ct_sns;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -947,7 +953,8 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > @@ -2887,7 +2894,8 @@ static void qla24xx_async_gpsc_sp_done(srb_t
> > > *sp, int res)
> > > >         qla24xx_handle_gpsc_event(vha, &ea);
> > > >
> > > >  done:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
> > > > @@ -2899,6 +2907,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> > > >                 return rval;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -2938,7 +2947,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > @@ -2987,7 +2997,8 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha,
> > > srb_t *sp)
> > > >                 break;
> > > >         }
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg
> > > *ea)
> > > > @@ -3126,13 +3137,15 @@ static void
> > qla2x00_async_gpnid_sp_done(srb_t
> > > *sp, int res)
> > > >         if (res) {
> > > >                 if (res == QLA_FUNCTION_TIMEOUT) {
> > > >                         qla24xx_post_gpnid_work(sp->vha, &ea.id);
> > > > -                       sp->free(sp);
> > > > +                       /* ref: INIT */
> > > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                         return;
> > > >                 }
> > > >         } else if (sp->gen1) {
> > > >                 /* There was another RSCN for this Nport ID */
> > > >                 qla24xx_post_gpnid_work(sp->vha, &ea.id);
> > > > -               sp->free(sp);
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                 return;
> > > >         }
> > > >
> > > > @@ -3153,7 +3166,8 @@ static void qla2x00_async_gpnid_sp_done(srb_t
> > > *sp, int res)
> > > >                                   sp->u.iocb_cmd.u.ctarg.rsp_dma);
> > > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > > >
> > > > -               sp->free(sp);
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                 return;
> > > >         }
> > > >
> > > > @@ -3173,6 +3187,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> > > port_id_t *id)
> > > >         if (!vha->flags.online)
> > > >                 goto done;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -3189,7 +3204,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> > > port_id_t *id)
> > > >                 if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
> > > >                         tsp->gen1++;
> > > >                         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > > > -                       sp->free(sp);
> > > > +                       /* ref: INIT */
> > > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                         goto done;
> > > >                 }
> > > >         }
> > > > @@ -3259,8 +3275,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha,
> > > port_id_t *id)
> > > >                         sp->u.iocb_cmd.u.ctarg.rsp_dma);
> > > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > > >         }
> > > > -
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > @@ -3315,7 +3331,8 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int
> > > res)
> > > >         ea.rc = res;
> > > >
> > > >         qla24xx_handle_gffid_event(vha, &ea);
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  /* Get FC4 Feature with Nport ID. */
> > > > @@ -3328,6 +3345,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> > > >                 return rval;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 return rval;
> > > > @@ -3366,7 +3384,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >
> > > >         return rval;
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > > >         return rval;
> > > >  }
> > > > @@ -3753,7 +3772,6 @@ static void
> > > qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
> > > >             "Async done-%s res %x FC4Type %x\n",
> > > >             sp->name, res, sp->gen2);
> > > >
> > > > -       del_timer(&sp->u.iocb_cmd.timer);
> > > >         sp->rc = res;
> > > >         if (res) {
> > > >                 unsigned long flags;
> > > > @@ -3921,8 +3939,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t
> > > *vha, struct srb *sp,
> > > >                     sp->u.iocb_cmd.u.ctarg.rsp_dma);
> > > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > > >         }
> > > > -
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >
> > > >         spin_lock_irqsave(&vha->work_lock, flags);
> > > >         vha->scan.scan_flags &= ~SF_SCANNING;
> > > > @@ -3974,9 +3992,12 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha,
> > u8
> > > fc4_type, srb_t *sp)
> > > >                 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
> > > >                     "%s: Performing FCP Scan\n", __func__);
> > > >
> > > > -               if (sp)
> > > > -                       sp->free(sp); /* should not happen */
> > > > +               if (sp) {
> > > > +                       /* ref: INIT */
> > > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > > +               }
> > > >
> > > > +               /* ref: INIT */
> > > >                 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > > >                 if (!sp) {
> > > >                         spin_lock_irqsave(&vha->work_lock, flags);
> > > > @@ -4021,6 +4042,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha,
> > u8
> > > fc4_type, srb_t *sp)
> > > >                             sp->u.iocb_cmd.u.ctarg.req,
> > > >                             sp->u.iocb_cmd.u.ctarg.req_dma);
> > > >                         sp->u.iocb_cmd.u.ctarg.req = NULL;
> > > > +                       /* ref: INIT */
> > > >                         qla2x00_rel_sp(sp);
> > > >                         return rval;
> > > >                 }
> > > > @@ -4083,7 +4105,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha,
> > u8
> > > fc4_type, srb_t *sp)
> > > >                 sp->u.iocb_cmd.u.ctarg.rsp = NULL;
> > > >         }
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >
> > > >         spin_lock_irqsave(&vha->work_lock, flags);
> > > >         vha->scan.scan_flags &= ~SF_SCANNING;
> > > > @@ -4147,7 +4170,8 @@ static void qla2x00_async_gnnid_sp_done(srb_t
> > > *sp, int res)
> > > >
> > > >         qla24xx_handle_gnnid_event(vha, &ea);
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> > > > @@ -4160,6 +4184,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >                 return rval;
> > > >
> > > >         qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -4200,7 +4225,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > > >  done:
> > > >         return rval;
> > > > @@ -4274,7 +4300,8 @@ static void qla2x00_async_gfpnid_sp_done(srb_t
> > > *sp, int res)
> > > >
> > > >         qla24xx_handle_gfpnid_event(vha, &ea);
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
> > > > @@ -4286,6 +4313,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >         if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
> > > >                 return rval;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -4326,7 +4354,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha,
> > > fc_port_t *fcport)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> > > > index e6f13cb6fa28..38c11b75f644 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_init.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_init.c
> > > > @@ -51,6 +51,9 @@ qla2x00_sp_timeout(struct timer_list *t)
> > > >         WARN_ON(irqs_disabled());
> > > >         iocb = &sp->u.iocb_cmd;
> > > >         iocb->timeout(sp);
> > > > +
> > > > +       /* ref: TMR */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  void qla2x00_sp_free(srb_t *sp)
> > > > @@ -125,8 +128,13 @@ static void qla24xx_abort_iocb_timeout(void
> > *data)
> > > >         }
> > > >         spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
> > > >
> > > > -       if (sp->cmd_sp)
> > > > +       if (sp->cmd_sp) {
> > > > +               /*
> > > > +                * This done function should take care of
> > > > +                * original command ref: INIT
> > > > +                */
> > > >                 sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
> > > > +       }
> > > >
> > > >         abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
> > > >         sp->done(sp, QLA_OS_TIMER_EXPIRED);
> > > > @@ -140,11 +148,11 @@ static void qla24xx_abort_sp_done(srb_t *sp, int
> > > res)
> > > >         if (orig_sp)
> > > >                 qla_wait_nvme_release_cmd_kref(orig_sp);
> > > >
> > > > -       del_timer(&sp->u.iocb_cmd.timer);
> > > >         if (sp->flags & SRB_WAKEUP_ON_COMP)
> > > >                 complete(&abt->u.abt.comp);
> > > >         else
> > > > -               sp->free(sp);
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
> > > > @@ -154,6 +162,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> > > wait)
> > > >         srb_t *sp;
> > > >         int rval = QLA_FUNCTION_FAILED;
> > > >
> > > > +       /* ref: INIT for ABTS command */
> > > >         sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp-
> > > >fcport,
> > > >                                   GFP_ATOMIC);
> > > >         if (!sp)
> > > > @@ -181,7 +190,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> > > wait)
> > > >
> > > >         rval = qla2x00_start_sp(sp);
> > > >         if (rval != QLA_SUCCESS) {
> > > > -               sp->free(sp);
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                 return rval;
> > > >         }
> > > >
> > > > @@ -189,7 +199,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool
> > > wait)
> > > >                 wait_for_completion(&abt_iocb->u.abt.comp);
> > > >                 rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
> > > >                         QLA_SUCCESS : QLA_ERR_FROM_FW;
> > > > -               sp->free(sp);
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         }
> > > >
> > > >         return rval;
> > > > @@ -287,7 +298,8 @@ static void qla2x00_async_login_sp_done(srb_t *sp,
> > > int res)
> > > >                 qla24xx_handle_plogi_done_event(vha, &ea);
> > > >         }
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int
> > > > @@ -306,6 +318,7 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> > > fc_port_t *fcport,
> > > >                 return rval;
> > > >         }
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -354,7 +367,8 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> > > fc_port_t *fcport,
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > > >  done:
> > > >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > > > @@ -366,7 +380,8 @@ static void qla2x00_async_logout_sp_done(srb_t
> > *sp,
> > > int res)
> > > >         sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > > >         sp->fcport->login_gen++;
> > > >         qlt_logo_completion_handler(sp->fcport, sp-
> > > >u.iocb_cmd.u.logio.data[0]);
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int
> > > > @@ -376,6 +391,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha,
> > > fc_port_t *fcport)
> > > >         int rval = QLA_FUNCTION_FAILED;
> > > >
> > > >         fcport->flags |= FCF_ASYNC_SENT;
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -397,7 +413,8 @@ qla2x00_async_logout(struct scsi_qla_host *vha,
> > > fc_port_t *fcport)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > > >         return rval;
> > > > @@ -423,7 +440,8 @@ static void qla2x00_async_prlo_sp_done(srb_t *sp,
> > > int res)
> > > >         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);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int
> > > > @@ -433,6 +451,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha,
> > > fc_port_t *fcport)
> > > >         int rval;
> > > >
> > > >         rval = QLA_FUNCTION_FAILED;
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -454,7 +473,8 @@ qla2x00_async_prlo(struct scsi_qla_host *vha,
> > > fc_port_t *fcport)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > > >         return rval;
> > > > @@ -539,8 +559,8 @@ static void qla2x00_async_adisc_sp_done(srb_t
> > *sp,
> > > int res)
> > > >         ea.sp = sp;
> > > >
> > > >         qla24xx_handle_adisc_event(vha, &ea);
> > > > -
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int
> > > > @@ -555,6 +575,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha,
> > > fc_port_t *fcport,
> > > >                 return rval;
> > > >
> > > >         fcport->flags |= FCF_ASYNC_SENT;
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -582,7 +603,8 @@ qla2x00_async_adisc(struct scsi_qla_host *vha,
> > > fc_port_t *fcport,
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > > >         qla2x00_post_async_adisc_work(vha, fcport, data);
> > > > @@ -1063,7 +1085,8 @@ static void qla24xx_async_gnl_sp_done(srb_t
> > *sp,
> > > int res)
> > > >         }
> > > >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
> > > > @@ -1093,6 +1116,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha,
> > > fc_port_t *fcport)
> > > >         vha->gnl.sent = 1;
> > > >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -1125,7 +1149,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha,
> > > fc_port_t *fcport)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
> > > >         return rval;
> > > > @@ -1171,7 +1196,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t
> > > *sp, int res)
> > > >         dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
> > > >                 sp->u.iocb_cmd.u.mbx.in_dma);
> > > >
> > > > -       sp->free(sp);
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
> > > > @@ -1216,7 +1241,7 @@ static void qla2x00_async_prli_sp_done(srb_t
> > *sp,
> > > int res)
> > > >                 qla24xx_handle_prli_done_event(vha, &ea);
> > > >         }
> > > >
> > > > -       sp->free(sp);
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int
> > > > @@ -1274,7 +1299,8 @@ qla24xx_async_prli(struct scsi_qla_host *vha,
> > > fc_port_t *fcport)
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > > >         return rval;
> > > >  }
> > > > @@ -1359,7 +1385,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host
> > *vha,
> > > fc_port_t *fcport, u8 opt)
> > > >         if (pd)
> > > >                 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
> > > >
> > > > -       sp->free(sp);
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > > >  done:
> > > >         fcport->flags &= ~FCF_ASYNC_ACTIVE;
> > > > @@ -1945,6 +1971,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
> > > uint32_t flags, uint32_t lun,
> > > >         srb_t *sp;
> > > >         int rval = QLA_FUNCTION_FAILED;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -1988,7 +2015,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
> > > uint32_t flags, uint32_t lun,
> > > >         }
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > > >  done:
> > > >         return rval;
> > > > diff --git a/drivers/scsi/qla2xxx/qla_inline.h
> > > b/drivers/scsi/qla2xxx/qla_inline.h
> > > > index 5f3b7995cc8f..db17f7f410cd 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_inline.h
> > > > +++ b/drivers/scsi/qla2xxx/qla_inline.h
> > > > @@ -184,6 +184,8 @@ static void qla2xxx_init_sp(srb_t *sp,
> > scsi_qla_host_t
> > > *vha,
> > > >         sp->vha = vha;
> > > >         sp->qpair = qpair;
> > > >         sp->cmd_type = TYPE_SRB;
> > > > +       /* ref : INIT - normal flow */
> > > > +       kref_init(&sp->cmd_kref);
> > > >         INIT_LIST_HEAD(&sp->elem);
> > > >  }
> > > >
> > > > diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> > > > index 95aae9a9631e..7dd82214d59f 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_iocb.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> > > > @@ -2560,6 +2560,14 @@ qla24xx_tm_iocb(srb_t *sp, struct
> > > tsk_mgmt_entry *tsk)
> > > >         }
> > > >  }
> > > >
> > > > +void
> > > > +qla2x00_sp_release(struct kref *kref)
> > > > +{
> > > > +       struct srb *sp = container_of(kref, struct srb, cmd_kref);
> > > > +
> > > > +       sp->free(sp);
> > > > +}
> > > > +
> > > >  void
> > > >  qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
> > > >                      void (*done)(struct srb *sp, int res))
> > > > @@ -2655,7 +2663,9 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > > els_opcode,
> > > >                return -ENOMEM;
> > > >         }
> > > >
> > > > -       /* Alloc SRB structure */
> > > > +       /* Alloc SRB structure
> > > > +        * ref: INIT
> > > > +        */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp) {
> > > >                 kfree(fcport);
> > > > @@ -2687,7 +2697,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > > els_opcode,
> > > >                             GFP_KERNEL);
> > > >
> > > >         if (!elsio->u.els_logo.els_logo_pyld) {
> > > > -               sp->free(sp);
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                 return QLA_FUNCTION_FAILED;
> > > >         }
> > > >
> > > > @@ -2710,7 +2721,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > > els_opcode,
> > > >
> > > >         rval = qla2x00_start_sp(sp);
> > > >         if (rval != QLA_SUCCESS) {
> > > > -               sp->free(sp);
> > > > +               /* ref: INIT */
> > > > +               kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                 return QLA_FUNCTION_FAILED;
> > > >         }
> > > >
> > > > @@ -2721,7 +2733,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int
> > > els_opcode,
> > > >
> > > >         wait_for_completion(&elsio->u.els_logo.comp);
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         return rval;
> > > >  }
> > > >
> > > > @@ -2854,7 +2867,6 @@ static void qla2x00_els_dcmd2_sp_done(srb_t
> > *sp,
> > > int res)
> > > >             sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
> > > >
> > > >         fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
> > > > -       del_timer(&sp->u.iocb_cmd.timer);
> > > >
> > > >         if (sp->flags & SRB_WAKEUP_ON_COMP)
> > > >                 complete(&lio->u.els_plogi.comp);
> > > > @@ -2964,7 +2976,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t
> > *sp,
> > > int res)
> > > >                         struct srb_iocb *elsio = &sp->u.iocb_cmd;
> > > >
> > > >                         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> > > > -                       sp->free(sp);
> > > > +                       /* ref: INIT */
> > > > +                       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >                         return;
> > > >                 }
> > > >                 e->u.iosb.sp = sp;
> > > > @@ -2982,7 +2995,9 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha,
> > int
> > > els_opcode,
> > > >         int rval = QLA_SUCCESS;
> > > >         void    *ptr, *resp_ptr;
> > > >
> > > > -       /* Alloc SRB structure */
> > > > +       /* Alloc SRB structure
> > > > +        * ref: INIT
> > > > +        */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp) {
> > > >                 ql_log(ql_log_info, vha, 0x70e6,
> > > > @@ -3071,7 +3086,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha,
> > int
> > > els_opcode,
> > > >  out:
> > > >         fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> > > >         qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > @@ -3882,8 +3898,15 @@ qla2x00_start_sp(srb_t *sp)
> > > >                 break;
> > > >         }
> > > >
> > > > -       if (sp->start_timer)
> > > > +       if (sp->start_timer) {
> > > > +               /* ref: TMR timer ref
> > > > +                * this code should be just before start_iocbs function
> > > > +                * This will make sure that caller function don't to do
> > > > +                * kref_put even on failure
> > > > +                */
> > > > +               kref_get(&sp->cmd_kref);
> > > >                 add_timer(&sp->u.iocb_cmd.timer);
> > > > +       }
> > > >
> > > >         wmb();
> > > >         qla2x00_start_iocbs(vha, qp->req);
> > > > diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> > > > index 2aacd3653245..38e0f02c75e1 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_mbx.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> > > > @@ -6479,6 +6479,7 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host
> > > *vha, mbx_cmd_t *mcp)
> > > >         if (!vha->hw->flags.fw_started)
> > > >                 goto done;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -6524,7 +6525,8 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host
> > > *vha, mbx_cmd_t *mcp)
> > > >         }
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
> > > > index c4a967c96fd6..e6b5c4ccce97 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_mid.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_mid.c
> > > > @@ -965,6 +965,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int
> > > cmd)
> > > >         if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
> > > >                 return QLA_PARAMETER_ERROR;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 return rval;
> > > > @@ -1007,6 +1008,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int
> > > cmd)
> > > >                 break;
> > > >         }
> > > >  done:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         return rval;
> > > >  }
> > > > diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
> > > > index e3ae0894c7a8..f726eb8449c5 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_mr.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_mr.c
> > > > @@ -1787,6 +1787,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t
> > > *fcport, uint16_t fx_type)
> > > >         struct register_host_info *preg_hsi;
> > > >         struct new_utsname *p_sysid = NULL;
> > > >
> > > > +       /* ref: INIT */
> > > >         sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
> > > >         if (!sp)
> > > >                 goto done;
> > > > @@ -1973,7 +1974,8 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t
> > > *fcport, uint16_t fx_type)
> > > >                 dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
> > > >                     fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         return rval;
> > > >  }
> > > > diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> > > > index abcd30917263..0a7b00d165c7 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_os.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_os.c
> > > > @@ -728,7 +728,8 @@ void qla2x00_sp_compl(srb_t *sp, int res)
> > > >         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
> > > >         struct completion *comp = sp->comp;
> > > >
> > > > -       sp->free(sp);
> > > > +       /* kref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         cmd->result = res;
> > > >         CMD_SP(cmd) = NULL;
> > > >         scsi_done(cmd);
> > > > @@ -819,7 +820,8 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
> > > >         struct scsi_cmnd *cmd = GET_CMD_SP(sp);
> > > >         struct completion *comp = sp->comp;
> > > >
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >         cmd->result = res;
> > > >         CMD_SP(cmd) = NULL;
> > > >         scsi_done(cmd);
> > > > @@ -919,6 +921,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host,
> > > struct scsi_cmnd *cmd)
> > > >                 goto qc24_target_busy;
> > > >
> > > >         sp = scsi_cmd_priv(cmd);
> > > > +       /* ref: INIT */
> > > >         qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
> > > >
> > > >         sp->u.scmd.cmd = cmd;
> > > > @@ -938,7 +941,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host,
> > > struct scsi_cmnd *cmd)
> > > >         return 0;
> > > >
> > > >  qc24_host_busy_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >
> > > >  qc24_target_busy:
> > > >         return SCSI_MLQUEUE_TARGET_BUSY;
> > > > @@ -1008,6 +1012,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host
> > *host,
> > > struct scsi_cmnd *cmd,
> > > >                 goto qc24_target_busy;
> > > >
> > > >         sp = scsi_cmd_priv(cmd);
> > > > +       /* ref: INIT */
> > > >         qla2xxx_init_sp(sp, vha, qpair, fcport);
> > > >
> > > >         sp->u.scmd.cmd = cmd;
> > > > @@ -1026,7 +1031,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host
> > *host,
> > > struct scsi_cmnd *cmd,
> > > >         return 0;
> > > >
> > > >  qc24_host_busy_free_sp:
> > > > -       sp->free(sp);
> > > > +       /* ref: INIT */
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >
> > > >  qc24_target_busy:
> > > >         return SCSI_MLQUEUE_TARGET_BUSY;
> > > > diff --git a/drivers/scsi/qla2xxx/qla_target.c
> > > b/drivers/scsi/qla2xxx/qla_target.c
> > > > index 83c8c55017d1..b0990f2ee91c 100644
> > > > --- a/drivers/scsi/qla2xxx/qla_target.c
> > > > +++ b/drivers/scsi/qla2xxx/qla_target.c
> > > > @@ -620,7 +620,7 @@ static void qla2x00_async_nack_sp_done(srb_t *sp,
> > > int res)
> > > >         }
> > > >         spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > > >
> > > > -       sp->free(sp);
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  }
> > > >
> > > >  int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
> > > > @@ -672,7 +672,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha,
> > > fc_port_t *fcport,
> > > >         return rval;
> > > >
> > > >  done_free_sp:
> > > > -       sp->free(sp);
> > > > +       kref_put(&sp->cmd_kref, qla2x00_sp_release);
> > > >  done:
> > > >         fcport->flags &= ~FCF_ASYNC_SENT;
> > > >         return rval;
> > > > --
> > > > 2.23.1
> > > >
>


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

end of thread, other threads:[~2022-02-09 20:10 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-10  5:02 [PATCH v2 00/17] qla2xxx misc bug fixes and features Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 01/17] qla2xxx: Refactor asynchronous command initialization Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 02/17] qla2xxx: Implement ref count for srb Nilesh Javali
2022-02-03 14:44   ` Ewan Milne
2022-02-04  7:16     ` Saurav Kashyap
2022-02-08 10:59       ` Saurav Kashyap
2022-02-09 20:09         ` Ewan Milne
2022-01-10  5:02 ` [PATCH v2 03/17] qla2xxx: fix stuck session in gpdb Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 04/17] qla2xxx: Fix warning message due to adisc is being flush Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 05/17] qla2xxx: Fix premature hw access after pci error Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 06/17] qla2xxx: Fix scheduling while atomic Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 07/17] qla2xxx: add retry for exec fw Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 08/17] qla2xxx: Show wrong FDMI data for 64G adaptor Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 09/17] qla2xxx: Add ql2xnvme_queues module param to configure number of NVME queues Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 10/17] qla2xxx: Fix device reconnect in loop topology Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 11/17] qla2xxx: fix warning for missing error code Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 12/17] qla2xxx: edif: Fix clang warning Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 13/17] qla2xxx: Fix T10 PI tag escape and IP guard options for 28XX adapters Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 14/17] qla2xxx: Suppress a kernel complaint in qla_create_qpair() Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 15/17] qla2xxx: Add devid's and conditionals for 28xx Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 16/17] qla2xxx: check for firmware dump already collected Nilesh Javali
2022-01-10  5:02 ` [PATCH v2 17/17] qla2xxx: Update version to 10.02.07.300-k Nilesh Javali
2022-01-25  5:00 ` [PATCH v2 00/17] qla2xxx misc bug fixes and features Martin K. Petersen
2022-02-01  2:04 ` Martin K. Petersen

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.