scsi: lpfc: Fix abort error path for NVMET
authorJames Smart <jsmart2021@gmail.com>
Tue, 26 Jun 2018 15:24:25 +0000 (08:24 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 11 Jul 2018 02:15:09 +0000 (22:15 -0400)
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 subsequently 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 <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nvmet.c

index 52cae87..150562b 100644 (file)
@@ -10387,6 +10387,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 "
index 7271c9d..102c970 100644 (file)
@@ -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;
 }