scsi: lpfc: Prevent failure to reregister with NVMe transport after PRLI retry
authorJustin Tee <justin.tee@broadcom.com>
Fri, 25 Apr 2025 19:48:02 +0000 (12:48 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 29 Apr 2025 01:38:14 +0000 (21:38 -0400)
A failure to unregister with the NVMe transport may occur when a PRLI is
retried.

Remove duplicate testing of NLP_NVME_TARGET flag. Add a secondary check
of the registered state based on the nrport information.  Further qualify
the ndlp reference count modification when nvme_fc_register_remoteport()
returns an error.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20250425194806.3585-5-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_nvme.c

index b5273cb1adbdb7d7347d4b0827763164109c06b4..9e585af05bec92c9f341ed869826f228ef3dc37c 100644 (file)
@@ -4695,9 +4695,7 @@ lpfc_nlp_unreg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
        if (ndlp->fc4_xpt_flags & NVME_XPT_REGD) {
                vport->phba->nport_event_cnt++;
                if (vport->phba->nvmet_support == 0) {
-                       /* Start devloss if target. */
-                       if (ndlp->nlp_type & NLP_NVME_TARGET)
-                               lpfc_nvme_unregister_port(vport, ndlp);
+                       lpfc_nvme_unregister_port(vport, ndlp);
                } else {
                        /* NVMET has no upcall. */
                        lpfc_nlp_put(ndlp);
index b1adb9f59097d083a3ae24f4ddf6413350a0368d..9d61e1251a2faa416d2e0d36d43103c0a2628e74 100644 (file)
@@ -2508,7 +2508,10 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                                 "6031 RemotePort Registration failed "
                                 "err: %d, DID x%06x ref %u\n",
                                 ret, ndlp->nlp_DID, kref_read(&ndlp->kref));
-               lpfc_nlp_put(ndlp);
+
+               /* Only release reference if one was taken for this request */
+               if (!oldrport)
+                       lpfc_nlp_put(ndlp);
        }
 
        return ret;
@@ -2614,7 +2617,8 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
         * clear any rport state until the transport calls back.
         */
 
-       if (ndlp->nlp_type & NLP_NVME_TARGET) {
+       if ((ndlp->nlp_type & NLP_NVME_TARGET) ||
+           (remoteport->port_role & FC_PORT_ROLE_NVME_TARGET)) {
                /* No concern about the role change on the nvme remoteport.
                 * The transport will update it.
                 */