summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Tee <justin.tee@broadcom.com>2026-02-13 00:30:03 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2026-02-24 21:06:52 +0300
commit2da10bcaa58a389ca60f8e788180e0dca00739bc (patch)
tree48f829d49024d5d54ae71912b6664f20261a020d
parent6b0bcf4b6430688984fe1ee69fce7165a3e24b92 (diff)
downloadlinux-2da10bcaa58a389ca60f8e788180e0dca00739bc.tar.xz
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 <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>
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c66
1 files changed, 24 insertions, 42 deletions
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);