]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
lpfc: Add Fabric assigned WWN support.
authorJames Smart <james.smart@broadcom.com>
Wed, 12 Jul 2017 22:38:40 +0000 (18:38 -0400)
committerChuck Anderson <chuck.anderson@oracle.com>
Fri, 14 Jul 2017 00:12:50 +0000 (17:12 -0700)
[backport of a2ed2d89b451f7ca26b049ea1664f4397c5df87b]
From: rkennedy <dick.kennedy@avagotech.com>

Orabug: 26439257

Adding support for Fabric assigned WWPN and WWNN.

Firmware sends first FLOGI to fabric with vendor version changes.
On link up driver gets updated service parameter with FAWWN assigned port
name.  Driver sends 2nd FLOGI with updated fawwpn and modifies the
vport->fc_portname in driver.

Note:
Soft wwpn will not be allowed when fawwpn is enabled.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.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

index 2bdf95a57979dce031e6676ccbb00a3b41a2762c..db07b1a8548c86da01730d876f78971207d73f15 100644 (file)
@@ -441,6 +441,8 @@ struct lpfc_vport {
        unsigned long rcv_buffer_time_stamp;
        uint32_t vport_flag;
 #define STATIC_VPORT   1
+#define FAWWPN_SET     2
+#define FAWWPN_PARAM_CHG       4
 
        uint16_t fdmi_num_disc;
        uint32_t fdmi_hba_mask;
index 0a97943ebcd07ed8f03219d0e4125abb503502e9..651d39cdda0d1eb2d29f504e596d496eeb384535 100644 (file)
@@ -2052,6 +2052,8 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_hba   *phba = vport->phba;
        unsigned int cnt = count;
+       uint8_t vvvl = vport->fc_sparam.cmn.valid_vendor_ver_level;
+       u32 *fawwpn_key = (uint32_t *)&vport->fc_sparam.vendorVersion[0];
 
        /*
         * We're doing a simple sanity check for soft_wwpn setting.
@@ -2065,6 +2067,12 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
         * here. The intent is to protect against the random user or
         * application that is just writing attributes.
         */
+       if (vvvl == 1 && cpu_to_be32(*fawwpn_key) == FAPWWN_KEY_VENDOR) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                "0051 "LPFC_DRIVER_NAME" soft wwpn can not"
+                                " be enabled: fawwpn is enabled\n");
+               return -EINVAL;
+       }
 
        /* count may include a LF at end of string */
        if (buf[cnt-1] == '\n')
index 0e21aa5a85a42144f84fd192faf7ada629692e36..fd45a798c2aa03ab30c9a6d25b5049e90be7d95a 100644 (file)
@@ -604,9 +604,11 @@ lpfc_check_clean_addr_bit(struct lpfc_vport *vport,
                memcmp(&vport->fabric_portname, &sp->portName,
                        sizeof(struct lpfc_name)) ||
                memcmp(&vport->fabric_nodename, &sp->nodeName,
-                       sizeof(struct lpfc_name)))
+                       sizeof(struct lpfc_name)) ||
+               (vport->vport_flag & FAWWPN_PARAM_CHG)) {
                fabric_param_changed = 1;
-
+               vport->vport_flag &= ~FAWWPN_PARAM_CHG;
+       }
        /*
         * Word 1 Bit 31 in common service parameter is overloaded.
         * Word 1 Bit 31 in FLOGI request is multiple NPort request
@@ -8579,7 +8581,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        pcmd += sizeof(uint32_t); /* Node Name */
        pcmd += sizeof(uint32_t); /* Node Name */
        memcpy(pcmd, &vport->fc_nodename, 8);
-
+       memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion));
        lpfc_set_disctmo(vport);
 
        phba->fc_stat.elsXmitFDISC++;
index e51549164ec3bc93be729ef0c5563386c3730bcd..d32d68e1a70e89090da918c2bb52c7ca75db7851 100644 (file)
@@ -2978,6 +2978,7 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        MAILBOX_t *mb = &pmb->u.mb;
        struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
        struct lpfc_vport  *vport = pmb->vport;
+       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
        struct serv_parm *sp = &vport->fc_sparam;
        uint32_t ed_tov;
 
@@ -3007,6 +3008,7 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        }
 
        lpfc_update_vport_wwn(vport);
+       fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
        if (vport->port_type == LPFC_PHYSICAL_PORT) {
                memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn));
                memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn));
@@ -3284,6 +3286,7 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        struct lpfc_mbx_read_top *la;
        MAILBOX_t *mb = &pmb->u.mb;
        struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+       uint8_t attn_type;
 
        /* Unblock ELS traffic */
        phba->sli.ring[LPFC_ELS_RING].flag &= ~LPFC_STOP_IOCB_EVENT;
@@ -3298,6 +3301,7 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        }
 
        la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop;
+       attn_type = bf_get(lpfc_mbx_read_top_att_type, la);
 
        memcpy(&phba->alpa_map[0], mp->virt, 128);
 
@@ -3310,7 +3314,7 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 
        if (phba->fc_eventTag <= la->eventTag) {
                phba->fc_stat.LinkMultiEvent++;
-               if (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)
+               if (attn_type == LPFC_ATT_LINK_UP)
                        if (phba->fc_eventTag != 0)
                                lpfc_linkdown(phba);
        }
@@ -3326,7 +3330,7 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        }
 
        phba->link_events++;
-       if ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) &&
+       if ((attn_type == LPFC_ATT_LINK_UP) &&
            !(phba->sli.sli_flag & LPFC_MENLO_MAINT)) {
                phba->fc_stat.LinkUp++;
                if (phba->link_flag & LS_LOOPBACK_MODE) {
@@ -3352,8 +3356,8 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                        phba->wait_4_mlo_maint_flg);
                }
                lpfc_mbx_process_link_up(phba, la);
-       } else if (bf_get(lpfc_mbx_read_top_att_type, la) ==
-                  LPFC_ATT_LINK_DOWN) {
+       } else if (attn_type == LPFC_ATT_LINK_DOWN ||
+                  attn_type == LPFC_ATT_UNEXP_WWPN) {
                phba->fc_stat.LinkDown++;
                if (phba->link_flag & LS_LOOPBACK_MODE)
                        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -3362,6 +3366,14 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                "Data: x%x x%x x%x\n",
                                la->eventTag, phba->fc_eventTag,
                                phba->pport->port_state, vport->fc_flag);
+               else if (attn_type == LPFC_ATT_UNEXP_WWPN)
+                       lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+                               "1313 Link Down UNEXP WWPN Event x%x received "
+                               "Data: x%x x%x x%x x%x x%x\n",
+                               la->eventTag, phba->fc_eventTag,
+                               phba->pport->port_state, vport->fc_flag,
+                               bf_get(lpfc_mbx_read_top_mm, la),
+                               bf_get(lpfc_mbx_read_top_fa, la));
                else
                        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
                                "1305 Link Down Event x%x received "
@@ -3372,8 +3384,8 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                bf_get(lpfc_mbx_read_top_fa, la));
                lpfc_mbx_issue_link_down(phba);
        }
-       if ((phba->sli.sli_flag & LPFC_MENLO_MAINT) &&
-           ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP))) {
+       if (phba->sli.sli_flag & LPFC_MENLO_MAINT &&
+           attn_type == LPFC_ATT_LINK_UP) {
                if (phba->link_state != LPFC_LINK_DOWN) {
                        phba->fc_stat.LinkDown++;
                        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
index 8519270415150ce17058544df6c270680badb79d..2aede76b2746fe089564784980a5946ece525fd2 100644 (file)
@@ -486,6 +486,8 @@ 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;
@@ -2851,6 +2853,7 @@ struct lpfc_mbx_read_top {
 #define LPFC_ATT_RESERVED    0x00      /* Reserved - attType */
 #define LPFC_ATT_LINK_UP     0x01      /* Link is up */
 #define LPFC_ATT_LINK_DOWN   0x02      /* Link is down */
+#define LPFC_ATT_UNEXP_WWPN  0x06      /* Link is down Unexpected WWWPN */
        uint32_t word3;
 #define lpfc_mbx_read_top_alpa_granted_SHIFT   24
 #define lpfc_mbx_read_top_alpa_granted_MASK    0x000000FF
index b156e911d9cf39945c981916d9ad4e0d6cf18bab..8b8eaa07931bca581c7c87811d7bb9a69f058071 100644 (file)
@@ -3495,6 +3495,7 @@ struct lpfc_acqe_fc_la {
 #define LPFC_FC_LA_TYPE_NO_HARD_ALPA   0x3
 #define LPFC_FC_LA_TYPE_MDS_LINK_DOWN  0x4
 #define LPFC_FC_LA_TYPE_MDS_LOOPBACK   0x5
+#define LPFC_FC_LA_TYPE_UNEXP_WWPN     0x6
 #define lpfc_acqe_fc_la_port_type_SHIFT                6
 #define lpfc_acqe_fc_la_port_type_MASK         0x00000003
 #define lpfc_acqe_fc_la_port_type_WORD         word0
index e46bf378dc5894c38bb8dde895f6ec161cc7889c..582c7a635b306b6e5a95c7854e14529d5893ea4e 100644 (file)
@@ -331,6 +331,9 @@ 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.vendorVersion[0];
+
        /* If the soft name exists then update it using the service params */
        if (vport->phba->cfg_soft_wwnn)
                u64_to_wwn(vport->phba->cfg_soft_wwnn,
@@ -350,9 +353,25 @@ lpfc_update_vport_wwn(struct lpfc_vport *vport)
                memcpy(&vport->fc_sparam.nodeName, &vport->fc_nodename,
                        sizeof(struct lpfc_name));
 
-       if (vport->fc_portname.u.wwn[0] == 0 || vport->phba->cfg_soft_wwpn)
+       /*
+        * If the port name has changed, then set the Param changes flag
+        * to unreg the login
+        */
+       if (vport->fc_portname.u.wwn[0] != 0 &&
+               memcmp(&vport->fc_portname, &vport->fc_sparam.portName,
+                       sizeof(struct lpfc_name)))
+               vport->vport_flag |= FAWWPN_PARAM_CHG;
+
+       if (vport->fc_portname.u.wwn[0] == 0 ||
+           vport->phba->cfg_soft_wwpn ||
+           (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;
+       }
        else
                memcpy(&vport->fc_sparam.portName, &vport->fc_portname,
                        sizeof(struct lpfc_name));
@@ -4182,9 +4201,15 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
                /* Parse and translate link attention fields */
                la = (struct lpfc_mbx_read_top *)&pmb->u.mb.un.varReadTop;
                la->eventTag = acqe_fc->event_tag;
-               bf_set(lpfc_mbx_read_top_att_type, la,
-                      LPFC_FC_LA_TYPE_LINK_DOWN);
 
+               if (phba->sli4_hba.link_state.status ==
+                   LPFC_FC_LA_TYPE_UNEXP_WWPN) {
+                       bf_set(lpfc_mbx_read_top_att_type, la,
+                              LPFC_FC_LA_TYPE_UNEXP_WWPN);
+               } else {
+                       bf_set(lpfc_mbx_read_top_att_type, la,
+                              LPFC_FC_LA_TYPE_LINK_DOWN);
+               }
                /* Invoke the mailbox command callback function */
                lpfc_mbx_cmpl_read_topology(phba, pmb);