diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 68e9f96242d3..bee27bb7123c 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -595,6 +595,7 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd, struct lpfc_sli4_hdw_queue *qp); void lpfc_nvme_cmd_template(void); void lpfc_nvmet_cmd_template(void); +void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn); extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c549212a2b49..8c0fb9baf723 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1546,6 +1546,8 @@ lpfc_sli4_offline_eratt(struct lpfc_hba *phba) spin_unlock_irq(&phba->hbalock); lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT); + lpfc_sli_flush_fcp_rings(phba); + lpfc_sli_flush_nvme_rings(phba); lpfc_offline(phba); lpfc_hba_down_post(phba); lpfc_unblock_mgmt_io(phba); @@ -1807,6 +1809,8 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action, "2887 Reset Needed: Attempting Port " "Recovery...\n"); lpfc_offline_prep(phba, mbx_action); + lpfc_sli_flush_fcp_rings(phba); + lpfc_sli_flush_nvme_rings(phba); lpfc_offline(phba); /* release interrupt for possible resource change */ lpfc_sli4_disable_intr(phba); diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 103708503592..c7f5b50c3820 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -2668,3 +2668,50 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba) } } } + +void +lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn) +{ +#if (IS_ENABLED(CONFIG_NVME_FC)) + struct lpfc_io_buf *lpfc_ncmd; + struct nvmefc_fcp_req *nCmd; + struct lpfc_nvme_fcpreq_priv *freqpriv; + + if (!pwqeIn->context1) { + lpfc_sli_release_iocbq(phba, pwqeIn); + return; + } + /* For abort iocb just return, IO iocb will do a done call */ + if (bf_get(wqe_cmnd, &pwqeIn->wqe.gen_req.wqe_com) == + CMD_ABORT_XRI_CX) { + lpfc_sli_release_iocbq(phba, pwqeIn); + return; + } + lpfc_ncmd = (struct lpfc_io_buf *)pwqeIn->context1; + + spin_lock(&lpfc_ncmd->buf_lock); + if (!lpfc_ncmd->nvmeCmd) { + spin_unlock(&lpfc_ncmd->buf_lock); + lpfc_release_nvme_buf(phba, lpfc_ncmd); + return; + } + + nCmd = lpfc_ncmd->nvmeCmd; + lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, + "6194 NVME Cancel xri %x\n", + lpfc_ncmd->cur_iocbq.sli4_xritag); + + nCmd->transferred_length = 0; + nCmd->rcv_rsplen = 0; + nCmd->status = NVME_SC_INTERNAL; + freqpriv = nCmd->private; + freqpriv->nvme_buf = NULL; + lpfc_ncmd->nvmeCmd = NULL; + + spin_unlock(&lpfc_ncmd->buf_lock); + nCmd->done(nCmd); + + /* Call release with XB=1 to queue the IO into the abort list. */ + lpfc_release_nvme_buf(phba, lpfc_ncmd); +#endif +} diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index be89a86f9649..c8db7ec31afb 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1391,9 +1391,12 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, while (!list_empty(iocblist)) { list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); - if (!piocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, piocb); - else { + if (!piocb->iocb_cmpl) { + if (piocb->iocb_flag & LPFC_IO_NVME) + lpfc_nvme_cancel_iocb(phba, piocb); + else + lpfc_sli_release_iocbq(phba, piocb); + } else { piocb->iocb.ulpStatus = ulpstatus; piocb->iocb.un.ulpWord[4] = ulpWord4; (piocb->iocb_cmpl) (phba, piocb, piocb);