summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Tee <justin.tee@broadcom.com>2024-06-28 20:20:07 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2024-07-05 06:24:51 +0300
commit15e21dc6d6b7d7feb6b0262422b45da5e3c4b34f (patch)
tree0a308e1ad3aa9108d141e4f6762f179a351152d5
parentaeaf117cc7d28b994652491c87b929d853519d20 (diff)
downloadlinux-15e21dc6d6b7d7feb6b0262422b45da5e3c4b34f.tar.xz
scsi: lpfc: Fix handling of fully recovered fabric node in dev_loss callbk
In rare cases when a fabric node is recovered after a link bounce and before dev_loss_tmo callbk is reached, the driver may leave the fabric node in an inconsistent state with the NLP_IN_DEV_LOSS flag perpetually set. In lpfc_dev_loss_tmo_callbk, a check is added for a recovered fabric node. If the node is recovered, then don't queue the lpfc_dev_loss_tmo_handler work. In lpfc_dev_loss_tmo_handler, the path taken for the recovered fabric nodes is updated to clear the NLP_IN_DEV_LOSS flag. Signed-off-by: Justin Tee <justin.tee@broadcom.com> Link: https://lore.kernel.org/r/20240628172011.25921-5-justintee8345@gmail.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 13b08c85440f..6943f6c6395c 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -214,6 +214,11 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
return;
+ /* check for recovered fabric node */
+ if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
+ ndlp->nlp_DID == Fabric_DID)
+ return;
+
if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn))
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6789 rport name %llx != node port name %llx",
@@ -546,6 +551,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
ndlp->nlp_DID, kref_read(&ndlp->kref),
ndlp, ndlp->nlp_flag,
vport->port_state);
+ spin_lock_irqsave(&ndlp->lock, iflags);
+ ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS;
+ spin_unlock_irqrestore(&ndlp->lock, iflags);
return fcf_inuse;
}