]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: lpfc: Fix incorrect txcmplq_cnt during cleanup in lpfc_sli_abort_ring()
authorJustin Tee <justin.tee@broadcom.com>
Thu, 12 Feb 2026 21:30:03 +0000 (13:30 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 24 Feb 2026 18:06:52 +0000 (13:06 -0500)
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 <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20260212213008.149873-9-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_sli.c

index fc7d478779f84e832ce615954f10c69d100d48f8..bd71292e7480e505888006359733de7bf12fcc7f 100644 (file)
@@ -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);