rmmod of driver hangs

As driver instances were being unloaded, the NVME target port was
unloaded first. During the unload, the NVME initiator port sent a
heartbeat IO. Because of the target port state, that IO was scheduled
for an Abort; however, that abort subseqentially failed. The failure
was not cleaned up properly and lpfc_sli4_xri_exchange_busy_wait
silently hung forever.

Clean failed abort properly and make lpfc_sli4_xri_exchange_busy_wait
not hangs silently while waiting for aborts to complete.

Signed-off-by: Dick Kennedy <[email protected]>
Signed-off-by: James Smart <[email protected]>
---
 drivers/scsi/lpfc/lpfc_init.c  |  5 +++++
 drivers/scsi/lpfc/lpfc_nvmet.c | 15 +++++++++++----
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7ae343b14630..139a8baa6e4c 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10386,6 +10386,11 @@ lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba)
        while (!fcp_xri_cmpl || !els_xri_cmpl || !nvme_xri_cmpl ||
               !nvmet_xri_cmpl) {
                if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) {
+                       if (!nvmet_xri_cmpl)
+                               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                               "6424 NVMET XRI exchange busy "
+                                               "wait time: %d seconds.\n",
+                                               wait_time/1000);
                        if (!nvme_xri_cmpl)
                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                                "6100 NVME XRI exchange busy "
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 7271c9d885dd..102c970a00e6 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -1732,9 +1732,12 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
        uint32_t *payload;
        uint32_t size, oxid, sid, rc;
 
+       fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
+       oxid = be16_to_cpu(fc_hdr->fh_ox_id);
+
        if (!nvmebuf || !phba->targetport) {
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
-                               "6154 LS Drop IO\n");
+                               "6154 LS Drop IO x%x\n", oxid);
                oxid = 0;
                size = 0;
                sid = 0;
@@ -1744,9 +1747,7 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
        payload = (uint32_t *)(nvmebuf->dbuf.virt);
-       fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
        size = bf_get(lpfc_rcqe_length,  &nvmebuf->cq_event.cqe.rcqe_cmpl);
-       oxid = be16_to_cpu(fc_hdr->fh_ox_id);
        sid = sli4_sid_from_fc_hdr(fc_hdr);
 
        ctxp = kzalloc(sizeof(struct lpfc_nvmet_rcv_ctx), GFP_ATOMIC);
@@ -3105,11 +3106,17 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
        }
 
 aerr:
-       ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+       spin_lock_irqsave(&ctxp->ctxlock, flags);
+       if (ctxp->flag & LPFC_NVMET_CTX_RLS)
+               list_del(&ctxp->list);
+       ctxp->flag &= ~(LPFC_NVMET_ABORT_OP | LPFC_NVMET_CTX_RLS);
+       spin_unlock_irqrestore(&ctxp->ctxlock, flags);
+
        atomic_inc(&tgtp->xmt_abort_rsp_error);
        lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
                        "6135 Failed to Issue ABTS for oxid x%x. Status x%x\n",
                        ctxp->oxid, rc);
+       lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
        return 1;
 }
 
-- 
2.13.1

Reply via email to