cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bfa_fcs_rport.c (89861B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
      4 * Copyright (c) 2014- QLogic Corporation.
      5 * All rights reserved
      6 * www.qlogic.com
      7 *
      8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
      9 */
     10
     11/*
     12 *  rport.c Remote port implementation.
     13 */
     14
     15#include "bfad_drv.h"
     16#include "bfad_im.h"
     17#include "bfa_fcs.h"
     18#include "bfa_fcbuild.h"
     19
     20BFA_TRC_FILE(FCS, RPORT);
     21
     22static u32
     23bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
     24	 /* In millisecs */
     25/*
     26 * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports
     27 * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports
     28 */
     29static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;
     30
     31/*
     32 * forward declarations
     33 */
     34static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
     35		struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
     36static void	bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
     37static void	bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
     38static void	bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport);
     39static void	bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport);
     40static void	bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport);
     41static void	bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);
     42static void	bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
     43					struct fc_logi_s *plogi);
     44static void	bfa_fcs_rport_timeout(void *arg);
     45static void	bfa_fcs_rport_send_plogi(void *rport_cbarg,
     46					 struct bfa_fcxp_s *fcxp_alloced);
     47static void	bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
     48					struct bfa_fcxp_s *fcxp_alloced);
     49static void	bfa_fcs_rport_plogi_response(void *fcsarg,
     50				struct bfa_fcxp_s *fcxp, void *cbarg,
     51				bfa_status_t req_status, u32 rsp_len,
     52				u32 resid_len, struct fchs_s *rsp_fchs);
     53static void	bfa_fcs_rport_send_adisc(void *rport_cbarg,
     54					 struct bfa_fcxp_s *fcxp_alloced);
     55static void	bfa_fcs_rport_adisc_response(void *fcsarg,
     56				struct bfa_fcxp_s *fcxp, void *cbarg,
     57				bfa_status_t req_status, u32 rsp_len,
     58				u32 resid_len, struct fchs_s *rsp_fchs);
     59static void	bfa_fcs_rport_send_nsdisc(void *rport_cbarg,
     60					 struct bfa_fcxp_s *fcxp_alloced);
     61static void	bfa_fcs_rport_gidpn_response(void *fcsarg,
     62				struct bfa_fcxp_s *fcxp, void *cbarg,
     63				bfa_status_t req_status, u32 rsp_len,
     64				u32 resid_len, struct fchs_s *rsp_fchs);
     65static void	bfa_fcs_rport_gpnid_response(void *fcsarg,
     66				struct bfa_fcxp_s *fcxp, void *cbarg,
     67				bfa_status_t req_status, u32 rsp_len,
     68				u32 resid_len, struct fchs_s *rsp_fchs);
     69static void	bfa_fcs_rport_send_logo(void *rport_cbarg,
     70					struct bfa_fcxp_s *fcxp_alloced);
     71static void	bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
     72static void	bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
     73					struct fchs_s *rx_fchs, u16 len);
     74static void	bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
     75				struct fchs_s *rx_fchs, u8 reason_code,
     76					  u8 reason_code_expl);
     77static void	bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
     78				struct fchs_s *rx_fchs, u16 len);
     79static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
     80static void	bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);
     81
     82static void	bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
     83					enum rport_event event);
     84static void	bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
     85						enum rport_event event);
     86static void	bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
     87						  enum rport_event event);
     88static void	bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
     89						enum rport_event event);
     90static void	bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
     91					enum rport_event event);
     92static void	bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
     93					enum rport_event event);
     94static void	bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
     95						enum rport_event event);
     96static void	bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
     97					enum rport_event event);
     98static void	bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
     99						 enum rport_event event);
    100static void	bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
    101					 enum rport_event event);
    102static void	bfa_fcs_rport_sm_adisc_online_sending(
    103			struct bfa_fcs_rport_s *rport, enum rport_event event);
    104static void	bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
    105					enum rport_event event);
    106static void	bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s
    107					*rport, enum rport_event event);
    108static void	bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
    109					enum rport_event event);
    110static void	bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
    111						enum rport_event event);
    112static void	bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
    113						enum rport_event event);
    114static void	bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
    115						enum rport_event event);
    116static void	bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
    117						enum rport_event event);
    118static void	bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
    119						enum rport_event event);
    120static void	bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
    121						enum rport_event event);
    122static void	bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
    123						enum rport_event event);
    124static void	bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
    125					 enum rport_event event);
    126static void	bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
    127						enum rport_event event);
    128static void	bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
    129						enum rport_event event);
    130static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
    131						enum rport_event event);
    132static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
    133						enum rport_event event);
    134static void	bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
    135						enum rport_event event);
    136static void	bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
    137						enum rport_event event);
    138
    139static struct bfa_sm_table_s rport_sm_table[] = {
    140	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
    141	{BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
    142	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
    143	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
    144	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
    145	{BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},
    146	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
    147	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
    148	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
    149	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
    150	{BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},
    151	{BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},
    152	{BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},
    153	{BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},
    154	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
    155	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
    156	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
    157	{BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
    158	{BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
    159	{BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
    160	{BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
    161	{BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
    162	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
    163	{BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
    164	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
    165};
    166
    167/*
    168 *		Beginning state.
    169 */
    170static void
    171bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
    172{
    173	bfa_trc(rport->fcs, rport->pwwn);
    174	bfa_trc(rport->fcs, rport->pid);
    175	bfa_trc(rport->fcs, event);
    176
    177	switch (event) {
    178	case RPSM_EVENT_PLOGI_SEND:
    179		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
    180		rport->plogi_retries = 0;
    181		bfa_fcs_rport_send_plogi(rport, NULL);
    182		break;
    183
    184	case RPSM_EVENT_PLOGI_RCVD:
    185		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
    186		bfa_fcs_rport_send_plogiacc(rport, NULL);
    187		break;
    188
    189	case RPSM_EVENT_PLOGI_COMP:
    190		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
    191		bfa_fcs_rport_hal_online(rport);
    192		break;
    193
    194	case RPSM_EVENT_ADDRESS_CHANGE:
    195	case RPSM_EVENT_ADDRESS_DISC:
    196		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
    197		rport->ns_retries = 0;
    198		bfa_fcs_rport_send_nsdisc(rport, NULL);
    199		break;
    200	default:
    201		bfa_sm_fault(rport->fcs, event);
    202	}
    203}
    204
    205/*
    206 *		PLOGI is being sent.
    207 */
    208static void
    209bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
    210	 enum rport_event event)
    211{
    212	bfa_trc(rport->fcs, rport->pwwn);
    213	bfa_trc(rport->fcs, rport->pid);
    214	bfa_trc(rport->fcs, event);
    215
    216	switch (event) {
    217	case RPSM_EVENT_FCXP_SENT:
    218		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
    219		break;
    220
    221	case RPSM_EVENT_DELETE:
    222		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
    223		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    224		bfa_fcs_rport_free(rport);
    225		break;
    226
    227	case RPSM_EVENT_PLOGI_RCVD:
    228		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
    229		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    230		bfa_fcs_rport_send_plogiacc(rport, NULL);
    231		break;
    232
    233	case RPSM_EVENT_SCN_OFFLINE:
    234		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    235		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    236		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    237				bfa_fcs_rport_timeout, rport,
    238				bfa_fcs_rport_del_timeout);
    239		break;
    240	case RPSM_EVENT_ADDRESS_CHANGE:
    241	case RPSM_EVENT_FAB_SCN:
    242		/* query the NS */
    243		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    244		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
    245					BFA_PORT_TOPOLOGY_LOOP));
    246		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
    247		rport->ns_retries = 0;
    248		bfa_fcs_rport_send_nsdisc(rport, NULL);
    249		break;
    250
    251	case RPSM_EVENT_LOGO_IMP:
    252		rport->pid = 0;
    253		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    254		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    255		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    256				bfa_fcs_rport_timeout, rport,
    257				bfa_fcs_rport_del_timeout);
    258		break;
    259
    260
    261	default:
    262		bfa_sm_fault(rport->fcs, event);
    263	}
    264}
    265
    266/*
    267 *		PLOGI is being sent.
    268 */
    269static void
    270bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
    271	 enum rport_event event)
    272{
    273	bfa_trc(rport->fcs, rport->pwwn);
    274	bfa_trc(rport->fcs, rport->pid);
    275	bfa_trc(rport->fcs, event);
    276
    277	switch (event) {
    278	case RPSM_EVENT_FCXP_SENT:
    279		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
    280		bfa_fcs_rport_fcs_online_action(rport);
    281		break;
    282
    283	case RPSM_EVENT_DELETE:
    284		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
    285		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    286		bfa_fcs_rport_free(rport);
    287		break;
    288
    289	case RPSM_EVENT_PLOGI_RCVD:
    290	case RPSM_EVENT_PLOGI_COMP:
    291	case RPSM_EVENT_FAB_SCN:
    292		/*
    293		 * Ignore, SCN is possibly online notification.
    294		 */
    295		break;
    296
    297	case RPSM_EVENT_SCN_OFFLINE:
    298		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    299		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    300		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    301				bfa_fcs_rport_timeout, rport,
    302				bfa_fcs_rport_del_timeout);
    303		break;
    304
    305	case RPSM_EVENT_ADDRESS_CHANGE:
    306		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    307		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
    308		rport->ns_retries = 0;
    309		bfa_fcs_rport_send_nsdisc(rport, NULL);
    310		break;
    311
    312	case RPSM_EVENT_LOGO_IMP:
    313		rport->pid = 0;
    314		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    315		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    316		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    317				bfa_fcs_rport_timeout, rport,
    318				bfa_fcs_rport_del_timeout);
    319		break;
    320
    321	case RPSM_EVENT_HCB_OFFLINE:
    322		/*
    323		 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
    324		 */
    325		break;
    326
    327	default:
    328		bfa_sm_fault(rport->fcs, event);
    329	}
    330}
    331
    332/*
    333 *		PLOGI is sent.
    334 */
    335static void
    336bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
    337			enum rport_event event)
    338{
    339	bfa_trc(rport->fcs, rport->pwwn);
    340	bfa_trc(rport->fcs, rport->pid);
    341	bfa_trc(rport->fcs, event);
    342
    343	switch (event) {
    344	case RPSM_EVENT_TIMEOUT:
    345		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
    346		bfa_fcs_rport_send_plogi(rport, NULL);
    347		break;
    348
    349	case RPSM_EVENT_DELETE:
    350		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
    351		bfa_timer_stop(&rport->timer);
    352		bfa_fcs_rport_free(rport);
    353		break;
    354
    355	case RPSM_EVENT_PRLO_RCVD:
    356	case RPSM_EVENT_LOGO_RCVD:
    357		break;
    358
    359	case RPSM_EVENT_PLOGI_RCVD:
    360		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
    361		bfa_timer_stop(&rport->timer);
    362		bfa_fcs_rport_send_plogiacc(rport, NULL);
    363		break;
    364
    365	case RPSM_EVENT_SCN_OFFLINE:
    366		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    367		bfa_timer_stop(&rport->timer);
    368		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    369				bfa_fcs_rport_timeout, rport,
    370				bfa_fcs_rport_del_timeout);
    371		break;
    372
    373	case RPSM_EVENT_ADDRESS_CHANGE:
    374	case RPSM_EVENT_FAB_SCN:
    375		bfa_timer_stop(&rport->timer);
    376		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
    377					BFA_PORT_TOPOLOGY_LOOP));
    378		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
    379		rport->ns_retries = 0;
    380		bfa_fcs_rport_send_nsdisc(rport, NULL);
    381		break;
    382
    383	case RPSM_EVENT_LOGO_IMP:
    384		rport->pid = 0;
    385		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    386		bfa_timer_stop(&rport->timer);
    387		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    388				bfa_fcs_rport_timeout, rport,
    389				bfa_fcs_rport_del_timeout);
    390		break;
    391
    392	case RPSM_EVENT_PLOGI_COMP:
    393		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
    394		bfa_timer_stop(&rport->timer);
    395		bfa_fcs_rport_fcs_online_action(rport);
    396		break;
    397
    398	default:
    399		bfa_sm_fault(rport->fcs, event);
    400	}
    401}
    402
    403/*
    404 *		PLOGI is sent.
    405 */
    406static void
    407bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
    408{
    409	bfa_trc(rport->fcs, rport->pwwn);
    410	bfa_trc(rport->fcs, rport->pid);
    411	bfa_trc(rport->fcs, event);
    412
    413	switch (event) {
    414	case RPSM_EVENT_ACCEPTED:
    415		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
    416		rport->plogi_retries = 0;
    417		bfa_fcs_rport_fcs_online_action(rport);
    418		break;
    419
    420	case RPSM_EVENT_LOGO_RCVD:
    421		bfa_fcs_rport_send_logo_acc(rport);
    422		fallthrough;
    423	case RPSM_EVENT_PRLO_RCVD:
    424		if (rport->prlo == BFA_TRUE)
    425			bfa_fcs_rport_send_prlo_acc(rport);
    426
    427		bfa_fcxp_discard(rport->fcxp);
    428		fallthrough;
    429	case RPSM_EVENT_FAILED:
    430		if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
    431			rport->plogi_retries++;
    432			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
    433			bfa_timer_start(rport->fcs->bfa, &rport->timer,
    434					bfa_fcs_rport_timeout, rport,
    435					BFA_FCS_RETRY_TIMEOUT);
    436		} else {
    437			bfa_stats(rport->port, rport_del_max_plogi_retry);
    438			rport->old_pid = rport->pid;
    439			rport->pid = 0;
    440			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    441			bfa_timer_start(rport->fcs->bfa, &rport->timer,
    442					bfa_fcs_rport_timeout, rport,
    443					bfa_fcs_rport_del_timeout);
    444		}
    445		break;
    446
    447	case RPSM_EVENT_SCN_ONLINE:
    448		break;
    449
    450	case RPSM_EVENT_SCN_OFFLINE:
    451		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    452		bfa_fcxp_discard(rport->fcxp);
    453		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    454				bfa_fcs_rport_timeout, rport,
    455				bfa_fcs_rport_del_timeout);
    456		break;
    457
    458	case RPSM_EVENT_PLOGI_RETRY:
    459		rport->plogi_retries = 0;
    460		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
    461		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    462				bfa_fcs_rport_timeout, rport,
    463				(FC_RA_TOV * 1000));
    464		break;
    465
    466	case RPSM_EVENT_LOGO_IMP:
    467		rport->pid = 0;
    468		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    469		bfa_fcxp_discard(rport->fcxp);
    470		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    471				bfa_fcs_rport_timeout, rport,
    472				bfa_fcs_rport_del_timeout);
    473		break;
    474
    475	case RPSM_EVENT_ADDRESS_CHANGE:
    476	case RPSM_EVENT_FAB_SCN:
    477		bfa_fcxp_discard(rport->fcxp);
    478		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
    479					BFA_PORT_TOPOLOGY_LOOP));
    480		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
    481		rport->ns_retries = 0;
    482		bfa_fcs_rport_send_nsdisc(rport, NULL);
    483		break;
    484
    485	case RPSM_EVENT_PLOGI_RCVD:
    486		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
    487		bfa_fcxp_discard(rport->fcxp);
    488		bfa_fcs_rport_send_plogiacc(rport, NULL);
    489		break;
    490
    491	case RPSM_EVENT_DELETE:
    492		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
    493		bfa_fcxp_discard(rport->fcxp);
    494		bfa_fcs_rport_free(rport);
    495		break;
    496
    497	case RPSM_EVENT_PLOGI_COMP:
    498		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
    499		bfa_fcxp_discard(rport->fcxp);
    500		bfa_fcs_rport_fcs_online_action(rport);
    501		break;
    502
    503	default:
    504		bfa_sm_fault(rport->fcs, event);
    505	}
    506}
    507
    508/*
    509 * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function
    510 */
    511static void
    512bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
    513				enum rport_event event)
    514{
    515	bfa_trc(rport->fcs, rport->pwwn);
    516	bfa_trc(rport->fcs, rport->pid);
    517	bfa_trc(rport->fcs, event);
    518
    519	switch (event) {
    520	case RPSM_EVENT_FC4_FCS_ONLINE:
    521		if (rport->scsi_function == BFA_RPORT_INITIATOR) {
    522			if (!BFA_FCS_PID_IS_WKA(rport->pid))
    523				bfa_fcs_rpf_rport_online(rport);
    524			bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
    525			break;
    526		}
    527
    528		if (!rport->bfa_rport)
    529			rport->bfa_rport =
    530				bfa_rport_create(rport->fcs->bfa, rport);
    531
    532		if (rport->bfa_rport) {
    533			bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
    534			bfa_fcs_rport_hal_online(rport);
    535		} else {
    536			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    537			bfa_fcs_rport_fcs_offline_action(rport);
    538		}
    539		break;
    540
    541	case RPSM_EVENT_PLOGI_RCVD:
    542		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    543		rport->plogi_pending = BFA_TRUE;
    544		bfa_fcs_rport_fcs_offline_action(rport);
    545		break;
    546
    547	case RPSM_EVENT_PLOGI_COMP:
    548	case RPSM_EVENT_LOGO_IMP:
    549	case RPSM_EVENT_ADDRESS_CHANGE:
    550	case RPSM_EVENT_FAB_SCN:
    551	case RPSM_EVENT_SCN_OFFLINE:
    552		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    553		bfa_fcs_rport_fcs_offline_action(rport);
    554		break;
    555
    556	case RPSM_EVENT_LOGO_RCVD:
    557	case RPSM_EVENT_PRLO_RCVD:
    558		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
    559		bfa_fcs_rport_fcs_offline_action(rport);
    560		break;
    561
    562	case RPSM_EVENT_DELETE:
    563		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    564		bfa_fcs_rport_fcs_offline_action(rport);
    565		break;
    566
    567	default:
    568		bfa_sm_fault(rport->fcs, event);
    569		break;
    570	}
    571}
    572
    573/*
    574 *		PLOGI is complete. Awaiting BFA rport online callback. FC-4s
    575 *		are offline.
    576 */
    577static void
    578bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
    579			enum rport_event event)
    580{
    581	bfa_trc(rport->fcs, rport->pwwn);
    582	bfa_trc(rport->fcs, rport->pid);
    583	bfa_trc(rport->fcs, event);
    584
    585	switch (event) {
    586	case RPSM_EVENT_HCB_ONLINE:
    587		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
    588		bfa_fcs_rport_hal_online_action(rport);
    589		break;
    590
    591	case RPSM_EVENT_PLOGI_COMP:
    592		break;
    593
    594	case RPSM_EVENT_PRLO_RCVD:
    595	case RPSM_EVENT_LOGO_RCVD:
    596		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
    597		bfa_fcs_rport_fcs_offline_action(rport);
    598		break;
    599
    600	case RPSM_EVENT_FAB_SCN:
    601	case RPSM_EVENT_LOGO_IMP:
    602	case RPSM_EVENT_ADDRESS_CHANGE:
    603	case RPSM_EVENT_SCN_OFFLINE:
    604		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    605		bfa_fcs_rport_fcs_offline_action(rport);
    606		break;
    607
    608	case RPSM_EVENT_PLOGI_RCVD:
    609		rport->plogi_pending = BFA_TRUE;
    610		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    611		bfa_fcs_rport_fcs_offline_action(rport);
    612		break;
    613
    614	case RPSM_EVENT_DELETE:
    615		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    616		bfa_fcs_rport_fcs_offline_action(rport);
    617		break;
    618
    619	default:
    620		bfa_sm_fault(rport->fcs, event);
    621	}
    622}
    623
    624/*
    625 *		Rport is ONLINE. FC-4s active.
    626 */
    627static void
    628bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
    629{
    630	bfa_trc(rport->fcs, rport->pwwn);
    631	bfa_trc(rport->fcs, rport->pid);
    632	bfa_trc(rport->fcs, event);
    633
    634	switch (event) {
    635	case RPSM_EVENT_FAB_SCN:
    636		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
    637			bfa_sm_set_state(rport,
    638					 bfa_fcs_rport_sm_nsquery_sending);
    639			rport->ns_retries = 0;
    640			bfa_fcs_rport_send_nsdisc(rport, NULL);
    641		} else {
    642			bfa_sm_set_state(rport,
    643				bfa_fcs_rport_sm_adisc_online_sending);
    644			bfa_fcs_rport_send_adisc(rport, NULL);
    645		}
    646		break;
    647
    648	case RPSM_EVENT_PLOGI_RCVD:
    649	case RPSM_EVENT_LOGO_IMP:
    650	case RPSM_EVENT_ADDRESS_CHANGE:
    651	case RPSM_EVENT_SCN_OFFLINE:
    652		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    653		bfa_fcs_rport_hal_offline_action(rport);
    654		break;
    655
    656	case RPSM_EVENT_DELETE:
    657		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    658		bfa_fcs_rport_hal_offline_action(rport);
    659		break;
    660
    661	case RPSM_EVENT_LOGO_RCVD:
    662	case RPSM_EVENT_PRLO_RCVD:
    663		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
    664		bfa_fcs_rport_hal_offline_action(rport);
    665		break;
    666
    667	case RPSM_EVENT_SCN_ONLINE:
    668	case RPSM_EVENT_PLOGI_COMP:
    669		break;
    670
    671	default:
    672		bfa_sm_fault(rport->fcs, event);
    673	}
    674}
    675
    676/*
    677 *		An SCN event is received in ONLINE state. NS query is being sent
    678 *		prior to ADISC authentication with rport. FC-4s are paused.
    679 */
    680static void
    681bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
    682	 enum rport_event event)
    683{
    684	bfa_trc(rport->fcs, rport->pwwn);
    685	bfa_trc(rport->fcs, rport->pid);
    686	bfa_trc(rport->fcs, event);
    687
    688	switch (event) {
    689	case RPSM_EVENT_FCXP_SENT:
    690		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
    691		break;
    692
    693	case RPSM_EVENT_DELETE:
    694		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    695		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    696		bfa_fcs_rport_hal_offline_action(rport);
    697		break;
    698
    699	case RPSM_EVENT_FAB_SCN:
    700		/*
    701		 * ignore SCN, wait for response to query itself
    702		 */
    703		break;
    704
    705	case RPSM_EVENT_LOGO_RCVD:
    706	case RPSM_EVENT_PRLO_RCVD:
    707		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
    708		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    709		bfa_fcs_rport_hal_offline_action(rport);
    710		break;
    711
    712	case RPSM_EVENT_LOGO_IMP:
    713	case RPSM_EVENT_PLOGI_RCVD:
    714	case RPSM_EVENT_ADDRESS_CHANGE:
    715	case RPSM_EVENT_PLOGI_COMP:
    716		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    717		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    718		bfa_fcs_rport_hal_offline_action(rport);
    719		break;
    720
    721	default:
    722		bfa_sm_fault(rport->fcs, event);
    723	}
    724}
    725
    726/*
    727 *	An SCN event is received in ONLINE state. NS query is sent to rport.
    728 *	FC-4s are paused.
    729 */
    730static void
    731bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
    732{
    733	bfa_trc(rport->fcs, rport->pwwn);
    734	bfa_trc(rport->fcs, rport->pid);
    735	bfa_trc(rport->fcs, event);
    736
    737	switch (event) {
    738	case RPSM_EVENT_ACCEPTED:
    739		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);
    740		bfa_fcs_rport_send_adisc(rport, NULL);
    741		break;
    742
    743	case RPSM_EVENT_FAILED:
    744		rport->ns_retries++;
    745		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
    746			bfa_sm_set_state(rport,
    747					 bfa_fcs_rport_sm_nsquery_sending);
    748			bfa_fcs_rport_send_nsdisc(rport, NULL);
    749		} else {
    750			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    751			bfa_fcs_rport_hal_offline_action(rport);
    752		}
    753		break;
    754
    755	case RPSM_EVENT_DELETE:
    756		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    757		bfa_fcxp_discard(rport->fcxp);
    758		bfa_fcs_rport_hal_offline_action(rport);
    759		break;
    760
    761	case RPSM_EVENT_FAB_SCN:
    762		break;
    763
    764	case RPSM_EVENT_LOGO_RCVD:
    765	case RPSM_EVENT_PRLO_RCVD:
    766		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
    767		bfa_fcxp_discard(rport->fcxp);
    768		bfa_fcs_rport_hal_offline_action(rport);
    769		break;
    770
    771	case RPSM_EVENT_PLOGI_COMP:
    772	case RPSM_EVENT_ADDRESS_CHANGE:
    773	case RPSM_EVENT_PLOGI_RCVD:
    774	case RPSM_EVENT_LOGO_IMP:
    775		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    776		bfa_fcxp_discard(rport->fcxp);
    777		bfa_fcs_rport_hal_offline_action(rport);
    778		break;
    779
    780	default:
    781		bfa_sm_fault(rport->fcs, event);
    782	}
    783}
    784
    785/*
    786 *	An SCN event is received in ONLINE state. ADISC is being sent for
    787 *	authenticating with rport. FC-4s are paused.
    788 */
    789static void
    790bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,
    791	 enum rport_event event)
    792{
    793	bfa_trc(rport->fcs, rport->pwwn);
    794	bfa_trc(rport->fcs, rport->pid);
    795	bfa_trc(rport->fcs, event);
    796
    797	switch (event) {
    798	case RPSM_EVENT_FCXP_SENT:
    799		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);
    800		break;
    801
    802	case RPSM_EVENT_DELETE:
    803		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    804		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    805		bfa_fcs_rport_hal_offline_action(rport);
    806		break;
    807
    808	case RPSM_EVENT_LOGO_IMP:
    809	case RPSM_EVENT_ADDRESS_CHANGE:
    810		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    811		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    812		bfa_fcs_rport_hal_offline_action(rport);
    813		break;
    814
    815	case RPSM_EVENT_LOGO_RCVD:
    816	case RPSM_EVENT_PRLO_RCVD:
    817		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
    818		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    819		bfa_fcs_rport_hal_offline_action(rport);
    820		break;
    821
    822	case RPSM_EVENT_FAB_SCN:
    823		break;
    824
    825	case RPSM_EVENT_PLOGI_RCVD:
    826		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    827		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    828		bfa_fcs_rport_hal_offline_action(rport);
    829		break;
    830
    831	default:
    832		bfa_sm_fault(rport->fcs, event);
    833	}
    834}
    835
    836/*
    837 *		An SCN event is received in ONLINE state. ADISC is to rport.
    838 *		FC-4s are paused.
    839 */
    840static void
    841bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
    842				enum rport_event event)
    843{
    844	bfa_trc(rport->fcs, rport->pwwn);
    845	bfa_trc(rport->fcs, rport->pid);
    846	bfa_trc(rport->fcs, event);
    847
    848	switch (event) {
    849	case RPSM_EVENT_ACCEPTED:
    850		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
    851		break;
    852
    853	case RPSM_EVENT_PLOGI_RCVD:
    854		/*
    855		 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
    856		 * At least go offline when a PLOGI is received.
    857		 */
    858		bfa_fcxp_discard(rport->fcxp);
    859		fallthrough;
    860
    861	case RPSM_EVENT_FAILED:
    862	case RPSM_EVENT_ADDRESS_CHANGE:
    863		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    864		bfa_fcs_rport_hal_offline_action(rport);
    865		break;
    866
    867	case RPSM_EVENT_DELETE:
    868		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
    869		bfa_fcxp_discard(rport->fcxp);
    870		bfa_fcs_rport_hal_offline_action(rport);
    871		break;
    872
    873	case RPSM_EVENT_FAB_SCN:
    874		/*
    875		 * already processing RSCN
    876		 */
    877		break;
    878
    879	case RPSM_EVENT_LOGO_IMP:
    880		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
    881		bfa_fcxp_discard(rport->fcxp);
    882		bfa_fcs_rport_hal_offline_action(rport);
    883		break;
    884
    885	case RPSM_EVENT_LOGO_RCVD:
    886	case RPSM_EVENT_PRLO_RCVD:
    887		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
    888		bfa_fcxp_discard(rport->fcxp);
    889		bfa_fcs_rport_hal_offline_action(rport);
    890		break;
    891
    892	default:
    893		bfa_sm_fault(rport->fcs, event);
    894	}
    895}
    896
    897/*
    898 * ADISC is being sent for authenticating with rport
    899 * Already did offline actions.
    900 */
    901static void
    902bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,
    903	enum rport_event event)
    904{
    905	bfa_trc(rport->fcs, rport->pwwn);
    906	bfa_trc(rport->fcs, rport->pid);
    907	bfa_trc(rport->fcs, event);
    908
    909	switch (event) {
    910	case RPSM_EVENT_FCXP_SENT:
    911		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);
    912		break;
    913
    914	case RPSM_EVENT_DELETE:
    915	case RPSM_EVENT_SCN_OFFLINE:
    916	case RPSM_EVENT_LOGO_IMP:
    917	case RPSM_EVENT_LOGO_RCVD:
    918	case RPSM_EVENT_PRLO_RCVD:
    919		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    920		bfa_fcxp_walloc_cancel(rport->fcs->bfa,
    921			&rport->fcxp_wqe);
    922		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    923			bfa_fcs_rport_timeout, rport,
    924			bfa_fcs_rport_del_timeout);
    925		break;
    926
    927	case RPSM_EVENT_PLOGI_RCVD:
    928		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
    929		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
    930		bfa_fcs_rport_send_plogiacc(rport, NULL);
    931		break;
    932
    933	default:
    934		bfa_sm_fault(rport->fcs, event);
    935	}
    936}
    937
    938/*
    939 * ADISC to rport
    940 * Already did offline actions
    941 */
    942static void
    943bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
    944			enum rport_event event)
    945{
    946	bfa_trc(rport->fcs, rport->pwwn);
    947	bfa_trc(rport->fcs, rport->pid);
    948	bfa_trc(rport->fcs, event);
    949
    950	switch (event) {
    951	case RPSM_EVENT_ACCEPTED:
    952		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
    953		bfa_fcs_rport_hal_online(rport);
    954		break;
    955
    956	case RPSM_EVENT_PLOGI_RCVD:
    957		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
    958		bfa_fcxp_discard(rport->fcxp);
    959		bfa_fcs_rport_send_plogiacc(rport, NULL);
    960		break;
    961
    962	case RPSM_EVENT_FAILED:
    963		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    964		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    965			bfa_fcs_rport_timeout, rport,
    966			bfa_fcs_rport_del_timeout);
    967		break;
    968
    969	case RPSM_EVENT_DELETE:
    970	case RPSM_EVENT_SCN_OFFLINE:
    971	case RPSM_EVENT_LOGO_IMP:
    972	case RPSM_EVENT_LOGO_RCVD:
    973	case RPSM_EVENT_PRLO_RCVD:
    974		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
    975		bfa_fcxp_discard(rport->fcxp);
    976		bfa_timer_start(rport->fcs->bfa, &rport->timer,
    977			bfa_fcs_rport_timeout, rport,
    978			bfa_fcs_rport_del_timeout);
    979		break;
    980
    981	default:
    982		bfa_sm_fault(rport->fcs, event);
    983	}
    984}
    985
    986/*
    987 * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
    988 */
    989static void
    990bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
    991			enum rport_event event)
    992{
    993	bfa_trc(rport->fcs, rport->pwwn);
    994	bfa_trc(rport->fcs, rport->pid);
    995	bfa_trc(rport->fcs, event);
    996
    997	switch (event) {
    998	case RPSM_EVENT_FC4_OFFLINE:
    999		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 */
   1029static void
   1030bfa_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 */
   1065static void
   1066bfa_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 */
   1116static void
   1117bfa_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 */
   1196static void
   1197bfa_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 */
   1275static void
   1276bfa_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 */
   1312static void
   1313bfa_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 */
   1354static void
   1355bfa_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 */
   1422static void
   1423bfa_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 */
   1479static void
   1480bfa_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 */
   1543static void
   1544bfa_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 */
   1634static void
   1635bfa_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 */
   1663static void
   1664bfa_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
   1692static void
   1693bfa_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
   1726static void
   1727bfa_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
   1812static void
   1813bfa_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
   1846static void
   1847bfa_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
   1878static void
   1879bfa_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
   1909static void
   1910bfa_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
   1947static void
   1948bfa_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
   2020static void
   2021bfa_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 */
   2065static void
   2066bfa_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 */
   2103static void
   2104bfa_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 */
   2143static void
   2144bfa_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
   2153static void
   2154bfa_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
   2199static void
   2200bfa_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
   2236static void
   2237bfa_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
   2275static void
   2276bfa_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
   2292static void
   2293bfa_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
   2301static struct bfa_fcs_rport_s *
   2302bfa_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
   2361static void
   2362bfa_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
   2390static void
   2391bfa_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
   2419static void
   2420bfa_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
   2430static void
   2431bfa_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
   2461static void
   2462bfa_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
   2470static void
   2471bfa_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 */
   2515static void
   2516bfa_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 */
   2573static void
   2574bfa_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 */
   2599struct bfa_fcs_rport_s *
   2600bfa_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 */
   2621struct bfa_fcs_rport_s *
   2622bfa_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 */
   2640void
   2641bfa_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 */
   2659void
   2660bfa_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 */
   2682void
   2683bfa_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 */
   2706void
   2707bfa_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 */
   2726void
   2727bfa_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 */
   2749void
   2750bfa_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 */
   2772void
   2773bfa_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
   2785void
   2786bfa_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
   2803void
   2804bfa_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
   2812void
   2813bfa_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 */
   2841void
   2842bfa_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 */
   2857void
   2858bfa_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 */
   2912static void
   2913bfa_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 */
   2937static void
   2938bfa_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 */
   2964int
   2965bfa_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 */
   2979void
   2980bfa_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}
   2986void
   2987bfa_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 */
   3000void
   3001bfa_fcs_rport_set_max_logins(u32 max_logins)
   3002{
   3003	if (max_logins > 0)
   3004		bfa_fcs_rport_max_logins = max_logins;
   3005}
   3006
   3007void
   3008bfa_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
   3061struct bfa_fcs_rport_s *
   3062bfa_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
   3076struct bfa_fcs_rport_s *
   3077bfa_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
   3098static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
   3099				struct bfa_fcxp_s *fcxp_alloced);
   3100static 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
   3108static void     bfa_fcs_rpf_timeout(void *arg);
   3109
   3110/*
   3111 *  fcs_rport_ftrs_sm FCS rport state machine events
   3112 */
   3113
   3114enum 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
   3124static void	bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
   3125					enum rpf_event event);
   3126static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
   3127				       enum rpf_event event);
   3128static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
   3129				       enum rpf_event event);
   3130static void	bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
   3131					enum rpf_event event);
   3132static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
   3133					enum rpf_event event);
   3134static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
   3135					enum rpf_event event);
   3136
   3137static void
   3138bfa_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
   3168static void
   3169bfa_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
   3191static void
   3192bfa_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
   3237static void
   3238bfa_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
   3263static void
   3264bfa_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
   3283static void
   3284bfa_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 */
   3308void
   3309bfa_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 */
   3322void
   3323bfa_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 */
   3337void
   3338bfa_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
   3349static void
   3350bfa_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
   3359static void
   3360bfa_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
   3391static void
   3392bfa_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}