scsi: lpfc: Change FA-PWWN detection methodology
authorJames Smart <jsmart2021@gmail.com>
Tue, 12 Apr 2022 22:20:04 +0000 (15:20 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 19 Apr 2022 02:48:47 +0000 (22:48 -0400)
Do not rely on vendor version field of the CSPs to determine if we are in a
FA-PWWN environment. Instead, use the following procedure:

First, during HBA initialization, driver does a READ_CONFIG to determine if
FA-PWWN is configured on the HBA. A LPFC_FAWWPN_CONFIG hba_flag is set
accordingly.

Next, when the link comes up before the driver gets a link up event, the
firmware logs into the fabric with FA-PWWN. If the fabric port does not
support FA-PWWN, the driver will get a Misconfigured FA-WWN async event
before the link up. A LPFC_FAWWPN_FABRIC hba_flag will be set accordingly.

Finally, if the fabric supports FA-PWWN, the firmware will replace its CSPs
WWN with the Fabric Assigned ones. Then after link up, the driver will
retrieve the Fabric Assigned WWN when it does a READ_SPARAM mbox command.

Link: https://lore.kernel.org/r/20220412222008.126521-23-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index a62cf1a19280836a5a20f80a1aa2608b71fa3f68..346661dc5bf2dd87a6170ea6b66a7210e2894707 100644 (file)
@@ -739,9 +739,8 @@ struct lpfc_vport {
        struct list_head rcv_buffer_list;
        unsigned long rcv_buffer_time_stamp;
        uint32_t vport_flag;
-#define STATIC_VPORT   1
-#define FAWWPN_SET     2
-#define FAWWPN_PARAM_CHG       4
+#define STATIC_VPORT           0x1
+#define FAWWPN_PARAM_CHG       0x2
 
        uint16_t fdmi_num_disc;
        uint32_t fdmi_hba_mask;
index 9b982cc270d93f5b7def61bb4e6f1fc0811a8c8d..ea6de542d42a29a07a5968b653eb8d6cbc0a24c2 100644 (file)
@@ -1120,12 +1120,22 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
                                len += scnprintf(buf + len, PAGE_SIZE-len,
                                                "   Private Loop\n");
                } else {
-                       if (vport->fc_flag & FC_FABRIC)
-                               len += scnprintf(buf + len, PAGE_SIZE-len,
-                                               "   Fabric\n");
-                       else
+                       if (vport->fc_flag & FC_FABRIC) {
+                               if (phba->sli_rev == LPFC_SLI_REV4 &&
+                                   vport->port_type == LPFC_PHYSICAL_PORT &&
+                                   phba->sli4_hba.fawwpn_flag &
+                                       LPFC_FAWWPN_FABRIC)
+                                       len += scnprintf(buf + len,
+                                                        PAGE_SIZE - len,
+                                                        "   Fabric FA-PWWN\n");
+                               else
+                                       len += scnprintf(buf + len,
+                                                        PAGE_SIZE - len,
+                                                        "   Fabric\n");
+                       } else {
                                len += scnprintf(buf + len, PAGE_SIZE-len,
                                                "   Point-2-Point\n");
+                       }
                }
        }
 
index f2baf3bd8dd8100e1e8676b0def88ca41027a92d..2d846256990c3e84e4b2779fd5a6a1cb686e0aa0 100644 (file)
@@ -1183,6 +1183,7 @@ lpfc_port_link_failure(struct lpfc_vport *vport)
 void
 lpfc_linkdown_port(struct lpfc_vport *vport)
 {
+       struct lpfc_hba *phba = vport->phba;
        struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 
        if (vport->cfg_enable_fc4_type != LPFC_ENABLE_NVME)
@@ -1200,6 +1201,13 @@ lpfc_linkdown_port(struct lpfc_vport *vport)
        vport->fc_flag &= ~FC_DISC_DELAYED;
        spin_unlock_irq(shost->host_lock);
        del_timer_sync(&vport->delayed_disc_tmo);
+
+       if (phba->sli_rev == LPFC_SLI_REV4 &&
+           vport->port_type == LPFC_PHYSICAL_PORT &&
+           phba->sli4_hba.fawwpn_flag & LPFC_FAWWPN_CONFIG) {
+               /* Assume success on link up */
+               phba->sli4_hba.fawwpn_flag |= LPFC_FAWWPN_FABRIC;
+       }
 }
 
 int
index 2f5537f57846a1a65f5d8379431eaba2234138cb..70c3dd7b7105e3c1f59157c41b98f708cc5413ab 100644 (file)
@@ -511,8 +511,6 @@ struct class_parms {
        uint8_t word3Reserved2; /* Fc Word 3, bit  0: 7 */
 };
 
-#define FAPWWN_KEY_VENDOR      0x42524344 /*valid vendor version fawwpn key*/
-
 struct serv_parm {     /* Structure is in Big Endian format */
        struct csp cmn;
        struct lpfc_name portName;
index 02e230ed62802474efa61ff9223b693448822186..6d20c97762e970ba7f765e4d00e124c29fba4bcb 100644 (file)
@@ -2893,6 +2893,9 @@ struct lpfc_mbx_read_config {
 #define lpfc_mbx_rd_conf_extnts_inuse_SHIFT    31
 #define lpfc_mbx_rd_conf_extnts_inuse_MASK     0x00000001
 #define lpfc_mbx_rd_conf_extnts_inuse_WORD     word1
+#define lpfc_mbx_rd_conf_fawwpn_SHIFT          30
+#define lpfc_mbx_rd_conf_fawwpn_MASK           0x00000001
+#define lpfc_mbx_rd_conf_fawwpn_WORD           word1
 #define lpfc_mbx_rd_conf_wcs_SHIFT             28      /* warning signaling */
 #define lpfc_mbx_rd_conf_wcs_MASK              0x00000001
 #define lpfc_mbx_rd_conf_wcs_WORD              word1
index fad7ad90c57fa10d07af37b9c5c0111eb4464787..39267016f33970b663dbafa68812e6a52af530e2 100644 (file)
@@ -350,8 +350,7 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 void
 lpfc_update_vport_wwn(struct lpfc_vport *vport)
 {
-       uint8_t vvvl = vport->fc_sparam.cmn.valid_vendor_ver_level;
-       u32 *fawwpn_key = (u32 *)&vport->fc_sparam.un.vendorVersion[0];
+       struct lpfc_hba *phba = vport->phba;
 
        /*
         * If the name is empty or there exists a soft name
@@ -370,21 +369,32 @@ lpfc_update_vport_wwn(struct lpfc_vport *vport)
         */
        if (vport->fc_portname.u.wwn[0] != 0 &&
                memcmp(&vport->fc_portname, &vport->fc_sparam.portName,
-                       sizeof(struct lpfc_name)))
+                      sizeof(struct lpfc_name))) {
                vport->vport_flag |= FAWWPN_PARAM_CHG;
 
-       if (vport->fc_portname.u.wwn[0] == 0 ||
-           (vvvl == 1 && cpu_to_be32(*fawwpn_key) == FAPWWN_KEY_VENDOR) ||
-           vport->vport_flag & FAWWPN_SET) {
-               memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
-                       sizeof(struct lpfc_name));
-               vport->vport_flag &= ~FAWWPN_SET;
-               if (vvvl == 1 && cpu_to_be32(*fawwpn_key) == FAPWWN_KEY_VENDOR)
-                       vport->vport_flag |= FAWWPN_SET;
+               if (phba->sli_rev == LPFC_SLI_REV4 &&
+                   vport->port_type == LPFC_PHYSICAL_PORT &&
+                   phba->sli4_hba.fawwpn_flag & LPFC_FAWWPN_FABRIC) {
+                       lpfc_printf_log(phba, KERN_INFO,
+                                       LOG_SLI | LOG_DISCOVERY | LOG_ELS,
+                                       "2701 FA-PWWN change WWPN from %llx to "
+                                       "%llx: vflag x%x fawwpn_flag x%x\n",
+                                       wwn_to_u64(vport->fc_portname.u.wwn),
+                                       wwn_to_u64
+                                          (vport->fc_sparam.portName.u.wwn),
+                                       vport->vport_flag,
+                                       phba->sli4_hba.fawwpn_flag);
+                       memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
+                              sizeof(struct lpfc_name));
+               }
        }
+
+       if (vport->fc_portname.u.wwn[0] == 0)
+               memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
+                      sizeof(struct lpfc_name));
        else
                memcpy(&vport->fc_sparam.portName, &vport->fc_portname,
-                       sizeof(struct lpfc_name));
+                      sizeof(struct lpfc_name));
 }
 
 /**
@@ -6542,12 +6552,15 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
        case LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN:
                /* Misconfigured WWN. Reports that the SLI Port is configured
                 * to use FA-WWN, but the attached device doesn’t support it.
-                * No driver action is required.
                 * Event Data1 - N.A, Event Data2 - N.A
+                * This event only happens on the physical port.
                 */
-               lpfc_log_msg(phba, KERN_WARNING, LOG_SLI,
-                            "2699 Misconfigured FA-WWN - Attached device does "
-                            "not support FA-WWN\n");
+               lpfc_log_msg(phba, KERN_WARNING, LOG_SLI | LOG_DISCOVERY,
+                            "2699 Misconfigured FA-PWWN - Attached device "
+                            "does not support FA-PWWN\n");
+               phba->sli4_hba.fawwpn_flag &= ~LPFC_FAWWPN_FABRIC;
+               memset(phba->pport->fc_portname.u.wwn, 0,
+                      sizeof(struct lpfc_name));
                break;
        case LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE:
                /* EEPROM failure. No driver action is required */
@@ -8004,6 +8017,18 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        rc = lpfc_sli4_read_config(phba);
        if (unlikely(rc))
                goto out_free_bsmbx;
+
+       if (phba->sli4_hba.fawwpn_flag & LPFC_FAWWPN_CONFIG) {
+               /* Right now the link is down, if FA-PWWN is configured the
+                * firmware will try FLOGI before the driver gets a link up.
+                * If it fails, the driver should get a MISCONFIGURED async
+                * event which will clear this flag. The only notification
+                * the driver gets is if it fails, if it succeeds there is no
+                * notification given. Assume success.
+                */
+               phba->sli4_hba.fawwpn_flag |= LPFC_FAWWPN_FABRIC;
+       }
+
        rc = lpfc_mem_alloc_active_rrq_pool_s4(phba);
        if (unlikely(rc))
                goto out_free_bsmbx;
@@ -9807,7 +9832,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
        struct lpfc_rsrc_desc_fcfcoe *desc;
        char *pdesc_0;
        uint16_t forced_link_speed;
-       uint32_t if_type, qmin;
+       uint32_t if_type, qmin, fawwpn;
        int length, i, rc = 0, rc2;
 
        pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -9849,10 +9874,23 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
                        phba->sli4_hba.bbscn_params.word0 = rd_config->word8;
                }
 
+               fawwpn = bf_get(lpfc_mbx_rd_conf_fawwpn, rd_config);
+
+               if (fawwpn) {
+                       lpfc_printf_log(phba, KERN_INFO,
+                                       LOG_INIT | LOG_DISCOVERY,
+                                       "2702 READ_CONFIG: FA-PWWN is "
+                                       "configured on\n");
+                       phba->sli4_hba.fawwpn_flag |= LPFC_FAWWPN_CONFIG;
+               } else {
+                       phba->sli4_hba.fawwpn_flag = 0;
+               }
+
                phba->sli4_hba.conf_trunk =
                        bf_get(lpfc_mbx_rd_conf_trunk, rd_config);
                phba->sli4_hba.extents_in_use =
                        bf_get(lpfc_mbx_rd_conf_extnts_inuse, rd_config);
+
                phba->sli4_hba.max_cfg_param.max_xri =
                        bf_get(lpfc_mbx_rd_conf_xri_count, rd_config);
                /* Reduce resource usage in kdump environment */
index c4b00e188f0f47d88d12ffae2536ab793c7e5c5e..22fe7de63fb6778815eef40efb514c6d397875ff 100644 (file)
@@ -5265,6 +5265,7 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
        phba->pport->stopped = 0;
        phba->link_state = LPFC_INIT_START;
        phba->hba_flag = 0;
+       phba->sli4_hba.fawwpn_flag = 0;
        spin_unlock_irq(&phba->hbalock);
 
        memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
index e0c25699f4b85920ae1636ac8ab5133454c41705..1ddad5b170a60a88f48a6efe02df7d3c935ae99f 100644 (file)
@@ -981,6 +981,9 @@ struct lpfc_sli4_hba {
 #define lpfc_conf_trunk_port3_nd_MASK  0x1
        uint8_t flash_id;
        uint8_t asic_rev;
+       uint16_t fawwpn_flag;   /* FA-WWPN support state */
+#define LPFC_FAWWPN_CONFIG     0x1 /* FA-PWWN is configured */
+#define LPFC_FAWWPN_FABRIC     0x2 /* FA-PWWN success with Fabric */
 };
 
 enum lpfc_sge_type {