scsi: lpfc: Allow lpfc_plogi_confirm_nport() logic to execute for Fabric nodes
authorJustin Tee <justin.tee@broadcom.com>
Wed, 31 Jan 2024 18:51:00 +0000 (10:51 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 6 Feb 2024 01:51:35 +0000 (20:51 -0500)
Remove the early return NLP_FABRIC check in lpfc_plogi_confirm_nport()
because it is possible for switch domain controllers to change WWPN.

As a result, allow lpfc_plogi_confirm_nport() to detect that a new ndlp
should be initialized in such cases.  The old ndlp object will be cleaned
up when dev_loss_tmo callbk executes.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20240131185112.149731-6-justintee8345@gmail.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_els.c

index 4d723200690a4bd7d7329cefacaefd0e0a6ab7d0..a17c66e316375024989ff41a4cdbca234b34cb5e 100644 (file)
@@ -1696,18 +1696,13 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
        struct serv_parm *sp;
        uint8_t  name[sizeof(struct lpfc_name)];
        uint32_t keepDID = 0, keep_nlp_flag = 0;
+       int rc;
        uint32_t keep_new_nlp_flag = 0;
        uint16_t keep_nlp_state;
        u32 keep_nlp_fc4_type = 0;
        struct lpfc_nvme_rport *keep_nrport = NULL;
        unsigned long *active_rrqs_xri_bitmap = NULL;
 
-       /* Fabric nodes can have the same WWPN so we don't bother searching
-        * by WWPN.  Just return the ndlp that was given to us.
-        */
-       if (ndlp->nlp_type & NLP_FABRIC)
-               return ndlp;
-
        sp = (struct serv_parm *) ((uint8_t *) prsp + sizeof(uint32_t));
        memset(name, 0, sizeof(struct lpfc_name));
 
@@ -1717,15 +1712,9 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
        new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName);
 
        /* return immediately if the WWPN matches ndlp */
-       if (!new_ndlp || (new_ndlp == ndlp))
+       if (new_ndlp == ndlp)
                return ndlp;
 
-       /*
-        * Unregister from backend if not done yet. Could have been skipped
-        * due to ADISC
-        */
-       lpfc_nlp_unreg_node(vport, new_ndlp);
-
        if (phba->sli_rev == LPFC_SLI_REV4) {
                active_rrqs_xri_bitmap = mempool_alloc(phba->active_rrq_pool,
                                                       GFP_KERNEL);
@@ -1742,11 +1731,37 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
                         (new_ndlp ? new_ndlp->nlp_flag : 0),
                         (new_ndlp ? new_ndlp->nlp_fc4_type : 0));
 
-       keepDID = new_ndlp->nlp_DID;
+       if (!new_ndlp) {
+               rc = memcmp(&ndlp->nlp_portname, name,
+                           sizeof(struct lpfc_name));
+               if (!rc) {
+                       if (active_rrqs_xri_bitmap)
+                               mempool_free(active_rrqs_xri_bitmap,
+                                            phba->active_rrq_pool);
+                       return ndlp;
+               }
+               new_ndlp = lpfc_nlp_init(vport, ndlp->nlp_DID);
+               if (!new_ndlp) {
+                       if (active_rrqs_xri_bitmap)
+                               mempool_free(active_rrqs_xri_bitmap,
+                                            phba->active_rrq_pool);
+                       return ndlp;
+               }
+       } else {
+               if (phba->sli_rev == LPFC_SLI_REV4 &&
+                   active_rrqs_xri_bitmap)
+                       memcpy(active_rrqs_xri_bitmap,
+                              new_ndlp->active_rrqs_xri_bitmap,
+                              phba->cfg_rrq_xri_bitmap_sz);
 
-       if (phba->sli_rev == LPFC_SLI_REV4 && active_rrqs_xri_bitmap)
-               memcpy(active_rrqs_xri_bitmap, new_ndlp->active_rrqs_xri_bitmap,
-                      phba->cfg_rrq_xri_bitmap_sz);
+               /*
+                * Unregister from backend if not done yet. Could have been
+                * skipped due to ADISC
+                */
+               lpfc_nlp_unreg_node(vport, new_ndlp);
+       }
+
+       keepDID = new_ndlp->nlp_DID;
 
        /* At this point in this routine, we know new_ndlp will be
         * returned. however, any previous GID_FTs that were done