static void    bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
                        enum bfa_itnim_aen_event event);
 
-/*
- *  fcs_itnim_sm FCS itnim state machine events
- */
-
-enum bfa_fcs_itnim_event {
-       BFA_FCS_ITNIM_SM_ONLINE = 1,    /*  rport online event */
-       BFA_FCS_ITNIM_SM_OFFLINE = 2,   /*  rport offline */
-       BFA_FCS_ITNIM_SM_FRMSENT = 3,   /*  prli frame is sent */
-       BFA_FCS_ITNIM_SM_RSP_OK = 4,    /*  good response */
-       BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /*  error response */
-       BFA_FCS_ITNIM_SM_TIMEOUT = 6,   /*  delay timeout */
-       BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /*  BFA online callback */
-       BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /*  BFA offline callback */
-       BFA_FCS_ITNIM_SM_INITIATOR = 9, /*  rport is initiator */
-       BFA_FCS_ITNIM_SM_DELETE = 10,   /*  delete event from rport */
-       BFA_FCS_ITNIM_SM_PRLO = 11,     /*  delete event from rport */
-       BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
-};
-
 static void    bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
                                         enum bfa_fcs_itnim_event event);
 static void    bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
                                            enum bfa_fcs_itnim_event event);
 static void    bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
                                            enum bfa_fcs_itnim_event event);
+static void    bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
+                                       enum bfa_fcs_itnim_event event);
 static void    bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
                                        enum bfa_fcs_itnim_event event);
 static void    bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
        bfa_trc(itnim->fcs, event);
 
        switch (event) {
-       case BFA_FCS_ITNIM_SM_ONLINE:
+       case BFA_FCS_ITNIM_SM_FCS_ONLINE:
                bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
                itnim->prli_retries = 0;
                bfa_fcs_itnim_send_prli(itnim, NULL);
        case BFA_FCS_ITNIM_SM_INITIATOR:
                bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
                bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+               bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
                break;
 
        case BFA_FCS_ITNIM_SM_OFFLINE:
 
        switch (event) {
        case BFA_FCS_ITNIM_SM_RSP_OK:
-               if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) {
+               if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR)
                        bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
-               } else {
-                       bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
-                       bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
-               }
+               else
+                       bfa_sm_set_state(itnim,
+                               bfa_fcs_itnim_sm_hal_rport_online);
+
+               bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
                break;
 
        case BFA_FCS_ITNIM_SM_RSP_ERROR:
        case BFA_FCS_ITNIM_SM_INITIATOR:
                bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
                bfa_fcxp_discard(itnim->fcxp);
+               bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
                break;
 
        case BFA_FCS_ITNIM_SM_DELETE:
        }
 }
 
+static void
+bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
+                               enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_HAL_ONLINE:
+               if (!itnim->bfa_itnim)
+                       itnim->bfa_itnim = bfa_itnim_create(itnim->fcs->bfa,
+                                       itnim->rport->bfa_rport, itnim);
+
+               if (itnim->bfa_itnim) {
+                       bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
+                       bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
+               } else {
+                       bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+                       bfa_sm_send_event(itnim->rport, RPSM_EVENT_DELETE);
+               }
+
+               break;
+
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_sm_fault(itnim->fcs, event);
+       }
+}
+
 static void
 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
                            enum bfa_fcs_itnim_event event)
        case BFA_FCS_ITNIM_SM_INITIATOR:
                bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
                bfa_timer_stop(&itnim->timer);
+               bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
                break;
 
        case BFA_FCS_ITNIM_SM_DELETE:
                break;
 
        case BFA_FCS_ITNIM_SM_OFFLINE:
-               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
                bfa_itnim_offline(itnim->bfa_itnim);
-               bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
                break;
 
        case BFA_FCS_ITNIM_SM_DELETE:
                bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
                break;
 
+       /*
+        * fcs_online is expected here for well known initiator ports
+        */
+       case BFA_FCS_ITNIM_SM_FCS_ONLINE:
+               bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
+               break;
+
        case BFA_FCS_ITNIM_SM_RSP_ERROR:
-       case BFA_FCS_ITNIM_SM_ONLINE:
        case BFA_FCS_ITNIM_SM_INITIATOR:
                break;
 
                        if (prli_resp->parampage.servparams.initiator) {
                                bfa_trc(itnim->fcs, prli_resp->parampage.type);
                                itnim->rport->scsi_function =
-                                        BFA_RPORT_INITIATOR;
+                                               BFA_RPORT_INITIATOR;
                                itnim->stats.prli_rsp_acc++;
                                itnim->stats.initiator++;
                                bfa_sm_send_event(itnim,
 static void
 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
 {
-       bfa_itnim_delete(itnim->bfa_itnim);
+       if (itnim->bfa_itnim) {
+               bfa_itnim_delete(itnim->bfa_itnim);
+               itnim->bfa_itnim = NULL;
+       }
+
        bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
 }
 
        struct bfa_fcs_lport_s *port = rport->port;
        struct bfa_fcs_itnim_s *itnim;
        struct bfad_itnim_s   *itnim_drv;
-       struct bfa_itnim_s *bfa_itnim;
 
        /*
         * call bfad to allocate the itnim
        itnim->fcs = rport->fcs;
        itnim->itnim_drv = itnim_drv;
 
-       /*
-        * call BFA to create the itnim
-        */
-       bfa_itnim =
-               bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
-
-       if (bfa_itnim == NULL) {
-               bfa_trc(port->fcs, rport->pwwn);
-               bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
-               WARN_ON(1);
-               return NULL;
-       }
-
-       itnim->bfa_itnim     = bfa_itnim;
+       itnim->bfa_itnim     = NULL;
        itnim->seq_rec       = BFA_FALSE;
        itnim->rec_support   = BFA_FALSE;
        itnim->conf_comp     = BFA_FALSE;
  * Notification from rport that PLOGI is complete to initiate FC-4 session.
  */
 void
-bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
+bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim)
 {
        itnim->stats.onlines++;
 
-       if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
-               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
-       } else {
-               /*
-                *  For well known addresses, we set the itnim to initiator
-                *  state
-                */
-               itnim->stats.initiator++;
-               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
-       }
+       if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid))
+               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HAL_ONLINE);
 }
 
 /*
 
 static u32
 bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
         /* In millisecs */
+/*
+ * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports
+ * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports
+ */
+static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;
+
 /*
  * forward declarations
  */
                struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
 static void    bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
 static void    bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
-static void    bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
-static void    bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
+static void    bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport);
+static void    bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport);
+static void    bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport);
+static void    bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);
 static void    bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
                                        struct fc_logi_s *plogi);
 static void    bfa_fcs_rport_timeout(void *arg);
 static void    bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
                                struct fchs_s *rx_fchs, u16 len);
 static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
+static void    bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);
 
 static void    bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
                                        enum rport_event event);
                                                enum rport_event event);
 static void    bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
                                        enum rport_event event);
+static void    bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
+                                       enum rport_event event);
 static void    bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
                                                enum rport_event event);
 static void    bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
                                                enum rport_event event);
 static void    bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
                                                enum rport_event event);
+static void    bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
+                                               enum rport_event event);
+static void    bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
+                                               enum rport_event event);
 
 static struct bfa_sm_table_s rport_sm_table[] = {
        {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
        {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
        {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
        {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
+       {BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},
        {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
        {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
        {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
 
        switch (event) {
        case RPSM_EVENT_FCXP_SENT:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-               bfa_fcs_rport_hal_online(rport);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        case RPSM_EVENT_DELETE:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
                bfa_timer_stop(&rport->timer);
-               bfa_fcs_rport_hal_online(rport);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        default:
 
        switch (event) {
        case RPSM_EVENT_ACCEPTED:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
                rport->plogi_retries = 0;
-               bfa_fcs_rport_hal_online(rport);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_hal_online(rport);
+               bfa_fcs_rport_fcs_online_action(rport);
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
+
+/*
+ * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function
+ */
+static void
+bfa_fcs_rport_sm_fc4_fcs_online(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_FC4_FCS_ONLINE:
+               if (rport->scsi_function == BFA_RPORT_INITIATOR) {
+                       if (!BFA_FCS_PID_IS_WKA(rport->pid))
+                               bfa_fcs_rpf_rport_online(rport);
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+                       break;
+               }
+
+               if (!rport->bfa_rport)
+                       rport->bfa_rport =
+                               bfa_rport_create(rport->fcs->bfa, rport);
+
+               if (rport->bfa_rport) {
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+                       bfa_fcs_rport_hal_online(rport);
+               } else {
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+                       bfa_fcs_rport_fcs_offline_action(rport);
+               }
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               rport->plogi_pending = BFA_TRUE;
+               bfa_fcs_rport_fcs_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_SCN:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcs_rport_fcs_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PRLO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+               bfa_fcs_rport_fcs_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
        default:
                bfa_sm_fault(rport->fcs, event);
+               break;
        }
 }
 
        switch (event) {
        case RPSM_EVENT_HCB_ONLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
-               bfa_fcs_rport_online_action(rport);
+               bfa_fcs_rport_hal_online_action(rport);
                break;
 
-       case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_PLOGI_COMP:
                break;
 
+       case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_LOGO_RCVD:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+               bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
+       case RPSM_EVENT_SCN:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
                rport->plogi_pending = BFA_TRUE;
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
        case RPSM_EVENT_DELETE:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
-               break;
-
-       case RPSM_EVENT_SCN:
-               /*
-                * @todo
-                * Ignore SCN - PLOGI just completed, FC-4 login should detect
-                * device failures.
-                */
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
        default:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_DELETE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
        case RPSM_EVENT_DELETE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_SCN:
        case RPSM_EVENT_PRLO_RCVD:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_LOGO_IMP:
-               rport->pid = 0;
-               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:
        case RPSM_EVENT_ADDRESS_CHANGE:
        case RPSM_EVENT_PLOGI_COMP:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        default:
                        bfa_fcs_rport_send_nsdisc(rport, NULL);
                } else {
                        bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-                       bfa_fcs_rport_offline_action(rport);
+                       bfa_fcs_rport_hal_offline_action(rport);
                }
                break;
 
        case RPSM_EVENT_DELETE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_SCN:
        case RPSM_EVENT_PRLO_RCVD:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
        case RPSM_EVENT_LOGO_IMP:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        default:
        case RPSM_EVENT_DELETE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_SCN:
        case RPSM_EVENT_PLOGI_RCVD:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        default:
        case RPSM_EVENT_FAILED:
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_DELETE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_SCN:
        case RPSM_EVENT_LOGO_IMP:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_offline_action(rport);
+               bfa_fcs_rport_hal_offline_action(rport);
                break;
 
        default:
        switch (event) {
        case RPSM_EVENT_FC4_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+               bfa_fcs_rport_hal_offline(rport);
                break;
 
        case RPSM_EVENT_DELETE:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               if (rport->pid && (rport->prlo == BFA_TRUE))
+                       bfa_fcs_rport_send_prlo_acc(rport);
+               if (rport->pid && (rport->prlo == BFA_FALSE))
+                       bfa_fcs_rport_send_logo_acc(rport);
+
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
                break;
 
+       case RPSM_EVENT_HCB_ONLINE:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_ADDRESS_CHANGE:
        switch (event) {
        case RPSM_EVENT_FC4_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+               bfa_fcs_rport_hal_offline(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_fcs_rport_send_logo_acc(rport);
+       case RPSM_EVENT_PRLO_RCVD:
+               if (rport->prlo == BFA_TRUE)
+                       bfa_fcs_rport_send_prlo_acc(rport);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
+               break;
+
+       case RPSM_EVENT_HCB_ONLINE:
+       case RPSM_EVENT_DELETE:
+               /* Rport is being deleted */
                break;
 
        default:
        switch (event) {
        case RPSM_EVENT_FC4_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+               bfa_fcs_rport_hal_offline(rport);
                break;
 
-       case RPSM_EVENT_SCN:
-       case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_LOGO_RCVD:
+               /*
+                * Rport is going offline. Just ack the logo
+                */
+               bfa_fcs_rport_send_logo_acc(rport);
+               break;
+
        case RPSM_EVENT_PRLO_RCVD:
+               bfa_fcs_rport_send_prlo_acc(rport);
+               break;
+
+       case RPSM_EVENT_HCB_ONLINE:
+       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
                /*
                 * rport is already going offline.
                 */
 
        case RPSM_EVENT_ADDRESS_CHANGE:
-               if (bfa_fcs_lport_is_online(rport->port)) {
-                       if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
-                               bfa_sm_set_state(rport,
-                                       bfa_fcs_rport_sm_nsdisc_sending);
-                               rport->ns_retries = 0;
-                               bfa_fcs_rport_send_nsdisc(rport, NULL);
-                       } else {
-                               bfa_sm_set_state(rport,
-                                       bfa_fcs_rport_sm_plogi_sending);
-                               rport->plogi_retries = 0;
-                               bfa_fcs_rport_send_plogi(rport, NULL);
-                       }
-               } else {
+               if (!bfa_fcs_lport_is_online(rport->port)) {
                        rport->pid = 0;
                        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;
+               }
+               if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+                       bfa_sm_set_state(rport,
+                               bfa_fcs_rport_sm_nsdisc_sending);
+                       rport->ns_retries = 0;
+                       bfa_fcs_rport_send_nsdisc(rport, NULL);
+               } else {
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+                       rport->plogi_retries = 0;
+                       bfa_fcs_rport_send_plogi(rport, NULL);
                }
                break;
 
                break;
 
        case RPSM_EVENT_DELETE:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
+               if (rport->pid && (rport->prlo == BFA_TRUE))
+                       bfa_fcs_rport_send_prlo_acc(rport);
+               if (rport->pid && (rport->prlo == BFA_FALSE))
+                       bfa_fcs_rport_send_logo_acc(rport);
                break;
 
        case RPSM_EVENT_LOGO_IMP:
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
+               bfa_fcs_rport_send_logo_acc(rport);
        case RPSM_EVENT_PRLO_RCVD:
+               if (rport->prlo == BFA_TRUE)
+                       bfa_fcs_rport_send_prlo_acc(rport);
+
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
+               break;
+
        case RPSM_EVENT_ADDRESS_CHANGE:
                break;
 
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
+               bfa_fcs_rport_send_logo_acc(rport);
        case RPSM_EVENT_PRLO_RCVD:
+               if (rport->prlo == BFA_TRUE)
+                       bfa_fcs_rport_send_prlo_acc(rport);
+
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
                bfa_fcs_rport_free(rport);
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
                bfa_timer_stop(&rport->timer);
-               bfa_fcs_rport_hal_online(rport);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        case RPSM_EVENT_PLOGI_SEND:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-               bfa_fcs_rport_hal_online(rport);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        default:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
                bfa_timer_stop(&rport->timer);
-               bfa_fcs_rport_hal_online(rport);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        default:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
                bfa_fcxp_discard(rport->fcxp);
-               bfa_fcs_rport_hal_online(rport);
+               bfa_fcs_rport_fcs_online_action(rport);
                break;
 
        default:
        }
 }
 
+/*
+ * Rport needs to be deleted
+ * waiting for ITNIM clean up to finish
+ */
+static void
+bfa_fcs_rport_sm_fc4_off_delete(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_FC4_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
+               bfa_fcs_rport_hal_offline(rport);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_PLOGI_RCVD:
+               /* Ignore these events */
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+               break;
+       }
+}
+
+/*
+ * RPort needs to be deleted
+ * waiting for BFA/FW to finish current processing
+ */
+static void
+bfa_fcs_rport_sm_delete_pending(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_HCB_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_PLOGI_RCVD:
+               /* Ignore these events */
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
 
 /*
  *  fcs_rport_private FCS RPORT provate functions
        bfa_rport_online(rport->bfa_rport, &rport_info);
 }
 
+static void
+bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)
+{
+       if (rport->bfa_rport)
+               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+       else
+               bfa_cb_rport_offline(rport);
+}
+
 static struct bfa_fcs_rport_s *
 bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
 {
        /*
         * allocate rport
         */
+       if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {
+               bfa_trc(fcs, rpid);
+               return NULL;
+       }
+
        if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
                != BFA_STATUS_OK) {
                bfa_trc(fcs, rpid);
        rport->pwwn = pwwn;
        rport->old_pid = 0;
 
-       /*
-        * allocate BFA rport
-        */
-       rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
-       if (!rport->bfa_rport) {
-               bfa_trc(fcs, rpid);
-               kfree(rport_drv);
-               return NULL;
-       }
+       rport->bfa_rport = NULL;
 
        /*
         * allocate FC-4s
                rport->itnim = bfa_fcs_itnim_create(rport);
                if (!rport->itnim) {
                        bfa_trc(fcs, rpid);
-                       bfa_sm_send_event(rport->bfa_rport,
-                                               BFA_RPORT_SM_DELETE);
                        kfree(rport_drv);
                        return NULL;
                }
        }
 
        bfa_fcs_lport_add_rport(port, rport);
+       fcs->num_rport_logins++;
 
        bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
 
 bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
 {
        struct bfa_fcs_lport_s *port = rport->port;
+       struct bfa_fcs_s *fcs = port->fcs;
 
        /*
         * - delete FC-4s
         * - delete BFA rport
         * - remove from queue of rports
         */
+       rport->plogi_pending = BFA_FALSE;
+
        if (bfa_fcs_lport_is_initiator(port)) {
                bfa_fcs_itnim_delete(rport->itnim);
                if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
                        bfa_fcs_rpf_rport_offline(rport);
        }
 
-       bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
+       if (rport->bfa_rport) {
+               bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
+               rport->bfa_rport = NULL;
+       }
+
        bfa_fcs_lport_del_rport(port, rport);
+       fcs->num_rport_logins--;
        kfree(rport->rp_drv);
 }
 
 }
 
 static void
-bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
+bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)
+{
+       if ((!rport->pid) || (!rport->pwwn)) {
+               bfa_trc(rport->fcs, rport->pid);
+               bfa_sm_fault(rport->fcs, rport->pid);
+       }
+
+       bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);
+}
+
+static void
+bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)
 {
        struct bfa_fcs_lport_s *port = rport->port;
        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
        }
 
        if (bfa_fcs_lport_is_initiator(port)) {
-               bfa_fcs_itnim_rport_online(rport->itnim);
+               bfa_fcs_itnim_brp_online(rport->itnim);
                if (!BFA_FCS_PID_IS_WKA(rport->pid))
                        bfa_fcs_rpf_rport_online(rport);
        };
 }
 
 static void
-bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
+bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)
+{
+       if (!BFA_FCS_PID_IS_WKA(rport->pid))
+               bfa_fcs_rpf_rport_offline(rport);
+
+       bfa_fcs_itnim_rport_offline(rport->itnim);
+}
+
+static void
+bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)
 {
        struct bfa_fcs_lport_s *port = rport->port;
        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
        char    lpwwn_buf[BFA_STRING_32];
        char    rpwwn_buf[BFA_STRING_32];
 
+       if (!rport->bfa_rport) {
+               bfa_fcs_rport_fcs_offline_action(rport);
+               return;
+       }
+
        rport->stats.offlines++;
-       rport->plogi_pending = BFA_FALSE;
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
        wwn2str(rpwwn_buf, rport->pwwn);
        bfa_sm_send_event(rport, RPSM_EVENT_SCN);
 }
 
-
 /*
  *     brief
  *     This routine BFA callback for bfa_rport_online() call.
        bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
 }
 
+/*
+ * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation
+ * which limits number of concurrent logins to remote ports
+ */
+void
+bfa_fcs_rport_set_max_logins(u32 max_logins)
+{
+       if (max_logins > 0)
+               bfa_fcs_rport_max_logins = max_logins;
+}
+
 void
 bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
                struct bfa_rport_attr_s *rport_attr)
        rport_attr->curr_speed  = rport->rpf.rpsc_speed;
        rport_attr->assigned_speed  = rport->rpf.assigned_speed;
 
-       qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
-       qos_attr.qos_flow_id =
-               cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
+       if (rport->bfa_rport) {
+               qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
+               qos_attr.qos_flow_id =
+                       cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
+       }
        rport_attr->qos_attr = qos_attr;
 
        rport_attr->trl_enforced = BFA_FALSE;