Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / bfa / bfa_fcs_rport.c
index cc43b2a58ce33ac9478cc25b9c9fc0509f4eeb96..2035b0d6435186186af4a497109a9a57b3843931 100644 (file)
@@ -106,9 +106,13 @@ static void        bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
                                                 enum rport_event event);
 static void    bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
                                         enum rport_event event);
-static void    bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
-                                               enum rport_event event);
-static void    bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+static void    bfa_fcs_rport_sm_adisc_online_sending(
+                       struct bfa_fcs_rport_s *rport, enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+                                       enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s
+                                       *rport, enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
                                        enum rport_event event);
 static void    bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
                                                enum rport_event event);
@@ -150,8 +154,10 @@ static struct bfa_sm_table_s rport_sm_table[] = {
        {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
        {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
        {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
-       {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
-       {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},
        {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
        {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
        {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
@@ -183,8 +189,8 @@ bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
-               bfa_fcs_rport_fcs_online_action(rport);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
@@ -231,10 +237,19 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /* query the NS */
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -280,12 +295,20 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
 
        case RPSM_EVENT_PLOGI_RCVD:
        case RPSM_EVENT_PLOGI_COMP:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * Ignore, SCN is possibly online notification.
                 */
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
@@ -346,9 +369,19 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_stop(&rport->timer);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                bfa_timer_stop(&rport->timer);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -422,7 +455,18 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
                }
                break;
 
-       case    RPSM_EVENT_PLOGI_RETRY:
+       case RPSM_EVENT_SCN_ONLINE:
+               break;
+
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_RETRY:
                rport->plogi_retries = 0;
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
                bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -440,8 +484,10 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
                break;
 
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                bfa_fcxp_discard(rport->fcxp);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -512,7 +558,8 @@ bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
        case RPSM_EVENT_PLOGI_COMP:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
@@ -561,9 +608,10 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
@@ -595,14 +643,15 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
        bfa_trc(rport->fcs, event);
 
        switch (event) {
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
                        bfa_sm_set_state(rport,
                                         bfa_fcs_rport_sm_nsquery_sending);
                        rport->ns_retries = 0;
                        bfa_fcs_rport_send_nsdisc(rport, NULL);
                } else {
-                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+                       bfa_sm_set_state(rport,
+                               bfa_fcs_rport_sm_adisc_online_sending);
                        bfa_fcs_rport_send_adisc(rport, NULL);
                }
                break;
@@ -610,6 +659,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
        case RPSM_EVENT_PLOGI_RCVD:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_hal_offline_action(rport);
                break;
@@ -625,6 +675,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
        case RPSM_EVENT_PLOGI_COMP:
                break;
 
@@ -656,7 +707,7 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * ignore SCN, wait for response to query itself
                 */
@@ -696,7 +747,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
 
        switch (event) {
        case RPSM_EVENT_ACCEPTED:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);
                bfa_fcs_rport_send_adisc(rport, NULL);
                break;
 
@@ -718,7 +769,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
@@ -747,7 +798,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
  *     authenticating with rport. FC-4s are paused.
  */
 static void
-bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,
         enum rport_event event)
 {
        bfa_trc(rport->fcs, rport->pwwn);
@@ -756,7 +807,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
 
        switch (event) {
        case RPSM_EVENT_FCXP_SENT:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);
                break;
 
        case RPSM_EVENT_DELETE:
@@ -779,7 +830,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
@@ -798,7 +849,8 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
  *             FC-4s are paused.
  */
 static void
-bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
+bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+                               enum rport_event event)
 {
        bfa_trc(rport->fcs, rport->pwwn);
        bfa_trc(rport->fcs, rport->pid);
@@ -831,7 +883,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * already processing RSCN
                 */
@@ -856,7 +908,96 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
 }
 
 /*
- *             Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ * ADISC is being sent for authenticating with rport
+ * Already did offline actions.
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,
+       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PRLO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa,
+                       &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
+
+/*
+ * ADISC to rport
+ * Already did offline actions
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_ACCEPTED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_FAILED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PRLO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
+
+/*
+ * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
  */
 static void
 bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
@@ -881,6 +1022,8 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_HCB_ONLINE:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
@@ -945,6 +1088,8 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+               break;
        case RPSM_EVENT_LOGO_RCVD:
                /*
                 * Rport is going offline. Just ack the logo
@@ -956,8 +1101,9 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_prlo_acc(rport);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_HCB_ONLINE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
                /*
@@ -1015,6 +1161,19 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
                                bfa_fcs_rport_sm_nsdisc_sending);
                        rport->ns_retries = 0;
                        bfa_fcs_rport_send_nsdisc(rport, NULL);
+               } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==
+                                       BFA_PORT_TOPOLOGY_LOOP) {
+                       if (rport->scn_online) {
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_adisc_offline_sending);
+                               bfa_fcs_rport_send_adisc(rport, NULL);
+                       } else {
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_offline);
+                               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                                       bfa_fcs_rport_timeout, rport,
+                                       bfa_fcs_rport_del_timeout);
+                       }
                } else {
                        bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
                        rport->plogi_retries = 0;
@@ -1027,7 +1186,9 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_PLOGI_RCVD:
@@ -1106,6 +1267,8 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
                /*
@@ -1146,6 +1309,8 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_ADDRESS_CHANGE:
                break;
 
@@ -1172,7 +1337,9 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
                break;
 
@@ -1209,10 +1376,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                bfa_timer_stop(&rport->timer);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
                break;
@@ -1232,6 +1401,7 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_SCN_OFFLINE:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
@@ -1240,6 +1410,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_fcs_online_action(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+               bfa_timer_stop(&rport->timer);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+               bfa_fcs_rport_send_plogi(rport, NULL);
+               break;
+
        case RPSM_EVENT_PLOGI_SEND:
                bfa_timer_stop(&rport->timer);
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
@@ -1280,7 +1456,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_PLOGI_SEND:
@@ -1326,7 +1502,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_nsdisc(rport, NULL);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                bfa_timer_stop(&rport->timer);
@@ -1439,7 +1615,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
        case RPSM_EVENT_PRLO_RCVD:
                bfa_fcs_rport_send_prlo_acc(rport);
                break;
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * ignore, wait for NS query response
                 */
@@ -2401,7 +2577,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
 
                port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
                bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
-                                         port->fabric->bb_credit, 0);
+                                         port->fabric->bb_credit);
        }
 
 }
@@ -2546,7 +2722,7 @@ void
 bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
 {
        rport->stats.rscns++;
-       bfa_sm_send_event(rport, RPSM_EVENT_SCN);
+       bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);
 }
 
 /*
@@ -2621,6 +2797,48 @@ bfa_cb_rport_qos_scn_flowid(void *cbarg,
        bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
 }
 
+void
+bfa_cb_rport_scn_online(struct bfa_s *bfa)
+{
+       struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+       struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+       struct bfa_fcs_rport_s *rp;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rp = (struct bfa_fcs_rport_s *) qe;
+               bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);
+               rp->scn_online = BFA_TRUE;
+       }
+
+       if (bfa_fcs_lport_is_online(port))
+               bfa_fcs_lport_lip_scn_online(port);
+}
+
+void
+bfa_cb_rport_scn_no_dev(void *rport)
+{
+       struct bfa_fcs_rport_s *rp = rport;
+
+       bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+       rp->scn_online = BFA_FALSE;
+}
+
+void
+bfa_cb_rport_scn_offline(struct bfa_s *bfa)
+{
+       struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+       struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+       struct bfa_fcs_rport_s *rp;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rp = (struct bfa_fcs_rport_s *) qe;
+               bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+               rp->scn_online = BFA_FALSE;
+       }
+}
+
 /*
  *     brief
  *     This routine is a static BFA callback when there is a QoS priority
@@ -2808,6 +3026,9 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
        struct bfa_rport_qos_attr_s qos_attr;
        struct bfa_fcs_lport_s *port = rport->port;
        bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+       struct bfa_port_attr_s port_attr;
+
+       bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
 
        memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
        memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
@@ -2838,7 +3059,8 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
                        rport_speed =
                                bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
 
-               if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+               if ((bfa_fcs_lport_get_rport_max_speed(port) !=
+                   BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
                        rport_attr->trl_enforced = BFA_TRUE;
        }
 }
@@ -3208,9 +3430,10 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
                num_ents = be16_to_cpu(rpsc2_acc->num_pids);
                bfa_trc(rport->fcs, num_ents);
                if (num_ents > 0) {
-                       WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid);
+                       WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) !=
+                                               bfa_ntoh3b(rport->pid));
                        bfa_trc(rport->fcs,
-                               be16_to_cpu(rpsc2_acc->port_info[0].pid));
+                               be32_to_cpu(rpsc2_acc->port_info[0].pid));
                        bfa_trc(rport->fcs,
                                be16_to_cpu(rpsc2_acc->port_info[0].speed));
                        bfa_trc(rport->fcs,