]> Pileus Git - ~andy/linux/blobdiff - drivers/scsi/bfa/bfa_fcs_lport.c
Merge tag 'for-3.7' of git://openrisc.net/jonas/linux
[~andy/linux] / drivers / scsi / bfa / bfa_fcs_lport.c
index bcc4966e8ba484d6f6772e6dbca499336ead788a..1224d0462a491a5911fa3eda6d37d36a1ec7caf2 100644 (file)
 
 BFA_TRC_FILE(FCS, PORT);
 
+/*
+ * ALPA to LIXA bitmap mapping
+ *
+ * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
+ * is for L_bit (login required) and is filled as ALPA 0x00 here.
+ */
+static const u8 loop_alpa_map[] = {
+       0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */
+       0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */
+       0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */
+       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */
+
+       0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */
+       0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */
+       0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */
+       0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */
+
+       0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */
+       0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */
+       0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */
+       0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */
+
+       0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */
+       0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */
+       0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */
+       0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */
+};
+
 static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
                                         struct fchs_s *rx_fchs, u8 reason_code,
                                         u8 reason_code_expl);
@@ -51,6 +79,10 @@ static void  bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
 static void    bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
 static void    bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
 
+static void    bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port);
+static void    bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port);
+static void    bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port);
+
 static struct {
        void            (*init) (struct bfa_fcs_lport_s *port);
        void            (*online) (struct bfa_fcs_lport_s *port);
@@ -62,7 +94,9 @@ static struct {
        bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
                        bfa_fcs_lport_fab_offline}, {
        bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
-                       bfa_fcs_lport_n2n_offline},
+                       bfa_fcs_lport_n2n_offline}, {
+       bfa_fcs_lport_loop_init, bfa_fcs_lport_loop_online,
+                       bfa_fcs_lport_loop_offline},
        };
 
 /*
@@ -131,6 +165,8 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
                /* If vport - send completion call back */
                if (port->vport)
                        bfa_fcs_vport_stop_comp(port->vport);
+               else
+                       bfa_wc_down(&(port->fabric->stop_wc));
                break;
 
        case BFA_FCS_PORT_SM_OFFLINE:
@@ -166,6 +202,8 @@ bfa_fcs_lport_sm_online(
                        /* If vport - send completion call back */
                        if (port->vport)
                                bfa_fcs_vport_stop_comp(port->vport);
+                       else
+                               bfa_wc_down(&(port->fabric->stop_wc));
                } else {
                        bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
                        list_for_each_safe(qe, qen, &port->rport_q) {
@@ -222,6 +260,8 @@ bfa_fcs_lport_sm_offline(
                        /* If vport - send completion call back */
                        if (port->vport)
                                bfa_fcs_vport_stop_comp(port->vport);
+                       else
+                               bfa_wc_down(&(port->fabric->stop_wc));
                } else {
                        bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
                        list_for_each_safe(qe, qen, &port->rport_q) {
@@ -267,6 +307,8 @@ bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
                        /* If vport - send completion call back */
                        if (port->vport)
                                bfa_fcs_vport_stop_comp(port->vport);
+                       else
+                               bfa_wc_down(&(port->fabric->stop_wc));
                }
                break;
 
@@ -340,7 +382,7 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
        bfa_trc(port->fcs, rx_fchs->d_id);
        bfa_trc(port->fcs, rx_fchs->s_id);
 
-       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
        if (!fcxp)
                return;
 
@@ -370,7 +412,7 @@ bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
        bfa_trc(port->fcs, rx_fchs->d_id);
        bfa_trc(port->fcs, rx_fchs->s_id);
 
-       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
        if (!fcxp)
                return;
 
@@ -507,7 +549,7 @@ bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
        bfa_trc(port->fcs, rx_fchs->s_id);
        bfa_trc(port->fcs, rx_fchs->d_id);
 
-       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
        if (!fcxp)
                return;
 
@@ -552,7 +594,7 @@ bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
        bfa_trc(port->fcs, rx_fchs->d_id);
        bfa_trc(port->fcs, rx_len);
 
-       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
        if (!fcxp)
                return;
 
@@ -684,7 +726,7 @@ bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
        bfa_trc(port->fcs, rx_fchs->d_id);
        bfa_trc(port->fcs, rx_fchs->s_id);
 
-       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
        if (!fcxp)
                return;
 
@@ -853,6 +895,25 @@ bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
        return NULL;
 }
 
+/*
+ * OLD_PID based Lookup for a R-Port in the Port R-Port Queue
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head        *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rport = (struct bfa_fcs_rport_s *) qe;
+               if (rport->old_pid == pid)
+                       return rport;
+       }
+
+       bfa_trc(port->fcs, pid);
+       return NULL;
+}
+
 /*
  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
  */
@@ -891,6 +952,26 @@ bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
        return NULL;
 }
 
+/*
+ * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port,
+                                    wwn_t pwwn, u32 pid)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head        *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rport = (struct bfa_fcs_rport_s *) qe;
+               if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid)
+                       return rport;
+       }
+
+       bfa_trc(port->fcs, pwwn);
+       return NULL;
+}
+
 /*
  * Called by rport module when new rports are discovered.
  */
@@ -938,6 +1019,16 @@ bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
        bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
 }
 
+/*
+ * Called by fabric for base port and by vport for virtual ports
+ * when target mode driver is unloaded.
+ */
+void
+bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port)
+{
+       bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP);
+}
+
 /*
  * Called by fabric to delete base lport and associated resources.
  *
@@ -1070,7 +1161,7 @@ static void
 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
 {
        bfa_fcs_lport_ns_online(port);
-       bfa_fcs_lport_scn_online(port);
+       bfa_fcs_lport_fab_scn_online(port);
 }
 
 /*
@@ -1164,6 +1255,98 @@ bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
        n2n_port->reply_oxid = 0;
 }
 
+void
+bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port)
+{
+       int i = 0, j = 0, bit = 0, alpa_bit = 0;
+       u8 k = 0;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa);
+
+       port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid;
+       port->pid = fcport->myalpa;
+       port->pid = bfa_hton3b(port->pid);
+
+       for (i = 0; i < (FC_ALPA_MAX / 8); i++) {
+               for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) {
+                       bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]);
+                       bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j)));
+                       if (bit) {
+                               port->port_topo.ploop.alpa_pos_map[k] =
+                                       loop_alpa_map[(i * 8) + alpa_bit];
+                               k++;
+                               bfa_trc(port->fcs->bfa, k);
+                               bfa_trc(port->fcs->bfa,
+                                        port->port_topo.ploop.alpa_pos_map[k]);
+                       }
+               }
+       }
+       port->port_topo.ploop.num_alpa = k;
+}
+
+/*
+ * Called by fcs/port to initialize Loop topology.
+ */
+static void
+bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port)
+{
+}
+
+/*
+ * Called by fcs/port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port)
+{
+       u8 num_alpa = 0, alpabm_valid = 0;
+       struct bfa_fcs_rport_s *rport;
+       u8 *alpa_map = NULL;
+       int i = 0;
+       u32 pid;
+
+       bfa_fcport_get_loop_attr(port);
+
+       num_alpa = port->port_topo.ploop.num_alpa;
+       alpabm_valid = port->port_topo.ploop.alpabm_valid;
+       alpa_map = port->port_topo.ploop.alpa_pos_map;
+
+       bfa_trc(port->fcs->bfa, port->pid);
+       bfa_trc(port->fcs->bfa, num_alpa);
+       if (alpabm_valid == 1) {
+               for (i = 0; i < num_alpa; i++) {
+                       bfa_trc(port->fcs->bfa, alpa_map[i]);
+                       if (alpa_map[i] != bfa_hton3b(port->pid)) {
+                               pid = alpa_map[i];
+                               bfa_trc(port->fcs->bfa, pid);
+                               rport = bfa_fcs_lport_get_rport_by_pid(port,
+                                               bfa_hton3b(pid));
+                               if (!rport)
+                                       rport = bfa_fcs_rport_create(port,
+                                               bfa_hton3b(pid));
+                       }
+               }
+       } else {
+               for (i = 0; i < MAX_ALPA_COUNT; i++) {
+                       if (alpa_map[i] != port->pid) {
+                               pid = loop_alpa_map[i];
+                               bfa_trc(port->fcs->bfa, pid);
+                               rport = bfa_fcs_lport_get_rport_by_pid(port,
+                                               bfa_hton3b(pid));
+                               if (!rport)
+                                       rport = bfa_fcs_rport_create(port,
+                                               bfa_hton3b(pid));
+                       }
+               }
+       }
+}
+
+/*
+ * Called by fcs/port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port)
+{
+}
+
 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
 
 /*
@@ -1657,10 +1840,11 @@ bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-                                       bfa_fcs_lport_fdmi_send_rhba, fdmi);
+                               bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE);
                return;
        }
        fdmi->fcxp = fcxp;
@@ -1830,13 +2014,10 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
                                         sizeof(templen));
        }
 
-       /*
-        * f/w Version = driver version
-        */
        attr = (struct fdmi_attr_s *) curr_ptr;
        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
-       templen = (u16) strlen(fcs_hba_attr->driver_version);
-       memcpy(attr->value, fcs_hba_attr->driver_version, templen);
+       templen = (u16) strlen(fcs_hba_attr->fw_version);
+       memcpy(attr->value, fcs_hba_attr->fw_version, templen);
        templen = fc_roundup(templen, sizeof(u32));
        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
        len += templen;
@@ -1931,10 +2112,11 @@ bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-                                       bfa_fcs_lport_fdmi_send_rprt, fdmi);
+                               bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
                return;
        }
        fdmi->fcxp = fcxp;
@@ -2146,10 +2328,11 @@ bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-                                       bfa_fcs_lport_fdmi_send_rpa, fdmi);
+                               bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
                return;
        }
        fdmi->fcxp = fcxp;
@@ -2236,6 +2419,7 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 {
        struct bfa_fcs_lport_s *port = fdmi->ms->port;
        struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
+       struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
 
        memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
 
@@ -2271,7 +2455,9 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
                                sizeof(driver_info->host_os_patch));
        }
 
-       hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
+       /* Retrieve the max frame size from the port attr */
+       bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
+       hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
 }
 
 static void
@@ -2331,7 +2517,7 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
        /*
         * Max PDU Size.
         */
-       port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
+       port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize);
 
        /*
         * OS device Name
@@ -2736,10 +2922,11 @@ bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->pid);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-                                       bfa_fcs_lport_ms_send_gmal, ms);
+                               bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
                return;
        }
        ms->fcxp = fcxp;
@@ -2936,10 +3123,11 @@ bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->pid);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-                                       bfa_fcs_lport_ms_send_gfn, ms);
+                               bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
                return;
        }
        ms->fcxp = fcxp;
@@ -3012,11 +3200,12 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->pid);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                port->stats.ms_plogi_alloc_wait++;
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-                                       bfa_fcs_lport_ms_send_plogi, ms);
+                               bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
                return;
        }
        ms->fcxp = fcxp;
@@ -3166,6 +3355,10 @@ static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
                                            struct bfa_fcxp_s *fcxp_alloced);
 static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
                                            struct bfa_fcxp_s *fcxp_alloced);
+static void    bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg,
+                                       struct bfa_fcxp_s *fcxp_alloced);
+static void    bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg,
+                                       struct bfa_fcxp_s *fcxp_alloced);
 static void     bfa_fcs_lport_ns_timeout(void *arg);
 static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
                                               struct bfa_fcxp_s *fcxp,
@@ -3202,6 +3395,20 @@ static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
                                                u32 rsp_len,
                                                u32 resid_len,
                                                struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rnn_id_response(void *fcsarg,
+                                               struct bfa_fcxp_s *fcxp,
+                                               void *cbarg,
+                                               bfa_status_t req_status,
+                                               u32 rsp_len,
+                                               u32 resid_len,
+                                               struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg,
+                                               struct bfa_fcxp_s *fcxp,
+                                               void *cbarg,
+                                               bfa_status_t req_status,
+                                               u32 rsp_len,
+                                               u32 resid_len,
+                                               struct fchs_s *rsp_fchs);
 static void     bfa_fcs_lport_ns_process_gidft_pids(
                                struct bfa_fcs_lport_s *port,
                                u32 *pid_buf, u32 n_pids);
@@ -3226,6 +3433,8 @@ enum vport_ns_event {
        NSSM_EVENT_RFTID_SENT = 9,
        NSSM_EVENT_RFFID_SENT = 10,
        NSSM_EVENT_GIDFT_SENT = 11,
+       NSSM_EVENT_RNNID_SENT = 12,
+       NSSM_EVENT_RSNN_NN_SENT = 13,
 };
 
 static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
@@ -3266,6 +3475,21 @@ static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
                                                enum vport_ns_event event);
 static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
                                          enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rnn_id(
+                                       struct bfa_fcs_lport_ns_s *ns,
+                                       enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
+                                       enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+                                               enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rsnn_nn(
+                                       struct bfa_fcs_lport_ns_s *ns,
+                                       enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
+                                               enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rsnn_nn_retry(
+                                       struct bfa_fcs_lport_ns_s *ns,
+                                       enum vport_ns_event event);
 /*
  *     Start in offline state - awaiting linkup
  */
@@ -3333,8 +3557,9 @@ bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
                break;
 
        case NSSM_EVENT_RSP_OK:
-               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
-               bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
+               ns->num_rnnid_retries = 0;
+               bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
                break;
 
        case NSSM_EVENT_PORT_OFFLINE:
@@ -3373,6 +3598,176 @@ bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
        }
 }
 
+static void
+bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns,
+                                       enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RNNID_SENT:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                                               &ns->fcxp_wqe);
+               break;
+       default:
+               bfa_sm_fault(ns->port->fcs, event);
+       }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
+                               enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSP_OK:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
+               ns->num_rnnid_retries = 0;
+               ns->num_rsnn_nn_retries = 0;
+               bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
+               break;
+
+       case NSSM_EVENT_RSP_ERROR:
+               if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) {
+                       bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry);
+                       ns->port->stats.ns_retries++;
+                       ns->num_rnnid_retries++;
+                       bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                               &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+                               BFA_FCS_RETRY_TIMEOUT);
+               } else {
+                       bfa_sm_set_state(ns,
+                               bfa_fcs_lport_ns_sm_sending_rspn_id);
+                       bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+               }
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_fcxp_discard(ns->fcxp);
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+               break;
+
+       default:
+               bfa_sm_fault(ns->port->fcs, event);
+       }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+                               enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
+               bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+               bfa_timer_stop(&ns->timer);
+               break;
+
+       default:
+               bfa_sm_fault(ns->port->fcs, event);
+       }
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
+                                       enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSNN_NN_SENT:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                       &ns->fcxp_wqe);
+               break;
+
+       default:
+               bfa_sm_fault(ns->port->fcs, event);
+       }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
+                               enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSP_OK:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+               ns->num_rsnn_nn_retries = 0;
+               bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_RSP_ERROR:
+               if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) {
+                       bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry);
+                       ns->port->stats.ns_retries++;
+                       ns->num_rsnn_nn_retries++;
+                       bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                                       &ns->timer, bfa_fcs_lport_ns_timeout,
+                                       ns, BFA_FCS_RETRY_TIMEOUT);
+               } else {
+                       bfa_sm_set_state(ns,
+                               bfa_fcs_lport_ns_sm_sending_rspn_id);
+                       bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+               }
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+               bfa_fcxp_discard(ns->fcxp);
+               break;
+
+       default:
+               bfa_sm_fault(ns->port->fcs, event);
+       }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns,
+                                       enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
+               bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+               bfa_timer_stop(&ns->timer);
+               break;
+
+       default:
+               bfa_sm_fault(ns->port->fcs, event);
+       }
+}
+
 static void
 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
                                   enum vport_ns_event event)
@@ -3770,11 +4165,12 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->pid);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                port->stats.ns_plogi_alloc_wait++;
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-                                       bfa_fcs_lport_ns_send_plogi, ns);
+                               bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
                return;
        }
        ns->fcxp = fcxp;
@@ -3852,6 +4248,162 @@ bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
        }
 }
 
+/*
+ * Register node name for port_id
+ */
+static void
+bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+       struct bfa_fcs_lport_s *port = ns->port;
+       struct fchs_s  fchs;
+       int     len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced :
+                       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
+       if (!fcxp) {
+               port->stats.ns_rnnid_alloc_wait++;
+               bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                               bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE);
+               return;
+       }
+
+       ns->fcxp = fcxp;
+
+       len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                               bfa_fcs_lport_get_fcid(port),
+                               bfa_fcs_lport_get_fcid(port),
+                               bfa_fcs_lport_get_nwwn(port));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                         FC_CLASS_3, len, &fchs,
+                         bfa_fcs_lport_ns_rnn_id_response, (void *)ns,
+                         FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+       port->stats.ns_rnnid_sent++;
+       bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                               void *cbarg, bfa_status_t req_status,
+                               u32 rsp_len, u32 resid_len,
+                               struct fchs_s *rsp_fchs)
+
+{
+       struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+       struct bfa_fcs_lport_s *port = ns->port;
+       struct ct_hdr_s *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               port->stats.ns_rnnid_rsp_err++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               port->stats.ns_rnnid_accepts++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               return;
+       }
+
+       port->stats.ns_rnnid_rejects++;
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/*
+ * Register the symbolic node name for a given node name.
+ */
+static void
+bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+       struct bfa_fcs_lport_s *port = ns->port;
+       struct fchs_s  fchs;
+       int     len;
+       struct bfa_fcxp_s *fcxp;
+       u8 *nsymbl;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced :
+                       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
+       if (!fcxp) {
+               port->stats.ns_rsnn_nn_alloc_wait++;
+               bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                               bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE);
+               return;
+       }
+       ns->fcxp = fcxp;
+
+       nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name(
+                                       bfa_fcs_get_base_port(port->fcs)));
+
+       len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                               bfa_fcs_lport_get_fcid(port),
+                               bfa_fcs_lport_get_nwwn(port), nsymbl);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                         FC_CLASS_3, len, &fchs,
+                         bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns,
+                         FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+       port->stats.ns_rsnn_nn_sent++;
+
+       bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                               void *cbarg, bfa_status_t req_status,
+                               u32 rsp_len, u32 resid_len,
+                               struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+       struct bfa_fcs_lport_s *port = ns->port;
+       struct ct_hdr_s *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               port->stats.ns_rsnn_nn_rsp_err++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               port->stats.ns_rsnn_nn_accepts++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               return;
+       }
+
+       port->stats.ns_rsnn_nn_rejects++;
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
 /*
  * Register the symbolic port name.
  */
@@ -3870,11 +4422,12 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                port->stats.ns_rspnid_alloc_wait++;
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-                                       bfa_fcs_lport_ns_send_rspn_id, ns);
+                               bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
                return;
        }
        ns->fcxp = fcxp;
@@ -3971,11 +4524,12 @@ bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                port->stats.ns_rftid_alloc_wait++;
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-                                       bfa_fcs_lport_ns_send_rft_id, ns);
+                               bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
                return;
        }
        ns->fcxp = fcxp;
@@ -4044,11 +4598,12 @@ bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                port->stats.ns_rffid_alloc_wait++;
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-                                       bfa_fcs_lport_ns_send_rff_id, ns);
+                               bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
                return;
        }
        ns->fcxp = fcxp;
@@ -4127,11 +4682,12 @@ bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->pid);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                port->stats.ns_gidft_alloc_wait++;
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-                                       bfa_fcs_lport_ns_send_gid_ft, ns);
+                               bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
                return;
        }
        ns->fcxp = fcxp;
@@ -4261,6 +4817,10 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
        struct fcgs_gidft_resp_s *gidft_entry;
        struct bfa_fcs_rport_s *rport;
        u32        ii;
+       struct bfa_fcs_fabric_s *fabric = port->fabric;
+       struct bfa_fcs_vport_s *vport;
+       struct list_head *qe;
+       u8 found = 0;
 
        for (ii = 0; ii < n_pids; ii++) {
                gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
@@ -4268,6 +4828,29 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
                if (gidft_entry->pid == port->pid)
                        continue;
 
+               /*
+                * Ignore PID if it is of base port
+                * (Avoid vports discovering base port as remote port)
+                */
+               if (gidft_entry->pid == fabric->bport.pid)
+                       continue;
+
+               /*
+                * Ignore PID if it is of vport created on the same base port
+                * (Avoid vport discovering every other vport created on the
+                * same port as remote port)
+                */
+               list_for_each(qe, &fabric->vport_q) {
+                       vport = (struct bfa_fcs_vport_s *) qe;
+                       if (vport->lport.pid == gidft_entry->pid)
+                               found = 1;
+               }
+
+               if (found) {
+                       found = 0;
+                       continue;
+               }
+
                /*
                 * Check if this rport already exists
                 */
@@ -4335,7 +4918,8 @@ bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
        struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
 
        bfa_trc(port->fcs, port->pid);
-       bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
+       if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online))
+               bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
 }
 
 static void
@@ -4355,6 +4939,70 @@ bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
        }
 }
 
+void
+bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_lport_ns_s *ns = cbarg;
+       struct bfa_fcs_lport_s *port = ns->port;
+       struct fchs_s fchs;
+       struct bfa_fcxp_s *fcxp;
+       u8 symbl[256];
+       u8 *psymbl = &symbl[0];
+       int len;
+
+       if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
+               return;
+
+       /* Avoid sending RSPN in the following states. */
+       if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
+           bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
+           bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) ||
+           bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) ||
+           bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry))
+               return;
+
+       memset(symbl, 0, sizeof(symbl));
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
+       if (!fcxp) {
+               port->stats.ns_rspnid_alloc_wait++;
+               bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                       bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
+               return;
+       }
+
+       ns->fcxp = fcxp;
+
+       if (port->vport) {
+               /*
+                * For Vports, we append the vport's port symbolic name
+                * to that of the base port.
+                */
+               strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name
+                       (bfa_fcs_get_base_port(port->fcs))),
+                       strlen((char *)&bfa_fcs_lport_get_psym_name(
+                       bfa_fcs_get_base_port(port->fcs))));
+
+               /* Ensure we have a null terminating string. */
+               ((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name(
+                bfa_fcs_get_base_port(port->fcs)))] = 0;
+
+               strncat((char *)psymbl,
+                       (char *)&(bfa_fcs_lport_get_psym_name(port)),
+                       strlen((char *)&bfa_fcs_lport_get_psym_name(port)));
+       }
+
+       len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                             bfa_fcs_lport_get_fcid(port), 0, psymbl);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+
+       port->stats.ns_rspnid_sent++;
+}
+
 /*
  * FCS SCN
  */
@@ -4529,10 +5177,11 @@ bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
        bfa_trc(port->fcs, port->pid);
        bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced :
+              bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
        if (!fcxp) {
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
-                                       bfa_fcs_lport_scn_send_scr, scn);
+                               bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
                return;
        }
        scn->fcxp = fcxp;
@@ -4614,7 +5263,7 @@ bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
 
        bfa_trc(port->fcs, rx_fchs->s_id);
 
-       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
        if (!fcxp)
                return;
 
@@ -4676,7 +5325,7 @@ bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
 }
 
 void
-bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
+bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)
 {
        struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
 
@@ -4688,14 +5337,33 @@ static void
 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
 {
        struct bfa_fcs_rport_s *rport;
+       struct bfa_fcs_fabric_s *fabric = port->fabric;
+       struct bfa_fcs_vport_s *vport;
+       struct list_head *qe;
 
        bfa_trc(port->fcs, rpid);
 
+       /*
+        * Ignore PID if it is of base port or of vports created on the
+        * same base port. It is to avoid vports discovering base port or
+        * other vports created on same base port as remote port
+        */
+       if (rpid == fabric->bport.pid)
+               return;
+
+       list_for_each(qe, &fabric->vport_q) {
+               vport = (struct bfa_fcs_vport_s *) qe;
+               if (vport->lport.pid == rpid)
+                       return;
+       }
        /*
         * If this is an unknown device, then it just came online.
         * Otherwise let rport handle the RSCN event.
         */
        rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
+       if (!rport)
+               rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
+
        if (rport == NULL) {
                /*
                 * If min cfg mode is enabled, we donot need to
@@ -4888,15 +5556,15 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
 }
 
 void
-bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
-        wwn_t rport_wwns[], int *nrports)
+bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
+               struct bfa_rport_qualifier_s rports[], int *nrports)
 {
        struct list_head        *qh, *qe;
        struct bfa_fcs_rport_s *rport = NULL;
        int     i;
        struct bfa_fcs_s        *fcs;
 
-       if (port == NULL || rport_wwns == NULL || *nrports == 0)
+       if (port == NULL || rports == NULL || *nrports == 0)
                return;
 
        fcs = port->fcs;
@@ -4916,7 +5584,13 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
                        continue;
                }
 
-               rport_wwns[i] = rport->pwwn;
+               if (!rport->pwwn && !rport->pid) {
+                       qe = bfa_q_next(qe);
+                       continue;
+               }
+
+               rports[i].pwwn = rport->pwwn;
+               rports[i].pid = rport->pid;
 
                i++;
                qe = bfa_q_next(qe);
@@ -5072,6 +5746,15 @@ bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
        memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
 }
 
+/*
+ * Let new loop map create missing rports
+ */
+void
+bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port)
+{
+       bfa_fcs_lport_loop_online(port);
+}
+
 /*
  * FCS virtual port state machine
  */
@@ -5760,6 +6443,16 @@ bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
 {
        vport->vport_stats.fab_cleanup++;
 }
+
+/*
+ * Stop notification from fabric SM. To be invoked from within FCS.
+ */
+void
+bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
+{
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
+}
+
 /*
  * delete notification from fabric SM. To be invoked from within FCS.
  */