For each SRB type, make the free function free all memory associated
with the SRB. Initialize the .free() function pointer after the
qla2x00_init_timer() call and before the first sp->free(sp) call to
make sure that all sp->free(sp) calls call the right .free() function.
Remove the qla24xx_sp_unmap() function because it is no longer
necessary.

This patch fixes a memory leak in the timeout handling code in
qla24xx_async_gpdb_sp_done().

Cc: Himanshu Madhani <hmadh...@marvell.com>
Cc: Giridhar Malavali <gmalav...@marvell.com>
Signed-off-by: Bart Van Assche <bvanass...@acm.org>
---
 drivers/scsi/qla2xxx/qla_def.h  |   2 +-
 drivers/scsi/qla2xxx/qla_gbl.h  |   1 -
 drivers/scsi/qla2xxx/qla_gs.c   | 209 ++++++++++++++------------------
 drivers/scsi/qla2xxx/qla_init.c |  24 ++--
 drivers/scsi/qla2xxx/qla_iocb.c |  48 ++++----
 drivers/scsi/qla2xxx/qla_nvme.c |  18 ++-
 drivers/scsi/qla2xxx/qla_os.c   |   4 +-
 7 files changed, 142 insertions(+), 164 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 78c5405482f6..3f398475d658 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -395,7 +395,7 @@ struct srb_iocb {
                        struct els_logo_payload *els_logo_pyld;
                        dma_addr_t els_logo_pyld_dma;
                } els_logo;
-               struct {
+               struct els_plogi {
 #define ELS_DCMD_PLOGI 0x3
                        uint32_t flags;
                        uint32_t els_cmd;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index aaa78f1020a7..b3affe8ddf29 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -676,7 +676,6 @@ int qla24xx_post_gnnid_work(struct scsi_qla_host *, 
fc_port_t *);
 int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
 void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
-void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);
 void qla_scan_work_fn(struct work_struct *);
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 013d64d2be10..863f98ac6a30 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -509,6 +509,28 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
        return (rval);
 }
 
+static void qla2x00_async_sns_sp_free(srb_t *sp)
+{
+       struct scsi_qla_host *vha = sp->vha;
+       struct ct_arg *ctarg = &sp->u.iocb_cmd.u.ctarg;
+
+       if (&ctarg->rsp) {
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 ctarg->rsp_allocated_size, ctarg->rsp,
+                                 ctarg->rsp_dma);
+               ctarg->rsp = NULL;
+       }
+
+       if (&ctarg->req) {
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 ctarg->req_allocated_size, ctarg->req,
+                                 ctarg->req_dma);
+               ctarg->req = NULL;
+       }
+
+       qla2x00_sp_free(sp);
+}
+
 static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
 {
        struct scsi_qla_host *vha = sp->vha;
@@ -549,24 +571,7 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
 err2:
        if (!e) {
                /* please ignore kernel warning. otherwise, we have mem leak. */
-               if (sp->u.iocb_cmd.u.ctarg.req) {
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                           sp->u.iocb_cmd.u.ctarg.req_allocated_size,
-                           sp->u.iocb_cmd.u.ctarg.req,
-                           sp->u.iocb_cmd.u.ctarg.req_dma);
-                       sp->u.iocb_cmd.u.ctarg.req = NULL;
-               }
-
-               if (sp->u.iocb_cmd.u.ctarg.rsp) {
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                           sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
-                           sp->u.iocb_cmd.u.ctarg.rsp,
-                           sp->u.iocb_cmd.u.ctarg.rsp_dma);
-                       sp->u.iocb_cmd.u.ctarg.rsp = NULL;
-               }
-
                sp->free(sp);
-
                return;
        }
 
@@ -608,6 +613,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);
+       sp->free = qla2x00_async_sns_sp_free;
+       sp->done = 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,
@@ -650,7 +657,6 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t 
*d_id)
        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",
@@ -706,6 +712,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);
+       sp->free = qla2x00_async_sns_sp_free;
+       sp->done = 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,
@@ -746,7 +754,6 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t 
*d_id,
        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",
@@ -799,6 +806,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);
+       sp->free = qla2x00_async_sns_sp_free;
+       sp->done = 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,
@@ -839,7 +848,6 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t 
*d_id,
        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",
@@ -909,6 +917,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);
+       sp->free = qla2x00_async_sns_sp_free;
+       sp->done = 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,
@@ -953,7 +963,6 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
        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",
@@ -3136,47 +3145,6 @@ int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, 
port_id_t *id)
        return qla2x00_post_work(vha, e);
 }
 
-void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
-{
-       struct srb_iocb *c = &sp->u.iocb_cmd;
-
-       switch (sp->type) {
-       case SRB_ELS_DCMD:
-               if (c->u.els_plogi.els_plogi_pyld)
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                           c->u.els_plogi.tx_size,
-                           c->u.els_plogi.els_plogi_pyld,
-                           c->u.els_plogi.els_plogi_pyld_dma);
-
-               if (c->u.els_plogi.els_resp_pyld)
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                           c->u.els_plogi.rx_size,
-                           c->u.els_plogi.els_resp_pyld,
-                           c->u.els_plogi.els_resp_pyld_dma);
-               break;
-       case SRB_CT_PTHRU_CMD:
-       default:
-               if (sp->u.iocb_cmd.u.ctarg.req) {
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                           sp->u.iocb_cmd.u.ctarg.req_allocated_size,
-                           sp->u.iocb_cmd.u.ctarg.req,
-                           sp->u.iocb_cmd.u.ctarg.req_dma);
-                       sp->u.iocb_cmd.u.ctarg.req = NULL;
-               }
-
-               if (sp->u.iocb_cmd.u.ctarg.rsp) {
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                           sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
-                           sp->u.iocb_cmd.u.ctarg.rsp,
-                           sp->u.iocb_cmd.u.ctarg.rsp_dma);
-                       sp->u.iocb_cmd.u.ctarg.rsp = NULL;
-               }
-               break;
-       }
-
-       sp->free(sp);
-}
-
 void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
        fc_port_t *fcport, *conflict, *t;
@@ -3278,6 +3246,33 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
        }
 }
 
+static void qla2x00_async_gpnid_sp_free(srb_t *sp)
+{
+       struct scsi_qla_host *vha = sp->vha;
+       struct ct_arg *ctarg = &sp->u.iocb_cmd.u.ctarg;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vha->hw->vport_slock, flags);
+       list_del_init(&sp->elem);
+       spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
+
+       if (ctarg->rsp) {
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 ctarg->rsp_allocated_size, ctarg->rsp,
+                                 ctarg->rsp_dma);
+               ctarg->rsp = NULL;
+       }
+
+       if (ctarg->req) {
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 ctarg->req_allocated_size, ctarg->req,
+                                 ctarg->req_dma);
+               ctarg->req = NULL;
+       }
+
+       qla2x00_sp_free(sp);
+}
+
 static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
 {
        struct scsi_qla_host *vha = sp->vha;
@@ -3310,7 +3305,7 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int 
res)
        ea.event = FCME_GPNID_DONE;
 
        spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
-       list_del(&sp->elem);
+       list_del_init(&sp->elem);
        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
        if (res) {
@@ -3331,21 +3326,6 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int 
res)
        e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
        if (!e) {
                /* please ignore kernel warning. otherwise, we have mem leak. */
-               if (sp->u.iocb_cmd.u.ctarg.req) {
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                               sp->u.iocb_cmd.u.ctarg.req_allocated_size,
-                               sp->u.iocb_cmd.u.ctarg.req,
-                               sp->u.iocb_cmd.u.ctarg.req_dma);
-                       sp->u.iocb_cmd.u.ctarg.req = NULL;
-               }
-               if (sp->u.iocb_cmd.u.ctarg.rsp) {
-                       dma_free_coherent(&vha->hw->pdev->dev,
-                               sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
-                               sp->u.iocb_cmd.u.ctarg.rsp,
-                               sp->u.iocb_cmd.u.ctarg.rsp_dma);
-                       sp->u.iocb_cmd.u.ctarg.rsp = NULL;
-               }
-
                sp->free(sp);
                return;
        }
@@ -3375,6 +3355,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t 
*id)
        sp->u.iocb_cmd.u.ctarg.id = *id;
        sp->gen1 = 0;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+       sp->free = qla2x00_async_gpnid_sp_free;
+       sp->done = qla2x00_async_gpnid_sp_done;
 
        spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
        list_for_each_entry(tsp, &vha->gpnid_list, elem) {
@@ -3425,7 +3407,6 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t 
*id)
        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,
@@ -3438,25 +3419,6 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t 
*id)
        return rval;
 
 done_free_sp:
-       spin_lock_irqsave(&vha->hw->vport_slock, flags);
-       list_del(&sp->elem);
-       spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
-
-       if (sp->u.iocb_cmd.u.ctarg.req) {
-               dma_free_coherent(&vha->hw->pdev->dev,
-                       sizeof(struct ct_sns_pkt),
-                       sp->u.iocb_cmd.u.ctarg.req,
-                       sp->u.iocb_cmd.u.ctarg.req_dma);
-               sp->u.iocb_cmd.u.ctarg.req = NULL;
-       }
-       if (sp->u.iocb_cmd.u.ctarg.rsp) {
-               dma_free_coherent(&vha->hw->pdev->dev,
-                       sizeof(struct ct_sns_pkt),
-                       sp->u.iocb_cmd.u.ctarg.rsp,
-                       sp->u.iocb_cmd.u.ctarg.rsp_dma);
-               sp->u.iocb_cmd.u.ctarg.rsp = NULL;
-       }
-
        sp->free(sp);
 done:
        return rval;
@@ -3747,7 +3709,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t 
*sp)
 
        recheck = 1;
 out:
-       qla24xx_sp_unmap(vha, sp);
+       sp->free(sp);
        spin_lock_irqsave(&vha->work_lock, flags);
        vha->scan.scan_flags &= ~SF_SCANNING;
        spin_unlock_irqrestore(&vha->work_lock, flags);
@@ -3894,6 +3856,26 @@ static void qla2x00_find_free_fcp_nvme_slot(struct 
scsi_qla_host *vha,
        }
 }
 
+static void qla2x00_async_gpnft_gnnft_sp_free(srb_t *sp)
+{
+       struct scsi_qla_host *vha = sp->vha;
+       struct ct_arg *ctarg = &sp->u.iocb_cmd.u.ctarg;
+
+       if (ctarg->rsp) {
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 ctarg->rsp_allocated_size, ctarg->rsp,
+                                 ctarg->rsp_dma);
+               ctarg->rsp = NULL;
+       }
+       if (ctarg->req) {
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 ctarg->req_allocated_size, ctarg->req,
+                                 ctarg->req_dma);
+               ctarg->req = NULL;
+       }
+       qla2x00_sp_free(sp);
+}
+
 static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
 {
        struct scsi_qla_host *vha = sp->vha;
@@ -3924,7 +3906,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, 
int res)
                    QLA_EVT_GNNFT_DONE);
                if (rc) {
                        /* Cleanup here to prevent memory leak */
-                       qla24xx_sp_unmap(vha, sp);
+                       sp->free(sp);
 
                        spin_lock_irqsave(&vha->work_lock, flags);
                        vha->scan.scan_flags &= ~SF_SCANNING;
@@ -3955,7 +3937,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, 
int res)
                sp->rc = res;
                rc = qla2x00_post_nvme_gpnft_work(vha, sp, QLA_EVT_GPNFT);
                if (rc) {
-                       qla24xx_sp_unmap(vha, sp);
+                       sp->free(sp);
                        set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
                        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                }
@@ -3971,7 +3953,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, 
int res)
        }
 
        if (rc) {
-               qla24xx_sp_unmap(vha, sp);
+               sp->free(sp);
                set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
                set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                return;
@@ -4025,6 +4007,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, 
struct srb *sp,
 
        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+       sp->free = qla2x00_async_gpnft_gnnft_sp_free;
+       sp->done = 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);
@@ -4040,8 +4024,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,21 +4039,6 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, 
struct srb *sp,
        return rval;
 
 done_free_sp:
-       if (sp->u.iocb_cmd.u.ctarg.req) {
-               dma_free_coherent(&vha->hw->pdev->dev,
-                   sp->u.iocb_cmd.u.ctarg.req_allocated_size,
-                   sp->u.iocb_cmd.u.ctarg.req,
-                   sp->u.iocb_cmd.u.ctarg.req_dma);
-               sp->u.iocb_cmd.u.ctarg.req = NULL;
-       }
-       if (sp->u.iocb_cmd.u.ctarg.rsp) {
-               dma_free_coherent(&vha->hw->pdev->dev,
-                   sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
-                   sp->u.iocb_cmd.u.ctarg.rsp,
-                   sp->u.iocb_cmd.u.ctarg.rsp_dma);
-               sp->u.iocb_cmd.u.ctarg.rsp = NULL;
-       }
-
        sp->free(sp);
 
        return rval;
@@ -4181,6 +4148,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 
fc4_type, srb_t *sp)
 
        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+       sp->free = qla2x00_async_gpnft_gnnft_sp_free;
+       sp->done = 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);
@@ -4195,8 +4164,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);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index fc46343f3363..3439cbb3c952 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1093,10 +1093,20 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, 
fc_port_t *fcport)
        return qla2x00_post_work(vha, e);
 }
 
-static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res)
+static void qla24xx_async_gpdb_sp_free(srb_t *sp)
 {
        struct scsi_qla_host *vha = sp->vha;
        struct qla_hw_data *ha = vha->hw;
+
+       if (sp->u.iocb_cmd.u.mbx.in)
+               dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
+                             sp->u.iocb_cmd.u.mbx.in_dma);
+       qla2x00_sp_free(sp);
+}
+
+static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res)
+{
+       struct scsi_qla_host *vha = sp->vha;
        fc_port_t *fcport = sp->fcport;
        u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
        struct event_arg ea;
@@ -1105,11 +1115,8 @@ static void qla24xx_async_gpdb_sp_done(srb_t *sp, int 
res)
            "Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
            sp->name, res, fcport->port_name, mb[1], mb[2]);
 
-       if (res == QLA_FUNCTION_TIMEOUT) {
-               dma_pool_free(sp->vha->hw->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
-                       sp->u.iocb_cmd.u.mbx.in_dma);
-               return;
-       }
+       if (res == QLA_FUNCTION_TIMEOUT)
+               goto free_sp;
 
        fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
        memset(&ea, 0, sizeof(ea));
@@ -1119,9 +1126,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res)
 
        qla2x00_fcport_event_handler(vha, &ea);
 
-       dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
-               sp->u.iocb_cmd.u.mbx.in_dma);
-
+free_sp:
        sp->free(sp);
 }
 
@@ -1283,6 +1288,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, 
fc_port_t *fcport, u8 opt)
        mbx->u.mbx.in = (void *)pd;
        mbx->u.mbx.in_dma = pd_dma;
 
+       sp->free = qla24xx_async_gpdb_sp_free;
        sp->done = qla24xx_async_gpdb_sp_done;
 
        ql_dbg(ql_dbg_disc, vha, 0x20dc,
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 77f3ea4c8a80..42dbe11fbb14 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2751,6 +2751,27 @@ qla2x00_els_dcmd2_iocb_timeout(void *data)
        sp->done(sp, QLA_FUNCTION_TIMEOUT);
 }
 
+static void qla2x00_els_dcmd2_sp_free(srb_t *sp)
+{
+       struct scsi_qla_host *vha = sp->vha;
+       struct srb_iocb *elsio = &sp->u.iocb_cmd;
+       struct els_plogi *els_plogi = &elsio->u.els_plogi;
+
+       if (els_plogi->els_plogi_pyld)
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 els_plogi->tx_size,
+                                 els_plogi->els_plogi_pyld,
+                                 els_plogi->els_plogi_pyld_dma);
+
+       if (els_plogi->els_resp_pyld)
+               dma_free_coherent(&vha->hw->pdev->dev,
+                                 els_plogi->rx_size,
+                                 els_plogi->els_resp_pyld,
+                                 els_plogi->els_resp_pyld_dma);
+
+       qla2x00_sp_free(sp);
+}
+
 static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
 {
        fc_port_t *fcport = sp->fcport;
@@ -2781,19 +2802,6 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
 
                e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
                if (!e) {
-                       struct srb_iocb *elsio = &sp->u.iocb_cmd;
-
-                       if (elsio->u.els_plogi.els_plogi_pyld)
-                               dma_free_coherent(&sp->vha->hw->pdev->dev,
-                                   elsio->u.els_plogi.tx_size,
-                                   elsio->u.els_plogi.els_plogi_pyld,
-                                   elsio->u.els_plogi.els_plogi_pyld_dma);
-
-                       if (elsio->u.els_plogi.els_resp_pyld)
-                               dma_free_coherent(&sp->vha->hw->pdev->dev,
-                                   elsio->u.els_plogi.rx_size,
-                                   elsio->u.els_plogi.els_resp_pyld,
-                                   elsio->u.els_plogi.els_resp_pyld_dma);
                        sp->free(sp);
                        return;
                }
@@ -2835,7 +2843,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int 
els_opcode,
                sp->flags = SRB_WAKEUP_ON_COMP;
 
        qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT + 2);
-
+       sp->free = qla2x00_els_dcmd2_sp_free;
        sp->done = qla2x00_els_dcmd2_sp_done;
        elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE;
 
@@ -2893,18 +2901,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int 
els_opcode,
 
 out:
        fcport->flags &= ~(FCF_ASYNC_SENT);
-       if (elsio->u.els_plogi.els_plogi_pyld)
-               dma_free_coherent(&sp->vha->hw->pdev->dev,
-                   elsio->u.els_plogi.tx_size,
-                   elsio->u.els_plogi.els_plogi_pyld,
-                   elsio->u.els_plogi.els_plogi_pyld_dma);
-
-       if (elsio->u.els_plogi.els_resp_pyld)
-               dma_free_coherent(&sp->vha->hw->pdev->dev,
-                   elsio->u.els_plogi.rx_size,
-                   elsio->u.els_plogi.els_resp_pyld,
-                   elsio->u.els_plogi.els_resp_pyld_dma);
-
        sp->free(sp);
 done:
        return rval;
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index fc0c57ecab25..07f83d161304 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -124,6 +124,11 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port 
*lport,
        return 0;
 }
 
+static void qla_nvme_sp_ls_free(srb_t *sp)
+{
+       qla2x00_rel_sp(sp);
+}
+
 static void qla_nvme_sp_ls_done(srb_t *sp, int res)
 {
        struct srb_iocb *nvme;
@@ -144,7 +149,12 @@ static void qla_nvme_sp_ls_done(srb_t *sp, int res)
        priv->comp_status = res;
        schedule_work(&priv->ls_work);
        /* work schedule doesn't need the sp */
-       qla2x00_rel_sp(sp);
+       sp->free(sp);
+}
+
+static void qla_nvme_sp_free(srb_t *sp)
+{
+       qla2xxx_rel_qpair_sp(sp->qpair, sp);
 }
 
 static void qla_nvme_sp_done(srb_t *sp, int res)
@@ -168,9 +178,7 @@ static void qla_nvme_sp_done(srb_t *sp, int res)
        }
        fd->status = 0;
        fd->done(fd);
-       qla2xxx_rel_qpair_sp(sp->qpair, sp);
-
-       return;
+       sp->free(sp);
 }
 
 static void qla_nvme_abort_work(struct work_struct *work)
@@ -247,6 +255,7 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
 
        sp->type = SRB_NVME_LS;
        sp->name = "nvme_ls";
+       sp->free = qla_nvme_sp_ls_free;
        sp->done = qla_nvme_sp_ls_done;
        nvme = &sp->u.iocb_cmd;
        priv->sp = sp;
@@ -508,6 +517,7 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port 
*lport,
        priv->sp = sp;
        sp->type = SRB_NVME_CMD;
        sp->name = "nvme_cmd";
+       sp->free = qla_nvme_sp_free;
        sp->done = qla_nvme_sp_done;
        sp->qpair = qpair;
        sp->vha = vha;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7b9f138ad9e4..619ab9b84b08 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5177,7 +5177,7 @@ static void qla_sp_retry(struct scsi_qla_host *vha, 
struct qla_work_evt *e)
                ql_dbg(ql_dbg_disc, vha, 0x2043,
                    "%s: %s: Re-issue IOCB failed (%d).\n",
                    __func__, sp->name, rval);
-               qla24xx_sp_unmap(vha, sp);
+               sp->free(sp);
        }
 }
 
@@ -5228,7 +5228,7 @@ qla2x00_do_work(struct scsi_qla_host *vha)
                        qla24xx_async_gpnid(vha, &e->u.gpnid.id);
                        break;
                case QLA_EVT_UNMAP:
-                       qla24xx_sp_unmap(vha, e->u.iosb.sp);
+                       e->u.iosb.sp->free(e->u.iosb.sp);
                        break;
                case QLA_EVT_RELOGIN:
                        qla2x00_relogin(vha);
-- 
2.22.0.rc3

Reply via email to