int lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *, struct lpfcMboxq *);
 void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
-
+int lpfc_mbox_rsrc_prep(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox);
+void lpfc_mbox_rsrc_cleanup(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
+                           enum lpfc_mbox_ctx locked);
 void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
 void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
 
 {
        struct lpfc_hba  *phba = vport->phba;
        LPFC_MBOXQ_t *mbox;
-       struct lpfc_dmabuf *mp;
        struct lpfc_nodelist *ndlp;
        struct serv_parm *sp;
        int rc;
        mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
        if (!mbox->ctx_ndlp) {
                err = 6;
-               goto fail_no_ndlp;
+               goto fail_free_mbox;
        }
 
        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
         * for the failed mbox command.
         */
        lpfc_nlp_put(ndlp);
-fail_no_ndlp:
-       mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
 fail_free_mbox:
-       mempool_free(mbox, phba->mbox_mem_pool);
-
+       lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
 fail:
        lpfc_vport_set_state(vport, FC_VPORT_FAILED);
        lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
 
        /* Supply CSP's only if we are fabric connect or pt-to-pt connect */
        if ((vport->fc_flag & FC_FABRIC) || (vport->fc_flag & FC_PT2PT)) {
-               dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-               if (!dmabuf) {
-                       rc = -ENOMEM;
-                       goto fail;
-               }
-               dmabuf->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &dmabuf->phys);
-               if (!dmabuf->virt) {
+               rc = lpfc_mbox_rsrc_prep(phba, mboxq);
+               if (rc) {
                        rc = -ENOMEM;
-                       goto fail;
+                       goto fail_mbox;
                }
+               dmabuf = mboxq->ctx_buf;
                memcpy(dmabuf->virt, &phba->fc_fabparam,
                       sizeof(struct serv_parm));
        }
 
        vport->port_state = LPFC_FABRIC_CFG_LINK;
-       if (dmabuf)
+       if (dmabuf) {
                lpfc_reg_vfi(mboxq, vport, dmabuf->phys);
-       else
+               /* lpfc_reg_vfi memsets the mailbox.  Restore the ctx_buf. */
+               mboxq->ctx_buf = dmabuf;
+       } else {
                lpfc_reg_vfi(mboxq, vport, 0);
+       }
 
        mboxq->mbox_cmpl = lpfc_mbx_cmpl_reg_vfi;
        mboxq->vport = vport;
-       mboxq->ctx_buf = dmabuf;
        rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
        if (rc == MBX_NOT_FINISHED) {
                rc = -ENXIO;
-               goto fail;
+               goto fail_mbox;
        }
        return 0;
 
+fail_mbox:
+       lpfc_mbox_rsrc_cleanup(phba, mboxq, MBOX_THD_UNLOCKED);
 fail:
-       if (mboxq)
-               mempool_free(mboxq, phba->mbox_mem_pool);
-       if (dmabuf) {
-               if (dmabuf->virt)
-                       lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
-               kfree(dmabuf);
-       }
-
        lpfc_vport_set_state(vport, FC_VPORT_FAILED);
        lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
                         "0289 Issue Register VFI failed: Err %d\n", rc);
        struct lpfc_hba *phba = vport->phba;
        struct lpfc_nodelist *ns_ndlp;
        LPFC_MBOXQ_t *mbox;
-       struct lpfc_dmabuf *mp;
 
        if (fc_ndlp->nlp_flag & NLP_RPI_REGISTERED)
                return rc;
        mbox->ctx_ndlp = lpfc_nlp_get(fc_ndlp);
        if (!mbox->ctx_ndlp) {
                rc = -ENOMEM;
-               goto out_mem;
+               goto out;
        }
 
        mbox->vport = vport;
        if (rc == MBX_NOT_FINISHED) {
                rc = -ENODEV;
                lpfc_nlp_put(fc_ndlp);
-               goto out_mem;
+               goto out;
        }
        /* Success path. Exit. */
        lpfc_nlp_set_state(vport, fc_ndlp,
                           NLP_STE_REG_LOGIN_ISSUE);
        return 0;
 
- out_mem:
-       fc_ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
-       mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-
  out:
-       mempool_free(mbox, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
        lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
                         "0938 %s: failed to format reg_login "
                         "Data: x%x x%x x%x x%x\n", __func__,
 void
 lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
        struct lpfc_nodelist *ndlp = pmb->ctx_ndlp;
        u32 mbx_flag = pmb->mbox_flag;
        u32 mbx_cmd = pmb->u.mb.mbxCommand;
 
-       pmb->ctx_buf = NULL;
-       pmb->ctx_ndlp = NULL;
-
        if (ndlp) {
                lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
                                 "0006 rpi x%x DID:%x flg:%x %d x%px "
                lpfc_drop_node(ndlp->vport, ndlp);
        }
 
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
-       return;
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 }
 
 /**
        struct Scsi_Host  *shost = vport ? lpfc_shost_from_vport(vport) : NULL;
        IOCB_t  *irsp;
        LPFC_MBOXQ_t *mbox = NULL;
-       struct lpfc_dmabuf *mp = NULL;
        u32 ulp_status, ulp_word4, tmo, did, iotag;
 
        if (!vport) {
 
        /* Check to see if link went down during discovery */
        if (!ndlp || lpfc_els_chk_latt(vport)) {
-               if (mbox) {
-                       mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
-                       if (mp) {
-                               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
-                       mempool_free(mbox, phba->mbox_mem_pool);
-               }
+               if (mbox)
+                       lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
                goto out;
        }
 
                                                         ndlp->nlp_state,
                                                         ndlp->nlp_rpi,
                                                         ndlp->nlp_flag);
-                                       mp = mbox->ctx_buf;
-                                       if (mp) {
-                                               lpfc_mbuf_free(phba, mp->virt,
-                                                              mp->phys);
-                                               kfree(mp);
-                                       }
-                                       mempool_free(mbox, phba->mbox_mem_pool);
-                                       goto out;
+                                       goto out_free_mbox;
                                }
                        }
 
                         */
                        mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
                        if (!mbox->ctx_ndlp)
-                               goto out;
+                               goto out_free_mbox;
 
                        mbox->vport = vport;
                        if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) {
                                ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
                                ndlp->nlp_rpi);
                }
-               mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
-               if (mp) {
-                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                       kfree(mp);
-               }
-               mempool_free(mbox, phba->mbox_mem_pool);
+out_free_mbox:
+               lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
        }
 out:
        if (ndlp && shost) {
 lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context)
 {
        LPFC_MBOXQ_t *mbox = NULL;
-       struct lpfc_dmabuf *mp;
        int rc;
 
        mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        }
 
        if (lpfc_sli4_dump_page_a0(phba, mbox))
-               goto prep_mbox_fail;
+               goto rdp_fail;
        mbox->vport = rdp_context->ndlp->vport;
        mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a0;
        mbox->ctx_ndlp = (struct lpfc_rdp_context *)rdp_context;
        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
        if (rc == MBX_NOT_FINISHED) {
-               mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               goto issue_mbox_fail;
+               lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
+               return 1;
        }
 
        return 0;
 
-prep_mbox_fail:
-issue_mbox_fail:
+rdp_fail:
        mempool_free(mbox, phba->mbox_mem_pool);
        return 1;
 }
 
 {
        struct lpfc_vport *vport = pmb->vport;
        LPFC_MBOXQ_t *sparam_mb;
-       struct lpfc_dmabuf *sparam_mp;
        u16 status = pmb->u.mb.mbxStatus;
        int rc;
 
                        sparam_mb->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
                        rc = lpfc_sli_issue_mbox(phba, sparam_mb, MBX_NOWAIT);
                        if (rc == MBX_NOT_FINISHED) {
-                               sparam_mp = (struct lpfc_dmabuf *)
-                                               sparam_mb->ctx_buf;
-                               lpfc_mbuf_free(phba, sparam_mp->virt,
-                                              sparam_mp->phys);
-                               kfree(sparam_mp);
-                               sparam_mb->ctx_buf = NULL;
-                               mempool_free(sparam_mb, phba->mbox_mem_pool);
+                               lpfc_mbox_rsrc_cleanup(phba, sparam_mb,
+                                                      MBOX_THD_UNLOCKED);
                                goto sparam_out;
                        }
 
 void
 lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
-       struct lpfc_dmabuf *dmabuf = mboxq->ctx_buf;
        struct lpfc_vport *vport = mboxq->vport;
        struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
        }
 
 out_free_mem:
-       mempool_free(mboxq, phba->mbox_mem_pool);
-       if (dmabuf) {
-               lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
-               kfree(dmabuf);
-       }
-       return;
+       lpfc_mbox_rsrc_cleanup(phba, mboxq, MBOX_THD_UNLOCKED);
 }
 
 static void
                memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn));
        }
 
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 
        /* Check if sending the FLOGI is being deferred to after we get
         * up to date CSPs from MBX_READ_SPARAM.
        return;
 
 out:
-       pmb->ctx_buf = NULL;
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
        lpfc_issue_clear_la(phba, vport);
-       mempool_free(pmb, phba->mbox_mem_pool);
-       return;
 }
 
 static void
        LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL;
        struct Scsi_Host *shost;
        int i;
-       struct lpfc_dmabuf *mp;
        int rc;
        struct fcf_record *fcf_record;
        uint32_t fc_flags = 0;
        sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
        rc = lpfc_sli_issue_mbox(phba, sparam_mbox, MBX_NOWAIT);
        if (rc == MBX_NOT_FINISHED) {
-               mp = (struct lpfc_dmabuf *)sparam_mbox->ctx_buf;
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-               mempool_free(sparam_mbox, phba->mbox_mem_pool);
+               lpfc_mbox_rsrc_cleanup(phba, sparam_mbox, MBOX_THD_UNLOCKED);
                goto out;
        }
 
        }
 
 lpfc_mbx_cmpl_read_topology_free_mbuf:
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
-       return;
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 }
 
 /*
 lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
        struct lpfc_vport  *vport = pmb->vport;
-       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
+       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
        struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
 
+       /* The driver calls the state machine with the pmb pointer
+        * but wants to make sure a stale ctx_buf isn't acted on.
+        * The ctx_buf is restored later and cleaned up.
+        */
        pmb->ctx_buf = NULL;
        pmb->ctx_ndlp = NULL;
 
 
        /* Call state machine */
        lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
+       pmb->ctx_buf = mp;
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
        /* decrement the node reference count held for this callback
         * function.
         */
 
        vport_buff = (uint8_t *) vport_info;
        do {
-               /* free dma buffer from previous round */
+               /* While loop iteration forces a free dma buffer from
+                * the previous loop because the mbox is reused and
+                * the dump routine is a single-use construct.
+                */
                if (pmb->ctx_buf) {
                        mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
                        lpfc_mbuf_free(phba, mp->virt, mp->phys);
                        kfree(mp);
+                       pmb->ctx_buf = NULL;
                }
                if (lpfc_dump_static_vport(phba, pmb, offset))
                        goto out;
 
 out:
        kfree(vport_info);
-       if (mbx_wait_rc != MBX_TIMEOUT) {
-               if (pmb->ctx_buf) {
-                       mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
-                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                       kfree(mp);
-               }
-               mempool_free(pmb, phba->mbox_mem_pool);
-       }
-
-       return;
+       if (mbx_wait_rc != MBX_TIMEOUT)
+               lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 }
 
 /*
 {
        struct lpfc_vport *vport = pmb->vport;
        MAILBOX_t *mb = &pmb->u.mb;
-       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
-       struct lpfc_nodelist *ndlp;
+       struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
        struct Scsi_Host *shost;
 
-       ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
        pmb->ctx_ndlp = NULL;
-       pmb->ctx_buf = NULL;
 
        if (mb->mbxStatus) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
                                 "0258 Register Fabric login error: 0x%x\n",
                                 mb->mbxStatus);
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-               mempool_free(pmb, phba->mbox_mem_pool);
-
+               lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
                if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
                        /* FLOGI failed, use loop map to make discovery list */
                        lpfc_disc_list_loopmap(vport);
                lpfc_do_scr_ns_plogi(phba, vport);
        }
 
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 
        /* Drop the reference count from the mbox at the end after
         * all the current reference to the ndlp have been done.
 lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
        MAILBOX_t *mb = &pmb->u.mb;
-       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
        struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
        struct lpfc_vport *vport = pmb->vport;
        int rc;
 
-       pmb->ctx_buf = NULL;
        pmb->ctx_ndlp = NULL;
        vport->gidft_inp = 0;
 
                 * callback function.
                 */
                lpfc_nlp_put(ndlp);
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-               mempool_free(pmb, phba->mbox_mem_pool);
+               lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 
                /* If the node is not registered with the scsi or nvme
                 * transport, remove the fabric node.  The failed reg_login
         * callback function.
         */
        lpfc_nlp_put(ndlp);
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
-
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
        return;
 }
 
 {
        struct lpfc_vport *vport = pmb->vport;
        MAILBOX_t *mb = &pmb->u.mb;
-       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
-       struct lpfc_nodelist *ndlp;
+       struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
 
-       ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
        pmb->ctx_ndlp = NULL;
-       pmb->ctx_buf = NULL;
-
        if (mb->mbxStatus) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
                                 "0933 %s: Register FC login error: 0x%x\n",
        lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
  out:
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 
        /* Drop the reference count from the mbox at the end after
         * all the current reference to the ndlp have been done.
 {
        struct lpfc_hba  *phba = vport->phba;
        LPFC_MBOXQ_t *mb, *nextmb;
-       struct lpfc_dmabuf *mp;
 
        /* Cleanup node for NPort <nlp_DID> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
                if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
                   !(mb->mbox_flag & LPFC_MBX_IMED_UNREG) &&
                    (ndlp == (struct lpfc_nodelist *)mb->ctx_ndlp)) {
-                       mp = (struct lpfc_dmabuf *)(mb->ctx_buf);
-                       if (mp) {
-                               __lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
                        list_del(&mb->list);
-                       mempool_free(mb, phba->mbox_mem_pool);
-                       /* We shall not invoke the lpfc_nlp_put to decrement
-                        * the ndlp reference count as we are in the process
-                        * of lpfc_nlp_release.
+                       lpfc_mbox_rsrc_cleanup(phba, mb, MBOX_THD_LOCKED);
+
+                       /* Don't invoke lpfc_nlp_put. The driver is in
+                        * lpfc_nlp_release context.
                         */
                }
        }
 lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
        MAILBOX_t *mb = &pmb->u.mb;
-       struct lpfc_dmabuf   *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
        struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
        struct lpfc_vport    *vport = pmb->vport;
 
-       pmb->ctx_buf = NULL;
        pmb->ctx_ndlp = NULL;
 
        if (phba->sli_rev < LPFC_SLI_REV4)
         * function.
         */
        lpfc_nlp_put(ndlp);
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
-
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
        return;
 }
 
 
                                "READ_SPARM mbxStatus x%x\n",
                                mb->mbxCommand, mb->mbxStatus);
                phba->link_state = LPFC_HBA_ERROR;
-               mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
-               mempool_free(pmb, phba->mbox_mem_pool);
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
+               lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
                return -EIO;
        }
 
        mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
 
+       /* This dmabuf was allocated by lpfc_read_sparam. The dmabuf is no
+        * longer needed.  Prevent unintended ctx_buf access as the mbox is
+        * reused.
+        */
        memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        struct lpfc_sli   *psli = &phba->sli;
        LPFC_MBOXQ_t *pmb;
        volatile uint32_t control;
-       struct lpfc_dmabuf *mp;
        int rc = 0;
 
        pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
                goto lpfc_handle_latt_err_exit;
        }
 
-       mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (!mp) {
+       rc = lpfc_mbox_rsrc_prep(phba, pmb);
+       if (rc) {
                rc = 2;
-               goto lpfc_handle_latt_free_pmb;
-       }
-
-       mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-       if (!mp->virt) {
-               rc = 3;
-               goto lpfc_handle_latt_free_mp;
+               mempool_free(pmb, phba->mbox_mem_pool);
+               goto lpfc_handle_latt_err_exit;
        }
 
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
-
        psli->slistat.link_event++;
-       lpfc_read_topology(phba, pmb, mp);
+       lpfc_read_topology(phba, pmb, (struct lpfc_dmabuf *)pmb->ctx_buf);
        pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
        pmb->vport = vport;
        /* Block ELS IOCBs until we have processed this mbox command */
 
 lpfc_handle_latt_free_mbuf:
        phba->sli.sli3_ring[LPFC_ELS_RING].flag &= ~LPFC_STOP_IOCB_EVENT;
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-lpfc_handle_latt_free_mp:
-       kfree(mp);
-lpfc_handle_latt_free_pmb:
-       mempool_free(pmb, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 lpfc_handle_latt_err_exit:
        /* Enable Link attention interrupts */
        spin_lock_irq(&phba->hbalock);
 lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
                         struct lpfc_acqe_link *acqe_link)
 {
-       struct lpfc_dmabuf *mp;
        LPFC_MBOXQ_t *pmb;
        MAILBOX_t *mb;
        struct lpfc_mbx_read_top *la;
                                "0395 The mboxq allocation failed\n");
                return;
        }
-       mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (!mp) {
+
+       rc = lpfc_mbox_rsrc_prep(phba, pmb);
+       if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
-                               "0396 The lpfc_dmabuf allocation failed\n");
+                               "0396 mailbox allocation failed\n");
                goto out_free_pmb;
        }
-       mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-       if (!mp->virt) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
-                               "0397 The mbuf allocation failed\n");
-               goto out_free_dmabuf;
-       }
 
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
        phba->sli.slistat.link_event++;
 
        /* Create lpfc_handle_latt mailbox command from link ACQE */
-       lpfc_read_topology(phba, pmb, mp);
+       lpfc_read_topology(phba, pmb, (struct lpfc_dmabuf *)pmb->ctx_buf);
        pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
        pmb->vport = phba->pport;
 
         */
        if (!(phba->hba_flag & HBA_FCOE_MODE)) {
                rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-               if (rc == MBX_NOT_FINISHED) {
-                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                       goto out_free_dmabuf;
-               }
+               if (rc == MBX_NOT_FINISHED)
+                       goto out_free_pmb;
                return;
        }
        /*
 
        return;
 
-out_free_dmabuf:
-       kfree(mp);
 out_free_pmb:
-       mempool_free(pmb, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 }
 
 /**
 static void
 lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
 {
-       struct lpfc_dmabuf *mp;
        LPFC_MBOXQ_t *pmb;
        MAILBOX_t *mb;
        struct lpfc_mbx_read_top *la;
                                "2897 The mboxq allocation failed\n");
                return;
        }
-       mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (!mp) {
+       rc = lpfc_mbox_rsrc_prep(phba, pmb);
+       if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
-                               "2898 The lpfc_dmabuf allocation failed\n");
+                               "2898 The mboxq prep failed\n");
                goto out_free_pmb;
        }
-       mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-       if (!mp->virt) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
-                               "2899 The mbuf allocation failed\n");
-               goto out_free_dmabuf;
-       }
 
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
        phba->sli.slistat.link_event++;
 
        /* Create lpfc_handle_latt mailbox command from link ACQE */
-       lpfc_read_topology(phba, pmb, mp);
+       lpfc_read_topology(phba, pmb, (struct lpfc_dmabuf *)pmb->ctx_buf);
        pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
        pmb->vport = phba->pport;
 
        }
 
        rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-       if (rc == MBX_NOT_FINISHED) {
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               goto out_free_dmabuf;
-       }
+       if (rc == MBX_NOT_FINISHED)
+               goto out_free_pmb;
        return;
 
-out_free_dmabuf:
-       kfree(mp);
 out_free_pmb:
-       mempool_free(pmb, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 }
 
 /**
 
 #include "lpfc_crtn.h"
 #include "lpfc_compat.h"
 
+/**
+ * lpfc_mbox_rsrc_prep - Prepare a mailbox with DMA buffer memory.
+ * @phba: pointer to lpfc hba data structure.
+ * @mbox: pointer to the driver internal queue element for mailbox command.
+ *
+ * A mailbox command consists of the pool memory for the command, @mbox, and
+ * one or more DMA buffers for the data transfer.  This routine provides
+ * a standard framework for allocating the dma buffer and assigning to the
+ * @mbox.  Callers should cleanup the mbox with a call to
+ * lpfc_mbox_rsrc_cleanup.
+ *
+ * The lpfc_mbuf_alloc routine acquires the hbalock so the caller is
+ * responsible to ensure the hbalock is released.  Also note that the
+ * driver design is a single dmabuf/mbuf per mbox in the ctx_buf.
+ *
+ **/
+int
+lpfc_mbox_rsrc_prep(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
+{
+       struct lpfc_dmabuf *mp;
+
+       mp = kmalloc(sizeof(*mp), GFP_KERNEL);
+       if (!mp)
+               return -ENOMEM;
+
+       mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
+       if (!mp->virt) {
+               kfree(mp);
+               return -ENOMEM;
+       }
+
+       memset(mp->virt, 0, LPFC_BPL_SIZE);
+
+       /* Initialization only.  Driver does not use a list of dmabufs. */
+       INIT_LIST_HEAD(&mp->list);
+       mbox->ctx_buf = mp;
+       return 0;
+}
+
+/**
+ * lpfc_mbox_rsrc_cleanup - Free the mailbox DMA buffer and virtual memory.
+ * @phba: pointer to lpfc hba data structure.
+ * @mbox: pointer to the driver internal queue element for mailbox command.
+ * @locked: value that indicates if the hbalock is held (1) or not (0).
+ *
+ * A mailbox command consists of the pool memory for the command, @mbox, and
+ * possibly a DMA buffer for the data transfer.  This routine provides
+ * a standard framework for releasing any dma buffers and freeing all
+ * memory resources in it as well as releasing the @mbox back to the @phba pool.
+ * Callers should use this routine for cleanup for all mailboxes prepped with
+ * lpfc_mbox_rsrc_prep.
+ *
+ **/
+void
+lpfc_mbox_rsrc_cleanup(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
+                      enum lpfc_mbox_ctx locked)
+{
+       struct lpfc_dmabuf *mp;
+
+       mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
+       mbox->ctx_buf = NULL;
+
+       /* Release the generic BPL buffer memory.  */
+       if (mp) {
+               if (locked == MBOX_THD_LOCKED)
+                       __lpfc_mbuf_free(phba, mp->virt, mp->phys);
+               else
+                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+               kfree(mp);
+       }
+
+       mempool_free(mbox, phba->mbox_mem_pool);
+}
+
 /**
  * lpfc_dump_static_vport - Dump HBA's static vport information.
  * @phba: pointer to lpfc hba data structure.
 {
        MAILBOX_t *mb;
        struct lpfc_dmabuf *mp;
+       int rc;
 
        mb = &pmb->u.mb;
 
                return 0;
        }
 
-       /* For SLI4 HBAs driver need to allocate memory */
-       mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (mp)
-               mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-
-       if (!mp || !mp->virt) {
-               kfree(mp);
+       rc = lpfc_mbox_rsrc_prep(phba, pmb);
+       if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-                       "2605 lpfc_dump_static_vport: memory"
-                       " allocation failed\n");
+                               "2605 %s: memory allocation failed\n",
+                               __func__);
                return 1;
        }
-       memset(mp->virt, 0, LPFC_BPL_SIZE);
-       INIT_LIST_HEAD(&mp->list);
-       /* save address for completion */
-       pmb->ctx_buf = (uint8_t *)mp;
+
+       mp = pmb->ctx_buf;
        mb->un.varWords[3] = putPaddrLow(mp->phys);
        mb->un.varWords[4] = putPaddrHigh(mp->phys);
        mb->un.varDmp.sli4_length = sizeof(struct static_vport_info);
 {
        struct lpfc_dmabuf *mp;
        MAILBOX_t *mb;
+       int rc;
 
-       mb = &pmb->u.mb;
        memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
-       mb->mbxOwner = OWN_HOST;
-
        /* Get a buffer to hold the HBAs Service Parameters */
-
-       mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-       if (mp)
-               mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-       if (!mp || !mp->virt) {
-               kfree(mp);
-               mb->mbxCommand = MBX_READ_SPARM64;
-               /* READ_SPARAM: no buffers */
+       rc = lpfc_mbox_rsrc_prep(phba, pmb);
+       if (rc) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
                                "0301 READ_SPARAM: no buffers\n");
-               return (1);
+               return 1;
        }
-       INIT_LIST_HEAD(&mp->list);
+
+       mp = pmb->ctx_buf;
+       mb = &pmb->u.mb;
+       mb->mbxOwner = OWN_HOST;
        mb->mbxCommand = MBX_READ_SPARM64;
        mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
        mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
        if (phba->sli_rev >= LPFC_SLI_REV3)
                mb->un.varRdSparm.vpi = phba->vpi_ids[vpi];
 
-       /* save address for completion */
-       pmb->ctx_buf = mp;
-
        return (0);
 }
 
        MAILBOX_t *mb = &pmb->u.mb;
        uint8_t *sparam;
        struct lpfc_dmabuf *mp;
+       int rc;
 
        memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
                mb->un.varRegLogin.vpi = phba->vpi_ids[vpi];
        mb->un.varRegLogin.did = did;
        mb->mbxOwner = OWN_HOST;
+
        /* Get a buffer to hold NPorts Service Parameters */
-       mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-       if (mp)
-               mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-       if (!mp || !mp->virt) {
-               kfree(mp);
+       rc = lpfc_mbox_rsrc_prep(phba, pmb);
+       if (rc) {
                mb->mbxCommand = MBX_REG_LOGIN64;
                /* REG_LOGIN: no buffers */
                lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
                                "rpi x%x\n", vpi, did, rpi);
                return 1;
        }
-       INIT_LIST_HEAD(&mp->list);
-       sparam = mp->virt;
 
        /* Copy param's into a new buffer */
+       mp = pmb->ctx_buf;
+       sparam = mp->virt;
        memcpy(sparam, param, sizeof (struct serv_parm));
 
-       /* save address for completion */
-       pmb->ctx_buf = (uint8_t *)mp;
-
+       /* Finish initializing the mailbox. */
        mb->mbxCommand = MBX_REG_LOGIN64;
        mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
        mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
  * @phba: pointer to lpfc hba data structure.
  * @mbox: pointer to lpfc mbox command.
  *
- * This routine frees SLI4 specific mailbox command for sending IOCTL command.
+ * This routine cleans up and releases an SLI4 mailbox command that was
+ * configured using lpfc_sli4_config.  It accounts for the embedded and
+ * non-embedded config types.
  **/
 void
 lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
 {
        struct lpfc_dmabuf *mp = NULL;
        MAILBOX_t *mb;
+       int rc;
 
        memset(mbox, 0, sizeof(*mbox));
        mb = &mbox->u.mb;
 
-       mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (mp)
-               mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-
-       if (!mp || !mp->virt) {
-               kfree(mp);
-               /* dump config region 23 failed to allocate memory */
+       rc = lpfc_mbox_rsrc_prep(phba, mbox);
+       if (rc) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
-                       "2569 lpfc dump config region 23: memory"
-                       " allocation failed\n");
+                               "2569 %s: memory allocation failed\n",
+                               __func__);
                return 1;
        }
 
-       memset(mp->virt, 0, LPFC_BPL_SIZE);
-       INIT_LIST_HEAD(&mp->list);
-
-       /* save address for completion */
-       mbox->ctx_buf = (uint8_t *)mp;
-
        mb->mbxCommand = MBX_DUMP_MEMORY;
        mb->un.varDmp.type = DMP_NV_PARAMS;
        mb->un.varDmp.region_id = DMP_REGION_23;
        mb->un.varDmp.sli4_length = DMP_RGN23_SIZE;
+       mp = mbox->ctx_buf;
        mb->un.varWords[3] = putPaddrLow(mp->phys);
        mb->un.varWords[4] = putPaddrHigh(mp->phys);
        return 0;
        rc = SUCCESS;
 
 mbx_failed:
-       lpfc_sli4_mbox_cmd_free(phba, mboxq);
+       lpfc_mbox_rsrc_cleanup(phba, mboxq, MBOX_THD_UNLOCKED);
        rdp_context->cmpl(phba, rdp_context, rc);
 }
 
                        (struct lpfc_rdp_context *)(mbox->ctx_ndlp);
 
        if (bf_get(lpfc_mqe_status, &mbox->u.mqe))
-               goto error_mbuf_free;
+               goto error_mbox_free;
 
        lpfc_sli_bemem_bcopy(mp->virt, &rdp_context->page_a2,
                                DMP_SFF_PAGE_A2_SIZE);
 
-       /* We don't need dma buffer for link stat. */
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-
-       memset(mbox, 0, sizeof(*mbox));
        lpfc_read_lnk_stat(phba, mbox);
        mbox->vport = rdp_context->ndlp->vport;
+
+       /* Save the dma buffer for cleanup in the final completion. */
+       mbox->ctx_buf = mp;
        mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_link_stat;
        mbox->ctx_ndlp = (struct lpfc_rdp_context *)rdp_context;
        if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == MBX_NOT_FINISHED)
-               goto error_cmd_free;
+               goto error_mbox_free;
 
        return;
 
-error_mbuf_free:
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-error_cmd_free:
-       lpfc_sli4_mbox_cmd_free(phba, mbox);
+error_mbox_free:
+       lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
        rdp_context->cmpl(phba, rdp_context, FAILURE);
 }
 
        return;
 
 error:
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       lpfc_sli4_mbox_cmd_free(phba, mbox);
+       lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
        rdp_context->cmpl(phba, rdp_context, FAILURE);
 }
 
 int
 lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
 {
+       int rc;
        struct lpfc_dmabuf *mp = NULL;
 
        memset(mbox, 0, sizeof(*mbox));
 
-       mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (mp)
-               mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-       if (!mp || !mp->virt) {
-               kfree(mp);
+       rc = lpfc_mbox_rsrc_prep(phba, mbox);
+       if (rc) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
                        "3569 dump type 3 page 0xA0 allocation failed\n");
                return 1;
        }
 
-       memset(mp->virt, 0, LPFC_BPL_SIZE);
-       INIT_LIST_HEAD(&mp->list);
-
        bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_DUMP_MEMORY);
-       /* save address for completion */
-       mbox->ctx_buf = mp;
-
        bf_set(lpfc_mbx_memory_dump_type3_type,
                &mbox->u.mqe.un.mem_dump_type3, DMP_LMSD);
        bf_set(lpfc_mbx_memory_dump_type3_link,
                &mbox->u.mqe.un.mem_dump_type3, DMP_PAGE_A0);
        bf_set(lpfc_mbx_memory_dump_type3_length,
                &mbox->u.mqe.un.mem_dump_type3, DMP_SFF_PAGE_A0_SIZE);
+
+       mp = mbox->ctx_buf;
        mbox->u.mqe.un.mem_dump_type3.addr_lo = putPaddrLow(mp->phys);
        mbox->u.mqe.un.mem_dump_type3.addr_hi = putPaddrHigh(mp->phys);
 
 
 {
        struct lpfc_hba    *phba = vport->phba;
        struct lpfc_dmabuf *pcmd;
-       struct lpfc_dmabuf *mp;
        uint64_t nlp_portwwn = 0;
        uint32_t *lp;
        union lpfc_wqe128 *wqe;
                 * a default RPI.
                 */
                if (phba->sli_rev == LPFC_SLI_REV4) {
-                       mp = (struct lpfc_dmabuf *)login_mbox->ctx_buf;
-                       if (mp) {
-                               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
-                       mempool_free(login_mbox, phba->mbox_mem_pool);
+                       lpfc_mbox_rsrc_cleanup(phba, login_mbox,
+                                              MBOX_THD_UNLOCKED);
                        login_mbox = NULL;
                } else {
                        /* In order to preserve RPIs, we want to cleanup
                stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
                rc = lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
                                         ndlp, login_mbox);
-               if (rc) {
-                       mp = (struct lpfc_dmabuf *)login_mbox->ctx_buf;
-                       if (mp) {
-                               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
-                       mempool_free(login_mbox, phba->mbox_mem_pool);
-               }
+               if (rc && login_mbox)
+                       lpfc_mbox_rsrc_cleanup(phba, login_mbox,
+                                              MBOX_THD_UNLOCKED);
                return 1;
        }
 
 {
        struct lpfc_hba    *phba = vport->phba;
        struct lpfc_iocbq  *cmdiocb, *rspiocb;
-       struct lpfc_dmabuf *pcmd, *prsp, *mp;
+       struct lpfc_dmabuf *pcmd, *prsp;
        uint32_t *lp;
        uint32_t vid, flag;
        struct serv_parm *sp;
                 * command
                 */
                lpfc_nlp_put(ndlp);
-               mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-               mempool_free(mbox, phba->mbox_mem_pool);
-
+               lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
                lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
                                 "0134 PLOGI: cannot issue reg_login "
                                 "Data: x%x x%x x%x x%x\n",
        struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
        LPFC_MBOXQ_t      *mb;
        LPFC_MBOXQ_t      *nextmb;
-       struct lpfc_dmabuf *mp;
        struct lpfc_nodelist *ns_ndlp;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
                if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
                   (ndlp == (struct lpfc_nodelist *)mb->ctx_ndlp)) {
-                       mp = (struct lpfc_dmabuf *)(mb->ctx_buf);
-                       if (mp) {
-                               __lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
                        ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
                        lpfc_nlp_put(ndlp);
                        list_del(&mb->list);
                        phba->sli.mboxq_cnt--;
-                       mempool_free(mb, phba->mbox_mem_pool);
+                       lpfc_mbox_rsrc_cleanup(phba, mb, MBOX_THD_LOCKED);
                }
        }
        spin_unlock_irq(&phba->hbalock);
 
 lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
        struct lpfc_vport  *vport = pmb->vport;
-       struct lpfc_dmabuf *mp;
        struct lpfc_nodelist *ndlp;
        struct Scsi_Host *shost;
        uint16_t rpi, vpi;
        int rc;
 
-       mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
-
-       if (mp) {
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-       }
-
        /*
         * If a REG_LOGIN succeeded  after node is destroyed or node
         * is in re-discovery driver need to cleanup the RPI.
        if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
                ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
                lpfc_nlp_put(ndlp);
-               pmb->ctx_buf = NULL;
-               pmb->ctx_ndlp = NULL;
        }
 
        if (pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) {
        if (bf_get(lpfc_mqe_command, &pmb->u.mqe) == MBX_SLI4_CONFIG)
                lpfc_sli4_mbox_cmd_free(phba, pmb);
        else
-               mempool_free(pmb, phba->mbox_mem_pool);
+               lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
 }
  /**
  * lpfc_sli4_unreg_rpi_cmpl_clr - mailbox completion handler
                        mboxq->mcqe.trailer);
 
        if (rc) {
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
                rc = -EIO;
                goto out_free_mboxq;
        }
        data_length = mqe->un.mb_words[5];
        if (data_length > DMP_RGN23_SIZE) {
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
                rc = -EIO;
                goto out_free_mboxq;
        }
 
        lpfc_parse_fcoe_conf(phba, mp->virt, data_length);
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
        rc = 0;
 
 out_free_mboxq:
-       mempool_free(mboxq, phba->mbox_mem_pool);
+       lpfc_mbox_rsrc_cleanup(phba, mboxq, MBOX_THD_UNLOCKED);
        return rc;
 }
 
        }
 
        /*
-        * This memory was allocated by the lpfc_read_sparam routine. Release
-        * it to the mbuf pool.
+        * This memory was allocated by the lpfc_read_sparam routine but is
+        * no longer needed.  It is released and ctx_buf NULLed to prevent
+        * unintended pointer access as the mbox is reused.
         */
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        struct lpfc_nodelist *ndlp = cmdiocb->ndlp;
        IOCB_t *irsp;
        LPFC_MBOXQ_t *mbox;
-       struct lpfc_dmabuf *mp;
        u32 ulp_command, ulp_status, ulp_word4, iotag;
 
        ulp_command = get_job_cmnd(phba, cmdiocb);
                 */
                if (cmdiocb->context_un.mbox) {
                        mbox = cmdiocb->context_un.mbox;
-                       mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
-                       if (mp) {
-                               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
-                       mempool_free(mbox, phba->mbox_mem_pool);
+                       lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
                        cmdiocb->context_un.mbox = NULL;
                }
        }
 
        mbox->vport = phba->pport;
        mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-       mbox->ctx_buf = NULL;
        mbox->ctx_ndlp = NULL;
        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        shdr = (union lpfc_sli4_cfg_shdr *) &eq_delay->header.cfg_shdr;
        }
        lpfc_sli_pcimem_bcopy((char *)mp->virt, rgn23_data, data_length);
 out:
-       mempool_free(mboxq, phba->mbox_mem_pool);
-       if (mp) {
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-       }
+       lpfc_mbox_rsrc_cleanup(phba, mboxq, MBOX_THD_UNLOCKED);
        return data_length;
 }
 
 {
        struct lpfc_hba *phba = vport->phba;
        LPFC_MBOXQ_t *mb, *nextmb;
-       struct lpfc_dmabuf *mp;
        struct lpfc_nodelist *ndlp;
        struct lpfc_nodelist *act_mbx_ndlp = NULL;
        LIST_HEAD(mbox_cmd_list);
        while (!list_empty(&mbox_cmd_list)) {
                list_remove_head(&mbox_cmd_list, mb, LPFC_MBOXQ_t, list);
                if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
-                       mp = (struct lpfc_dmabuf *)(mb->ctx_buf);
-                       if (mp) {
-                               __lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
-                       mb->ctx_buf = NULL;
                        ndlp = (struct lpfc_nodelist *)mb->ctx_ndlp;
                        mb->ctx_ndlp = NULL;
                        if (ndlp) {
                                lpfc_nlp_put(ndlp);
                        }
                }
-               mempool_free(mb, phba->mbox_mem_pool);
+               lpfc_mbox_rsrc_cleanup(phba, mb, MBOX_THD_UNLOCKED);
        }
 
        /* Release the ndlp with the cleaned-up active mailbox command */
 
        mbox->vport = phba->pport;
        mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-       mbox->ctx_buf = NULL;
        mbox->ctx_ndlp = NULL;
 
        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        }
 
  exit:
+       /* This is an embedded SLI4 mailbox with an external buffer allocated.
+        * Free the pcmd and then cleanup with the correct routine.
+        */
        lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
        kfree(pcmd);
-       mempool_free(mbox, phba->mbox_mem_pool);
+       lpfc_sli4_mbox_cmd_free(phba, mbox);
        return byte_cnt;
 }
 
 
        LPFC_CTX_HOST
 } lpfc_ctx_cmd;
 
+/* Enumeration to describe the thread lock context. */
+enum lpfc_mbox_ctx {
+       MBOX_THD_UNLOCKED,
+       MBOX_THD_LOCKED
+};
+
 union lpfc_vmid_tag {
        uint32_t app_id;
        uint8_t cs_ctl_vmid;
 
        }
 
        /*
-        * Grab buffer pointer and clear context1 so we can use
-        * lpfc_sli_issue_box_wait
+        * Wait for the read_sparams mailbox to complete.  Driver needs
+        * this per vport to start the FDISC.  If the mailbox fails,
+        * just cleanup and return an error unless the failure is a
+        * mailbox timeout.  For MBX_TIMEOUT, allow the default
+        * mbox completion handler to take care of the cleanup.  This
+        * is safe as the mailbox command isn't one that triggers
+        * another mailbox.
         */
-       mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
-       pmb->ctx_buf = NULL;
-
        pmb->vport = vport;
        rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
        if (rc != MBX_SUCCESS) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
                                         "1830 Signal aborted mbxCmd x%x\n",
                                         mb->mbxCommand);
-                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                       kfree(mp);
                        if (rc != MBX_TIMEOUT)
-                               mempool_free(pmb, phba->mbox_mem_pool);
+                               lpfc_mbox_rsrc_cleanup(phba, pmb,
+                                                      MBOX_THD_UNLOCKED);
                        return -EINTR;
                } else {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
                                         "1818 VPort failed init, mbxCmd x%x "
                                         "READ_SPARM mbxStatus x%x, rc = x%x\n",
                                         mb->mbxCommand, mb->mbxStatus, rc);
-                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                       kfree(mp);
                        if (rc != MBX_TIMEOUT)
-                               mempool_free(pmb, phba->mbox_mem_pool);
+                               lpfc_mbox_rsrc_cleanup(phba, pmb,
+                                                      MBOX_THD_UNLOCKED);
                        return -EIO;
                }
        }
 
+       mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
        memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
        memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
               sizeof (struct lpfc_name));
        memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
               sizeof (struct lpfc_name));
-
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       mempool_free(pmb, phba->mbox_mem_pool);
-
+       lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
        return 0;
 }