scsi: lpfc: Add FDMI Vendor MIB support
authorJames Smart <james.smart@broadcom.com>
Tue, 20 Oct 2020 20:27:17 +0000 (13:27 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 27 Oct 2020 01:42:39 +0000 (21:42 -0400)
Created new attribute lpfc_enable_mi, which by default is enabled.

Add command definition bits for SLI-4 parameters that recognize whether the
adapter has MIB information support and what revision of MIB data.  Using
the adapter information, register vendor-specific MIB support with FDMI.
The registration will be done every link up.

During FDMI registration, encountered a couple of errors when reverting to
FDMI rev1. Code needed to exist once reverting. Fixed these.

Link: https://lore.kernel.org/r/20201020202719.54726-8-james.smart@broadcom.com
Co-developed-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.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_ct.c
drivers/scsi/lpfc/lpfc_els.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_sli4.h

index 93e5076..3c77e02 100644 (file)
@@ -744,7 +744,8 @@ struct lpfc_hba {
 #define LS_NPIV_FAB_SUPPORTED 0x2      /* Fabric supports NPIV */
 #define LS_IGNORE_ERATT       0x4      /* intr handler should ignore ERATT */
 #define LS_MDS_LINK_DOWN      0x8      /* MDS Diagnostics Link Down */
-#define LS_MDS_LOOPBACK      0x10      /* MDS Diagnostics Link Up (Loopback) */
+#define LS_MDS_LOOPBACK       0x10     /* MDS Diagnostics Link Up (Loopback) */
+#define LS_CT_VEN_RPA         0x20     /* Vendor RPA sent to switch */
 
        uint32_t hba_flag;      /* hba generic flags */
 #define HBA_ERATT_HANDLED      0x1 /* This flag is set when eratt handled */
@@ -922,6 +923,7 @@ struct lpfc_hba {
 #define LPFC_ENABLE_NVME 2
 #define LPFC_ENABLE_BOTH 3
        uint32_t cfg_enable_pbde;
+       uint32_t cfg_enable_mi;
        struct nvmet_fc_target_port *targetport;
        lpfc_vpd_t vpd;         /* vital product data */
 
index 2d81047..0673d94 100644 (file)
@@ -6134,6 +6134,14 @@ LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
  */
 LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
 
+/*
+ * lpfc_enable_mi: Enable FDMI MIB
+ *       0  = disabled
+ *       1  = enabled (default)
+ * Value range is [0,1].
+ */
+LPFC_ATTR_R(enable_mi, 1, 0, 1, "Enable MI");
+
 struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_nvme_info,
        &dev_attr_scsi_stat,
@@ -6251,6 +6259,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_ras_fwlog_func,
        &dev_attr_lpfc_enable_bbcr,
        &dev_attr_lpfc_enable_dpp,
+       &dev_attr_lpfc_enable_mi,
        NULL,
 };
 
@@ -7355,6 +7364,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        lpfc_irq_chann_init(phba, lpfc_irq_chann);
        lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
        lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
+       lpfc_enable_mi_init(phba, lpfc_enable_mi);
 
        if (phba->sli_rev != LPFC_SLI_REV4) {
                /* NVME only supported on SLI4 */
index a8bf4d0..434e39d 100644 (file)
@@ -1959,6 +1959,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
                                /* Start over */
                                lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
+                               return;
                        }
                        if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
                                vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
@@ -1968,12 +1969,21 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        return;
 
                case SLI_MGMT_RPA:
+                       /* No retry on Vendor RPA */
+                       if (phba->link_flag & LS_CT_VEN_RPA) {
+                               lpfc_printf_vlog(vport, KERN_ERR,
+                                                LOG_DISCOVERY | LOG_ELS,
+                                                "6460 VEN FDMI RPA failure\n");
+                               phba->link_flag &= ~LS_CT_VEN_RPA;
+                               return;
+                       }
                        if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) {
                                /* Fallback to FDMI-1 */
                                vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR;
                                vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
                                /* Start over */
                                lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
+                               return;
                        }
                        if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
                                vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
@@ -2004,6 +2014,33 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                else
                        lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0);
                break;
+       case SLI_MGMT_RPA:
+               if (vport->port_type == LPFC_PHYSICAL_PORT &&
+                   phba->cfg_enable_mi &&
+                   phba->sli4_hba.pc_sli4_params.mi_ver > LPFC_MIB1_SUPPORT) {
+                       /* mi is only for the phyical port, no vports */
+                       if (phba->link_flag & LS_CT_VEN_RPA) {
+                               lpfc_printf_vlog(vport, KERN_INFO,
+                                                LOG_DISCOVERY | LOG_ELS,
+                                                "6449 VEN RPA Success\n");
+                               break;
+                       }
+
+                       if (lpfc_fdmi_cmd(vport, ndlp, cmd,
+                                         LPFC_FDMI_VENDOR_ATTR_mi) == 0)
+                               phba->link_flag |= LS_CT_VEN_RPA;
+                       lpfc_printf_vlog(vport, KERN_INFO,
+                                       LOG_DISCOVERY | LOG_ELS,
+                                       "6458 Send MI FDMI:%x Flag x%x\n",
+                                       phba->sli4_hba.pc_sli4_params.mi_value,
+                                       phba->link_flag);
+               } else {
+                       lpfc_printf_vlog(vport, KERN_INFO,
+                                        LOG_DISCOVERY | LOG_ELS,
+                                        "6459 No FDMI VEN MI support - "
+                                        "RPA Success\n");
+               }
+               break;
        }
        return;
 }
@@ -2974,6 +3011,28 @@ lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport,
        return size;
 }
 
+int
+lpfc_fdmi_vendor_attr_mi(struct lpfc_vport *vport,
+                         struct lpfc_fdmi_attr_def *ad)
+{
+       struct lpfc_hba *phba = vport->phba;
+       struct lpfc_fdmi_attr_entry *ae;
+       uint32_t len, size;
+       char mibrevision[16];
+
+       ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+       memset(ae, 0, 256);
+       sprintf(mibrevision, "ELXE2EM:%04d",
+               phba->sli4_hba.pc_sli4_params.mi_value);
+       strncpy(ae->un.AttrString, &mibrevision[0], sizeof(ae->un.AttrString));
+       len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
+       len += (len & 3) ? (4 - (len & 3)) : 4;
+       size = FOURBYTES + len;
+       ad->AttrLen = cpu_to_be16(size);
+       ad->AttrType = cpu_to_be16(RPRT_VENDOR_MI);
+       return size;
+}
+
 /* RHBA attribute jump table */
 int (*lpfc_fdmi_hba_action[])
        (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = {
@@ -3025,6 +3084,7 @@ int (*lpfc_fdmi_port_action[])
        lpfc_fdmi_smart_attr_port_info,     /* bit20  RPRT_SMART_PORT_INFO    */
        lpfc_fdmi_smart_attr_qos,           /* bit21  RPRT_SMART_QOS          */
        lpfc_fdmi_smart_attr_security,      /* bit22  RPRT_SMART_SECURITY     */
+       lpfc_fdmi_vendor_attr_mi,           /* bit23  RPRT_VENDOR_MI          */
 };
 
 /**
index b609451..de3a59f 100644 (file)
@@ -3335,6 +3335,12 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry)
                lpfc_els_free_iocb(phba, elsiocb);
                return 1;
        }
+
+       /* Only keep the ndlp if RDF is being sent */
+       if (!phba->cfg_enable_mi ||
+           phba->sli4_hba.pc_sli4_params.mi_ver < LPFC_MIB3_SUPPORT)
+               return 0;
+
        /* This will cause the callback-function lpfc_cmpl_els_cmd to
         * trigger the release of node.
         */
index 9746d2f..c61eb60 100644 (file)
@@ -3205,7 +3205,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
        }
 
        phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la);
-       phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
+       phba->link_flag &= ~(LS_NPIV_FAB_SUPPORTED | LS_CT_VEN_RPA);
 
        shost = lpfc_shost_from_vport(vport);
        if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
@@ -4133,7 +4133,9 @@ out:
                /* Issue SCR just before NameServer GID_FT Query */
                lpfc_issue_els_scr(vport, 0);
 
-               lpfc_issue_els_rdf(vport, 0);
+               if (!phba->cfg_enable_mi ||
+                   phba->sli4_hba.pc_sli4_params.mi_ver < LPFC_MIB3_SUPPORT)
+                       lpfc_issue_els_rdf(vport, 0);
        }
 
        vport->fc_ns_retry = 0;
index c20034b..28b8a39 100644 (file)
@@ -1465,7 +1465,7 @@ struct lpfc_fdmi_reg_portattr {
 #define LPFC_FDMI2_HBA_ATTR                    0x0002efff
 
 /*
- * Port Attrubute Types
+ * Port Attribute Types
  */
 #define  RPRT_SUPPORTED_FC4_TYPES     0x1 /* 32 byte binary array */
 #define  RPRT_SUPPORTED_SPEED         0x2 /* 32-bit unsigned int */
@@ -1483,6 +1483,7 @@ struct lpfc_fdmi_reg_portattr {
 #define  RPRT_PORT_STATE              0x101 /* 32-bit unsigned int */
 #define  RPRT_DISC_PORT               0x102 /* 32-bit unsigned int */
 #define  RPRT_PORT_ID                 0x103 /* 32-bit unsigned int */
+#define  RPRT_VENDOR_MI               0xf047 /* vendor ascii string */
 #define  RPRT_SMART_SERVICE           0xf100 /* 4 to 256 byte ASCII string */
 #define  RPRT_SMART_GUID              0xf101 /* 8 byte WWNN + 8 byte WWPN */
 #define  RPRT_SMART_VERSION           0xf102 /* 4 to 256 byte ASCII string */
@@ -1515,6 +1516,7 @@ struct lpfc_fdmi_reg_portattr {
 #define LPFC_FDMI_SMART_ATTR_port_info         0x00100000 /* Vendor specific */
 #define LPFC_FDMI_SMART_ATTR_qos               0x00200000 /* Vendor specific */
 #define LPFC_FDMI_SMART_ATTR_security          0x00400000 /* Vendor specific */
+#define LPFC_FDMI_VENDOR_ATTR_mi               0x00800000 /* Vendor specific */
 
 /* Bit mask for FDMI-1 defined PORT attributes */
 #define LPFC_FDMI1_PORT_ATTR                   0x0000003f
index 12e4e76..49f5559 100644 (file)
@@ -3506,8 +3506,14 @@ struct lpfc_sli4_parameters {
 #define cfg_max_tow_xri_MASK                   0x0000ffff
 #define cfg_max_tow_xri_WORD                   word20
 
-       uint32_t word21;                        /* RESERVED */
-       uint32_t word22;                        /* RESERVED */
+       uint32_t word21;
+#define cfg_mib_bde_cnt_SHIFT                  16
+#define cfg_mib_bde_cnt_MASK                   0x000000ff
+#define cfg_mib_bde_cnt_WORD                   word21
+#define cfg_mi_ver_SHIFT                       0
+#define cfg_mi_ver_MASK                                0x0000ffff
+#define cfg_mi_ver_WORD                                word21
+       uint32_t mib_size;
        uint32_t word23;                        /* RESERVED */
 
        uint32_t word24;
index e5879dc..aa7931a 100644 (file)
@@ -12314,6 +12314,21 @@ fcponly:
        else
                phba->nsler = 0;
 
+       /* Save PB info for use during HBA setup */
+       sli4_params->mi_ver = bf_get(cfg_mi_ver, mbx_sli4_parameters);
+       sli4_params->mib_bde_cnt = bf_get(cfg_mib_bde_cnt, mbx_sli4_parameters);
+       sli4_params->mib_size = mbx_sli4_parameters->mib_size;
+       sli4_params->mi_value = LPFC_DFLT_MIB_VAL;
+
+       /* Next we check for Vendor MIB support */
+       if (sli4_params->mi_ver && phba->cfg_enable_mi)
+               phba->cfg_fdmi_on = LPFC_FDMI_SUPPORT;
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                       "6461 MIB attr %d  enable %d  FDMI %d buf %d:%d\n",
+                       sli4_params->mi_ver, phba->cfg_enable_mi,
+                       sli4_params->mi_value, sli4_params->mib_bde_cnt,
+                       sli4_params->mib_size);
        return 0;
 }
 
index 100cb1a..26f19c9 100644 (file)
@@ -549,6 +549,14 @@ struct lpfc_pc_sli4_params {
        uint32_t hdr_pp_align;
        uint32_t sgl_pages_max;
        uint32_t sgl_pp_align;
+       uint32_t mib_size;
+       uint16_t mi_ver;
+#define LPFC_MIB1_SUPPORT      1
+#define LPFC_MIB2_SUPPORT      2
+#define LPFC_MIB3_SUPPORT      3
+       uint16_t mi_value;
+#define LPFC_DFLT_MIB_VAL      2
+       uint8_t mib_bde_cnt;
        uint8_t cqv;
        uint8_t mqv;
        uint8_t wqv;