Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
0004  * Copyright (c) 2014- QLogic Corporation.
0005  * All rights reserved
0006  * www.qlogic.com
0007  *
0008  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
0009  */
0010 
0011 /*
0012  *  rport.c Remote port implementation.
0013  */
0014 
0015 #include "bfad_drv.h"
0016 #include "bfad_im.h"
0017 #include "bfa_fcs.h"
0018 #include "bfa_fcbuild.h"
0019 
0020 BFA_TRC_FILE(FCS, RPORT);
0021 
0022 static u32
0023 bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
0024      /* In millisecs */
0025 /*
0026  * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports
0027  * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports
0028  */
0029 static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;
0030 
0031 /*
0032  * forward declarations
0033  */
0034 static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
0035         struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
0036 static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
0037 static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
0038 static void bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport);
0039 static void bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport);
0040 static void bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport);
0041 static void bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);
0042 static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
0043                     struct fc_logi_s *plogi);
0044 static void bfa_fcs_rport_timeout(void *arg);
0045 static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
0046                      struct bfa_fcxp_s *fcxp_alloced);
0047 static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
0048                     struct bfa_fcxp_s *fcxp_alloced);
0049 static void bfa_fcs_rport_plogi_response(void *fcsarg,
0050                 struct bfa_fcxp_s *fcxp, void *cbarg,
0051                 bfa_status_t req_status, u32 rsp_len,
0052                 u32 resid_len, struct fchs_s *rsp_fchs);
0053 static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
0054                      struct bfa_fcxp_s *fcxp_alloced);
0055 static void bfa_fcs_rport_adisc_response(void *fcsarg,
0056                 struct bfa_fcxp_s *fcxp, void *cbarg,
0057                 bfa_status_t req_status, u32 rsp_len,
0058                 u32 resid_len, struct fchs_s *rsp_fchs);
0059 static void bfa_fcs_rport_send_nsdisc(void *rport_cbarg,
0060                      struct bfa_fcxp_s *fcxp_alloced);
0061 static void bfa_fcs_rport_gidpn_response(void *fcsarg,
0062                 struct bfa_fcxp_s *fcxp, void *cbarg,
0063                 bfa_status_t req_status, u32 rsp_len,
0064                 u32 resid_len, struct fchs_s *rsp_fchs);
0065 static void bfa_fcs_rport_gpnid_response(void *fcsarg,
0066                 struct bfa_fcxp_s *fcxp, void *cbarg,
0067                 bfa_status_t req_status, u32 rsp_len,
0068                 u32 resid_len, struct fchs_s *rsp_fchs);
0069 static void bfa_fcs_rport_send_logo(void *rport_cbarg,
0070                     struct bfa_fcxp_s *fcxp_alloced);
0071 static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
0072 static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
0073                     struct fchs_s *rx_fchs, u16 len);
0074 static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
0075                 struct fchs_s *rx_fchs, u8 reason_code,
0076                       u8 reason_code_expl);
0077 static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
0078                 struct fchs_s *rx_fchs, u16 len);
0079 static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
0080 static void bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);
0081 
0082 static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
0083                     enum rport_event event);
0084 static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
0085                         enum rport_event event);
0086 static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
0087                           enum rport_event event);
0088 static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
0089                         enum rport_event event);
0090 static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
0091                     enum rport_event event);
0092 static void bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
0093                     enum rport_event event);
0094 static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
0095                         enum rport_event event);
0096 static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
0097                     enum rport_event event);
0098 static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
0099                          enum rport_event event);
0100 static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
0101                      enum rport_event event);
0102 static void bfa_fcs_rport_sm_adisc_online_sending(
0103             struct bfa_fcs_rport_s *rport, enum rport_event event);
0104 static void bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
0105                     enum rport_event event);
0106 static void bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s
0107                     *rport, enum rport_event event);
0108 static void bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
0109                     enum rport_event event);
0110 static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
0111                         enum rport_event event);
0112 static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
0113                         enum rport_event event);
0114 static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
0115                         enum rport_event event);
0116 static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
0117                         enum rport_event event);
0118 static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
0119                         enum rport_event event);
0120 static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
0121                         enum rport_event event);
0122 static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
0123                         enum rport_event event);
0124 static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
0125                      enum rport_event event);
0126 static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
0127                         enum rport_event event);
0128 static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
0129                         enum rport_event event);
0130 static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
0131                         enum rport_event event);
0132 static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
0133                         enum rport_event event);
0134 static void bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
0135                         enum rport_event event);
0136 static void bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
0137                         enum rport_event event);
0138 
0139 static struct bfa_sm_table_s rport_sm_table[] = {
0140     {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
0141     {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
0142     {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
0143     {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
0144     {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
0145     {BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},
0146     {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
0147     {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
0148     {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
0149     {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
0150     {BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},
0151     {BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},
0152     {BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},
0153     {BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},
0154     {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
0155     {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
0156     {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
0157     {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
0158     {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
0159     {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
0160     {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
0161     {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
0162     {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
0163     {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
0164     {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
0165 };
0166 
0167 /*
0168  *      Beginning state.
0169  */
0170 static void
0171 bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
0172 {
0173     bfa_trc(rport->fcs, rport->pwwn);
0174     bfa_trc(rport->fcs, rport->pid);
0175     bfa_trc(rport->fcs, event);
0176 
0177     switch (event) {
0178     case RPSM_EVENT_PLOGI_SEND:
0179         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
0180         rport->plogi_retries = 0;
0181         bfa_fcs_rport_send_plogi(rport, NULL);
0182         break;
0183 
0184     case RPSM_EVENT_PLOGI_RCVD:
0185         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
0186         bfa_fcs_rport_send_plogiacc(rport, NULL);
0187         break;
0188 
0189     case RPSM_EVENT_PLOGI_COMP:
0190         bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
0191         bfa_fcs_rport_hal_online(rport);
0192         break;
0193 
0194     case RPSM_EVENT_ADDRESS_CHANGE:
0195     case RPSM_EVENT_ADDRESS_DISC:
0196         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
0197         rport->ns_retries = 0;
0198         bfa_fcs_rport_send_nsdisc(rport, NULL);
0199         break;
0200     default:
0201         bfa_sm_fault(rport->fcs, event);
0202     }
0203 }
0204 
0205 /*
0206  *      PLOGI is being sent.
0207  */
0208 static void
0209 bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
0210      enum rport_event event)
0211 {
0212     bfa_trc(rport->fcs, rport->pwwn);
0213     bfa_trc(rport->fcs, rport->pid);
0214     bfa_trc(rport->fcs, event);
0215 
0216     switch (event) {
0217     case RPSM_EVENT_FCXP_SENT:
0218         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
0219         break;
0220 
0221     case RPSM_EVENT_DELETE:
0222         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
0223         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0224         bfa_fcs_rport_free(rport);
0225         break;
0226 
0227     case RPSM_EVENT_PLOGI_RCVD:
0228         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
0229         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0230         bfa_fcs_rport_send_plogiacc(rport, NULL);
0231         break;
0232 
0233     case RPSM_EVENT_SCN_OFFLINE:
0234         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0235         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0236         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0237                 bfa_fcs_rport_timeout, rport,
0238                 bfa_fcs_rport_del_timeout);
0239         break;
0240     case RPSM_EVENT_ADDRESS_CHANGE:
0241     case RPSM_EVENT_FAB_SCN:
0242         /* query the NS */
0243         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0244         WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
0245                     BFA_PORT_TOPOLOGY_LOOP));
0246         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
0247         rport->ns_retries = 0;
0248         bfa_fcs_rport_send_nsdisc(rport, NULL);
0249         break;
0250 
0251     case RPSM_EVENT_LOGO_IMP:
0252         rport->pid = 0;
0253         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0254         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0255         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0256                 bfa_fcs_rport_timeout, rport,
0257                 bfa_fcs_rport_del_timeout);
0258         break;
0259 
0260 
0261     default:
0262         bfa_sm_fault(rport->fcs, event);
0263     }
0264 }
0265 
0266 /*
0267  *      PLOGI is being sent.
0268  */
0269 static void
0270 bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
0271      enum rport_event event)
0272 {
0273     bfa_trc(rport->fcs, rport->pwwn);
0274     bfa_trc(rport->fcs, rport->pid);
0275     bfa_trc(rport->fcs, event);
0276 
0277     switch (event) {
0278     case RPSM_EVENT_FCXP_SENT:
0279         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
0280         bfa_fcs_rport_fcs_online_action(rport);
0281         break;
0282 
0283     case RPSM_EVENT_DELETE:
0284         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
0285         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0286         bfa_fcs_rport_free(rport);
0287         break;
0288 
0289     case RPSM_EVENT_PLOGI_RCVD:
0290     case RPSM_EVENT_PLOGI_COMP:
0291     case RPSM_EVENT_FAB_SCN:
0292         /*
0293          * Ignore, SCN is possibly online notification.
0294          */
0295         break;
0296 
0297     case RPSM_EVENT_SCN_OFFLINE:
0298         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0299         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0300         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0301                 bfa_fcs_rport_timeout, rport,
0302                 bfa_fcs_rport_del_timeout);
0303         break;
0304 
0305     case RPSM_EVENT_ADDRESS_CHANGE:
0306         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0307         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
0308         rport->ns_retries = 0;
0309         bfa_fcs_rport_send_nsdisc(rport, NULL);
0310         break;
0311 
0312     case RPSM_EVENT_LOGO_IMP:
0313         rport->pid = 0;
0314         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0315         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0316         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0317                 bfa_fcs_rport_timeout, rport,
0318                 bfa_fcs_rport_del_timeout);
0319         break;
0320 
0321     case RPSM_EVENT_HCB_OFFLINE:
0322         /*
0323          * Ignore BFA callback, on a PLOGI receive we call bfa offline.
0324          */
0325         break;
0326 
0327     default:
0328         bfa_sm_fault(rport->fcs, event);
0329     }
0330 }
0331 
0332 /*
0333  *      PLOGI is sent.
0334  */
0335 static void
0336 bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
0337             enum rport_event event)
0338 {
0339     bfa_trc(rport->fcs, rport->pwwn);
0340     bfa_trc(rport->fcs, rport->pid);
0341     bfa_trc(rport->fcs, event);
0342 
0343     switch (event) {
0344     case RPSM_EVENT_TIMEOUT:
0345         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
0346         bfa_fcs_rport_send_plogi(rport, NULL);
0347         break;
0348 
0349     case RPSM_EVENT_DELETE:
0350         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
0351         bfa_timer_stop(&rport->timer);
0352         bfa_fcs_rport_free(rport);
0353         break;
0354 
0355     case RPSM_EVENT_PRLO_RCVD:
0356     case RPSM_EVENT_LOGO_RCVD:
0357         break;
0358 
0359     case RPSM_EVENT_PLOGI_RCVD:
0360         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
0361         bfa_timer_stop(&rport->timer);
0362         bfa_fcs_rport_send_plogiacc(rport, NULL);
0363         break;
0364 
0365     case RPSM_EVENT_SCN_OFFLINE:
0366         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0367         bfa_timer_stop(&rport->timer);
0368         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0369                 bfa_fcs_rport_timeout, rport,
0370                 bfa_fcs_rport_del_timeout);
0371         break;
0372 
0373     case RPSM_EVENT_ADDRESS_CHANGE:
0374     case RPSM_EVENT_FAB_SCN:
0375         bfa_timer_stop(&rport->timer);
0376         WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
0377                     BFA_PORT_TOPOLOGY_LOOP));
0378         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
0379         rport->ns_retries = 0;
0380         bfa_fcs_rport_send_nsdisc(rport, NULL);
0381         break;
0382 
0383     case RPSM_EVENT_LOGO_IMP:
0384         rport->pid = 0;
0385         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0386         bfa_timer_stop(&rport->timer);
0387         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0388                 bfa_fcs_rport_timeout, rport,
0389                 bfa_fcs_rport_del_timeout);
0390         break;
0391 
0392     case RPSM_EVENT_PLOGI_COMP:
0393         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
0394         bfa_timer_stop(&rport->timer);
0395         bfa_fcs_rport_fcs_online_action(rport);
0396         break;
0397 
0398     default:
0399         bfa_sm_fault(rport->fcs, event);
0400     }
0401 }
0402 
0403 /*
0404  *      PLOGI is sent.
0405  */
0406 static void
0407 bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
0408 {
0409     bfa_trc(rport->fcs, rport->pwwn);
0410     bfa_trc(rport->fcs, rport->pid);
0411     bfa_trc(rport->fcs, event);
0412 
0413     switch (event) {
0414     case RPSM_EVENT_ACCEPTED:
0415         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
0416         rport->plogi_retries = 0;
0417         bfa_fcs_rport_fcs_online_action(rport);
0418         break;
0419 
0420     case RPSM_EVENT_LOGO_RCVD:
0421         bfa_fcs_rport_send_logo_acc(rport);
0422         fallthrough;
0423     case RPSM_EVENT_PRLO_RCVD:
0424         if (rport->prlo == BFA_TRUE)
0425             bfa_fcs_rport_send_prlo_acc(rport);
0426 
0427         bfa_fcxp_discard(rport->fcxp);
0428         fallthrough;
0429     case RPSM_EVENT_FAILED:
0430         if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
0431             rport->plogi_retries++;
0432             bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
0433             bfa_timer_start(rport->fcs->bfa, &rport->timer,
0434                     bfa_fcs_rport_timeout, rport,
0435                     BFA_FCS_RETRY_TIMEOUT);
0436         } else {
0437             bfa_stats(rport->port, rport_del_max_plogi_retry);
0438             rport->old_pid = rport->pid;
0439             rport->pid = 0;
0440             bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0441             bfa_timer_start(rport->fcs->bfa, &rport->timer,
0442                     bfa_fcs_rport_timeout, rport,
0443                     bfa_fcs_rport_del_timeout);
0444         }
0445         break;
0446 
0447     case RPSM_EVENT_SCN_ONLINE:
0448         break;
0449 
0450     case RPSM_EVENT_SCN_OFFLINE:
0451         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0452         bfa_fcxp_discard(rport->fcxp);
0453         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0454                 bfa_fcs_rport_timeout, rport,
0455                 bfa_fcs_rport_del_timeout);
0456         break;
0457 
0458     case RPSM_EVENT_PLOGI_RETRY:
0459         rport->plogi_retries = 0;
0460         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
0461         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0462                 bfa_fcs_rport_timeout, rport,
0463                 (FC_RA_TOV * 1000));
0464         break;
0465 
0466     case RPSM_EVENT_LOGO_IMP:
0467         rport->pid = 0;
0468         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0469         bfa_fcxp_discard(rport->fcxp);
0470         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0471                 bfa_fcs_rport_timeout, rport,
0472                 bfa_fcs_rport_del_timeout);
0473         break;
0474 
0475     case RPSM_EVENT_ADDRESS_CHANGE:
0476     case RPSM_EVENT_FAB_SCN:
0477         bfa_fcxp_discard(rport->fcxp);
0478         WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
0479                     BFA_PORT_TOPOLOGY_LOOP));
0480         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
0481         rport->ns_retries = 0;
0482         bfa_fcs_rport_send_nsdisc(rport, NULL);
0483         break;
0484 
0485     case RPSM_EVENT_PLOGI_RCVD:
0486         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
0487         bfa_fcxp_discard(rport->fcxp);
0488         bfa_fcs_rport_send_plogiacc(rport, NULL);
0489         break;
0490 
0491     case RPSM_EVENT_DELETE:
0492         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
0493         bfa_fcxp_discard(rport->fcxp);
0494         bfa_fcs_rport_free(rport);
0495         break;
0496 
0497     case RPSM_EVENT_PLOGI_COMP:
0498         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
0499         bfa_fcxp_discard(rport->fcxp);
0500         bfa_fcs_rport_fcs_online_action(rport);
0501         break;
0502 
0503     default:
0504         bfa_sm_fault(rport->fcs, event);
0505     }
0506 }
0507 
0508 /*
0509  * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function
0510  */
0511 static void
0512 bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
0513                 enum rport_event event)
0514 {
0515     bfa_trc(rport->fcs, rport->pwwn);
0516     bfa_trc(rport->fcs, rport->pid);
0517     bfa_trc(rport->fcs, event);
0518 
0519     switch (event) {
0520     case RPSM_EVENT_FC4_FCS_ONLINE:
0521         if (rport->scsi_function == BFA_RPORT_INITIATOR) {
0522             if (!BFA_FCS_PID_IS_WKA(rport->pid))
0523                 bfa_fcs_rpf_rport_online(rport);
0524             bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
0525             break;
0526         }
0527 
0528         if (!rport->bfa_rport)
0529             rport->bfa_rport =
0530                 bfa_rport_create(rport->fcs->bfa, rport);
0531 
0532         if (rport->bfa_rport) {
0533             bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
0534             bfa_fcs_rport_hal_online(rport);
0535         } else {
0536             bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0537             bfa_fcs_rport_fcs_offline_action(rport);
0538         }
0539         break;
0540 
0541     case RPSM_EVENT_PLOGI_RCVD:
0542         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0543         rport->plogi_pending = BFA_TRUE;
0544         bfa_fcs_rport_fcs_offline_action(rport);
0545         break;
0546 
0547     case RPSM_EVENT_PLOGI_COMP:
0548     case RPSM_EVENT_LOGO_IMP:
0549     case RPSM_EVENT_ADDRESS_CHANGE:
0550     case RPSM_EVENT_FAB_SCN:
0551     case RPSM_EVENT_SCN_OFFLINE:
0552         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0553         bfa_fcs_rport_fcs_offline_action(rport);
0554         break;
0555 
0556     case RPSM_EVENT_LOGO_RCVD:
0557     case RPSM_EVENT_PRLO_RCVD:
0558         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
0559         bfa_fcs_rport_fcs_offline_action(rport);
0560         break;
0561 
0562     case RPSM_EVENT_DELETE:
0563         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0564         bfa_fcs_rport_fcs_offline_action(rport);
0565         break;
0566 
0567     default:
0568         bfa_sm_fault(rport->fcs, event);
0569         break;
0570     }
0571 }
0572 
0573 /*
0574  *      PLOGI is complete. Awaiting BFA rport online callback. FC-4s
0575  *      are offline.
0576  */
0577 static void
0578 bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
0579             enum rport_event event)
0580 {
0581     bfa_trc(rport->fcs, rport->pwwn);
0582     bfa_trc(rport->fcs, rport->pid);
0583     bfa_trc(rport->fcs, event);
0584 
0585     switch (event) {
0586     case RPSM_EVENT_HCB_ONLINE:
0587         bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
0588         bfa_fcs_rport_hal_online_action(rport);
0589         break;
0590 
0591     case RPSM_EVENT_PLOGI_COMP:
0592         break;
0593 
0594     case RPSM_EVENT_PRLO_RCVD:
0595     case RPSM_EVENT_LOGO_RCVD:
0596         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
0597         bfa_fcs_rport_fcs_offline_action(rport);
0598         break;
0599 
0600     case RPSM_EVENT_FAB_SCN:
0601     case RPSM_EVENT_LOGO_IMP:
0602     case RPSM_EVENT_ADDRESS_CHANGE:
0603     case RPSM_EVENT_SCN_OFFLINE:
0604         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0605         bfa_fcs_rport_fcs_offline_action(rport);
0606         break;
0607 
0608     case RPSM_EVENT_PLOGI_RCVD:
0609         rport->plogi_pending = BFA_TRUE;
0610         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0611         bfa_fcs_rport_fcs_offline_action(rport);
0612         break;
0613 
0614     case RPSM_EVENT_DELETE:
0615         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0616         bfa_fcs_rport_fcs_offline_action(rport);
0617         break;
0618 
0619     default:
0620         bfa_sm_fault(rport->fcs, event);
0621     }
0622 }
0623 
0624 /*
0625  *      Rport is ONLINE. FC-4s active.
0626  */
0627 static void
0628 bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
0629 {
0630     bfa_trc(rport->fcs, rport->pwwn);
0631     bfa_trc(rport->fcs, rport->pid);
0632     bfa_trc(rport->fcs, event);
0633 
0634     switch (event) {
0635     case RPSM_EVENT_FAB_SCN:
0636         if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
0637             bfa_sm_set_state(rport,
0638                      bfa_fcs_rport_sm_nsquery_sending);
0639             rport->ns_retries = 0;
0640             bfa_fcs_rport_send_nsdisc(rport, NULL);
0641         } else {
0642             bfa_sm_set_state(rport,
0643                 bfa_fcs_rport_sm_adisc_online_sending);
0644             bfa_fcs_rport_send_adisc(rport, NULL);
0645         }
0646         break;
0647 
0648     case RPSM_EVENT_PLOGI_RCVD:
0649     case RPSM_EVENT_LOGO_IMP:
0650     case RPSM_EVENT_ADDRESS_CHANGE:
0651     case RPSM_EVENT_SCN_OFFLINE:
0652         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0653         bfa_fcs_rport_hal_offline_action(rport);
0654         break;
0655 
0656     case RPSM_EVENT_DELETE:
0657         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0658         bfa_fcs_rport_hal_offline_action(rport);
0659         break;
0660 
0661     case RPSM_EVENT_LOGO_RCVD:
0662     case RPSM_EVENT_PRLO_RCVD:
0663         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
0664         bfa_fcs_rport_hal_offline_action(rport);
0665         break;
0666 
0667     case RPSM_EVENT_SCN_ONLINE:
0668     case RPSM_EVENT_PLOGI_COMP:
0669         break;
0670 
0671     default:
0672         bfa_sm_fault(rport->fcs, event);
0673     }
0674 }
0675 
0676 /*
0677  *      An SCN event is received in ONLINE state. NS query is being sent
0678  *      prior to ADISC authentication with rport. FC-4s are paused.
0679  */
0680 static void
0681 bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
0682      enum rport_event event)
0683 {
0684     bfa_trc(rport->fcs, rport->pwwn);
0685     bfa_trc(rport->fcs, rport->pid);
0686     bfa_trc(rport->fcs, event);
0687 
0688     switch (event) {
0689     case RPSM_EVENT_FCXP_SENT:
0690         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
0691         break;
0692 
0693     case RPSM_EVENT_DELETE:
0694         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0695         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0696         bfa_fcs_rport_hal_offline_action(rport);
0697         break;
0698 
0699     case RPSM_EVENT_FAB_SCN:
0700         /*
0701          * ignore SCN, wait for response to query itself
0702          */
0703         break;
0704 
0705     case RPSM_EVENT_LOGO_RCVD:
0706     case RPSM_EVENT_PRLO_RCVD:
0707         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
0708         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0709         bfa_fcs_rport_hal_offline_action(rport);
0710         break;
0711 
0712     case RPSM_EVENT_LOGO_IMP:
0713     case RPSM_EVENT_PLOGI_RCVD:
0714     case RPSM_EVENT_ADDRESS_CHANGE:
0715     case RPSM_EVENT_PLOGI_COMP:
0716         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0717         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0718         bfa_fcs_rport_hal_offline_action(rport);
0719         break;
0720 
0721     default:
0722         bfa_sm_fault(rport->fcs, event);
0723     }
0724 }
0725 
0726 /*
0727  *  An SCN event is received in ONLINE state. NS query is sent to rport.
0728  *  FC-4s are paused.
0729  */
0730 static void
0731 bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
0732 {
0733     bfa_trc(rport->fcs, rport->pwwn);
0734     bfa_trc(rport->fcs, rport->pid);
0735     bfa_trc(rport->fcs, event);
0736 
0737     switch (event) {
0738     case RPSM_EVENT_ACCEPTED:
0739         bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);
0740         bfa_fcs_rport_send_adisc(rport, NULL);
0741         break;
0742 
0743     case RPSM_EVENT_FAILED:
0744         rport->ns_retries++;
0745         if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
0746             bfa_sm_set_state(rport,
0747                      bfa_fcs_rport_sm_nsquery_sending);
0748             bfa_fcs_rport_send_nsdisc(rport, NULL);
0749         } else {
0750             bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0751             bfa_fcs_rport_hal_offline_action(rport);
0752         }
0753         break;
0754 
0755     case RPSM_EVENT_DELETE:
0756         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0757         bfa_fcxp_discard(rport->fcxp);
0758         bfa_fcs_rport_hal_offline_action(rport);
0759         break;
0760 
0761     case RPSM_EVENT_FAB_SCN:
0762         break;
0763 
0764     case RPSM_EVENT_LOGO_RCVD:
0765     case RPSM_EVENT_PRLO_RCVD:
0766         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
0767         bfa_fcxp_discard(rport->fcxp);
0768         bfa_fcs_rport_hal_offline_action(rport);
0769         break;
0770 
0771     case RPSM_EVENT_PLOGI_COMP:
0772     case RPSM_EVENT_ADDRESS_CHANGE:
0773     case RPSM_EVENT_PLOGI_RCVD:
0774     case RPSM_EVENT_LOGO_IMP:
0775         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0776         bfa_fcxp_discard(rport->fcxp);
0777         bfa_fcs_rport_hal_offline_action(rport);
0778         break;
0779 
0780     default:
0781         bfa_sm_fault(rport->fcs, event);
0782     }
0783 }
0784 
0785 /*
0786  *  An SCN event is received in ONLINE state. ADISC is being sent for
0787  *  authenticating with rport. FC-4s are paused.
0788  */
0789 static void
0790 bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,
0791      enum rport_event event)
0792 {
0793     bfa_trc(rport->fcs, rport->pwwn);
0794     bfa_trc(rport->fcs, rport->pid);
0795     bfa_trc(rport->fcs, event);
0796 
0797     switch (event) {
0798     case RPSM_EVENT_FCXP_SENT:
0799         bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);
0800         break;
0801 
0802     case RPSM_EVENT_DELETE:
0803         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0804         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0805         bfa_fcs_rport_hal_offline_action(rport);
0806         break;
0807 
0808     case RPSM_EVENT_LOGO_IMP:
0809     case RPSM_EVENT_ADDRESS_CHANGE:
0810         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0811         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0812         bfa_fcs_rport_hal_offline_action(rport);
0813         break;
0814 
0815     case RPSM_EVENT_LOGO_RCVD:
0816     case RPSM_EVENT_PRLO_RCVD:
0817         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
0818         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0819         bfa_fcs_rport_hal_offline_action(rport);
0820         break;
0821 
0822     case RPSM_EVENT_FAB_SCN:
0823         break;
0824 
0825     case RPSM_EVENT_PLOGI_RCVD:
0826         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0827         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0828         bfa_fcs_rport_hal_offline_action(rport);
0829         break;
0830 
0831     default:
0832         bfa_sm_fault(rport->fcs, event);
0833     }
0834 }
0835 
0836 /*
0837  *      An SCN event is received in ONLINE state. ADISC is to rport.
0838  *      FC-4s are paused.
0839  */
0840 static void
0841 bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
0842                 enum rport_event event)
0843 {
0844     bfa_trc(rport->fcs, rport->pwwn);
0845     bfa_trc(rport->fcs, rport->pid);
0846     bfa_trc(rport->fcs, event);
0847 
0848     switch (event) {
0849     case RPSM_EVENT_ACCEPTED:
0850         bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
0851         break;
0852 
0853     case RPSM_EVENT_PLOGI_RCVD:
0854         /*
0855          * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
0856          * At least go offline when a PLOGI is received.
0857          */
0858         bfa_fcxp_discard(rport->fcxp);
0859         fallthrough;
0860 
0861     case RPSM_EVENT_FAILED:
0862     case RPSM_EVENT_ADDRESS_CHANGE:
0863         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0864         bfa_fcs_rport_hal_offline_action(rport);
0865         break;
0866 
0867     case RPSM_EVENT_DELETE:
0868         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
0869         bfa_fcxp_discard(rport->fcxp);
0870         bfa_fcs_rport_hal_offline_action(rport);
0871         break;
0872 
0873     case RPSM_EVENT_FAB_SCN:
0874         /*
0875          * already processing RSCN
0876          */
0877         break;
0878 
0879     case RPSM_EVENT_LOGO_IMP:
0880         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
0881         bfa_fcxp_discard(rport->fcxp);
0882         bfa_fcs_rport_hal_offline_action(rport);
0883         break;
0884 
0885     case RPSM_EVENT_LOGO_RCVD:
0886     case RPSM_EVENT_PRLO_RCVD:
0887         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
0888         bfa_fcxp_discard(rport->fcxp);
0889         bfa_fcs_rport_hal_offline_action(rport);
0890         break;
0891 
0892     default:
0893         bfa_sm_fault(rport->fcs, event);
0894     }
0895 }
0896 
0897 /*
0898  * ADISC is being sent for authenticating with rport
0899  * Already did offline actions.
0900  */
0901 static void
0902 bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,
0903     enum rport_event event)
0904 {
0905     bfa_trc(rport->fcs, rport->pwwn);
0906     bfa_trc(rport->fcs, rport->pid);
0907     bfa_trc(rport->fcs, event);
0908 
0909     switch (event) {
0910     case RPSM_EVENT_FCXP_SENT:
0911         bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);
0912         break;
0913 
0914     case RPSM_EVENT_DELETE:
0915     case RPSM_EVENT_SCN_OFFLINE:
0916     case RPSM_EVENT_LOGO_IMP:
0917     case RPSM_EVENT_LOGO_RCVD:
0918     case RPSM_EVENT_PRLO_RCVD:
0919         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0920         bfa_fcxp_walloc_cancel(rport->fcs->bfa,
0921             &rport->fcxp_wqe);
0922         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0923             bfa_fcs_rport_timeout, rport,
0924             bfa_fcs_rport_del_timeout);
0925         break;
0926 
0927     case RPSM_EVENT_PLOGI_RCVD:
0928         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
0929         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
0930         bfa_fcs_rport_send_plogiacc(rport, NULL);
0931         break;
0932 
0933     default:
0934         bfa_sm_fault(rport->fcs, event);
0935     }
0936 }
0937 
0938 /*
0939  * ADISC to rport
0940  * Already did offline actions
0941  */
0942 static void
0943 bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
0944             enum rport_event event)
0945 {
0946     bfa_trc(rport->fcs, rport->pwwn);
0947     bfa_trc(rport->fcs, rport->pid);
0948     bfa_trc(rport->fcs, event);
0949 
0950     switch (event) {
0951     case RPSM_EVENT_ACCEPTED:
0952         bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
0953         bfa_fcs_rport_hal_online(rport);
0954         break;
0955 
0956     case RPSM_EVENT_PLOGI_RCVD:
0957         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
0958         bfa_fcxp_discard(rport->fcxp);
0959         bfa_fcs_rport_send_plogiacc(rport, NULL);
0960         break;
0961 
0962     case RPSM_EVENT_FAILED:
0963         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0964         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0965             bfa_fcs_rport_timeout, rport,
0966             bfa_fcs_rport_del_timeout);
0967         break;
0968 
0969     case RPSM_EVENT_DELETE:
0970     case RPSM_EVENT_SCN_OFFLINE:
0971     case RPSM_EVENT_LOGO_IMP:
0972     case RPSM_EVENT_LOGO_RCVD:
0973     case RPSM_EVENT_PRLO_RCVD:
0974         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
0975         bfa_fcxp_discard(rport->fcxp);
0976         bfa_timer_start(rport->fcs->bfa, &rport->timer,
0977             bfa_fcs_rport_timeout, rport,
0978             bfa_fcs_rport_del_timeout);
0979         break;
0980 
0981     default:
0982         bfa_sm_fault(rport->fcs, event);
0983     }
0984 }
0985 
0986 /*
0987  * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
0988  */
0989 static void
0990 bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
0991             enum rport_event event)
0992 {
0993     bfa_trc(rport->fcs, rport->pwwn);
0994     bfa_trc(rport->fcs, rport->pid);
0995     bfa_trc(rport->fcs, event);
0996 
0997     switch (event) {
0998     case RPSM_EVENT_FC4_OFFLINE:
0999         bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
1000         bfa_fcs_rport_hal_offline(rport);
1001         break;
1002 
1003     case RPSM_EVENT_DELETE:
1004         if (rport->pid && (rport->prlo == BFA_TRUE))
1005             bfa_fcs_rport_send_prlo_acc(rport);
1006         if (rport->pid && (rport->prlo == BFA_FALSE))
1007             bfa_fcs_rport_send_logo_acc(rport);
1008 
1009         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
1010         break;
1011 
1012     case RPSM_EVENT_SCN_ONLINE:
1013     case RPSM_EVENT_SCN_OFFLINE:
1014     case RPSM_EVENT_HCB_ONLINE:
1015     case RPSM_EVENT_LOGO_RCVD:
1016     case RPSM_EVENT_PRLO_RCVD:
1017     case RPSM_EVENT_ADDRESS_CHANGE:
1018         break;
1019 
1020     default:
1021         bfa_sm_fault(rport->fcs, event);
1022     }
1023 }
1024 
1025 /*
1026  *      LOGO needs to be sent to rport. Awaiting FC-4 offline completion
1027  *      callback.
1028  */
1029 static void
1030 bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
1031      enum rport_event event)
1032 {
1033     bfa_trc(rport->fcs, rport->pwwn);
1034     bfa_trc(rport->fcs, rport->pid);
1035     bfa_trc(rport->fcs, event);
1036 
1037     switch (event) {
1038     case RPSM_EVENT_FC4_OFFLINE:
1039         bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
1040         bfa_fcs_rport_hal_offline(rport);
1041         break;
1042 
1043     case RPSM_EVENT_LOGO_RCVD:
1044         bfa_fcs_rport_send_logo_acc(rport);
1045         fallthrough;
1046     case RPSM_EVENT_PRLO_RCVD:
1047         if (rport->prlo == BFA_TRUE)
1048             bfa_fcs_rport_send_prlo_acc(rport);
1049         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
1050         break;
1051 
1052     case RPSM_EVENT_HCB_ONLINE:
1053     case RPSM_EVENT_DELETE:
1054         /* Rport is being deleted */
1055         break;
1056 
1057     default:
1058         bfa_sm_fault(rport->fcs, event);
1059     }
1060 }
1061 
1062 /*
1063  *  Rport is going offline. Awaiting FC-4 offline completion callback.
1064  */
1065 static void
1066 bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
1067             enum rport_event event)
1068 {
1069     bfa_trc(rport->fcs, rport->pwwn);
1070     bfa_trc(rport->fcs, rport->pid);
1071     bfa_trc(rport->fcs, event);
1072 
1073     switch (event) {
1074     case RPSM_EVENT_FC4_OFFLINE:
1075         bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1076         bfa_fcs_rport_hal_offline(rport);
1077         break;
1078 
1079     case RPSM_EVENT_SCN_ONLINE:
1080         break;
1081     case RPSM_EVENT_LOGO_RCVD:
1082         /*
1083          * Rport is going offline. Just ack the logo
1084          */
1085         bfa_fcs_rport_send_logo_acc(rport);
1086         break;
1087 
1088     case RPSM_EVENT_PRLO_RCVD:
1089         bfa_fcs_rport_send_prlo_acc(rport);
1090         break;
1091 
1092     case RPSM_EVENT_SCN_OFFLINE:
1093     case RPSM_EVENT_HCB_ONLINE:
1094     case RPSM_EVENT_FAB_SCN:
1095     case RPSM_EVENT_LOGO_IMP:
1096     case RPSM_EVENT_ADDRESS_CHANGE:
1097         /*
1098          * rport is already going offline.
1099          * SCN - ignore and wait till transitioning to offline state
1100          */
1101         break;
1102 
1103     case RPSM_EVENT_DELETE:
1104         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
1105         break;
1106 
1107     default:
1108         bfa_sm_fault(rport->fcs, event);
1109     }
1110 }
1111 
1112 /*
1113  *      Rport is offline. FC-4s are offline. Awaiting BFA rport offline
1114  *      callback.
1115  */
1116 static void
1117 bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
1118                 enum rport_event event)
1119 {
1120     bfa_trc(rport->fcs, rport->pwwn);
1121     bfa_trc(rport->fcs, rport->pid);
1122     bfa_trc(rport->fcs, event);
1123 
1124     switch (event) {
1125     case RPSM_EVENT_HCB_OFFLINE:
1126         if (bfa_fcs_lport_is_online(rport->port) &&
1127             (rport->plogi_pending)) {
1128             rport->plogi_pending = BFA_FALSE;
1129             bfa_sm_set_state(rport,
1130                 bfa_fcs_rport_sm_plogiacc_sending);
1131             bfa_fcs_rport_send_plogiacc(rport, NULL);
1132             break;
1133         }
1134         fallthrough;
1135 
1136     case RPSM_EVENT_ADDRESS_CHANGE:
1137         if (!bfa_fcs_lport_is_online(rport->port)) {
1138             rport->pid = 0;
1139             bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1140             bfa_timer_start(rport->fcs->bfa, &rport->timer,
1141                     bfa_fcs_rport_timeout, rport,
1142                     bfa_fcs_rport_del_timeout);
1143             break;
1144         }
1145         if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
1146             bfa_sm_set_state(rport,
1147                 bfa_fcs_rport_sm_nsdisc_sending);
1148             rport->ns_retries = 0;
1149             bfa_fcs_rport_send_nsdisc(rport, NULL);
1150         } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==
1151                     BFA_PORT_TOPOLOGY_LOOP) {
1152             if (rport->scn_online) {
1153                 bfa_sm_set_state(rport,
1154                     bfa_fcs_rport_sm_adisc_offline_sending);
1155                 bfa_fcs_rport_send_adisc(rport, NULL);
1156             } else {
1157                 bfa_sm_set_state(rport,
1158                     bfa_fcs_rport_sm_offline);
1159                 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1160                     bfa_fcs_rport_timeout, rport,
1161                     bfa_fcs_rport_del_timeout);
1162             }
1163         } else {
1164             bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1165             rport->plogi_retries = 0;
1166             bfa_fcs_rport_send_plogi(rport, NULL);
1167         }
1168         break;
1169 
1170     case RPSM_EVENT_DELETE:
1171         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1172         bfa_fcs_rport_free(rport);
1173         break;
1174 
1175     case RPSM_EVENT_SCN_ONLINE:
1176     case RPSM_EVENT_SCN_OFFLINE:
1177     case RPSM_EVENT_FAB_SCN:
1178     case RPSM_EVENT_LOGO_RCVD:
1179     case RPSM_EVENT_PRLO_RCVD:
1180     case RPSM_EVENT_PLOGI_RCVD:
1181     case RPSM_EVENT_LOGO_IMP:
1182         /*
1183          * Ignore, already offline.
1184          */
1185         break;
1186 
1187     default:
1188         bfa_sm_fault(rport->fcs, event);
1189     }
1190 }
1191 
1192 /*
1193  *      Rport is offline. FC-4s are offline. Awaiting BFA rport offline
1194  *      callback to send LOGO accept.
1195  */
1196 static void
1197 bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
1198             enum rport_event event)
1199 {
1200     bfa_trc(rport->fcs, rport->pwwn);
1201     bfa_trc(rport->fcs, rport->pid);
1202     bfa_trc(rport->fcs, event);
1203 
1204     switch (event) {
1205     case RPSM_EVENT_HCB_OFFLINE:
1206     case RPSM_EVENT_ADDRESS_CHANGE:
1207         if (rport->pid && (rport->prlo == BFA_TRUE))
1208             bfa_fcs_rport_send_prlo_acc(rport);
1209         if (rport->pid && (rport->prlo == BFA_FALSE))
1210             bfa_fcs_rport_send_logo_acc(rport);
1211         /*
1212          * If the lport is online and if the rport is not a well
1213          * known address port,
1214          * we try to re-discover the r-port.
1215          */
1216         if (bfa_fcs_lport_is_online(rport->port) &&
1217             (!BFA_FCS_PID_IS_WKA(rport->pid))) {
1218             if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
1219                 bfa_sm_set_state(rport,
1220                     bfa_fcs_rport_sm_nsdisc_sending);
1221                 rport->ns_retries = 0;
1222                 bfa_fcs_rport_send_nsdisc(rport, NULL);
1223             } else {
1224                 /* For N2N  Direct Attach, try to re-login */
1225                 bfa_sm_set_state(rport,
1226                     bfa_fcs_rport_sm_plogi_sending);
1227                 rport->plogi_retries = 0;
1228                 bfa_fcs_rport_send_plogi(rport, NULL);
1229             }
1230         } else {
1231             /*
1232              * if it is not a well known address, reset the
1233              * pid to 0.
1234              */
1235             if (!BFA_FCS_PID_IS_WKA(rport->pid))
1236                 rport->pid = 0;
1237             bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1238             bfa_timer_start(rport->fcs->bfa, &rport->timer,
1239                     bfa_fcs_rport_timeout, rport,
1240                     bfa_fcs_rport_del_timeout);
1241         }
1242         break;
1243 
1244     case RPSM_EVENT_DELETE:
1245         bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1246         if (rport->pid && (rport->prlo == BFA_TRUE))
1247             bfa_fcs_rport_send_prlo_acc(rport);
1248         if (rport->pid && (rport->prlo == BFA_FALSE))
1249             bfa_fcs_rport_send_logo_acc(rport);
1250         break;
1251 
1252     case RPSM_EVENT_LOGO_IMP:
1253         bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1254         break;
1255 
1256     case RPSM_EVENT_SCN_ONLINE:
1257     case RPSM_EVENT_SCN_OFFLINE:
1258     case RPSM_EVENT_LOGO_RCVD:
1259     case RPSM_EVENT_PRLO_RCVD:
1260         /*
1261          * Ignore - already processing a LOGO.
1262          */
1263         break;
1264 
1265     default:
1266         bfa_sm_fault(rport->fcs, event);
1267     }
1268 }
1269 
1270 /*
1271  *      Rport is being deleted. FC-4s are offline.
1272  *  Awaiting BFA rport offline
1273  *      callback to send LOGO.
1274  */
1275 static void
1276 bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
1277          enum rport_event event)
1278 {
1279     bfa_trc(rport->fcs, rport->pwwn);
1280     bfa_trc(rport->fcs, rport->pid);
1281     bfa_trc(rport->fcs, event);
1282 
1283     switch (event) {
1284     case RPSM_EVENT_HCB_OFFLINE:
1285         bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
1286         bfa_fcs_rport_send_logo(rport, NULL);
1287         break;
1288 
1289     case RPSM_EVENT_LOGO_RCVD:
1290         bfa_fcs_rport_send_logo_acc(rport);
1291         fallthrough;
1292     case RPSM_EVENT_PRLO_RCVD:
1293         if (rport->prlo == BFA_TRUE)
1294             bfa_fcs_rport_send_prlo_acc(rport);
1295 
1296         bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1297         break;
1298 
1299     case RPSM_EVENT_SCN_ONLINE:
1300     case RPSM_EVENT_SCN_OFFLINE:
1301     case RPSM_EVENT_ADDRESS_CHANGE:
1302         break;
1303 
1304     default:
1305         bfa_sm_fault(rport->fcs, event);
1306     }
1307 }
1308 
1309 /*
1310  *      Rport is being deleted. FC-4s are offline. LOGO is being sent.
1311  */
1312 static void
1313 bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
1314      enum rport_event event)
1315 {
1316     bfa_trc(rport->fcs, rport->pwwn);
1317     bfa_trc(rport->fcs, rport->pid);
1318     bfa_trc(rport->fcs, event);
1319 
1320     switch (event) {
1321     case RPSM_EVENT_FCXP_SENT:
1322         /* Once LOGO is sent, we donot wait for the response */
1323         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1324         bfa_fcs_rport_free(rport);
1325         break;
1326 
1327     case RPSM_EVENT_SCN_ONLINE:
1328     case RPSM_EVENT_SCN_OFFLINE:
1329     case RPSM_EVENT_FAB_SCN:
1330     case RPSM_EVENT_ADDRESS_CHANGE:
1331         break;
1332 
1333     case RPSM_EVENT_LOGO_RCVD:
1334         bfa_fcs_rport_send_logo_acc(rport);
1335         fallthrough;
1336     case RPSM_EVENT_PRLO_RCVD:
1337         if (rport->prlo == BFA_TRUE)
1338             bfa_fcs_rport_send_prlo_acc(rport);
1339 
1340         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1341         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1342         bfa_fcs_rport_free(rport);
1343         break;
1344 
1345     default:
1346         bfa_sm_fault(rport->fcs, event);
1347     }
1348 }
1349 
1350 /*
1351  *      Rport is offline. FC-4s are offline. BFA rport is offline.
1352  *      Timer active to delete stale rport.
1353  */
1354 static void
1355 bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1356 {
1357     bfa_trc(rport->fcs, rport->pwwn);
1358     bfa_trc(rport->fcs, rport->pid);
1359     bfa_trc(rport->fcs, event);
1360 
1361     switch (event) {
1362     case RPSM_EVENT_TIMEOUT:
1363         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1364         bfa_fcs_rport_free(rport);
1365         break;
1366 
1367     case RPSM_EVENT_FAB_SCN:
1368     case RPSM_EVENT_ADDRESS_CHANGE:
1369         bfa_timer_stop(&rport->timer);
1370         WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
1371                     BFA_PORT_TOPOLOGY_LOOP));
1372         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1373         rport->ns_retries = 0;
1374         bfa_fcs_rport_send_nsdisc(rport, NULL);
1375         break;
1376 
1377     case RPSM_EVENT_DELETE:
1378         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1379         bfa_timer_stop(&rport->timer);
1380         bfa_fcs_rport_free(rport);
1381         break;
1382 
1383     case RPSM_EVENT_PLOGI_RCVD:
1384         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1385         bfa_timer_stop(&rport->timer);
1386         bfa_fcs_rport_send_plogiacc(rport, NULL);
1387         break;
1388 
1389     case RPSM_EVENT_LOGO_RCVD:
1390     case RPSM_EVENT_PRLO_RCVD:
1391     case RPSM_EVENT_LOGO_IMP:
1392     case RPSM_EVENT_SCN_OFFLINE:
1393         break;
1394 
1395     case RPSM_EVENT_PLOGI_COMP:
1396         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1397         bfa_timer_stop(&rport->timer);
1398         bfa_fcs_rport_fcs_online_action(rport);
1399         break;
1400 
1401     case RPSM_EVENT_SCN_ONLINE:
1402         bfa_timer_stop(&rport->timer);
1403         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1404         bfa_fcs_rport_send_plogi(rport, NULL);
1405         break;
1406 
1407     case RPSM_EVENT_PLOGI_SEND:
1408         bfa_timer_stop(&rport->timer);
1409         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1410         rport->plogi_retries = 0;
1411         bfa_fcs_rport_send_plogi(rport, NULL);
1412         break;
1413 
1414     default:
1415         bfa_sm_fault(rport->fcs, event);
1416     }
1417 }
1418 
1419 /*
1420  *  Rport address has changed. Nameserver discovery request is being sent.
1421  */
1422 static void
1423 bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
1424      enum rport_event event)
1425 {
1426     bfa_trc(rport->fcs, rport->pwwn);
1427     bfa_trc(rport->fcs, rport->pid);
1428     bfa_trc(rport->fcs, event);
1429 
1430     switch (event) {
1431     case RPSM_EVENT_FCXP_SENT:
1432         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
1433         break;
1434 
1435     case RPSM_EVENT_DELETE:
1436         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1437         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1438         bfa_fcs_rport_free(rport);
1439         break;
1440 
1441     case RPSM_EVENT_PLOGI_RCVD:
1442         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1443         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1444         bfa_fcs_rport_send_plogiacc(rport, NULL);
1445         break;
1446 
1447     case RPSM_EVENT_FAB_SCN:
1448     case RPSM_EVENT_LOGO_RCVD:
1449     case RPSM_EVENT_PRLO_RCVD:
1450     case RPSM_EVENT_PLOGI_SEND:
1451         break;
1452 
1453     case RPSM_EVENT_ADDRESS_CHANGE:
1454         rport->ns_retries = 0; /* reset the retry count */
1455         break;
1456 
1457     case RPSM_EVENT_LOGO_IMP:
1458         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1459         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1460         bfa_timer_start(rport->fcs->bfa, &rport->timer,
1461                 bfa_fcs_rport_timeout, rport,
1462                 bfa_fcs_rport_del_timeout);
1463         break;
1464 
1465     case RPSM_EVENT_PLOGI_COMP:
1466         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1467         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1468         bfa_fcs_rport_fcs_online_action(rport);
1469         break;
1470 
1471     default:
1472         bfa_sm_fault(rport->fcs, event);
1473     }
1474 }
1475 
1476 /*
1477  *      Nameserver discovery failed. Waiting for timeout to retry.
1478  */
1479 static void
1480 bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
1481      enum rport_event event)
1482 {
1483     bfa_trc(rport->fcs, rport->pwwn);
1484     bfa_trc(rport->fcs, rport->pid);
1485     bfa_trc(rport->fcs, event);
1486 
1487     switch (event) {
1488     case RPSM_EVENT_TIMEOUT:
1489         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1490         bfa_fcs_rport_send_nsdisc(rport, NULL);
1491         break;
1492 
1493     case RPSM_EVENT_FAB_SCN:
1494     case RPSM_EVENT_ADDRESS_CHANGE:
1495         bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1496         bfa_timer_stop(&rport->timer);
1497         rport->ns_retries = 0;
1498         bfa_fcs_rport_send_nsdisc(rport, NULL);
1499         break;
1500 
1501     case RPSM_EVENT_DELETE:
1502         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1503         bfa_timer_stop(&rport->timer);
1504         bfa_fcs_rport_free(rport);
1505         break;
1506 
1507     case RPSM_EVENT_PLOGI_RCVD:
1508         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1509         bfa_timer_stop(&rport->timer);
1510         bfa_fcs_rport_send_plogiacc(rport, NULL);
1511         break;
1512 
1513     case RPSM_EVENT_LOGO_IMP:
1514         rport->pid = 0;
1515         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1516         bfa_timer_stop(&rport->timer);
1517         bfa_timer_start(rport->fcs->bfa, &rport->timer,
1518                 bfa_fcs_rport_timeout, rport,
1519                 bfa_fcs_rport_del_timeout);
1520         break;
1521 
1522     case RPSM_EVENT_LOGO_RCVD:
1523         bfa_fcs_rport_send_logo_acc(rport);
1524         break;
1525     case RPSM_EVENT_PRLO_RCVD:
1526         bfa_fcs_rport_send_prlo_acc(rport);
1527         break;
1528 
1529     case RPSM_EVENT_PLOGI_COMP:
1530         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1531         bfa_timer_stop(&rport->timer);
1532         bfa_fcs_rport_fcs_online_action(rport);
1533         break;
1534 
1535     default:
1536         bfa_sm_fault(rport->fcs, event);
1537     }
1538 }
1539 
1540 /*
1541  *      Rport address has changed. Nameserver discovery request is sent.
1542  */
1543 static void
1544 bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1545             enum rport_event event)
1546 {
1547     bfa_trc(rport->fcs, rport->pwwn);
1548     bfa_trc(rport->fcs, rport->pid);
1549     bfa_trc(rport->fcs, event);
1550 
1551     switch (event) {
1552     case RPSM_EVENT_ACCEPTED:
1553     case RPSM_EVENT_ADDRESS_CHANGE:
1554         if (rport->pid) {
1555             bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1556             bfa_fcs_rport_send_plogi(rport, NULL);
1557         } else {
1558             bfa_sm_set_state(rport,
1559                  bfa_fcs_rport_sm_nsdisc_sending);
1560             rport->ns_retries = 0;
1561             bfa_fcs_rport_send_nsdisc(rport, NULL);
1562         }
1563         break;
1564 
1565     case RPSM_EVENT_FAILED:
1566         rport->ns_retries++;
1567         if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
1568             bfa_sm_set_state(rport,
1569                  bfa_fcs_rport_sm_nsdisc_sending);
1570             bfa_fcs_rport_send_nsdisc(rport, NULL);
1571         } else {
1572             rport->old_pid = rport->pid;
1573             rport->pid = 0;
1574             bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1575             bfa_timer_start(rport->fcs->bfa, &rport->timer,
1576                     bfa_fcs_rport_timeout, rport,
1577                     bfa_fcs_rport_del_timeout);
1578         }
1579         break;
1580 
1581     case RPSM_EVENT_DELETE:
1582         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1583         bfa_fcxp_discard(rport->fcxp);
1584         bfa_fcs_rport_free(rport);
1585         break;
1586 
1587     case RPSM_EVENT_PLOGI_RCVD:
1588         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1589         bfa_fcxp_discard(rport->fcxp);
1590         bfa_fcs_rport_send_plogiacc(rport, NULL);
1591         break;
1592 
1593     case RPSM_EVENT_LOGO_IMP:
1594         rport->pid = 0;
1595         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1596         bfa_fcxp_discard(rport->fcxp);
1597         bfa_timer_start(rport->fcs->bfa, &rport->timer,
1598                 bfa_fcs_rport_timeout, rport,
1599                 bfa_fcs_rport_del_timeout);
1600         break;
1601 
1602 
1603     case RPSM_EVENT_PRLO_RCVD:
1604         bfa_fcs_rport_send_prlo_acc(rport);
1605         break;
1606     case RPSM_EVENT_FAB_SCN:
1607         /*
1608          * ignore, wait for NS query response
1609          */
1610         break;
1611 
1612     case RPSM_EVENT_LOGO_RCVD:
1613         /*
1614          * Not logged-in yet. Accept LOGO.
1615          */
1616         bfa_fcs_rport_send_logo_acc(rport);
1617         break;
1618 
1619     case RPSM_EVENT_PLOGI_COMP:
1620         bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1621         bfa_fcxp_discard(rport->fcxp);
1622         bfa_fcs_rport_fcs_online_action(rport);
1623         break;
1624 
1625     default:
1626         bfa_sm_fault(rport->fcs, event);
1627     }
1628 }
1629 
1630 /*
1631  * Rport needs to be deleted
1632  * waiting for ITNIM clean up to finish
1633  */
1634 static void
1635 bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
1636                 enum rport_event event)
1637 {
1638     bfa_trc(rport->fcs, rport->pwwn);
1639     bfa_trc(rport->fcs, rport->pid);
1640     bfa_trc(rport->fcs, event);
1641 
1642     switch (event) {
1643     case RPSM_EVENT_FC4_OFFLINE:
1644         bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1645         bfa_fcs_rport_hal_offline(rport);
1646         break;
1647 
1648     case RPSM_EVENT_DELETE:
1649     case RPSM_EVENT_PLOGI_RCVD:
1650         /* Ignore these events */
1651         break;
1652 
1653     default:
1654         bfa_sm_fault(rport->fcs, event);
1655         break;
1656     }
1657 }
1658 
1659 /*
1660  * RPort needs to be deleted
1661  * waiting for BFA/FW to finish current processing
1662  */
1663 static void
1664 bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
1665                 enum rport_event event)
1666 {
1667     bfa_trc(rport->fcs, rport->pwwn);
1668     bfa_trc(rport->fcs, rport->pid);
1669     bfa_trc(rport->fcs, event);
1670 
1671     switch (event) {
1672     case RPSM_EVENT_HCB_OFFLINE:
1673         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1674         bfa_fcs_rport_free(rport);
1675         break;
1676 
1677     case RPSM_EVENT_DELETE:
1678     case RPSM_EVENT_LOGO_IMP:
1679     case RPSM_EVENT_PLOGI_RCVD:
1680         /* Ignore these events */
1681         break;
1682 
1683     default:
1684         bfa_sm_fault(rport->fcs, event);
1685     }
1686 }
1687 
1688 /*
1689  *  fcs_rport_private FCS RPORT provate functions
1690  */
1691 
1692 static void
1693 bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1694 {
1695     struct bfa_fcs_rport_s *rport = rport_cbarg;
1696     struct bfa_fcs_lport_s *port = rport->port;
1697     struct fchs_s   fchs;
1698     int     len;
1699     struct bfa_fcxp_s *fcxp;
1700 
1701     bfa_trc(rport->fcs, rport->pwwn);
1702 
1703     fcxp = fcxp_alloced ? fcxp_alloced :
1704            bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1705     if (!fcxp) {
1706         bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1707                 bfa_fcs_rport_send_plogi, rport, BFA_TRUE);
1708         return;
1709     }
1710     rport->fcxp = fcxp;
1711 
1712     len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1713                 bfa_fcs_lport_get_fcid(port), 0,
1714                 port->port_cfg.pwwn, port->port_cfg.nwwn,
1715                 bfa_fcport_get_maxfrsize(port->fcs->bfa),
1716                 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
1717 
1718     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1719             FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
1720             (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1721 
1722     rport->stats.plogis++;
1723     bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1724 }
1725 
1726 static void
1727 bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1728                 bfa_status_t req_status, u32 rsp_len,
1729                 u32 resid_len, struct fchs_s *rsp_fchs)
1730 {
1731     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1732     struct fc_logi_s    *plogi_rsp;
1733     struct fc_ls_rjt_s  *ls_rjt;
1734     struct bfa_fcs_rport_s *twin;
1735     struct list_head    *qe;
1736 
1737     bfa_trc(rport->fcs, rport->pwwn);
1738 
1739     /*
1740      * Sanity Checks
1741      */
1742     if (req_status != BFA_STATUS_OK) {
1743         bfa_trc(rport->fcs, req_status);
1744         rport->stats.plogi_failed++;
1745         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1746         return;
1747     }
1748 
1749     plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
1750 
1751     /*
1752      * Check for failure first.
1753      */
1754     if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
1755         ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
1756 
1757         bfa_trc(rport->fcs, ls_rjt->reason_code);
1758         bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1759 
1760         if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&
1761          (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {
1762             rport->stats.rjt_insuff_res++;
1763             bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);
1764             return;
1765         }
1766 
1767         rport->stats.plogi_rejects++;
1768         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1769         return;
1770     }
1771 
1772     /*
1773      * PLOGI is complete. Make sure this device is not one of the known
1774      * device with a new FC port address.
1775      */
1776     list_for_each(qe, &rport->port->rport_q) {
1777         twin = (struct bfa_fcs_rport_s *) qe;
1778         if (twin == rport)
1779             continue;
1780         if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
1781             bfa_trc(rport->fcs, twin->pid);
1782             bfa_trc(rport->fcs, rport->pid);
1783 
1784             /* Update plogi stats in twin */
1785             twin->stats.plogis  += rport->stats.plogis;
1786             twin->stats.plogi_rejects  +=
1787                  rport->stats.plogi_rejects;
1788             twin->stats.plogi_timeouts  +=
1789                  rport->stats.plogi_timeouts;
1790             twin->stats.plogi_failed +=
1791                  rport->stats.plogi_failed;
1792             twin->stats.plogi_rcvd    += rport->stats.plogi_rcvd;
1793             twin->stats.plogi_accs++;
1794 
1795             bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
1796 
1797             bfa_fcs_rport_update(twin, plogi_rsp);
1798             twin->pid = rsp_fchs->s_id;
1799             bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
1800             return;
1801         }
1802     }
1803 
1804     /*
1805      * Normal login path -- no evil twins.
1806      */
1807     rport->stats.plogi_accs++;
1808     bfa_fcs_rport_update(rport, plogi_rsp);
1809     bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1810 }
1811 
1812 static void
1813 bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1814 {
1815     struct bfa_fcs_rport_s *rport = rport_cbarg;
1816     struct bfa_fcs_lport_s *port = rport->port;
1817     struct fchs_s       fchs;
1818     int     len;
1819     struct bfa_fcxp_s *fcxp;
1820 
1821     bfa_trc(rport->fcs, rport->pwwn);
1822     bfa_trc(rport->fcs, rport->reply_oxid);
1823 
1824     fcxp = fcxp_alloced ? fcxp_alloced :
1825            bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
1826     if (!fcxp) {
1827         bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1828                 bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);
1829         return;
1830     }
1831     rport->fcxp = fcxp;
1832 
1833     len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1834                  rport->pid, bfa_fcs_lport_get_fcid(port),
1835                  rport->reply_oxid, port->port_cfg.pwwn,
1836                  port->port_cfg.nwwn,
1837                  bfa_fcport_get_maxfrsize(port->fcs->bfa),
1838                  bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
1839 
1840     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1841             FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1842 
1843     bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1844 }
1845 
1846 static void
1847 bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1848 {
1849     struct bfa_fcs_rport_s *rport = rport_cbarg;
1850     struct bfa_fcs_lport_s *port = rport->port;
1851     struct fchs_s       fchs;
1852     int     len;
1853     struct bfa_fcxp_s *fcxp;
1854 
1855     bfa_trc(rport->fcs, rport->pwwn);
1856 
1857     fcxp = fcxp_alloced ? fcxp_alloced :
1858            bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1859     if (!fcxp) {
1860         bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1861                 bfa_fcs_rport_send_adisc, rport, BFA_TRUE);
1862         return;
1863     }
1864     rport->fcxp = fcxp;
1865 
1866     len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1867                 bfa_fcs_lport_get_fcid(port), 0,
1868                 port->port_cfg.pwwn, port->port_cfg.nwwn);
1869 
1870     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1871             FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
1872             rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1873 
1874     rport->stats.adisc_sent++;
1875     bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1876 }
1877 
1878 static void
1879 bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1880                 bfa_status_t req_status, u32 rsp_len,
1881                 u32 resid_len, struct fchs_s *rsp_fchs)
1882 {
1883     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1884     void        *pld = bfa_fcxp_get_rspbuf(fcxp);
1885     struct fc_ls_rjt_s  *ls_rjt;
1886 
1887     if (req_status != BFA_STATUS_OK) {
1888         bfa_trc(rport->fcs, req_status);
1889         rport->stats.adisc_failed++;
1890         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1891         return;
1892     }
1893 
1894     if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
1895                 rport->nwwn)  == FC_PARSE_OK) {
1896         rport->stats.adisc_accs++;
1897         bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1898         return;
1899     }
1900 
1901     rport->stats.adisc_rejects++;
1902     ls_rjt = pld;
1903     bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
1904     bfa_trc(rport->fcs, ls_rjt->reason_code);
1905     bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1906     bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1907 }
1908 
1909 static void
1910 bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1911 {
1912     struct bfa_fcs_rport_s *rport = rport_cbarg;
1913     struct bfa_fcs_lport_s *port = rport->port;
1914     struct fchs_s   fchs;
1915     struct bfa_fcxp_s *fcxp;
1916     int     len;
1917     bfa_cb_fcxp_send_t cbfn;
1918 
1919     bfa_trc(rport->fcs, rport->pid);
1920 
1921     fcxp = fcxp_alloced ? fcxp_alloced :
1922            bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1923     if (!fcxp) {
1924         bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1925                 bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);
1926         return;
1927     }
1928     rport->fcxp = fcxp;
1929 
1930     if (rport->pwwn) {
1931         len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1932                 bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);
1933         cbfn = bfa_fcs_rport_gidpn_response;
1934     } else {
1935         len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1936                 bfa_fcs_lport_get_fcid(port), 0, rport->pid);
1937         cbfn = bfa_fcs_rport_gpnid_response;
1938     }
1939 
1940     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1941             FC_CLASS_3, len, &fchs, cbfn,
1942             (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
1943 
1944     bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1945 }
1946 
1947 static void
1948 bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1949                 bfa_status_t req_status, u32 rsp_len,
1950                 u32 resid_len, struct fchs_s *rsp_fchs)
1951 {
1952     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1953     struct ct_hdr_s *cthdr;
1954     struct fcgs_gidpn_resp_s    *gidpn_rsp;
1955     struct bfa_fcs_rport_s  *twin;
1956     struct list_head    *qe;
1957 
1958     bfa_trc(rport->fcs, rport->pwwn);
1959 
1960     cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1961     cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1962 
1963     if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1964         /* Check if the pid is the same as before. */
1965         gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
1966 
1967         if (gidpn_rsp->dap == rport->pid) {
1968             /* Device is online  */
1969             bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1970         } else {
1971             /*
1972              * Device's PID has changed. We need to cleanup
1973              * and re-login. If there is another device with
1974              * the the newly discovered pid, send an scn notice
1975              * so that its new pid can be discovered.
1976              */
1977             list_for_each(qe, &rport->port->rport_q) {
1978                 twin = (struct bfa_fcs_rport_s *) qe;
1979                 if (twin == rport)
1980                     continue;
1981                 if (gidpn_rsp->dap == twin->pid) {
1982                     bfa_trc(rport->fcs, twin->pid);
1983                     bfa_trc(rport->fcs, rport->pid);
1984 
1985                     twin->pid = 0;
1986                     bfa_sm_send_event(twin,
1987                      RPSM_EVENT_ADDRESS_CHANGE);
1988                 }
1989             }
1990             rport->pid = gidpn_rsp->dap;
1991             bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
1992         }
1993         return;
1994     }
1995 
1996     /*
1997      * Reject Response
1998      */
1999     switch (cthdr->reason_code) {
2000     case CT_RSN_LOGICAL_BUSY:
2001         /*
2002          * Need to retry
2003          */
2004         bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
2005         break;
2006 
2007     case CT_RSN_UNABLE_TO_PERF:
2008         /*
2009          * device doesn't exist : Start timer to cleanup this later.
2010          */
2011         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2012         break;
2013 
2014     default:
2015         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2016         break;
2017     }
2018 }
2019 
2020 static void
2021 bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
2022                 bfa_status_t req_status, u32 rsp_len,
2023                 u32 resid_len, struct fchs_s *rsp_fchs)
2024 {
2025     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2026     struct ct_hdr_s *cthdr;
2027 
2028     bfa_trc(rport->fcs, rport->pwwn);
2029 
2030     cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2031     cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2032 
2033     if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2034         bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
2035         return;
2036     }
2037 
2038     /*
2039      * Reject Response
2040      */
2041     switch (cthdr->reason_code) {
2042     case CT_RSN_LOGICAL_BUSY:
2043         /*
2044          * Need to retry
2045          */
2046         bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
2047         break;
2048 
2049     case CT_RSN_UNABLE_TO_PERF:
2050         /*
2051          * device doesn't exist : Start timer to cleanup this later.
2052          */
2053         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2054         break;
2055 
2056     default:
2057         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2058         break;
2059     }
2060 }
2061 
2062 /*
2063  *  Called to send a logout to the rport.
2064  */
2065 static void
2066 bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2067 {
2068     struct bfa_fcs_rport_s *rport = rport_cbarg;
2069     struct bfa_fcs_lport_s *port;
2070     struct fchs_s   fchs;
2071     struct bfa_fcxp_s *fcxp;
2072     u16 len;
2073 
2074     bfa_trc(rport->fcs, rport->pid);
2075 
2076     port = rport->port;
2077 
2078     fcxp = fcxp_alloced ? fcxp_alloced :
2079            bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2080     if (!fcxp) {
2081         bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
2082                 bfa_fcs_rport_send_logo, rport, BFA_FALSE);
2083         return;
2084     }
2085     rport->fcxp = fcxp;
2086 
2087     len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
2088                 bfa_fcs_lport_get_fcid(port), 0,
2089                 bfa_fcs_lport_get_pwwn(port));
2090 
2091     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2092             FC_CLASS_3, len, &fchs, NULL,
2093             rport, FC_MAX_PDUSZ, FC_ELS_TOV);
2094 
2095     rport->stats.logos++;
2096     bfa_fcxp_discard(rport->fcxp);
2097     bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
2098 }
2099 
2100 /*
2101  *  Send ACC for a LOGO received.
2102  */
2103 static void
2104 bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
2105 {
2106     struct bfa_fcs_rport_s *rport = rport_cbarg;
2107     struct bfa_fcs_lport_s *port;
2108     struct fchs_s   fchs;
2109     struct bfa_fcxp_s *fcxp;
2110     u16 len;
2111 
2112     bfa_trc(rport->fcs, rport->pid);
2113 
2114     port = rport->port;
2115 
2116     fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2117     if (!fcxp)
2118         return;
2119 
2120     rport->stats.logo_rcvd++;
2121     len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2122                 rport->pid, bfa_fcs_lport_get_fcid(port),
2123                 rport->reply_oxid);
2124 
2125     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2126             FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2127 }
2128 
2129 /*
2130  *  brief
2131  *  This routine will be called by bfa_timer on timer timeouts.
2132  *
2133  *  param[in]   rport           - pointer to bfa_fcs_lport_ns_t.
2134  *  param[out]  rport_status    - pointer to return vport status in
2135  *
2136  *  return
2137  *      void
2138  *
2139  *  Special Considerations:
2140  *
2141  *  note
2142  */
2143 static void
2144 bfa_fcs_rport_timeout(void *arg)
2145 {
2146     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;
2147 
2148     rport->stats.plogi_timeouts++;
2149     bfa_stats(rport->port, rport_plogi_timeouts);
2150     bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
2151 }
2152 
2153 static void
2154 bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
2155             struct fchs_s *rx_fchs, u16 len)
2156 {
2157     struct bfa_fcxp_s *fcxp;
2158     struct fchs_s   fchs;
2159     struct bfa_fcs_lport_s *port = rport->port;
2160     struct fc_prli_s    *prli;
2161 
2162     bfa_trc(port->fcs, rx_fchs->s_id);
2163     bfa_trc(port->fcs, rx_fchs->d_id);
2164 
2165     rport->stats.prli_rcvd++;
2166 
2167     /*
2168      * We are in Initiator Mode
2169      */
2170     prli = (struct fc_prli_s *) (rx_fchs + 1);
2171 
2172     if (prli->parampage.servparams.target) {
2173         /*
2174          * PRLI from a target ?
2175          * Send the Acc.
2176          * PRLI sent by us will be used to transition the IT nexus,
2177          * once the response is received from the target.
2178          */
2179         bfa_trc(port->fcs, rx_fchs->s_id);
2180         rport->scsi_function = BFA_RPORT_TARGET;
2181     } else {
2182         bfa_trc(rport->fcs, prli->parampage.type);
2183         rport->scsi_function = BFA_RPORT_INITIATOR;
2184         bfa_fcs_itnim_is_initiator(rport->itnim);
2185     }
2186 
2187     fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2188     if (!fcxp)
2189         return;
2190 
2191     len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2192                 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2193                 rx_fchs->ox_id, port->port_cfg.roles);
2194 
2195     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2196             FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2197 }
2198 
2199 static void
2200 bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
2201             struct fchs_s *rx_fchs, u16 len)
2202 {
2203     struct bfa_fcxp_s *fcxp;
2204     struct fchs_s   fchs;
2205     struct bfa_fcs_lport_s *port = rport->port;
2206     struct fc_rpsc_speed_info_s speeds;
2207     struct bfa_port_attr_s pport_attr;
2208 
2209     bfa_trc(port->fcs, rx_fchs->s_id);
2210     bfa_trc(port->fcs, rx_fchs->d_id);
2211 
2212     rport->stats.rpsc_rcvd++;
2213     speeds.port_speed_cap =
2214         RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
2215         RPSC_SPEED_CAP_8G;
2216 
2217     /*
2218      * get curent speed from pport attributes from BFA
2219      */
2220     bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2221 
2222     speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
2223 
2224     fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2225     if (!fcxp)
2226         return;
2227 
2228     len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2229                 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2230                 rx_fchs->ox_id, &speeds);
2231 
2232     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2233             FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2234 }
2235 
2236 static void
2237 bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
2238             struct fchs_s *rx_fchs, u16 len)
2239 {
2240     struct bfa_fcxp_s *fcxp;
2241     struct fchs_s   fchs;
2242     struct bfa_fcs_lport_s *port = rport->port;
2243 
2244     bfa_trc(port->fcs, rx_fchs->s_id);
2245     bfa_trc(port->fcs, rx_fchs->d_id);
2246 
2247     rport->stats.adisc_rcvd++;
2248 
2249     /*
2250      * Accept if the itnim for this rport is online.
2251      * Else reject the ADISC.
2252      */
2253     if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
2254 
2255         fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2256         if (!fcxp)
2257             return;
2258 
2259         len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2260              rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2261              rx_fchs->ox_id, port->port_cfg.pwwn,
2262              port->port_cfg.nwwn);
2263 
2264         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
2265                 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2266                 FC_MAX_PDUSZ, 0);
2267     } else {
2268         rport->stats.adisc_rejected++;
2269         bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
2270                       FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
2271                       FC_LS_RJT_EXP_LOGIN_REQUIRED);
2272     }
2273 }
2274 
2275 static void
2276 bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
2277 {
2278     struct bfa_fcs_lport_s *port = rport->port;
2279     struct bfa_rport_info_s rport_info;
2280 
2281     rport_info.pid = rport->pid;
2282     rport_info.local_pid = port->pid;
2283     rport_info.lp_tag = port->lp_tag;
2284     rport_info.vf_id = port->fabric->vf_id;
2285     rport_info.vf_en = port->fabric->is_vf;
2286     rport_info.fc_class = rport->fc_cos;
2287     rport_info.cisc = rport->cisc;
2288     rport_info.max_frmsz = rport->maxfrsize;
2289     bfa_rport_online(rport->bfa_rport, &rport_info);
2290 }
2291 
2292 static void
2293 bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)
2294 {
2295     if (rport->bfa_rport)
2296         bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
2297     else
2298         bfa_cb_rport_offline(rport);
2299 }
2300 
2301 static struct bfa_fcs_rport_s *
2302 bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
2303 {
2304     struct bfa_fcs_s    *fcs = port->fcs;
2305     struct bfa_fcs_rport_s *rport;
2306     struct bfad_rport_s *rport_drv;
2307 
2308     /*
2309      * allocate rport
2310      */
2311     if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {
2312         bfa_trc(fcs, rpid);
2313         return NULL;
2314     }
2315 
2316     if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
2317         != BFA_STATUS_OK) {
2318         bfa_trc(fcs, rpid);
2319         return NULL;
2320     }
2321 
2322     /*
2323      * Initialize r-port
2324      */
2325     rport->port = port;
2326     rport->fcs = fcs;
2327     rport->rp_drv = rport_drv;
2328     rport->pid = rpid;
2329     rport->pwwn = pwwn;
2330     rport->old_pid = 0;
2331 
2332     rport->bfa_rport = NULL;
2333 
2334     /*
2335      * allocate FC-4s
2336      */
2337     WARN_ON(!bfa_fcs_lport_is_initiator(port));
2338 
2339     if (bfa_fcs_lport_is_initiator(port)) {
2340         rport->itnim = bfa_fcs_itnim_create(rport);
2341         if (!rport->itnim) {
2342             bfa_trc(fcs, rpid);
2343             kfree(rport_drv);
2344             return NULL;
2345         }
2346     }
2347 
2348     bfa_fcs_lport_add_rport(port, rport);
2349     fcs->num_rport_logins++;
2350 
2351     bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
2352 
2353     /* Initialize the Rport Features(RPF) Sub Module  */
2354     if (!BFA_FCS_PID_IS_WKA(rport->pid))
2355         bfa_fcs_rpf_init(rport);
2356 
2357     return rport;
2358 }
2359 
2360 
2361 static void
2362 bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2363 {
2364     struct bfa_fcs_lport_s *port = rport->port;
2365     struct bfa_fcs_s *fcs = port->fcs;
2366 
2367     /*
2368      * - delete FC-4s
2369      * - delete BFA rport
2370      * - remove from queue of rports
2371      */
2372     rport->plogi_pending = BFA_FALSE;
2373 
2374     if (bfa_fcs_lport_is_initiator(port)) {
2375         bfa_fcs_itnim_delete(rport->itnim);
2376         if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
2377             bfa_fcs_rpf_rport_offline(rport);
2378     }
2379 
2380     if (rport->bfa_rport) {
2381         bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
2382         rport->bfa_rport = NULL;
2383     }
2384 
2385     bfa_fcs_lport_del_rport(port, rport);
2386     fcs->num_rport_logins--;
2387     kfree(rport->rp_drv);
2388 }
2389 
2390 static void
2391 bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2392             enum bfa_rport_aen_event event,
2393             struct bfa_rport_aen_data_s *data)
2394 {
2395     struct bfa_fcs_lport_s *port = rport->port;
2396     struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2397     struct bfa_aen_entry_s  *aen_entry;
2398 
2399     bfad_get_aen_entry(bfad, aen_entry);
2400     if (!aen_entry)
2401         return;
2402 
2403     if (event == BFA_RPORT_AEN_QOS_PRIO)
2404         aen_entry->aen_data.rport.priv.qos = data->priv.qos;
2405     else if (event == BFA_RPORT_AEN_QOS_FLOWID)
2406         aen_entry->aen_data.rport.priv.qos = data->priv.qos;
2407 
2408     aen_entry->aen_data.rport.vf_id = rport->port->fabric->vf_id;
2409     aen_entry->aen_data.rport.ppwwn = bfa_fcs_lport_get_pwwn(
2410                     bfa_fcs_get_base_port(rport->fcs));
2411     aen_entry->aen_data.rport.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
2412     aen_entry->aen_data.rport.rpwwn = rport->pwwn;
2413 
2414     /* Send the AEN notification */
2415     bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
2416                   BFA_AEN_CAT_RPORT, event);
2417 }
2418 
2419 static void
2420 bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)
2421 {
2422     if ((!rport->pid) || (!rport->pwwn)) {
2423         bfa_trc(rport->fcs, rport->pid);
2424         bfa_sm_fault(rport->fcs, rport->pid);
2425     }
2426 
2427     bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);
2428 }
2429 
2430 static void
2431 bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)
2432 {
2433     struct bfa_fcs_lport_s *port = rport->port;
2434     struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2435     char    lpwwn_buf[BFA_STRING_32];
2436     char    rpwwn_buf[BFA_STRING_32];
2437 
2438     rport->stats.onlines++;
2439 
2440     if ((!rport->pid) || (!rport->pwwn)) {
2441         bfa_trc(rport->fcs, rport->pid);
2442         bfa_sm_fault(rport->fcs, rport->pid);
2443     }
2444 
2445     if (bfa_fcs_lport_is_initiator(port)) {
2446         bfa_fcs_itnim_brp_online(rport->itnim);
2447         if (!BFA_FCS_PID_IS_WKA(rport->pid))
2448             bfa_fcs_rpf_rport_online(rport);
2449     }
2450 
2451     wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2452     wwn2str(rpwwn_buf, rport->pwwn);
2453     if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2454         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2455         "Remote port (WWN = %s) online for logical port (WWN = %s)\n",
2456         rpwwn_buf, lpwwn_buf);
2457         bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
2458     }
2459 }
2460 
2461 static void
2462 bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)
2463 {
2464     if (!BFA_FCS_PID_IS_WKA(rport->pid))
2465         bfa_fcs_rpf_rport_offline(rport);
2466 
2467     bfa_fcs_itnim_rport_offline(rport->itnim);
2468 }
2469 
2470 static void
2471 bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)
2472 {
2473     struct bfa_fcs_lport_s *port = rport->port;
2474     struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2475     char    lpwwn_buf[BFA_STRING_32];
2476     char    rpwwn_buf[BFA_STRING_32];
2477 
2478     if (!rport->bfa_rport) {
2479         bfa_fcs_rport_fcs_offline_action(rport);
2480         return;
2481     }
2482 
2483     rport->stats.offlines++;
2484 
2485     wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2486     wwn2str(rpwwn_buf, rport->pwwn);
2487     if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2488         if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) {
2489             BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2490                 "Remote port (WWN = %s) connectivity lost for "
2491                 "logical port (WWN = %s)\n",
2492                 rpwwn_buf, lpwwn_buf);
2493             bfa_fcs_rport_aen_post(rport,
2494                 BFA_RPORT_AEN_DISCONNECT, NULL);
2495         } else {
2496             BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2497                 "Remote port (WWN = %s) offlined by "
2498                 "logical port (WWN = %s)\n",
2499                 rpwwn_buf, lpwwn_buf);
2500             bfa_fcs_rport_aen_post(rport,
2501                 BFA_RPORT_AEN_OFFLINE, NULL);
2502         }
2503     }
2504 
2505     if (bfa_fcs_lport_is_initiator(port)) {
2506         bfa_fcs_itnim_rport_offline(rport->itnim);
2507         if (!BFA_FCS_PID_IS_WKA(rport->pid))
2508             bfa_fcs_rpf_rport_offline(rport);
2509     }
2510 }
2511 
2512 /*
2513  * Update rport parameters from PLOGI or PLOGI accept.
2514  */
2515 static void
2516 bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2517 {
2518     bfa_fcs_lport_t *port = rport->port;
2519 
2520     /*
2521      * - port name
2522      * - node name
2523      */
2524     rport->pwwn = plogi->port_name;
2525     rport->nwwn = plogi->node_name;
2526 
2527     /*
2528      * - class of service
2529      */
2530     rport->fc_cos = 0;
2531     if (plogi->class3.class_valid)
2532         rport->fc_cos = FC_CLASS_3;
2533 
2534     if (plogi->class2.class_valid)
2535         rport->fc_cos |= FC_CLASS_2;
2536 
2537     /*
2538      * - CISC
2539      * - MAX receive frame size
2540      */
2541     rport->cisc = plogi->csp.cisc;
2542     if (be16_to_cpu(plogi->class3.rxsz) < be16_to_cpu(plogi->csp.rxsz))
2543         rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz);
2544     else
2545         rport->maxfrsize = be16_to_cpu(plogi->csp.rxsz);
2546 
2547     bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
2548     bfa_trc(port->fcs, port->fabric->bb_credit);
2549     /*
2550      * Direct Attach P2P mode :
2551      * This is to handle a bug (233476) in IBM targets in Direct Attach
2552      *  Mode. Basically, in FLOGI Accept the target would have
2553      * erroneously set the BB Credit to the value used in the FLOGI
2554      * sent by the HBA. It uses the correct value (its own BB credit)
2555      * in PLOGI.
2556      */
2557     if ((!bfa_fcs_fabric_is_switched(port->fabric))  &&
2558         (be16_to_cpu(plogi->csp.bbcred) < port->fabric->bb_credit)) {
2559 
2560         bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
2561         bfa_trc(port->fcs, port->fabric->bb_credit);
2562 
2563         port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
2564         bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
2565                       port->fabric->bb_credit);
2566     }
2567 
2568 }
2569 
2570 /*
2571  *  Called to handle LOGO received from an existing remote port.
2572  */
2573 static void
2574 bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2575 {
2576     rport->reply_oxid = fchs->ox_id;
2577     bfa_trc(rport->fcs, rport->reply_oxid);
2578 
2579     rport->prlo = BFA_FALSE;
2580     rport->stats.logo_rcvd++;
2581     bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2582 }
2583 
2584 
2585 
2586 /*
2587  *  fcs_rport_public FCS rport public interfaces
2588  */
2589 
2590 /*
2591  *  Called by bport/vport to create a remote port instance for a discovered
2592  *  remote device.
2593  *
2594  * @param[in] port  - base port or vport
2595  * @param[in] rpid  - remote port ID
2596  *
2597  * @return None
2598  */
2599 struct bfa_fcs_rport_s *
2600 bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)
2601 {
2602     struct bfa_fcs_rport_s *rport;
2603 
2604     bfa_trc(port->fcs, rpid);
2605     rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2606     if (!rport)
2607         return NULL;
2608 
2609     bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2610     return rport;
2611 }
2612 
2613 /*
2614  * Called to create a rport for which only the wwn is known.
2615  *
2616  * @param[in] port  - base port
2617  * @param[in] rpwwn - remote port wwn
2618  *
2619  * @return None
2620  */
2621 struct bfa_fcs_rport_s *
2622 bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
2623 {
2624     struct bfa_fcs_rport_s *rport;
2625     bfa_trc(port->fcs, rpwwn);
2626     rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2627     if (!rport)
2628         return NULL;
2629 
2630     bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2631     return rport;
2632 }
2633 /*
2634  * Called by bport in private loop topology to indicate that a
2635  * rport has been discovered and plogi has been completed.
2636  *
2637  * @param[in] port  - base port or vport
2638  * @param[in] rpid  - remote port ID
2639  */
2640 void
2641 bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2642      struct fc_logi_s *plogi)
2643 {
2644     struct bfa_fcs_rport_s *rport;
2645 
2646     rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2647     if (!rport)
2648         return;
2649 
2650     bfa_fcs_rport_update(rport, plogi);
2651 
2652     bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2653 }
2654 
2655 /*
2656  *  Called by bport/vport to handle PLOGI received from a new remote port.
2657  *  If an existing rport does a plogi, it will be handled separately.
2658  */
2659 void
2660 bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2661                 struct fc_logi_s *plogi)
2662 {
2663     struct bfa_fcs_rport_s *rport;
2664 
2665     rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2666     if (!rport)
2667         return;
2668 
2669     bfa_fcs_rport_update(rport, plogi);
2670 
2671     rport->reply_oxid = fchs->ox_id;
2672     bfa_trc(rport->fcs, rport->reply_oxid);
2673 
2674     rport->stats.plogi_rcvd++;
2675     bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2676 }
2677 
2678 /*
2679  *  Called by bport/vport to handle PLOGI received from an existing
2680  *   remote port.
2681  */
2682 void
2683 bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2684             struct fc_logi_s *plogi)
2685 {
2686     /*
2687      * @todo Handle P2P and initiator-initiator.
2688      */
2689 
2690     bfa_fcs_rport_update(rport, plogi);
2691 
2692     rport->reply_oxid = rx_fchs->ox_id;
2693     bfa_trc(rport->fcs, rport->reply_oxid);
2694 
2695     rport->pid = rx_fchs->s_id;
2696     bfa_trc(rport->fcs, rport->pid);
2697 
2698     rport->stats.plogi_rcvd++;
2699     bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2700 }
2701 
2702 
2703 /*
2704  *  Called by bport/vport to notify SCN for the remote port
2705  */
2706 void
2707 bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2708 {
2709     rport->stats.rscns++;
2710     bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);
2711 }
2712 
2713 /*
2714  *  brief
2715  *  This routine BFA callback for bfa_rport_online() call.
2716  *
2717  *  param[in]   cb_arg  -  rport struct.
2718  *
2719  *  return
2720  *      void
2721  *
2722  *  Special Considerations:
2723  *
2724  *  note
2725  */
2726 void
2727 bfa_cb_rport_online(void *cbarg)
2728 {
2729 
2730     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2731 
2732     bfa_trc(rport->fcs, rport->pwwn);
2733     bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2734 }
2735 
2736 /*
2737  *  brief
2738  *  This routine BFA callback for bfa_rport_offline() call.
2739  *
2740  *  param[in]   rport   -
2741  *
2742  *  return
2743  *      void
2744  *
2745  *  Special Considerations:
2746  *
2747  *  note
2748  */
2749 void
2750 bfa_cb_rport_offline(void *cbarg)
2751 {
2752     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2753 
2754     bfa_trc(rport->fcs, rport->pwwn);
2755     bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2756 }
2757 
2758 /*
2759  *  brief
2760  *  This routine is a static BFA callback when there is a QoS flow_id
2761  *  change notification
2762  *
2763  *  param[in]   rport   -
2764  *
2765  *  return
2766  *      void
2767  *
2768  *  Special Considerations:
2769  *
2770  *  note
2771  */
2772 void
2773 bfa_cb_rport_qos_scn_flowid(void *cbarg,
2774         struct bfa_rport_qos_attr_s old_qos_attr,
2775         struct bfa_rport_qos_attr_s new_qos_attr)
2776 {
2777     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2778     struct bfa_rport_aen_data_s aen_data;
2779 
2780     bfa_trc(rport->fcs, rport->pwwn);
2781     aen_data.priv.qos = new_qos_attr;
2782     bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
2783 }
2784 
2785 void
2786 bfa_cb_rport_scn_online(struct bfa_s *bfa)
2787 {
2788     struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
2789     struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
2790     struct bfa_fcs_rport_s *rp;
2791     struct list_head *qe;
2792 
2793     list_for_each(qe, &port->rport_q) {
2794         rp = (struct bfa_fcs_rport_s *) qe;
2795         bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);
2796         rp->scn_online = BFA_TRUE;
2797     }
2798 
2799     if (bfa_fcs_lport_is_online(port))
2800         bfa_fcs_lport_lip_scn_online(port);
2801 }
2802 
2803 void
2804 bfa_cb_rport_scn_no_dev(void *rport)
2805 {
2806     struct bfa_fcs_rport_s *rp = rport;
2807 
2808     bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
2809     rp->scn_online = BFA_FALSE;
2810 }
2811 
2812 void
2813 bfa_cb_rport_scn_offline(struct bfa_s *bfa)
2814 {
2815     struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
2816     struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
2817     struct bfa_fcs_rport_s *rp;
2818     struct list_head *qe;
2819 
2820     list_for_each(qe, &port->rport_q) {
2821         rp = (struct bfa_fcs_rport_s *) qe;
2822         bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
2823         rp->scn_online = BFA_FALSE;
2824     }
2825 }
2826 
2827 /*
2828  *  brief
2829  *  This routine is a static BFA callback when there is a QoS priority
2830  *  change notification
2831  *
2832  *  param[in]   rport   -
2833  *
2834  *  return
2835  *      void
2836  *
2837  *  Special Considerations:
2838  *
2839  *  note
2840  */
2841 void
2842 bfa_cb_rport_qos_scn_prio(void *cbarg,
2843         struct bfa_rport_qos_attr_s old_qos_attr,
2844         struct bfa_rport_qos_attr_s new_qos_attr)
2845 {
2846     struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2847     struct bfa_rport_aen_data_s aen_data;
2848 
2849     bfa_trc(rport->fcs, rport->pwwn);
2850     aen_data.priv.qos = new_qos_attr;
2851     bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
2852 }
2853 
2854 /*
2855  *      Called to process any unsolicted frames from this remote port
2856  */
2857 void
2858 bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
2859             struct fchs_s *fchs, u16 len)
2860 {
2861     struct bfa_fcs_lport_s *port = rport->port;
2862     struct fc_els_cmd_s *els_cmd;
2863 
2864     bfa_trc(rport->fcs, fchs->s_id);
2865     bfa_trc(rport->fcs, fchs->d_id);
2866     bfa_trc(rport->fcs, fchs->type);
2867 
2868     if (fchs->type != FC_TYPE_ELS)
2869         return;
2870 
2871     els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2872 
2873     bfa_trc(rport->fcs, els_cmd->els_code);
2874 
2875     switch (els_cmd->els_code) {
2876     case FC_ELS_LOGO:
2877         bfa_stats(port, plogi_rcvd);
2878         bfa_fcs_rport_process_logo(rport, fchs);
2879         break;
2880 
2881     case FC_ELS_ADISC:
2882         bfa_stats(port, adisc_rcvd);
2883         bfa_fcs_rport_process_adisc(rport, fchs, len);
2884         break;
2885 
2886     case FC_ELS_PRLO:
2887         bfa_stats(port, prlo_rcvd);
2888         if (bfa_fcs_lport_is_initiator(port))
2889             bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
2890         break;
2891 
2892     case FC_ELS_PRLI:
2893         bfa_stats(port, prli_rcvd);
2894         bfa_fcs_rport_process_prli(rport, fchs, len);
2895         break;
2896 
2897     case FC_ELS_RPSC:
2898         bfa_stats(port, rpsc_rcvd);
2899         bfa_fcs_rport_process_rpsc(rport, fchs, len);
2900         break;
2901 
2902     default:
2903         bfa_stats(port, un_handled_els_rcvd);
2904         bfa_fcs_rport_send_ls_rjt(rport, fchs,
2905                       FC_LS_RJT_RSN_CMD_NOT_SUPP,
2906                       FC_LS_RJT_EXP_NO_ADDL_INFO);
2907         break;
2908     }
2909 }
2910 
2911 /* send best case  acc to prlo */
2912 static void
2913 bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
2914 {
2915     struct bfa_fcs_lport_s *port = rport->port;
2916     struct fchs_s   fchs;
2917     struct bfa_fcxp_s *fcxp;
2918     int     len;
2919 
2920     bfa_trc(rport->fcs, rport->pid);
2921 
2922     fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2923     if (!fcxp)
2924         return;
2925     len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2926             rport->pid, bfa_fcs_lport_get_fcid(port),
2927             rport->reply_oxid, 0);
2928 
2929     bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
2930         port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
2931         NULL, NULL, FC_MAX_PDUSZ, 0);
2932 }
2933 
2934 /*
2935  * Send a LS reject
2936  */
2937 static void
2938 bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2939               u8 reason_code, u8 reason_code_expl)
2940 {
2941     struct bfa_fcs_lport_s *port = rport->port;
2942     struct fchs_s   fchs;
2943     struct bfa_fcxp_s *fcxp;
2944     int     len;
2945 
2946     bfa_trc(rport->fcs, rx_fchs->s_id);
2947 
2948     fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);
2949     if (!fcxp)
2950         return;
2951 
2952     len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2953                 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2954                 rx_fchs->ox_id, reason_code, reason_code_expl);
2955 
2956     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
2957             BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2958             FC_MAX_PDUSZ, 0);
2959 }
2960 
2961 /*
2962  * Return state of rport.
2963  */
2964 int
2965 bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2966 {
2967     return bfa_sm_to_state(rport_sm_table, rport->sm);
2968 }
2969 
2970 
2971 /*
2972  *  brief
2973  *       Called by the Driver to set rport delete/ageout timeout
2974  *
2975  *  param[in]       rport timeout value in seconds.
2976  *
2977  *  return None
2978  */
2979 void
2980 bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2981 {
2982     /* convert to Millisecs */
2983     if (rport_tmo > 0)
2984         bfa_fcs_rport_del_timeout = rport_tmo * 1000;
2985 }
2986 void
2987 bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
2988 {
2989     bfa_trc(rport->fcs, rport->pid);
2990 
2991     rport->prlo = BFA_TRUE;
2992     rport->reply_oxid = ox_id;
2993     bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
2994 }
2995 
2996 /*
2997  * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation
2998  * which limits number of concurrent logins to remote ports
2999  */
3000 void
3001 bfa_fcs_rport_set_max_logins(u32 max_logins)
3002 {
3003     if (max_logins > 0)
3004         bfa_fcs_rport_max_logins = max_logins;
3005 }
3006 
3007 void
3008 bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
3009         struct bfa_rport_attr_s *rport_attr)
3010 {
3011     struct bfa_rport_qos_attr_s qos_attr;
3012     struct bfa_fcs_lport_s *port = rport->port;
3013     bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
3014     struct bfa_port_attr_s port_attr;
3015 
3016     bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
3017 
3018     memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
3019     memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
3020 
3021     rport_attr->pid = rport->pid;
3022     rport_attr->pwwn = rport->pwwn;
3023     rport_attr->nwwn = rport->nwwn;
3024     rport_attr->cos_supported = rport->fc_cos;
3025     rport_attr->df_sz = rport->maxfrsize;
3026     rport_attr->state = bfa_fcs_rport_get_state(rport);
3027     rport_attr->fc_cos = rport->fc_cos;
3028     rport_attr->cisc = rport->cisc;
3029     rport_attr->scsi_function = rport->scsi_function;
3030     rport_attr->curr_speed  = rport->rpf.rpsc_speed;
3031     rport_attr->assigned_speed  = rport->rpf.assigned_speed;
3032 
3033     if (rport->bfa_rport) {
3034         qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
3035         qos_attr.qos_flow_id =
3036             cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
3037     }
3038     rport_attr->qos_attr = qos_attr;
3039 
3040     rport_attr->trl_enforced = BFA_FALSE;
3041     if (bfa_fcport_is_ratelim(port->fcs->bfa) &&
3042         (rport->scsi_function == BFA_RPORT_TARGET)) {
3043         if (rport_speed == BFA_PORT_SPEED_UNKNOWN)
3044             rport_speed =
3045                 bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
3046 
3047         if ((bfa_fcs_lport_get_rport_max_speed(port) !=
3048             BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
3049             rport_attr->trl_enforced = BFA_TRUE;
3050     }
3051 }
3052 
3053 /*
3054  * Remote port implementation.
3055  */
3056 
3057 /*
3058  *  fcs_rport_api FCS rport API.
3059  */
3060 
3061 struct bfa_fcs_rport_s *
3062 bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
3063 {
3064     struct bfa_fcs_rport_s *rport;
3065 
3066     rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
3067     if (rport == NULL) {
3068         /*
3069          * TBD Error handling
3070          */
3071     }
3072 
3073     return rport;
3074 }
3075 
3076 struct bfa_fcs_rport_s *
3077 bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
3078 {
3079     struct bfa_fcs_rport_s *rport;
3080 
3081     rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);
3082     if (rport == NULL) {
3083         /*
3084          * TBD Error handling
3085          */
3086     }
3087 
3088     return rport;
3089 }
3090 
3091 /*
3092  * Remote port features (RPF) implementation.
3093  */
3094 
3095 #define BFA_FCS_RPF_RETRIES (3)
3096 #define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
3097 
3098 static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
3099                 struct bfa_fcxp_s *fcxp_alloced);
3100 static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
3101             struct bfa_fcxp_s *fcxp,
3102             void *cbarg,
3103             bfa_status_t req_status,
3104             u32 rsp_len,
3105             u32 resid_len,
3106             struct fchs_s *rsp_fchs);
3107 
3108 static void     bfa_fcs_rpf_timeout(void *arg);
3109 
3110 /*
3111  *  fcs_rport_ftrs_sm FCS rport state machine events
3112  */
3113 
3114 enum rpf_event {
3115     RPFSM_EVENT_RPORT_OFFLINE  = 1, /* Rport offline        */
3116     RPFSM_EVENT_RPORT_ONLINE   = 2, /* Rport online         */
3117     RPFSM_EVENT_FCXP_SENT      = 3, /* Frame from has been sent */
3118     RPFSM_EVENT_TIMEOUT    = 4, /* Rport SM timeout event   */
3119     RPFSM_EVENT_RPSC_COMP      = 5,
3120     RPFSM_EVENT_RPSC_FAIL      = 6,
3121     RPFSM_EVENT_RPSC_ERROR     = 7,
3122 };
3123 
3124 static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
3125                     enum rpf_event event);
3126 static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
3127                        enum rpf_event event);
3128 static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
3129                        enum rpf_event event);
3130 static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
3131                     enum rpf_event event);
3132 static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
3133                     enum rpf_event event);
3134 static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
3135                     enum rpf_event event);
3136 
3137 static void
3138 bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3139 {
3140     struct bfa_fcs_rport_s *rport = rpf->rport;
3141     struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
3142 
3143     bfa_trc(rport->fcs, rport->pwwn);
3144     bfa_trc(rport->fcs, rport->pid);
3145     bfa_trc(rport->fcs, event);
3146 
3147     switch (event) {
3148     case RPFSM_EVENT_RPORT_ONLINE:
3149         /* Send RPSC2 to a Brocade fabric only. */
3150         if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
3151             ((rport->port->fabric->lps->brcd_switch) ||
3152             (bfa_fcs_fabric_get_switch_oui(fabric) ==
3153                         BFA_FCS_BRCD_SWITCH_OUI))) {
3154             bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3155             rpf->rpsc_retries = 0;
3156             bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3157         }
3158         break;
3159 
3160     case RPFSM_EVENT_RPORT_OFFLINE:
3161         break;
3162 
3163     default:
3164         bfa_sm_fault(rport->fcs, event);
3165     }
3166 }
3167 
3168 static void
3169 bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3170 {
3171     struct bfa_fcs_rport_s *rport = rpf->rport;
3172 
3173     bfa_trc(rport->fcs, event);
3174 
3175     switch (event) {
3176     case RPFSM_EVENT_FCXP_SENT:
3177         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
3178         break;
3179 
3180     case RPFSM_EVENT_RPORT_OFFLINE:
3181         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3182         bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
3183         rpf->rpsc_retries = 0;
3184         break;
3185 
3186     default:
3187         bfa_sm_fault(rport->fcs, event);
3188     }
3189 }
3190 
3191 static void
3192 bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3193 {
3194     struct bfa_fcs_rport_s *rport = rpf->rport;
3195 
3196     bfa_trc(rport->fcs, rport->pid);
3197     bfa_trc(rport->fcs, event);
3198 
3199     switch (event) {
3200     case RPFSM_EVENT_RPSC_COMP:
3201         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3202         /* Update speed info in f/w via BFA */
3203         if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)
3204             bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
3205         else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)
3206             bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
3207         break;
3208 
3209     case RPFSM_EVENT_RPSC_FAIL:
3210         /* RPSC not supported by rport */
3211         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3212         break;
3213 
3214     case RPFSM_EVENT_RPSC_ERROR:
3215         /* need to retry...delayed a bit. */
3216         if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
3217             bfa_timer_start(rport->fcs->bfa, &rpf->timer,
3218                     bfa_fcs_rpf_timeout, rpf,
3219                     BFA_FCS_RPF_RETRY_TIMEOUT);
3220             bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
3221         } else {
3222             bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3223         }
3224         break;
3225 
3226     case RPFSM_EVENT_RPORT_OFFLINE:
3227         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3228         bfa_fcxp_discard(rpf->fcxp);
3229         rpf->rpsc_retries = 0;
3230         break;
3231 
3232     default:
3233         bfa_sm_fault(rport->fcs, event);
3234     }
3235 }
3236 
3237 static void
3238 bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3239 {
3240     struct bfa_fcs_rport_s *rport = rpf->rport;
3241 
3242     bfa_trc(rport->fcs, rport->pid);
3243     bfa_trc(rport->fcs, event);
3244 
3245     switch (event) {
3246     case RPFSM_EVENT_TIMEOUT:
3247         /* re-send the RPSC */
3248         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3249         bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3250         break;
3251 
3252     case RPFSM_EVENT_RPORT_OFFLINE:
3253         bfa_timer_stop(&rpf->timer);
3254         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3255         rpf->rpsc_retries = 0;
3256         break;
3257 
3258     default:
3259         bfa_sm_fault(rport->fcs, event);
3260     }
3261 }
3262 
3263 static void
3264 bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3265 {
3266     struct bfa_fcs_rport_s *rport = rpf->rport;
3267 
3268     bfa_trc(rport->fcs, rport->pwwn);
3269     bfa_trc(rport->fcs, rport->pid);
3270     bfa_trc(rport->fcs, event);
3271 
3272     switch (event) {
3273     case RPFSM_EVENT_RPORT_OFFLINE:
3274         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3275         rpf->rpsc_retries = 0;
3276         break;
3277 
3278     default:
3279         bfa_sm_fault(rport->fcs, event);
3280     }
3281 }
3282 
3283 static void
3284 bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3285 {
3286     struct bfa_fcs_rport_s *rport = rpf->rport;
3287 
3288     bfa_trc(rport->fcs, rport->pwwn);
3289     bfa_trc(rport->fcs, rport->pid);
3290     bfa_trc(rport->fcs, event);
3291 
3292     switch (event) {
3293     case RPFSM_EVENT_RPORT_ONLINE:
3294         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3295         bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3296         break;
3297 
3298     case RPFSM_EVENT_RPORT_OFFLINE:
3299         break;
3300 
3301     default:
3302         bfa_sm_fault(rport->fcs, event);
3303     }
3304 }
3305 /*
3306  * Called when Rport is created.
3307  */
3308 void
3309 bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
3310 {
3311     struct bfa_fcs_rpf_s *rpf = &rport->rpf;
3312 
3313     bfa_trc(rport->fcs, rport->pid);
3314     rpf->rport = rport;
3315 
3316     bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
3317 }
3318 
3319 /*
3320  * Called when Rport becomes online
3321  */
3322 void
3323 bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
3324 {
3325     bfa_trc(rport->fcs, rport->pid);
3326 
3327     if (__fcs_min_cfg(rport->port->fcs))
3328         return;
3329 
3330     if (bfa_fcs_fabric_is_switched(rport->port->fabric))
3331         bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
3332 }
3333 
3334 /*
3335  * Called when Rport becomes offline
3336  */
3337 void
3338 bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
3339 {
3340     bfa_trc(rport->fcs, rport->pid);
3341 
3342     if (__fcs_min_cfg(rport->port->fcs))
3343         return;
3344 
3345     rport->rpf.rpsc_speed = 0;
3346     bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
3347 }
3348 
3349 static void
3350 bfa_fcs_rpf_timeout(void *arg)
3351 {
3352     struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
3353     struct bfa_fcs_rport_s *rport = rpf->rport;
3354 
3355     bfa_trc(rport->fcs, rport->pid);
3356     bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
3357 }
3358 
3359 static void
3360 bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3361 {
3362     struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
3363     struct bfa_fcs_rport_s *rport = rpf->rport;
3364     struct bfa_fcs_lport_s *port = rport->port;
3365     struct fchs_s   fchs;
3366     int     len;
3367     struct bfa_fcxp_s *fcxp;
3368 
3369     bfa_trc(rport->fcs, rport->pwwn);
3370 
3371     fcxp = fcxp_alloced ? fcxp_alloced :
3372            bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3373     if (!fcxp) {
3374         bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
3375                 bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);
3376         return;
3377     }
3378     rpf->fcxp = fcxp;
3379 
3380     len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
3381                 bfa_fcs_lport_get_fcid(port), &rport->pid, 1);
3382 
3383     bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3384               FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
3385               rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
3386     rport->stats.rpsc_sent++;
3387     bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
3388 
3389 }
3390 
3391 static void
3392 bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
3393                 bfa_status_t req_status, u32 rsp_len,
3394                 u32 resid_len, struct fchs_s *rsp_fchs)
3395 {
3396     struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
3397     struct bfa_fcs_rport_s *rport = rpf->rport;
3398     struct fc_ls_rjt_s *ls_rjt;
3399     struct fc_rpsc2_acc_s *rpsc2_acc;
3400     u16 num_ents;
3401 
3402     bfa_trc(rport->fcs, req_status);
3403 
3404     if (req_status != BFA_STATUS_OK) {
3405         bfa_trc(rport->fcs, req_status);
3406         if (req_status == BFA_STATUS_ETIMER)
3407             rport->stats.rpsc_failed++;
3408         bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3409         return;
3410     }
3411 
3412     rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
3413     if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
3414         rport->stats.rpsc_accs++;
3415         num_ents = be16_to_cpu(rpsc2_acc->num_pids);
3416         bfa_trc(rport->fcs, num_ents);
3417         if (num_ents > 0) {
3418             WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) !=
3419                         bfa_ntoh3b(rport->pid));
3420             bfa_trc(rport->fcs,
3421                 be32_to_cpu(rpsc2_acc->port_info[0].pid));
3422             bfa_trc(rport->fcs,
3423                 be16_to_cpu(rpsc2_acc->port_info[0].speed));
3424             bfa_trc(rport->fcs,
3425                 be16_to_cpu(rpsc2_acc->port_info[0].index));
3426             bfa_trc(rport->fcs,
3427                 rpsc2_acc->port_info[0].type);
3428 
3429             if (rpsc2_acc->port_info[0].speed == 0) {
3430                 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3431                 return;
3432             }
3433 
3434             rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
3435                 be16_to_cpu(rpsc2_acc->port_info[0].speed));
3436 
3437             bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
3438         }
3439     } else {
3440         ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3441         bfa_trc(rport->fcs, ls_rjt->reason_code);
3442         bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
3443         rport->stats.rpsc_rejects++;
3444         if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
3445             bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
3446         else
3447             bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3448     }
3449 }