From: Justin Tee Date: Thu, 12 Feb 2026 21:30:03 +0000 (-0800) Subject: scsi: lpfc: Fix incorrect txcmplq_cnt during cleanup in lpfc_sli_abort_ring() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2da10bcaa58a389ca60f8e788180e0dca00739bc;p=thirdparty%2Flinux.git scsi: lpfc: Fix incorrect txcmplq_cnt during cleanup in lpfc_sli_abort_ring() When a port is offline in lpfc_sli_abort_ring, the phba->txcmplq is cleared but the phba->txcmplq_cnt is not reset to zero. This can sometimes result in a phba->txcmplq_cnt that never reaches zero, which hangs the cleanup process. Update lpfc_sli_abort_ring so that txcmplq_cnt is reset to zero and also ensure that the LPFC_IO_ON_TXCMPLQ flag is properly cleared. Signed-off-by: Justin Tee Link: https://patch.msgid.link/20260212213008.149873-9-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index fc7d478779f8..bd71292e7480 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4572,59 +4572,41 @@ void lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { LIST_HEAD(tx_completions); - LIST_HEAD(txcmplq_completions); + spinlock_t *plock; /* for transmit queue access */ struct lpfc_iocbq *iocb, *next_iocb; int offline; - if (pring->ringno == LPFC_ELS_RING) { + if (phba->sli_rev >= LPFC_SLI_REV4) + plock = &pring->ring_lock; + else + plock = &phba->hbalock; + + if (pring->ringno == LPFC_ELS_RING) lpfc_fabric_abort_hba(phba); - } + offline = pci_channel_offline(phba->pcidev); - /* Error everything on txq and txcmplq - * First do the txq. - */ - if (phba->sli_rev >= LPFC_SLI_REV4) { - spin_lock_irq(&pring->ring_lock); - list_splice_init(&pring->txq, &tx_completions); - pring->txq_cnt = 0; + /* Cancel everything on txq */ + spin_lock_irq(plock); + list_splice_init(&pring->txq, &tx_completions); + pring->txq_cnt = 0; - if (offline) { - list_splice_init(&pring->txcmplq, - &txcmplq_completions); - } else { - /* Next issue ABTS for everything on the txcmplq */ - list_for_each_entry_safe(iocb, next_iocb, - &pring->txcmplq, list) - lpfc_sli_issue_abort_iotag(phba, pring, - iocb, NULL); - } - spin_unlock_irq(&pring->ring_lock); + if (offline) { + /* Cancel everything on txcmplq */ + list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) + iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + list_splice_init(&pring->txcmplq, &tx_completions); + pring->txcmplq_cnt = 0; } else { - spin_lock_irq(&phba->hbalock); - list_splice_init(&pring->txq, &tx_completions); - pring->txq_cnt = 0; - - if (offline) { - list_splice_init(&pring->txcmplq, &txcmplq_completions); - } else { - /* Next issue ABTS for everything on the txcmplq */ - list_for_each_entry_safe(iocb, next_iocb, - &pring->txcmplq, list) - lpfc_sli_issue_abort_iotag(phba, pring, - iocb, NULL); - } - spin_unlock_irq(&phba->hbalock); + /* Issue ABTS for everything on the txcmplq */ + list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) + lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); } + spin_unlock_irq(plock); - if (offline) { - /* Cancel all the IOCBs from the completions list */ - lpfc_sli_cancel_iocbs(phba, &txcmplq_completions, - IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); - } else { - /* Make sure HBA is alive */ + if (!offline) lpfc_issue_hb_tmo(phba); - } + /* Cancel all the IOCBs from the completions list */ lpfc_sli_cancel_iocbs(phba, &tx_completions, IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED);