brintos

brintos / linux-shallow public Read only

0
0
Text · 87.8 KiB · ce52a9c Raw
3452 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.4 * Copyright (c) 2014- QLogic Corporation.5 * All rights reserved6 * www.qlogic.com7 *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 u3223bfa_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_rports27 * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports28 */29static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;30 31/*32 * forward declarations33 */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_s107					*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 139struct bfa_fcs_rport_sm_table_s {140	bfa_fcs_rport_sm_t sm;		/*  state machine function	*/141	enum bfa_rport_state state;	/*  state machine encoding	*/142	char		*name;		/*  state name for display	*/143};144 145static inline enum bfa_rport_state146bfa_rport_sm_to_state(struct bfa_fcs_rport_sm_table_s *smt, bfa_fcs_rport_sm_t sm)147{148	int i = 0;149 150	while (smt[i].sm && smt[i].sm != sm)151		i++;152	return smt[i].state;153}154 155static struct bfa_fcs_rport_sm_table_s rport_sm_table[] = {156	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},157	{BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},158	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},159	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},160	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},161	{BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},162	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},163	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},164	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},165	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},166	{BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},167	{BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},168	{BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},169	{BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},170	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},171	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},172	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},173	{BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},174	{BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},175	{BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},176	{BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},177	{BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},178	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},179	{BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},180	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},181};182 183/*184 *		Beginning state.185 */186static void187bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)188{189	bfa_trc(rport->fcs, rport->pwwn);190	bfa_trc(rport->fcs, rport->pid);191	bfa_trc(rport->fcs, event);192 193	switch (event) {194	case RPSM_EVENT_PLOGI_SEND:195		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);196		rport->plogi_retries = 0;197		bfa_fcs_rport_send_plogi(rport, NULL);198		break;199 200	case RPSM_EVENT_PLOGI_RCVD:201		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);202		bfa_fcs_rport_send_plogiacc(rport, NULL);203		break;204 205	case RPSM_EVENT_PLOGI_COMP:206		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);207		bfa_fcs_rport_hal_online(rport);208		break;209 210	case RPSM_EVENT_ADDRESS_CHANGE:211	case RPSM_EVENT_ADDRESS_DISC:212		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);213		rport->ns_retries = 0;214		bfa_fcs_rport_send_nsdisc(rport, NULL);215		break;216	default:217		bfa_sm_fault(rport->fcs, event);218	}219}220 221/*222 *		PLOGI is being sent.223 */224static void225bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,226	 enum rport_event event)227{228	bfa_trc(rport->fcs, rport->pwwn);229	bfa_trc(rport->fcs, rport->pid);230	bfa_trc(rport->fcs, event);231 232	switch (event) {233	case RPSM_EVENT_FCXP_SENT:234		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);235		break;236 237	case RPSM_EVENT_DELETE:238		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);239		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);240		bfa_fcs_rport_free(rport);241		break;242 243	case RPSM_EVENT_PLOGI_RCVD:244		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);245		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);246		bfa_fcs_rport_send_plogiacc(rport, NULL);247		break;248 249	case RPSM_EVENT_SCN_OFFLINE:250		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);251		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);252		bfa_timer_start(rport->fcs->bfa, &rport->timer,253				bfa_fcs_rport_timeout, rport,254				bfa_fcs_rport_del_timeout);255		break;256	case RPSM_EVENT_ADDRESS_CHANGE:257	case RPSM_EVENT_FAB_SCN:258		/* query the NS */259		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);260		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=261					BFA_PORT_TOPOLOGY_LOOP));262		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);263		rport->ns_retries = 0;264		bfa_fcs_rport_send_nsdisc(rport, NULL);265		break;266 267	case RPSM_EVENT_LOGO_IMP:268		rport->pid = 0;269		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);270		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);271		bfa_timer_start(rport->fcs->bfa, &rport->timer,272				bfa_fcs_rport_timeout, rport,273				bfa_fcs_rport_del_timeout);274		break;275 276 277	default:278		bfa_sm_fault(rport->fcs, event);279	}280}281 282/*283 *		PLOGI is being sent.284 */285static void286bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,287	 enum rport_event event)288{289	bfa_trc(rport->fcs, rport->pwwn);290	bfa_trc(rport->fcs, rport->pid);291	bfa_trc(rport->fcs, event);292 293	switch (event) {294	case RPSM_EVENT_FCXP_SENT:295		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);296		bfa_fcs_rport_fcs_online_action(rport);297		break;298 299	case RPSM_EVENT_DELETE:300		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);301		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);302		bfa_fcs_rport_free(rport);303		break;304 305	case RPSM_EVENT_PLOGI_RCVD:306	case RPSM_EVENT_PLOGI_COMP:307	case RPSM_EVENT_FAB_SCN:308		/*309		 * Ignore, SCN is possibly online notification.310		 */311		break;312 313	case RPSM_EVENT_SCN_OFFLINE: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_ADDRESS_CHANGE:322		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);323		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);324		rport->ns_retries = 0;325		bfa_fcs_rport_send_nsdisc(rport, NULL);326		break;327 328	case RPSM_EVENT_LOGO_IMP:329		rport->pid = 0;330		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);331		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);332		bfa_timer_start(rport->fcs->bfa, &rport->timer,333				bfa_fcs_rport_timeout, rport,334				bfa_fcs_rport_del_timeout);335		break;336 337	case RPSM_EVENT_HCB_OFFLINE:338		/*339		 * Ignore BFA callback, on a PLOGI receive we call bfa offline.340		 */341		break;342 343	default:344		bfa_sm_fault(rport->fcs, event);345	}346}347 348/*349 *		PLOGI is sent.350 */351static void352bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,353			enum rport_event event)354{355	bfa_trc(rport->fcs, rport->pwwn);356	bfa_trc(rport->fcs, rport->pid);357	bfa_trc(rport->fcs, event);358 359	switch (event) {360	case RPSM_EVENT_TIMEOUT:361		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);362		bfa_fcs_rport_send_plogi(rport, NULL);363		break;364 365	case RPSM_EVENT_DELETE:366		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);367		bfa_timer_stop(&rport->timer);368		bfa_fcs_rport_free(rport);369		break;370 371	case RPSM_EVENT_PRLO_RCVD:372	case RPSM_EVENT_LOGO_RCVD:373		break;374 375	case RPSM_EVENT_PLOGI_RCVD:376		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);377		bfa_timer_stop(&rport->timer);378		bfa_fcs_rport_send_plogiacc(rport, NULL);379		break;380 381	case RPSM_EVENT_SCN_OFFLINE:382		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);383		bfa_timer_stop(&rport->timer);384		bfa_timer_start(rport->fcs->bfa, &rport->timer,385				bfa_fcs_rport_timeout, rport,386				bfa_fcs_rport_del_timeout);387		break;388 389	case RPSM_EVENT_ADDRESS_CHANGE:390	case RPSM_EVENT_FAB_SCN:391		bfa_timer_stop(&rport->timer);392		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=393					BFA_PORT_TOPOLOGY_LOOP));394		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);395		rport->ns_retries = 0;396		bfa_fcs_rport_send_nsdisc(rport, NULL);397		break;398 399	case RPSM_EVENT_LOGO_IMP:400		rport->pid = 0;401		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);402		bfa_timer_stop(&rport->timer);403		bfa_timer_start(rport->fcs->bfa, &rport->timer,404				bfa_fcs_rport_timeout, rport,405				bfa_fcs_rport_del_timeout);406		break;407 408	case RPSM_EVENT_PLOGI_COMP:409		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);410		bfa_timer_stop(&rport->timer);411		bfa_fcs_rport_fcs_online_action(rport);412		break;413 414	default:415		bfa_sm_fault(rport->fcs, event);416	}417}418 419/*420 *		PLOGI is sent.421 */422static void423bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)424{425	bfa_trc(rport->fcs, rport->pwwn);426	bfa_trc(rport->fcs, rport->pid);427	bfa_trc(rport->fcs, event);428 429	switch (event) {430	case RPSM_EVENT_ACCEPTED:431		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);432		rport->plogi_retries = 0;433		bfa_fcs_rport_fcs_online_action(rport);434		break;435 436	case RPSM_EVENT_LOGO_RCVD:437		bfa_fcs_rport_send_logo_acc(rport);438		fallthrough;439	case RPSM_EVENT_PRLO_RCVD:440		if (rport->prlo == BFA_TRUE)441			bfa_fcs_rport_send_prlo_acc(rport);442 443		bfa_fcxp_discard(rport->fcxp);444		fallthrough;445	case RPSM_EVENT_FAILED:446		if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {447			rport->plogi_retries++;448			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);449			bfa_timer_start(rport->fcs->bfa, &rport->timer,450					bfa_fcs_rport_timeout, rport,451					BFA_FCS_RETRY_TIMEOUT);452		} else {453			bfa_stats(rport->port, rport_del_max_plogi_retry);454			rport->old_pid = rport->pid;455			rport->pid = 0;456			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);457			bfa_timer_start(rport->fcs->bfa, &rport->timer,458					bfa_fcs_rport_timeout, rport,459					bfa_fcs_rport_del_timeout);460		}461		break;462 463	case RPSM_EVENT_SCN_ONLINE:464		break;465 466	case RPSM_EVENT_SCN_OFFLINE:467		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);468		bfa_fcxp_discard(rport->fcxp);469		bfa_timer_start(rport->fcs->bfa, &rport->timer,470				bfa_fcs_rport_timeout, rport,471				bfa_fcs_rport_del_timeout);472		break;473 474	case RPSM_EVENT_PLOGI_RETRY:475		rport->plogi_retries = 0;476		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);477		bfa_timer_start(rport->fcs->bfa, &rport->timer,478				bfa_fcs_rport_timeout, rport,479				(FC_RA_TOV * 1000));480		break;481 482	case RPSM_EVENT_LOGO_IMP:483		rport->pid = 0;484		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);485		bfa_fcxp_discard(rport->fcxp);486		bfa_timer_start(rport->fcs->bfa, &rport->timer,487				bfa_fcs_rport_timeout, rport,488				bfa_fcs_rport_del_timeout);489		break;490 491	case RPSM_EVENT_ADDRESS_CHANGE:492	case RPSM_EVENT_FAB_SCN:493		bfa_fcxp_discard(rport->fcxp);494		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=495					BFA_PORT_TOPOLOGY_LOOP));496		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);497		rport->ns_retries = 0;498		bfa_fcs_rport_send_nsdisc(rport, NULL);499		break;500 501	case RPSM_EVENT_PLOGI_RCVD:502		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);503		bfa_fcxp_discard(rport->fcxp);504		bfa_fcs_rport_send_plogiacc(rport, NULL);505		break;506 507	case RPSM_EVENT_DELETE:508		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);509		bfa_fcxp_discard(rport->fcxp);510		bfa_fcs_rport_free(rport);511		break;512 513	case RPSM_EVENT_PLOGI_COMP:514		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);515		bfa_fcxp_discard(rport->fcxp);516		bfa_fcs_rport_fcs_online_action(rport);517		break;518 519	default:520		bfa_sm_fault(rport->fcs, event);521	}522}523 524/*525 * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function526 */527static void528bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,529				enum rport_event event)530{531	bfa_trc(rport->fcs, rport->pwwn);532	bfa_trc(rport->fcs, rport->pid);533	bfa_trc(rport->fcs, event);534 535	switch (event) {536	case RPSM_EVENT_FC4_FCS_ONLINE:537		if (rport->scsi_function == BFA_RPORT_INITIATOR) {538			if (!BFA_FCS_PID_IS_WKA(rport->pid))539				bfa_fcs_rpf_rport_online(rport);540			bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);541			break;542		}543 544		if (!rport->bfa_rport)545			rport->bfa_rport =546				bfa_rport_create(rport->fcs->bfa, rport);547 548		if (rport->bfa_rport) {549			bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);550			bfa_fcs_rport_hal_online(rport);551		} else {552			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);553			bfa_fcs_rport_fcs_offline_action(rport);554		}555		break;556 557	case RPSM_EVENT_PLOGI_RCVD:558		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);559		rport->plogi_pending = BFA_TRUE;560		bfa_fcs_rport_fcs_offline_action(rport);561		break;562 563	case RPSM_EVENT_PLOGI_COMP:564	case RPSM_EVENT_LOGO_IMP:565	case RPSM_EVENT_ADDRESS_CHANGE:566	case RPSM_EVENT_FAB_SCN:567	case RPSM_EVENT_SCN_OFFLINE:568		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);569		bfa_fcs_rport_fcs_offline_action(rport);570		break;571 572	case RPSM_EVENT_LOGO_RCVD:573	case RPSM_EVENT_PRLO_RCVD:574		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);575		bfa_fcs_rport_fcs_offline_action(rport);576		break;577 578	case RPSM_EVENT_DELETE:579		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);580		bfa_fcs_rport_fcs_offline_action(rport);581		break;582 583	default:584		bfa_sm_fault(rport->fcs, event);585		break;586	}587}588 589/*590 *		PLOGI is complete. Awaiting BFA rport online callback. FC-4s591 *		are offline.592 */593static void594bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,595			enum rport_event event)596{597	bfa_trc(rport->fcs, rport->pwwn);598	bfa_trc(rport->fcs, rport->pid);599	bfa_trc(rport->fcs, event);600 601	switch (event) {602	case RPSM_EVENT_HCB_ONLINE:603		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);604		bfa_fcs_rport_hal_online_action(rport);605		break;606 607	case RPSM_EVENT_PLOGI_COMP:608		break;609 610	case RPSM_EVENT_PRLO_RCVD:611	case RPSM_EVENT_LOGO_RCVD:612		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);613		bfa_fcs_rport_fcs_offline_action(rport);614		break;615 616	case RPSM_EVENT_FAB_SCN:617	case RPSM_EVENT_LOGO_IMP:618	case RPSM_EVENT_ADDRESS_CHANGE:619	case RPSM_EVENT_SCN_OFFLINE:620		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);621		bfa_fcs_rport_fcs_offline_action(rport);622		break;623 624	case RPSM_EVENT_PLOGI_RCVD:625		rport->plogi_pending = BFA_TRUE;626		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);627		bfa_fcs_rport_fcs_offline_action(rport);628		break;629 630	case RPSM_EVENT_DELETE:631		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);632		bfa_fcs_rport_fcs_offline_action(rport);633		break;634 635	default:636		bfa_sm_fault(rport->fcs, event);637	}638}639 640/*641 *		Rport is ONLINE. FC-4s active.642 */643static void644bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)645{646	bfa_trc(rport->fcs, rport->pwwn);647	bfa_trc(rport->fcs, rport->pid);648	bfa_trc(rport->fcs, event);649 650	switch (event) {651	case RPSM_EVENT_FAB_SCN:652		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {653			bfa_sm_set_state(rport,654					 bfa_fcs_rport_sm_nsquery_sending);655			rport->ns_retries = 0;656			bfa_fcs_rport_send_nsdisc(rport, NULL);657		} else {658			bfa_sm_set_state(rport,659				bfa_fcs_rport_sm_adisc_online_sending);660			bfa_fcs_rport_send_adisc(rport, NULL);661		}662		break;663 664	case RPSM_EVENT_PLOGI_RCVD:665	case RPSM_EVENT_LOGO_IMP:666	case RPSM_EVENT_ADDRESS_CHANGE:667	case RPSM_EVENT_SCN_OFFLINE:668		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);669		bfa_fcs_rport_hal_offline_action(rport);670		break;671 672	case RPSM_EVENT_DELETE:673		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);674		bfa_fcs_rport_hal_offline_action(rport);675		break;676 677	case RPSM_EVENT_LOGO_RCVD:678	case RPSM_EVENT_PRLO_RCVD:679		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);680		bfa_fcs_rport_hal_offline_action(rport);681		break;682 683	case RPSM_EVENT_SCN_ONLINE:684	case RPSM_EVENT_PLOGI_COMP:685		break;686 687	default:688		bfa_sm_fault(rport->fcs, event);689	}690}691 692/*693 *		An SCN event is received in ONLINE state. NS query is being sent694 *		prior to ADISC authentication with rport. FC-4s are paused.695 */696static void697bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,698	 enum rport_event event)699{700	bfa_trc(rport->fcs, rport->pwwn);701	bfa_trc(rport->fcs, rport->pid);702	bfa_trc(rport->fcs, event);703 704	switch (event) {705	case RPSM_EVENT_FCXP_SENT:706		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);707		break;708 709	case RPSM_EVENT_DELETE:710		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);711		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);712		bfa_fcs_rport_hal_offline_action(rport);713		break;714 715	case RPSM_EVENT_FAB_SCN:716		/*717		 * ignore SCN, wait for response to query itself718		 */719		break;720 721	case RPSM_EVENT_LOGO_RCVD:722	case RPSM_EVENT_PRLO_RCVD:723		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);724		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);725		bfa_fcs_rport_hal_offline_action(rport);726		break;727 728	case RPSM_EVENT_LOGO_IMP:729	case RPSM_EVENT_PLOGI_RCVD:730	case RPSM_EVENT_ADDRESS_CHANGE:731	case RPSM_EVENT_PLOGI_COMP:732		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);733		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);734		bfa_fcs_rport_hal_offline_action(rport);735		break;736 737	default:738		bfa_sm_fault(rport->fcs, event);739	}740}741 742/*743 *	An SCN event is received in ONLINE state. NS query is sent to rport.744 *	FC-4s are paused.745 */746static void747bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)748{749	bfa_trc(rport->fcs, rport->pwwn);750	bfa_trc(rport->fcs, rport->pid);751	bfa_trc(rport->fcs, event);752 753	switch (event) {754	case RPSM_EVENT_ACCEPTED:755		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);756		bfa_fcs_rport_send_adisc(rport, NULL);757		break;758 759	case RPSM_EVENT_FAILED:760		rport->ns_retries++;761		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {762			bfa_sm_set_state(rport,763					 bfa_fcs_rport_sm_nsquery_sending);764			bfa_fcs_rport_send_nsdisc(rport, NULL);765		} else {766			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);767			bfa_fcs_rport_hal_offline_action(rport);768		}769		break;770 771	case RPSM_EVENT_DELETE:772		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);773		bfa_fcxp_discard(rport->fcxp);774		bfa_fcs_rport_hal_offline_action(rport);775		break;776 777	case RPSM_EVENT_FAB_SCN:778		break;779 780	case RPSM_EVENT_LOGO_RCVD:781	case RPSM_EVENT_PRLO_RCVD:782		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);783		bfa_fcxp_discard(rport->fcxp);784		bfa_fcs_rport_hal_offline_action(rport);785		break;786 787	case RPSM_EVENT_PLOGI_COMP:788	case RPSM_EVENT_ADDRESS_CHANGE:789	case RPSM_EVENT_PLOGI_RCVD:790	case RPSM_EVENT_LOGO_IMP:791		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);792		bfa_fcxp_discard(rport->fcxp);793		bfa_fcs_rport_hal_offline_action(rport);794		break;795 796	default:797		bfa_sm_fault(rport->fcs, event);798	}799}800 801/*802 *	An SCN event is received in ONLINE state. ADISC is being sent for803 *	authenticating with rport. FC-4s are paused.804 */805static void806bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,807	 enum rport_event event)808{809	bfa_trc(rport->fcs, rport->pwwn);810	bfa_trc(rport->fcs, rport->pid);811	bfa_trc(rport->fcs, event);812 813	switch (event) {814	case RPSM_EVENT_FCXP_SENT:815		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);816		break;817 818	case RPSM_EVENT_DELETE:819		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);820		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);821		bfa_fcs_rport_hal_offline_action(rport);822		break;823 824	case RPSM_EVENT_LOGO_IMP:825	case RPSM_EVENT_ADDRESS_CHANGE: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	case RPSM_EVENT_LOGO_RCVD:832	case RPSM_EVENT_PRLO_RCVD:833		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);834		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);835		bfa_fcs_rport_hal_offline_action(rport);836		break;837 838	case RPSM_EVENT_FAB_SCN:839		break;840 841	case RPSM_EVENT_PLOGI_RCVD:842		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);843		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);844		bfa_fcs_rport_hal_offline_action(rport);845		break;846 847	default:848		bfa_sm_fault(rport->fcs, event);849	}850}851 852/*853 *		An SCN event is received in ONLINE state. ADISC is to rport.854 *		FC-4s are paused.855 */856static void857bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,858				enum rport_event event)859{860	bfa_trc(rport->fcs, rport->pwwn);861	bfa_trc(rport->fcs, rport->pid);862	bfa_trc(rport->fcs, event);863 864	switch (event) {865	case RPSM_EVENT_ACCEPTED:866		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);867		break;868 869	case RPSM_EVENT_PLOGI_RCVD:870		/*871		 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.872		 * At least go offline when a PLOGI is received.873		 */874		bfa_fcxp_discard(rport->fcxp);875		fallthrough;876 877	case RPSM_EVENT_FAILED:878	case RPSM_EVENT_ADDRESS_CHANGE:879		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);880		bfa_fcs_rport_hal_offline_action(rport);881		break;882 883	case RPSM_EVENT_DELETE:884		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);885		bfa_fcxp_discard(rport->fcxp);886		bfa_fcs_rport_hal_offline_action(rport);887		break;888 889	case RPSM_EVENT_FAB_SCN:890		/*891		 * already processing RSCN892		 */893		break;894 895	case RPSM_EVENT_LOGO_IMP:896		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);897		bfa_fcxp_discard(rport->fcxp);898		bfa_fcs_rport_hal_offline_action(rport);899		break;900 901	case RPSM_EVENT_LOGO_RCVD:902	case RPSM_EVENT_PRLO_RCVD:903		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);904		bfa_fcxp_discard(rport->fcxp);905		bfa_fcs_rport_hal_offline_action(rport);906		break;907 908	default:909		bfa_sm_fault(rport->fcs, event);910	}911}912 913/*914 * ADISC is being sent for authenticating with rport915 * Already did offline actions.916 */917static void918bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,919	enum rport_event event)920{921	bfa_trc(rport->fcs, rport->pwwn);922	bfa_trc(rport->fcs, rport->pid);923	bfa_trc(rport->fcs, event);924 925	switch (event) {926	case RPSM_EVENT_FCXP_SENT:927		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);928		break;929 930	case RPSM_EVENT_DELETE:931	case RPSM_EVENT_SCN_OFFLINE:932	case RPSM_EVENT_LOGO_IMP:933	case RPSM_EVENT_LOGO_RCVD:934	case RPSM_EVENT_PRLO_RCVD:935		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);936		bfa_fcxp_walloc_cancel(rport->fcs->bfa,937			&rport->fcxp_wqe);938		bfa_timer_start(rport->fcs->bfa, &rport->timer,939			bfa_fcs_rport_timeout, rport,940			bfa_fcs_rport_del_timeout);941		break;942 943	case RPSM_EVENT_PLOGI_RCVD:944		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);945		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);946		bfa_fcs_rport_send_plogiacc(rport, NULL);947		break;948 949	default:950		bfa_sm_fault(rport->fcs, event);951	}952}953 954/*955 * ADISC to rport956 * Already did offline actions957 */958static void959bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,960			enum rport_event event)961{962	bfa_trc(rport->fcs, rport->pwwn);963	bfa_trc(rport->fcs, rport->pid);964	bfa_trc(rport->fcs, event);965 966	switch (event) {967	case RPSM_EVENT_ACCEPTED:968		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);969		bfa_fcs_rport_hal_online(rport);970		break;971 972	case RPSM_EVENT_PLOGI_RCVD:973		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);974		bfa_fcxp_discard(rport->fcxp);975		bfa_fcs_rport_send_plogiacc(rport, NULL);976		break;977 978	case RPSM_EVENT_FAILED:979		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);980		bfa_timer_start(rport->fcs->bfa, &rport->timer,981			bfa_fcs_rport_timeout, rport,982			bfa_fcs_rport_del_timeout);983		break;984 985	case RPSM_EVENT_DELETE:986	case RPSM_EVENT_SCN_OFFLINE:987	case RPSM_EVENT_LOGO_IMP:988	case RPSM_EVENT_LOGO_RCVD:989	case RPSM_EVENT_PRLO_RCVD:990		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);991		bfa_fcxp_discard(rport->fcxp);992		bfa_timer_start(rport->fcs->bfa, &rport->timer,993			bfa_fcs_rport_timeout, rport,994			bfa_fcs_rport_del_timeout);995		break;996 997	default:998		bfa_sm_fault(rport->fcs, event);999	}1000}1001 1002/*1003 * Rport has sent LOGO. Awaiting FC-4 offline completion callback.1004 */1005static void1006bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,1007			enum rport_event event)1008{1009	bfa_trc(rport->fcs, rport->pwwn);1010	bfa_trc(rport->fcs, rport->pid);1011	bfa_trc(rport->fcs, event);1012 1013	switch (event) {1014	case RPSM_EVENT_FC4_OFFLINE:1015		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);1016		bfa_fcs_rport_hal_offline(rport);1017		break;1018 1019	case RPSM_EVENT_DELETE:1020		if (rport->pid && (rport->prlo == BFA_TRUE))1021			bfa_fcs_rport_send_prlo_acc(rport);1022		if (rport->pid && (rport->prlo == BFA_FALSE))1023			bfa_fcs_rport_send_logo_acc(rport);1024 1025		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);1026		break;1027 1028	case RPSM_EVENT_SCN_ONLINE:1029	case RPSM_EVENT_SCN_OFFLINE:1030	case RPSM_EVENT_HCB_ONLINE:1031	case RPSM_EVENT_LOGO_RCVD:1032	case RPSM_EVENT_PRLO_RCVD:1033	case RPSM_EVENT_ADDRESS_CHANGE:1034		break;1035 1036	default:1037		bfa_sm_fault(rport->fcs, event);1038	}1039}1040 1041/*1042 *		LOGO needs to be sent to rport. Awaiting FC-4 offline completion1043 *		callback.1044 */1045static void1046bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,1047	 enum rport_event event)1048{1049	bfa_trc(rport->fcs, rport->pwwn);1050	bfa_trc(rport->fcs, rport->pid);1051	bfa_trc(rport->fcs, event);1052 1053	switch (event) {1054	case RPSM_EVENT_FC4_OFFLINE:1055		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);1056		bfa_fcs_rport_hal_offline(rport);1057		break;1058 1059	case RPSM_EVENT_LOGO_RCVD:1060		bfa_fcs_rport_send_logo_acc(rport);1061		fallthrough;1062	case RPSM_EVENT_PRLO_RCVD:1063		if (rport->prlo == BFA_TRUE)1064			bfa_fcs_rport_send_prlo_acc(rport);1065		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);1066		break;1067 1068	case RPSM_EVENT_HCB_ONLINE:1069	case RPSM_EVENT_DELETE:1070		/* Rport is being deleted */1071		break;1072 1073	default:1074		bfa_sm_fault(rport->fcs, event);1075	}1076}1077 1078/*1079 *	Rport is going offline. Awaiting FC-4 offline completion callback.1080 */1081static void1082bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,1083			enum rport_event event)1084{1085	bfa_trc(rport->fcs, rport->pwwn);1086	bfa_trc(rport->fcs, rport->pid);1087	bfa_trc(rport->fcs, event);1088 1089	switch (event) {1090	case RPSM_EVENT_FC4_OFFLINE:1091		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);1092		bfa_fcs_rport_hal_offline(rport);1093		break;1094 1095	case RPSM_EVENT_SCN_ONLINE:1096		break;1097	case RPSM_EVENT_LOGO_RCVD:1098		/*1099		 * Rport is going offline. Just ack the logo1100		 */1101		bfa_fcs_rport_send_logo_acc(rport);1102		break;1103 1104	case RPSM_EVENT_PRLO_RCVD:1105		bfa_fcs_rport_send_prlo_acc(rport);1106		break;1107 1108	case RPSM_EVENT_SCN_OFFLINE:1109	case RPSM_EVENT_HCB_ONLINE:1110	case RPSM_EVENT_FAB_SCN:1111	case RPSM_EVENT_LOGO_IMP:1112	case RPSM_EVENT_ADDRESS_CHANGE:1113		/*1114		 * rport is already going offline.1115		 * SCN - ignore and wait till transitioning to offline state1116		 */1117		break;1118 1119	case RPSM_EVENT_DELETE:1120		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);1121		break;1122 1123	default:1124		bfa_sm_fault(rport->fcs, event);1125	}1126}1127 1128/*1129 *		Rport is offline. FC-4s are offline. Awaiting BFA rport offline1130 *		callback.1131 */1132static void1133bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,1134				enum rport_event event)1135{1136	bfa_trc(rport->fcs, rport->pwwn);1137	bfa_trc(rport->fcs, rport->pid);1138	bfa_trc(rport->fcs, event);1139 1140	switch (event) {1141	case RPSM_EVENT_HCB_OFFLINE:1142		if (bfa_fcs_lport_is_online(rport->port) &&1143		    (rport->plogi_pending)) {1144			rport->plogi_pending = BFA_FALSE;1145			bfa_sm_set_state(rport,1146				bfa_fcs_rport_sm_plogiacc_sending);1147			bfa_fcs_rport_send_plogiacc(rport, NULL);1148			break;1149		}1150		fallthrough;1151 1152	case RPSM_EVENT_ADDRESS_CHANGE:1153		if (!bfa_fcs_lport_is_online(rport->port)) {1154			rport->pid = 0;1155			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1156			bfa_timer_start(rport->fcs->bfa, &rport->timer,1157					bfa_fcs_rport_timeout, rport,1158					bfa_fcs_rport_del_timeout);1159			break;1160		}1161		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {1162			bfa_sm_set_state(rport,1163				bfa_fcs_rport_sm_nsdisc_sending);1164			rport->ns_retries = 0;1165			bfa_fcs_rport_send_nsdisc(rport, NULL);1166		} else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==1167					BFA_PORT_TOPOLOGY_LOOP) {1168			if (rport->scn_online) {1169				bfa_sm_set_state(rport,1170					bfa_fcs_rport_sm_adisc_offline_sending);1171				bfa_fcs_rport_send_adisc(rport, NULL);1172			} else {1173				bfa_sm_set_state(rport,1174					bfa_fcs_rport_sm_offline);1175				bfa_timer_start(rport->fcs->bfa, &rport->timer,1176					bfa_fcs_rport_timeout, rport,1177					bfa_fcs_rport_del_timeout);1178			}1179		} else {1180			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1181			rport->plogi_retries = 0;1182			bfa_fcs_rport_send_plogi(rport, NULL);1183		}1184		break;1185 1186	case RPSM_EVENT_DELETE:1187		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1188		bfa_fcs_rport_free(rport);1189		break;1190 1191	case RPSM_EVENT_SCN_ONLINE:1192	case RPSM_EVENT_SCN_OFFLINE:1193	case RPSM_EVENT_FAB_SCN:1194	case RPSM_EVENT_LOGO_RCVD:1195	case RPSM_EVENT_PRLO_RCVD:1196	case RPSM_EVENT_PLOGI_RCVD:1197	case RPSM_EVENT_LOGO_IMP:1198		/*1199		 * Ignore, already offline.1200		 */1201		break;1202 1203	default:1204		bfa_sm_fault(rport->fcs, event);1205	}1206}1207 1208/*1209 *		Rport is offline. FC-4s are offline. Awaiting BFA rport offline1210 *		callback to send LOGO accept.1211 */1212static void1213bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,1214			enum rport_event event)1215{1216	bfa_trc(rport->fcs, rport->pwwn);1217	bfa_trc(rport->fcs, rport->pid);1218	bfa_trc(rport->fcs, event);1219 1220	switch (event) {1221	case RPSM_EVENT_HCB_OFFLINE:1222	case RPSM_EVENT_ADDRESS_CHANGE:1223		if (rport->pid && (rport->prlo == BFA_TRUE))1224			bfa_fcs_rport_send_prlo_acc(rport);1225		if (rport->pid && (rport->prlo == BFA_FALSE))1226			bfa_fcs_rport_send_logo_acc(rport);1227		/*1228		 * If the lport is online and if the rport is not a well1229		 * known address port,1230		 * we try to re-discover the r-port.1231		 */1232		if (bfa_fcs_lport_is_online(rport->port) &&1233			(!BFA_FCS_PID_IS_WKA(rport->pid))) {1234			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {1235				bfa_sm_set_state(rport,1236					bfa_fcs_rport_sm_nsdisc_sending);1237				rport->ns_retries = 0;1238				bfa_fcs_rport_send_nsdisc(rport, NULL);1239			} else {1240				/* For N2N  Direct Attach, try to re-login */1241				bfa_sm_set_state(rport,1242					bfa_fcs_rport_sm_plogi_sending);1243				rport->plogi_retries = 0;1244				bfa_fcs_rport_send_plogi(rport, NULL);1245			}1246		} else {1247			/*1248			 * if it is not a well known address, reset the1249			 * pid to 0.1250			 */1251			if (!BFA_FCS_PID_IS_WKA(rport->pid))1252				rport->pid = 0;1253			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1254			bfa_timer_start(rport->fcs->bfa, &rport->timer,1255					bfa_fcs_rport_timeout, rport,1256					bfa_fcs_rport_del_timeout);1257		}1258		break;1259 1260	case RPSM_EVENT_DELETE:1261		bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);1262		if (rport->pid && (rport->prlo == BFA_TRUE))1263			bfa_fcs_rport_send_prlo_acc(rport);1264		if (rport->pid && (rport->prlo == BFA_FALSE))1265			bfa_fcs_rport_send_logo_acc(rport);1266		break;1267 1268	case RPSM_EVENT_LOGO_IMP:1269		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);1270		break;1271 1272	case RPSM_EVENT_SCN_ONLINE:1273	case RPSM_EVENT_SCN_OFFLINE:1274	case RPSM_EVENT_LOGO_RCVD:1275	case RPSM_EVENT_PRLO_RCVD:1276		/*1277		 * Ignore - already processing a LOGO.1278		 */1279		break;1280 1281	default:1282		bfa_sm_fault(rport->fcs, event);1283	}1284}1285 1286/*1287 *		Rport is being deleted. FC-4s are offline.1288 *  Awaiting BFA rport offline1289 *		callback to send LOGO.1290 */1291static void1292bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,1293		 enum rport_event event)1294{1295	bfa_trc(rport->fcs, rport->pwwn);1296	bfa_trc(rport->fcs, rport->pid);1297	bfa_trc(rport->fcs, event);1298 1299	switch (event) {1300	case RPSM_EVENT_HCB_OFFLINE:1301		bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);1302		bfa_fcs_rport_send_logo(rport, NULL);1303		break;1304 1305	case RPSM_EVENT_LOGO_RCVD:1306		bfa_fcs_rport_send_logo_acc(rport);1307		fallthrough;1308	case RPSM_EVENT_PRLO_RCVD:1309		if (rport->prlo == BFA_TRUE)1310			bfa_fcs_rport_send_prlo_acc(rport);1311 1312		bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);1313		break;1314 1315	case RPSM_EVENT_SCN_ONLINE:1316	case RPSM_EVENT_SCN_OFFLINE:1317	case RPSM_EVENT_ADDRESS_CHANGE:1318		break;1319 1320	default:1321		bfa_sm_fault(rport->fcs, event);1322	}1323}1324 1325/*1326 *		Rport is being deleted. FC-4s are offline. LOGO is being sent.1327 */1328static void1329bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,1330	 enum rport_event event)1331{1332	bfa_trc(rport->fcs, rport->pwwn);1333	bfa_trc(rport->fcs, rport->pid);1334	bfa_trc(rport->fcs, event);1335 1336	switch (event) {1337	case RPSM_EVENT_FCXP_SENT:1338		/* Once LOGO is sent, we donot wait for the response */1339		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1340		bfa_fcs_rport_free(rport);1341		break;1342 1343	case RPSM_EVENT_SCN_ONLINE:1344	case RPSM_EVENT_SCN_OFFLINE:1345	case RPSM_EVENT_FAB_SCN:1346	case RPSM_EVENT_ADDRESS_CHANGE:1347		break;1348 1349	case RPSM_EVENT_LOGO_RCVD:1350		bfa_fcs_rport_send_logo_acc(rport);1351		fallthrough;1352	case RPSM_EVENT_PRLO_RCVD:1353		if (rport->prlo == BFA_TRUE)1354			bfa_fcs_rport_send_prlo_acc(rport);1355 1356		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1357		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1358		bfa_fcs_rport_free(rport);1359		break;1360 1361	default:1362		bfa_sm_fault(rport->fcs, event);1363	}1364}1365 1366/*1367 *		Rport is offline. FC-4s are offline. BFA rport is offline.1368 *		Timer active to delete stale rport.1369 */1370static void1371bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)1372{1373	bfa_trc(rport->fcs, rport->pwwn);1374	bfa_trc(rport->fcs, rport->pid);1375	bfa_trc(rport->fcs, event);1376 1377	switch (event) {1378	case RPSM_EVENT_TIMEOUT:1379		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1380		bfa_fcs_rport_free(rport);1381		break;1382 1383	case RPSM_EVENT_FAB_SCN:1384	case RPSM_EVENT_ADDRESS_CHANGE:1385		bfa_timer_stop(&rport->timer);1386		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=1387					BFA_PORT_TOPOLOGY_LOOP));1388		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);1389		rport->ns_retries = 0;1390		bfa_fcs_rport_send_nsdisc(rport, NULL);1391		break;1392 1393	case RPSM_EVENT_DELETE:1394		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1395		bfa_timer_stop(&rport->timer);1396		bfa_fcs_rport_free(rport);1397		break;1398 1399	case RPSM_EVENT_PLOGI_RCVD:1400		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1401		bfa_timer_stop(&rport->timer);1402		bfa_fcs_rport_send_plogiacc(rport, NULL);1403		break;1404 1405	case RPSM_EVENT_LOGO_RCVD:1406	case RPSM_EVENT_PRLO_RCVD:1407	case RPSM_EVENT_LOGO_IMP:1408	case RPSM_EVENT_SCN_OFFLINE:1409		break;1410 1411	case RPSM_EVENT_PLOGI_COMP:1412		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1413		bfa_timer_stop(&rport->timer);1414		bfa_fcs_rport_fcs_online_action(rport);1415		break;1416 1417	case RPSM_EVENT_SCN_ONLINE:1418		bfa_timer_stop(&rport->timer);1419		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1420		bfa_fcs_rport_send_plogi(rport, NULL);1421		break;1422 1423	case RPSM_EVENT_PLOGI_SEND:1424		bfa_timer_stop(&rport->timer);1425		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1426		rport->plogi_retries = 0;1427		bfa_fcs_rport_send_plogi(rport, NULL);1428		break;1429 1430	default:1431		bfa_sm_fault(rport->fcs, event);1432	}1433}1434 1435/*1436 *	Rport address has changed. Nameserver discovery request is being sent.1437 */1438static void1439bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,1440	 enum rport_event event)1441{1442	bfa_trc(rport->fcs, rport->pwwn);1443	bfa_trc(rport->fcs, rport->pid);1444	bfa_trc(rport->fcs, event);1445 1446	switch (event) {1447	case RPSM_EVENT_FCXP_SENT:1448		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);1449		break;1450 1451	case RPSM_EVENT_DELETE:1452		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1453		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1454		bfa_fcs_rport_free(rport);1455		break;1456 1457	case RPSM_EVENT_PLOGI_RCVD:1458		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1459		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1460		bfa_fcs_rport_send_plogiacc(rport, NULL);1461		break;1462 1463	case RPSM_EVENT_FAB_SCN:1464	case RPSM_EVENT_LOGO_RCVD:1465	case RPSM_EVENT_PRLO_RCVD:1466	case RPSM_EVENT_PLOGI_SEND:1467		break;1468 1469	case RPSM_EVENT_ADDRESS_CHANGE:1470		rport->ns_retries = 0; /* reset the retry count */1471		break;1472 1473	case RPSM_EVENT_LOGO_IMP:1474		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1475		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1476		bfa_timer_start(rport->fcs->bfa, &rport->timer,1477				bfa_fcs_rport_timeout, rport,1478				bfa_fcs_rport_del_timeout);1479		break;1480 1481	case RPSM_EVENT_PLOGI_COMP:1482		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1483		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1484		bfa_fcs_rport_fcs_online_action(rport);1485		break;1486 1487	default:1488		bfa_sm_fault(rport->fcs, event);1489	}1490}1491 1492/*1493 *		Nameserver discovery failed. Waiting for timeout to retry.1494 */1495static void1496bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,1497	 enum rport_event event)1498{1499	bfa_trc(rport->fcs, rport->pwwn);1500	bfa_trc(rport->fcs, rport->pid);1501	bfa_trc(rport->fcs, event);1502 1503	switch (event) {1504	case RPSM_EVENT_TIMEOUT:1505		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);1506		bfa_fcs_rport_send_nsdisc(rport, NULL);1507		break;1508 1509	case RPSM_EVENT_FAB_SCN:1510	case RPSM_EVENT_ADDRESS_CHANGE:1511		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);1512		bfa_timer_stop(&rport->timer);1513		rport->ns_retries = 0;1514		bfa_fcs_rport_send_nsdisc(rport, NULL);1515		break;1516 1517	case RPSM_EVENT_DELETE:1518		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1519		bfa_timer_stop(&rport->timer);1520		bfa_fcs_rport_free(rport);1521		break;1522 1523	case RPSM_EVENT_PLOGI_RCVD:1524		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1525		bfa_timer_stop(&rport->timer);1526		bfa_fcs_rport_send_plogiacc(rport, NULL);1527		break;1528 1529	case RPSM_EVENT_LOGO_IMP:1530		rport->pid = 0;1531		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1532		bfa_timer_stop(&rport->timer);1533		bfa_timer_start(rport->fcs->bfa, &rport->timer,1534				bfa_fcs_rport_timeout, rport,1535				bfa_fcs_rport_del_timeout);1536		break;1537 1538	case RPSM_EVENT_LOGO_RCVD:1539		bfa_fcs_rport_send_logo_acc(rport);1540		break;1541	case RPSM_EVENT_PRLO_RCVD:1542		bfa_fcs_rport_send_prlo_acc(rport);1543		break;1544 1545	case RPSM_EVENT_PLOGI_COMP:1546		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1547		bfa_timer_stop(&rport->timer);1548		bfa_fcs_rport_fcs_online_action(rport);1549		break;1550 1551	default:1552		bfa_sm_fault(rport->fcs, event);1553	}1554}1555 1556/*1557 *		Rport address has changed. Nameserver discovery request is sent.1558 */1559static void1560bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,1561			enum rport_event event)1562{1563	bfa_trc(rport->fcs, rport->pwwn);1564	bfa_trc(rport->fcs, rport->pid);1565	bfa_trc(rport->fcs, event);1566 1567	switch (event) {1568	case RPSM_EVENT_ACCEPTED:1569	case RPSM_EVENT_ADDRESS_CHANGE:1570		if (rport->pid) {1571			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1572			bfa_fcs_rport_send_plogi(rport, NULL);1573		} else {1574			bfa_sm_set_state(rport,1575				 bfa_fcs_rport_sm_nsdisc_sending);1576			rport->ns_retries = 0;1577			bfa_fcs_rport_send_nsdisc(rport, NULL);1578		}1579		break;1580 1581	case RPSM_EVENT_FAILED:1582		rport->ns_retries++;1583		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {1584			bfa_sm_set_state(rport,1585				 bfa_fcs_rport_sm_nsdisc_sending);1586			bfa_fcs_rport_send_nsdisc(rport, NULL);1587		} else {1588			rport->old_pid = rport->pid;1589			rport->pid = 0;1590			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1591			bfa_timer_start(rport->fcs->bfa, &rport->timer,1592					bfa_fcs_rport_timeout, rport,1593					bfa_fcs_rport_del_timeout);1594		}1595		break;1596 1597	case RPSM_EVENT_DELETE:1598		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1599		bfa_fcxp_discard(rport->fcxp);1600		bfa_fcs_rport_free(rport);1601		break;1602 1603	case RPSM_EVENT_PLOGI_RCVD:1604		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1605		bfa_fcxp_discard(rport->fcxp);1606		bfa_fcs_rport_send_plogiacc(rport, NULL);1607		break;1608 1609	case RPSM_EVENT_LOGO_IMP:1610		rport->pid = 0;1611		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1612		bfa_fcxp_discard(rport->fcxp);1613		bfa_timer_start(rport->fcs->bfa, &rport->timer,1614				bfa_fcs_rport_timeout, rport,1615				bfa_fcs_rport_del_timeout);1616		break;1617 1618 1619	case RPSM_EVENT_PRLO_RCVD:1620		bfa_fcs_rport_send_prlo_acc(rport);1621		break;1622	case RPSM_EVENT_FAB_SCN:1623		/*1624		 * ignore, wait for NS query response1625		 */1626		break;1627 1628	case RPSM_EVENT_LOGO_RCVD:1629		/*1630		 * Not logged-in yet. Accept LOGO.1631		 */1632		bfa_fcs_rport_send_logo_acc(rport);1633		break;1634 1635	case RPSM_EVENT_PLOGI_COMP:1636		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1637		bfa_fcxp_discard(rport->fcxp);1638		bfa_fcs_rport_fcs_online_action(rport);1639		break;1640 1641	default:1642		bfa_sm_fault(rport->fcs, event);1643	}1644}1645 1646/*1647 * Rport needs to be deleted1648 * waiting for ITNIM clean up to finish1649 */1650static void1651bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,1652				enum rport_event event)1653{1654	bfa_trc(rport->fcs, rport->pwwn);1655	bfa_trc(rport->fcs, rport->pid);1656	bfa_trc(rport->fcs, event);1657 1658	switch (event) {1659	case RPSM_EVENT_FC4_OFFLINE:1660		bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);1661		bfa_fcs_rport_hal_offline(rport);1662		break;1663 1664	case RPSM_EVENT_DELETE:1665	case RPSM_EVENT_PLOGI_RCVD:1666		/* Ignore these events */1667		break;1668 1669	default:1670		bfa_sm_fault(rport->fcs, event);1671		break;1672	}1673}1674 1675/*1676 * RPort needs to be deleted1677 * waiting for BFA/FW to finish current processing1678 */1679static void1680bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,1681				enum rport_event event)1682{1683	bfa_trc(rport->fcs, rport->pwwn);1684	bfa_trc(rport->fcs, rport->pid);1685	bfa_trc(rport->fcs, event);1686 1687	switch (event) {1688	case RPSM_EVENT_HCB_OFFLINE:1689		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1690		bfa_fcs_rport_free(rport);1691		break;1692 1693	case RPSM_EVENT_DELETE:1694	case RPSM_EVENT_LOGO_IMP:1695	case RPSM_EVENT_PLOGI_RCVD:1696		/* Ignore these events */1697		break;1698 1699	default:1700		bfa_sm_fault(rport->fcs, event);1701	}1702}1703 1704/*1705 *  fcs_rport_private FCS RPORT provate functions1706 */1707 1708static void1709bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1710{1711	struct bfa_fcs_rport_s *rport = rport_cbarg;1712	struct bfa_fcs_lport_s *port = rport->port;1713	struct fchs_s	fchs;1714	int		len;1715	struct bfa_fcxp_s *fcxp;1716 1717	bfa_trc(rport->fcs, rport->pwwn);1718 1719	fcxp = fcxp_alloced ? fcxp_alloced :1720	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);1721	if (!fcxp) {1722		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1723				bfa_fcs_rport_send_plogi, rport, BFA_TRUE);1724		return;1725	}1726	rport->fcxp = fcxp;1727 1728	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,1729				bfa_fcs_lport_get_fcid(port), 0,1730				port->port_cfg.pwwn, port->port_cfg.nwwn,1731				bfa_fcport_get_maxfrsize(port->fcs->bfa),1732				bfa_fcport_get_rx_bbcredit(port->fcs->bfa));1733 1734	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1735			FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,1736			(void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);1737 1738	rport->stats.plogis++;1739	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1740}1741 1742static void1743bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1744				bfa_status_t req_status, u32 rsp_len,1745				u32 resid_len, struct fchs_s *rsp_fchs)1746{1747	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;1748	struct fc_logi_s	*plogi_rsp;1749	struct fc_ls_rjt_s	*ls_rjt;1750	struct bfa_fcs_rport_s *twin;1751	struct list_head	*qe;1752 1753	bfa_trc(rport->fcs, rport->pwwn);1754 1755	/*1756	 * Sanity Checks1757	 */1758	if (req_status != BFA_STATUS_OK) {1759		bfa_trc(rport->fcs, req_status);1760		rport->stats.plogi_failed++;1761		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1762		return;1763	}1764 1765	plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);1766 1767	/*1768	 * Check for failure first.1769	 */1770	if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {1771		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);1772 1773		bfa_trc(rport->fcs, ls_rjt->reason_code);1774		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);1775 1776		if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&1777		 (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {1778			rport->stats.rjt_insuff_res++;1779			bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);1780			return;1781		}1782 1783		rport->stats.plogi_rejects++;1784		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1785		return;1786	}1787 1788	/*1789	 * PLOGI is complete. Make sure this device is not one of the known1790	 * device with a new FC port address.1791	 */1792	list_for_each(qe, &rport->port->rport_q) {1793		twin = (struct bfa_fcs_rport_s *) qe;1794		if (twin == rport)1795			continue;1796		if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {1797			bfa_trc(rport->fcs, twin->pid);1798			bfa_trc(rport->fcs, rport->pid);1799 1800			/* Update plogi stats in twin */1801			twin->stats.plogis  += rport->stats.plogis;1802			twin->stats.plogi_rejects  +=1803				 rport->stats.plogi_rejects;1804			twin->stats.plogi_timeouts  +=1805				 rport->stats.plogi_timeouts;1806			twin->stats.plogi_failed +=1807				 rport->stats.plogi_failed;1808			twin->stats.plogi_rcvd	  += rport->stats.plogi_rcvd;1809			twin->stats.plogi_accs++;1810 1811			bfa_sm_send_event(rport, RPSM_EVENT_DELETE);1812 1813			bfa_fcs_rport_update(twin, plogi_rsp);1814			twin->pid = rsp_fchs->s_id;1815			bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);1816			return;1817		}1818	}1819 1820	/*1821	 * Normal login path -- no evil twins.1822	 */1823	rport->stats.plogi_accs++;1824	bfa_fcs_rport_update(rport, plogi_rsp);1825	bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);1826}1827 1828static void1829bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1830{1831	struct bfa_fcs_rport_s *rport = rport_cbarg;1832	struct bfa_fcs_lport_s *port = rport->port;1833	struct fchs_s		fchs;1834	int		len;1835	struct bfa_fcxp_s *fcxp;1836 1837	bfa_trc(rport->fcs, rport->pwwn);1838	bfa_trc(rport->fcs, rport->reply_oxid);1839 1840	fcxp = fcxp_alloced ? fcxp_alloced :1841	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);1842	if (!fcxp) {1843		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1844				bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);1845		return;1846	}1847	rport->fcxp = fcxp;1848 1849	len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1850				 rport->pid, bfa_fcs_lport_get_fcid(port),1851				 rport->reply_oxid, port->port_cfg.pwwn,1852				 port->port_cfg.nwwn,1853				 bfa_fcport_get_maxfrsize(port->fcs->bfa),1854				 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));1855 1856	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1857			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);1858 1859	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1860}1861 1862static void1863bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1864{1865	struct bfa_fcs_rport_s *rport = rport_cbarg;1866	struct bfa_fcs_lport_s *port = rport->port;1867	struct fchs_s		fchs;1868	int		len;1869	struct bfa_fcxp_s *fcxp;1870 1871	bfa_trc(rport->fcs, rport->pwwn);1872 1873	fcxp = fcxp_alloced ? fcxp_alloced :1874	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);1875	if (!fcxp) {1876		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1877				bfa_fcs_rport_send_adisc, rport, BFA_TRUE);1878		return;1879	}1880	rport->fcxp = fcxp;1881 1882	len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,1883				bfa_fcs_lport_get_fcid(port), 0,1884				port->port_cfg.pwwn, port->port_cfg.nwwn);1885 1886	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1887			FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,1888			rport, FC_MAX_PDUSZ, FC_ELS_TOV);1889 1890	rport->stats.adisc_sent++;1891	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1892}1893 1894static void1895bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1896				bfa_status_t req_status, u32 rsp_len,1897				u32 resid_len, struct fchs_s *rsp_fchs)1898{1899	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;1900	void		*pld = bfa_fcxp_get_rspbuf(fcxp);1901	struct fc_ls_rjt_s	*ls_rjt;1902 1903	if (req_status != BFA_STATUS_OK) {1904		bfa_trc(rport->fcs, req_status);1905		rport->stats.adisc_failed++;1906		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1907		return;1908	}1909 1910	if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,1911				rport->nwwn)  == FC_PARSE_OK) {1912		rport->stats.adisc_accs++;1913		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);1914		return;1915	}1916 1917	rport->stats.adisc_rejects++;1918	ls_rjt = pld;1919	bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);1920	bfa_trc(rport->fcs, ls_rjt->reason_code);1921	bfa_trc(rport->fcs, ls_rjt->reason_code_expl);1922	bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1923}1924 1925static void1926bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1927{1928	struct bfa_fcs_rport_s *rport = rport_cbarg;1929	struct bfa_fcs_lport_s *port = rport->port;1930	struct fchs_s	fchs;1931	struct bfa_fcxp_s *fcxp;1932	int		len;1933	bfa_cb_fcxp_send_t cbfn;1934 1935	bfa_trc(rport->fcs, rport->pid);1936 1937	fcxp = fcxp_alloced ? fcxp_alloced :1938	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);1939	if (!fcxp) {1940		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1941				bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);1942		return;1943	}1944	rport->fcxp = fcxp;1945 1946	if (rport->pwwn) {1947		len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1948				bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);1949		cbfn = bfa_fcs_rport_gidpn_response;1950	} else {1951		len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1952				bfa_fcs_lport_get_fcid(port), 0, rport->pid);1953		cbfn = bfa_fcs_rport_gpnid_response;1954	}1955 1956	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1957			FC_CLASS_3, len, &fchs, cbfn,1958			(void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);1959 1960	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1961}1962 1963static void1964bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1965				bfa_status_t req_status, u32 rsp_len,1966				u32 resid_len, struct fchs_s *rsp_fchs)1967{1968	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;1969	struct ct_hdr_s	*cthdr;1970	struct fcgs_gidpn_resp_s	*gidpn_rsp;1971	struct bfa_fcs_rport_s	*twin;1972	struct list_head	*qe;1973 1974	bfa_trc(rport->fcs, rport->pwwn);1975 1976	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);1977	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);1978 1979	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {1980		/* Check if the pid is the same as before. */1981		gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);1982 1983		if (gidpn_rsp->dap == rport->pid) {1984			/* Device is online  */1985			bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);1986		} else {1987			/*1988			 * Device's PID has changed. We need to cleanup1989			 * and re-login. If there is another device with1990			 * the the newly discovered pid, send an scn notice1991			 * so that its new pid can be discovered.1992			 */1993			list_for_each(qe, &rport->port->rport_q) {1994				twin = (struct bfa_fcs_rport_s *) qe;1995				if (twin == rport)1996					continue;1997				if (gidpn_rsp->dap == twin->pid) {1998					bfa_trc(rport->fcs, twin->pid);1999					bfa_trc(rport->fcs, rport->pid);2000 2001					twin->pid = 0;2002					bfa_sm_send_event(twin,2003					 RPSM_EVENT_ADDRESS_CHANGE);2004				}2005			}2006			rport->pid = gidpn_rsp->dap;2007			bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);2008		}2009		return;2010	}2011 2012	/*2013	 * Reject Response2014	 */2015	switch (cthdr->reason_code) {2016	case CT_RSN_LOGICAL_BUSY:2017		/*2018		 * Need to retry2019		 */2020		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);2021		break;2022 2023	case CT_RSN_UNABLE_TO_PERF:2024		/*2025		 * device doesn't exist : Start timer to cleanup this later.2026		 */2027		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2028		break;2029 2030	default:2031		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2032		break;2033	}2034}2035 2036static void2037bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,2038				bfa_status_t req_status, u32 rsp_len,2039				u32 resid_len, struct fchs_s *rsp_fchs)2040{2041	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2042	struct ct_hdr_s	*cthdr;2043 2044	bfa_trc(rport->fcs, rport->pwwn);2045 2046	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);2047	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);2048 2049	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {2050		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);2051		return;2052	}2053 2054	/*2055	 * Reject Response2056	 */2057	switch (cthdr->reason_code) {2058	case CT_RSN_LOGICAL_BUSY:2059		/*2060		 * Need to retry2061		 */2062		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);2063		break;2064 2065	case CT_RSN_UNABLE_TO_PERF:2066		/*2067		 * device doesn't exist : Start timer to cleanup this later.2068		 */2069		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2070		break;2071 2072	default:2073		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2074		break;2075	}2076}2077 2078/*2079 *	Called to send a logout to the rport.2080 */2081static void2082bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)2083{2084	struct bfa_fcs_rport_s *rport = rport_cbarg;2085	struct bfa_fcs_lport_s *port;2086	struct fchs_s	fchs;2087	struct bfa_fcxp_s *fcxp;2088	u16	len;2089 2090	bfa_trc(rport->fcs, rport->pid);2091 2092	port = rport->port;2093 2094	fcxp = fcxp_alloced ? fcxp_alloced :2095	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2096	if (!fcxp) {2097		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,2098				bfa_fcs_rport_send_logo, rport, BFA_FALSE);2099		return;2100	}2101	rport->fcxp = fcxp;2102 2103	len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,2104				bfa_fcs_lport_get_fcid(port), 0,2105				bfa_fcs_lport_get_pwwn(port));2106 2107	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2108			FC_CLASS_3, len, &fchs, NULL,2109			rport, FC_MAX_PDUSZ, FC_ELS_TOV);2110 2111	rport->stats.logos++;2112	bfa_fcxp_discard(rport->fcxp);2113	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);2114}2115 2116/*2117 *	Send ACC for a LOGO received.2118 */2119static void2120bfa_fcs_rport_send_logo_acc(void *rport_cbarg)2121{2122	struct bfa_fcs_rport_s *rport = rport_cbarg;2123	struct bfa_fcs_lport_s *port;2124	struct fchs_s	fchs;2125	struct bfa_fcxp_s *fcxp;2126	u16	len;2127 2128	bfa_trc(rport->fcs, rport->pid);2129 2130	port = rport->port;2131 2132	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2133	if (!fcxp)2134		return;2135 2136	rport->stats.logo_rcvd++;2137	len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2138				rport->pid, bfa_fcs_lport_get_fcid(port),2139				rport->reply_oxid);2140 2141	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2142			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);2143}2144 2145/*2146 *	brief2147 *	This routine will be called by bfa_timer on timer timeouts.2148 *2149 *	param[in]	rport			- pointer to bfa_fcs_lport_ns_t.2150 *	param[out]	rport_status	- pointer to return vport status in2151 *2152 *	return2153 *		void2154 *2155 *	Special Considerations:2156 *2157 *	note2158 */2159static void2160bfa_fcs_rport_timeout(void *arg)2161{2162	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;2163 2164	rport->stats.plogi_timeouts++;2165	bfa_stats(rport->port, rport_plogi_timeouts);2166	bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);2167}2168 2169static void2170bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,2171			struct fchs_s *rx_fchs, u16 len)2172{2173	struct bfa_fcxp_s *fcxp;2174	struct fchs_s	fchs;2175	struct bfa_fcs_lport_s *port = rport->port;2176	struct fc_prli_s	*prli;2177 2178	bfa_trc(port->fcs, rx_fchs->s_id);2179	bfa_trc(port->fcs, rx_fchs->d_id);2180 2181	rport->stats.prli_rcvd++;2182 2183	/*2184	 * We are in Initiator Mode2185	 */2186	prli = (struct fc_prli_s *) (rx_fchs + 1);2187 2188	if (prli->parampage.servparams.target) {2189		/*2190		 * PRLI from a target ?2191		 * Send the Acc.2192		 * PRLI sent by us will be used to transition the IT nexus,2193		 * once the response is received from the target.2194		 */2195		bfa_trc(port->fcs, rx_fchs->s_id);2196		rport->scsi_function = BFA_RPORT_TARGET;2197	} else {2198		bfa_trc(rport->fcs, prli->parampage.type);2199		rport->scsi_function = BFA_RPORT_INITIATOR;2200		bfa_fcs_itnim_is_initiator(rport->itnim);2201	}2202 2203	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2204	if (!fcxp)2205		return;2206 2207	len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2208				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2209				rx_fchs->ox_id, port->port_cfg.roles);2210 2211	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2212			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);2213}2214 2215static void2216bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,2217			struct fchs_s *rx_fchs, u16 len)2218{2219	struct bfa_fcxp_s *fcxp;2220	struct fchs_s	fchs;2221	struct bfa_fcs_lport_s *port = rport->port;2222	struct fc_rpsc_speed_info_s speeds;2223	struct bfa_port_attr_s pport_attr;2224 2225	bfa_trc(port->fcs, rx_fchs->s_id);2226	bfa_trc(port->fcs, rx_fchs->d_id);2227 2228	rport->stats.rpsc_rcvd++;2229	speeds.port_speed_cap =2230		RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |2231		RPSC_SPEED_CAP_8G;2232 2233	/*2234	 * get curent speed from pport attributes from BFA2235	 */2236	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);2237 2238	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);2239 2240	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2241	if (!fcxp)2242		return;2243 2244	len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2245				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2246				rx_fchs->ox_id, &speeds);2247 2248	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2249			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);2250}2251 2252static void2253bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,2254			struct fchs_s *rx_fchs, u16 len)2255{2256	struct bfa_fcxp_s *fcxp;2257	struct fchs_s	fchs;2258	struct bfa_fcs_lport_s *port = rport->port;2259 2260	bfa_trc(port->fcs, rx_fchs->s_id);2261	bfa_trc(port->fcs, rx_fchs->d_id);2262 2263	rport->stats.adisc_rcvd++;2264 2265	/*2266	 * Accept if the itnim for this rport is online.2267	 * Else reject the ADISC.2268	 */2269	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {2270 2271		fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2272		if (!fcxp)2273			return;2274 2275		len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2276			 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2277			 rx_fchs->ox_id, port->port_cfg.pwwn,2278			 port->port_cfg.nwwn);2279 2280		bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,2281				BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,2282				FC_MAX_PDUSZ, 0);2283	} else {2284		rport->stats.adisc_rejected++;2285		bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,2286					  FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,2287					  FC_LS_RJT_EXP_LOGIN_REQUIRED);2288	}2289}2290 2291static void2292bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)2293{2294	struct bfa_fcs_lport_s *port = rport->port;2295	struct bfa_rport_info_s rport_info;2296 2297	rport_info.pid = rport->pid;2298	rport_info.local_pid = port->pid;2299	rport_info.lp_tag = port->lp_tag;2300	rport_info.vf_id = port->fabric->vf_id;2301	rport_info.vf_en = port->fabric->is_vf;2302	rport_info.fc_class = rport->fc_cos;2303	rport_info.cisc = rport->cisc;2304	rport_info.max_frmsz = rport->maxfrsize;2305	bfa_rport_online(rport->bfa_rport, &rport_info);2306}2307 2308static void2309bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)2310{2311	if (rport->bfa_rport)2312		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);2313	else2314		bfa_cb_rport_offline(rport);2315}2316 2317static struct bfa_fcs_rport_s *2318bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)2319{2320	struct bfa_fcs_s	*fcs = port->fcs;2321	struct bfa_fcs_rport_s *rport;2322	struct bfad_rport_s	*rport_drv;2323 2324	/*2325	 * allocate rport2326	 */2327	if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {2328		bfa_trc(fcs, rpid);2329		return NULL;2330	}2331 2332	if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)2333		!= BFA_STATUS_OK) {2334		bfa_trc(fcs, rpid);2335		return NULL;2336	}2337 2338	/*2339	 * Initialize r-port2340	 */2341	rport->port = port;2342	rport->fcs = fcs;2343	rport->rp_drv = rport_drv;2344	rport->pid = rpid;2345	rport->pwwn = pwwn;2346	rport->old_pid = 0;2347 2348	rport->bfa_rport = NULL;2349 2350	/*2351	 * allocate FC-4s2352	 */2353	WARN_ON(!bfa_fcs_lport_is_initiator(port));2354 2355	if (bfa_fcs_lport_is_initiator(port)) {2356		rport->itnim = bfa_fcs_itnim_create(rport);2357		if (!rport->itnim) {2358			bfa_trc(fcs, rpid);2359			kfree(rport_drv);2360			return NULL;2361		}2362	}2363 2364	bfa_fcs_lport_add_rport(port, rport);2365	fcs->num_rport_logins++;2366 2367	bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);2368 2369	/* Initialize the Rport Features(RPF) Sub Module  */2370	if (!BFA_FCS_PID_IS_WKA(rport->pid))2371		bfa_fcs_rpf_init(rport);2372 2373	return rport;2374}2375 2376 2377static void2378bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)2379{2380	struct bfa_fcs_lport_s *port = rport->port;2381	struct bfa_fcs_s *fcs = port->fcs;2382 2383	/*2384	 * - delete FC-4s2385	 * - delete BFA rport2386	 * - remove from queue of rports2387	 */2388	rport->plogi_pending = BFA_FALSE;2389 2390	if (bfa_fcs_lport_is_initiator(port)) {2391		bfa_fcs_itnim_delete(rport->itnim);2392		if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))2393			bfa_fcs_rpf_rport_offline(rport);2394	}2395 2396	if (rport->bfa_rport) {2397		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);2398		rport->bfa_rport = NULL;2399	}2400 2401	bfa_fcs_lport_del_rport(port, rport);2402	fcs->num_rport_logins--;2403	kfree(rport->rp_drv);2404}2405 2406static void2407bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,2408			enum bfa_rport_aen_event event,2409			struct bfa_rport_aen_data_s *data)2410{2411	struct bfa_fcs_lport_s *port = rport->port;2412	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;2413	struct bfa_aen_entry_s  *aen_entry;2414 2415	bfad_get_aen_entry(bfad, aen_entry);2416	if (!aen_entry)2417		return;2418 2419	if (event == BFA_RPORT_AEN_QOS_PRIO)2420		aen_entry->aen_data.rport.priv.qos = data->priv.qos;2421	else if (event == BFA_RPORT_AEN_QOS_FLOWID)2422		aen_entry->aen_data.rport.priv.qos = data->priv.qos;2423 2424	aen_entry->aen_data.rport.vf_id = rport->port->fabric->vf_id;2425	aen_entry->aen_data.rport.ppwwn = bfa_fcs_lport_get_pwwn(2426					bfa_fcs_get_base_port(rport->fcs));2427	aen_entry->aen_data.rport.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);2428	aen_entry->aen_data.rport.rpwwn = rport->pwwn;2429 2430	/* Send the AEN notification */2431	bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,2432				  BFA_AEN_CAT_RPORT, event);2433}2434 2435static void2436bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)2437{2438	if ((!rport->pid) || (!rport->pwwn)) {2439		bfa_trc(rport->fcs, rport->pid);2440		bfa_sm_fault(rport->fcs, rport->pid);2441	}2442 2443	bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);2444}2445 2446static void2447bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)2448{2449	struct bfa_fcs_lport_s *port = rport->port;2450	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;2451	char	lpwwn_buf[BFA_STRING_32];2452	char	rpwwn_buf[BFA_STRING_32];2453 2454	rport->stats.onlines++;2455 2456	if ((!rport->pid) || (!rport->pwwn)) {2457		bfa_trc(rport->fcs, rport->pid);2458		bfa_sm_fault(rport->fcs, rport->pid);2459	}2460 2461	if (bfa_fcs_lport_is_initiator(port)) {2462		bfa_fcs_itnim_brp_online(rport->itnim);2463		if (!BFA_FCS_PID_IS_WKA(rport->pid))2464			bfa_fcs_rpf_rport_online(rport);2465	}2466 2467	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));2468	wwn2str(rpwwn_buf, rport->pwwn);2469	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {2470		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2471		"Remote port (WWN = %s) online for logical port (WWN = %s)\n",2472		rpwwn_buf, lpwwn_buf);2473		bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);2474	}2475}2476 2477static void2478bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)2479{2480	if (!BFA_FCS_PID_IS_WKA(rport->pid))2481		bfa_fcs_rpf_rport_offline(rport);2482 2483	bfa_fcs_itnim_rport_offline(rport->itnim);2484}2485 2486static void2487bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)2488{2489	struct bfa_fcs_lport_s *port = rport->port;2490	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;2491	char	lpwwn_buf[BFA_STRING_32];2492	char	rpwwn_buf[BFA_STRING_32];2493 2494	if (!rport->bfa_rport) {2495		bfa_fcs_rport_fcs_offline_action(rport);2496		return;2497	}2498 2499	rport->stats.offlines++;2500 2501	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));2502	wwn2str(rpwwn_buf, rport->pwwn);2503	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {2504		if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) {2505			BFA_LOG(KERN_ERR, bfad, bfa_log_level,2506				"Remote port (WWN = %s) connectivity lost for "2507				"logical port (WWN = %s)\n",2508				rpwwn_buf, lpwwn_buf);2509			bfa_fcs_rport_aen_post(rport,2510				BFA_RPORT_AEN_DISCONNECT, NULL);2511		} else {2512			BFA_LOG(KERN_INFO, bfad, bfa_log_level,2513				"Remote port (WWN = %s) offlined by "2514				"logical port (WWN = %s)\n",2515				rpwwn_buf, lpwwn_buf);2516			bfa_fcs_rport_aen_post(rport,2517				BFA_RPORT_AEN_OFFLINE, NULL);2518		}2519	}2520 2521	if (bfa_fcs_lport_is_initiator(port)) {2522		bfa_fcs_itnim_rport_offline(rport->itnim);2523		if (!BFA_FCS_PID_IS_WKA(rport->pid))2524			bfa_fcs_rpf_rport_offline(rport);2525	}2526}2527 2528/*2529 * Update rport parameters from PLOGI or PLOGI accept.2530 */2531static void2532bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)2533{2534	bfa_fcs_lport_t *port = rport->port;2535 2536	/*2537	 * - port name2538	 * - node name2539	 */2540	rport->pwwn = plogi->port_name;2541	rport->nwwn = plogi->node_name;2542 2543	/*2544	 * - class of service2545	 */2546	rport->fc_cos = 0;2547	if (plogi->class3.class_valid)2548		rport->fc_cos = FC_CLASS_3;2549 2550	if (plogi->class2.class_valid)2551		rport->fc_cos |= FC_CLASS_2;2552 2553	/*2554	 * - CISC2555	 * - MAX receive frame size2556	 */2557	rport->cisc = plogi->csp.cisc;2558	if (be16_to_cpu(plogi->class3.rxsz) < be16_to_cpu(plogi->csp.rxsz))2559		rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz);2560	else2561		rport->maxfrsize = be16_to_cpu(plogi->csp.rxsz);2562 2563	bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));2564	bfa_trc(port->fcs, port->fabric->bb_credit);2565	/*2566	 * Direct Attach P2P mode :2567	 * This is to handle a bug (233476) in IBM targets in Direct Attach2568	 *  Mode. Basically, in FLOGI Accept the target would have2569	 * erroneously set the BB Credit to the value used in the FLOGI2570	 * sent by the HBA. It uses the correct value (its own BB credit)2571	 * in PLOGI.2572	 */2573	if ((!bfa_fcs_fabric_is_switched(port->fabric))	 &&2574		(be16_to_cpu(plogi->csp.bbcred) < port->fabric->bb_credit)) {2575 2576		bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));2577		bfa_trc(port->fcs, port->fabric->bb_credit);2578 2579		port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);2580		bfa_fcport_set_tx_bbcredit(port->fcs->bfa,2581					  port->fabric->bb_credit);2582	}2583 2584}2585 2586/*2587 *	Called to handle LOGO received from an existing remote port.2588 */2589static void2590bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)2591{2592	rport->reply_oxid = fchs->ox_id;2593	bfa_trc(rport->fcs, rport->reply_oxid);2594 2595	rport->prlo = BFA_FALSE;2596	rport->stats.logo_rcvd++;2597	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);2598}2599 2600 2601 2602/*2603 *  fcs_rport_public FCS rport public interfaces2604 */2605 2606/*2607 *	Called by bport/vport to create a remote port instance for a discovered2608 *	remote device.2609 *2610 * @param[in] port	- base port or vport2611 * @param[in] rpid	- remote port ID2612 *2613 * @return None2614 */2615struct bfa_fcs_rport_s *2616bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)2617{2618	struct bfa_fcs_rport_s *rport;2619 2620	bfa_trc(port->fcs, rpid);2621	rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);2622	if (!rport)2623		return NULL;2624 2625	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);2626	return rport;2627}2628 2629/*2630 * Called to create a rport for which only the wwn is known.2631 *2632 * @param[in] port	- base port2633 * @param[in] rpwwn	- remote port wwn2634 *2635 * @return None2636 */2637struct bfa_fcs_rport_s *2638bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)2639{2640	struct bfa_fcs_rport_s *rport;2641	bfa_trc(port->fcs, rpwwn);2642	rport = bfa_fcs_rport_alloc(port, rpwwn, 0);2643	if (!rport)2644		return NULL;2645 2646	bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);2647	return rport;2648}2649/*2650 * Called by bport in private loop topology to indicate that a2651 * rport has been discovered and plogi has been completed.2652 *2653 * @param[in] port	- base port or vport2654 * @param[in] rpid	- remote port ID2655 */2656void2657bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,2658	 struct fc_logi_s *plogi)2659{2660	struct bfa_fcs_rport_s *rport;2661 2662	rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);2663	if (!rport)2664		return;2665 2666	bfa_fcs_rport_update(rport, plogi);2667 2668	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);2669}2670 2671/*2672 *	Called by bport/vport to handle PLOGI received from a new remote port.2673 *	If an existing rport does a plogi, it will be handled separately.2674 */2675void2676bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,2677				struct fc_logi_s *plogi)2678{2679	struct bfa_fcs_rport_s *rport;2680 2681	rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);2682	if (!rport)2683		return;2684 2685	bfa_fcs_rport_update(rport, plogi);2686 2687	rport->reply_oxid = fchs->ox_id;2688	bfa_trc(rport->fcs, rport->reply_oxid);2689 2690	rport->stats.plogi_rcvd++;2691	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);2692}2693 2694/*2695 *	Called by bport/vport to handle PLOGI received from an existing2696 *	 remote port.2697 */2698void2699bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,2700			struct fc_logi_s *plogi)2701{2702	/*2703	 * @todo Handle P2P and initiator-initiator.2704	 */2705 2706	bfa_fcs_rport_update(rport, plogi);2707 2708	rport->reply_oxid = rx_fchs->ox_id;2709	bfa_trc(rport->fcs, rport->reply_oxid);2710 2711	rport->pid = rx_fchs->s_id;2712	bfa_trc(rport->fcs, rport->pid);2713 2714	rport->stats.plogi_rcvd++;2715	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);2716}2717 2718 2719/*2720 *	Called by bport/vport to notify SCN for the remote port2721 */2722void2723bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)2724{2725	rport->stats.rscns++;2726	bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);2727}2728 2729/*2730 *	brief2731 *	This routine BFA callback for bfa_rport_online() call.2732 *2733 *	param[in]	cb_arg	-  rport struct.2734 *2735 *	return2736 *		void2737 *2738 *	Special Considerations:2739 *2740 *	note2741 */2742void2743bfa_cb_rport_online(void *cbarg)2744{2745 2746	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2747 2748	bfa_trc(rport->fcs, rport->pwwn);2749	bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);2750}2751 2752/*2753 *	brief2754 *	This routine BFA callback for bfa_rport_offline() call.2755 *2756 *	param[in]	rport	-2757 *2758 *	return2759 *		void2760 *2761 *	Special Considerations:2762 *2763 *	note2764 */2765void2766bfa_cb_rport_offline(void *cbarg)2767{2768	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2769 2770	bfa_trc(rport->fcs, rport->pwwn);2771	bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);2772}2773 2774/*2775 *	brief2776 *	This routine is a static BFA callback when there is a QoS flow_id2777 *	change notification2778 *2779 *	param[in]	rport	-2780 *2781 *	return2782 *		void2783 *2784 *	Special Considerations:2785 *2786 *	note2787 */2788void2789bfa_cb_rport_qos_scn_flowid(void *cbarg,2790		struct bfa_rport_qos_attr_s old_qos_attr,2791		struct bfa_rport_qos_attr_s new_qos_attr)2792{2793	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2794	struct bfa_rport_aen_data_s aen_data;2795 2796	bfa_trc(rport->fcs, rport->pwwn);2797	aen_data.priv.qos = new_qos_attr;2798	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);2799}2800 2801void2802bfa_cb_rport_scn_online(struct bfa_s *bfa)2803{2804	struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;2805	struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);2806	struct bfa_fcs_rport_s *rp;2807	struct list_head *qe;2808 2809	list_for_each(qe, &port->rport_q) {2810		rp = (struct bfa_fcs_rport_s *) qe;2811		bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);2812		rp->scn_online = BFA_TRUE;2813	}2814 2815	if (bfa_fcs_lport_is_online(port))2816		bfa_fcs_lport_lip_scn_online(port);2817}2818 2819void2820bfa_cb_rport_scn_no_dev(void *rport)2821{2822	struct bfa_fcs_rport_s *rp = rport;2823 2824	bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);2825	rp->scn_online = BFA_FALSE;2826}2827 2828void2829bfa_cb_rport_scn_offline(struct bfa_s *bfa)2830{2831	struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;2832	struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);2833	struct bfa_fcs_rport_s *rp;2834	struct list_head *qe;2835 2836	list_for_each(qe, &port->rport_q) {2837		rp = (struct bfa_fcs_rport_s *) qe;2838		bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);2839		rp->scn_online = BFA_FALSE;2840	}2841}2842 2843/*2844 *	brief2845 *	This routine is a static BFA callback when there is a QoS priority2846 *	change notification2847 *2848 *	param[in]	rport	-2849 *2850 *	return2851 *		void2852 *2853 *	Special Considerations:2854 *2855 *	note2856 */2857void2858bfa_cb_rport_qos_scn_prio(void *cbarg,2859		struct bfa_rport_qos_attr_s old_qos_attr,2860		struct bfa_rport_qos_attr_s new_qos_attr)2861{2862	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2863	struct bfa_rport_aen_data_s aen_data;2864 2865	bfa_trc(rport->fcs, rport->pwwn);2866	aen_data.priv.qos = new_qos_attr;2867	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);2868}2869 2870/*2871 *		Called to process any unsolicted frames from this remote port2872 */2873void2874bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,2875			struct fchs_s *fchs, u16 len)2876{2877	struct bfa_fcs_lport_s *port = rport->port;2878	struct fc_els_cmd_s	*els_cmd;2879 2880	bfa_trc(rport->fcs, fchs->s_id);2881	bfa_trc(rport->fcs, fchs->d_id);2882	bfa_trc(rport->fcs, fchs->type);2883 2884	if (fchs->type != FC_TYPE_ELS)2885		return;2886 2887	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);2888 2889	bfa_trc(rport->fcs, els_cmd->els_code);2890 2891	switch (els_cmd->els_code) {2892	case FC_ELS_LOGO:2893		bfa_stats(port, plogi_rcvd);2894		bfa_fcs_rport_process_logo(rport, fchs);2895		break;2896 2897	case FC_ELS_ADISC:2898		bfa_stats(port, adisc_rcvd);2899		bfa_fcs_rport_process_adisc(rport, fchs, len);2900		break;2901 2902	case FC_ELS_PRLO:2903		bfa_stats(port, prlo_rcvd);2904		if (bfa_fcs_lport_is_initiator(port))2905			bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);2906		break;2907 2908	case FC_ELS_PRLI:2909		bfa_stats(port, prli_rcvd);2910		bfa_fcs_rport_process_prli(rport, fchs, len);2911		break;2912 2913	case FC_ELS_RPSC:2914		bfa_stats(port, rpsc_rcvd);2915		bfa_fcs_rport_process_rpsc(rport, fchs, len);2916		break;2917 2918	default:2919		bfa_stats(port, un_handled_els_rcvd);2920		bfa_fcs_rport_send_ls_rjt(rport, fchs,2921					  FC_LS_RJT_RSN_CMD_NOT_SUPP,2922					  FC_LS_RJT_EXP_NO_ADDL_INFO);2923		break;2924	}2925}2926 2927/* send best case  acc to prlo */2928static void2929bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)2930{2931	struct bfa_fcs_lport_s *port = rport->port;2932	struct fchs_s	fchs;2933	struct bfa_fcxp_s *fcxp;2934	int		len;2935 2936	bfa_trc(rport->fcs, rport->pid);2937 2938	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2939	if (!fcxp)2940		return;2941	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2942			rport->pid, bfa_fcs_lport_get_fcid(port),2943			rport->reply_oxid, 0);2944 2945	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,2946		port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,2947		NULL, NULL, FC_MAX_PDUSZ, 0);2948}2949 2950/*2951 * Send a LS reject2952 */2953static void2954bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,2955			  u8 reason_code, u8 reason_code_expl)2956{2957	struct bfa_fcs_lport_s *port = rport->port;2958	struct fchs_s	fchs;2959	struct bfa_fcxp_s *fcxp;2960	int		len;2961 2962	bfa_trc(rport->fcs, rx_fchs->s_id);2963 2964	fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);2965	if (!fcxp)2966		return;2967 2968	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2969				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2970				rx_fchs->ox_id, reason_code, reason_code_expl);2971 2972	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,2973			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,2974			FC_MAX_PDUSZ, 0);2975}2976 2977/*2978 * Return state of rport.2979 */2980int2981bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)2982{2983	return bfa_rport_sm_to_state(rport_sm_table, rport->sm);2984}2985 2986 2987/*2988 *	brief2989 *		 Called by the Driver to set rport delete/ageout timeout2990 *2991 *	param[in]		rport timeout value in seconds.2992 *2993 *	return None2994 */2995void2996bfa_fcs_rport_set_del_timeout(u8 rport_tmo)2997{2998	/* convert to Millisecs */2999	if (rport_tmo > 0)3000		bfa_fcs_rport_del_timeout = rport_tmo * 1000;3001}3002void3003bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)3004{3005	bfa_trc(rport->fcs, rport->pid);3006 3007	rport->prlo = BFA_TRUE;3008	rport->reply_oxid = ox_id;3009	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);3010}3011 3012/*3013 * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation3014 * which limits number of concurrent logins to remote ports3015 */3016void3017bfa_fcs_rport_set_max_logins(u32 max_logins)3018{3019	if (max_logins > 0)3020		bfa_fcs_rport_max_logins = max_logins;3021}3022 3023void3024bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,3025		struct bfa_rport_attr_s *rport_attr)3026{3027	struct bfa_rport_qos_attr_s qos_attr;3028	struct bfa_fcs_lport_s *port = rport->port;3029	bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;3030	struct bfa_port_attr_s port_attr;3031 3032	bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);3033 3034	memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));3035	memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));3036 3037	rport_attr->pid = rport->pid;3038	rport_attr->pwwn = rport->pwwn;3039	rport_attr->nwwn = rport->nwwn;3040	rport_attr->cos_supported = rport->fc_cos;3041	rport_attr->df_sz = rport->maxfrsize;3042	rport_attr->state = bfa_fcs_rport_get_state(rport);3043	rport_attr->fc_cos = rport->fc_cos;3044	rport_attr->cisc = rport->cisc;3045	rport_attr->scsi_function = rport->scsi_function;3046	rport_attr->curr_speed  = rport->rpf.rpsc_speed;3047	rport_attr->assigned_speed  = rport->rpf.assigned_speed;3048 3049	if (rport->bfa_rport) {3050		qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;3051		qos_attr.qos_flow_id =3052			cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);3053	}3054	rport_attr->qos_attr = qos_attr;3055 3056	rport_attr->trl_enforced = BFA_FALSE;3057	if (bfa_fcport_is_ratelim(port->fcs->bfa) &&3058	    (rport->scsi_function == BFA_RPORT_TARGET)) {3059		if (rport_speed == BFA_PORT_SPEED_UNKNOWN)3060			rport_speed =3061				bfa_fcport_get_ratelim_speed(rport->fcs->bfa);3062 3063		if ((bfa_fcs_lport_get_rport_max_speed(port) !=3064		    BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))3065			rport_attr->trl_enforced = BFA_TRUE;3066	}3067}3068 3069/*3070 * Remote port implementation.3071 */3072 3073/*3074 *  fcs_rport_api FCS rport API.3075 */3076 3077struct bfa_fcs_rport_s *3078bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)3079{3080	struct bfa_fcs_rport_s *rport;3081 3082	rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);3083	if (rport == NULL) {3084		/*3085		 * TBD Error handling3086		 */3087	}3088 3089	return rport;3090}3091 3092struct bfa_fcs_rport_s *3093bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)3094{3095	struct bfa_fcs_rport_s *rport;3096 3097	rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);3098	if (rport == NULL) {3099		/*3100		 * TBD Error handling3101		 */3102	}3103 3104	return rport;3105}3106 3107/*3108 * Remote port features (RPF) implementation.3109 */3110 3111#define BFA_FCS_RPF_RETRIES	(3)3112#define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */3113 3114static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,3115				struct bfa_fcxp_s *fcxp_alloced);3116static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,3117			struct bfa_fcxp_s *fcxp,3118			void *cbarg,3119			bfa_status_t req_status,3120			u32 rsp_len,3121			u32 resid_len,3122			struct fchs_s *rsp_fchs);3123 3124static void     bfa_fcs_rpf_timeout(void *arg);3125 3126static void	bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,3127					enum rpf_event event);3128static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,3129				       enum rpf_event event);3130static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,3131				       enum rpf_event event);3132static void	bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,3133					enum rpf_event event);3134static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,3135					enum rpf_event event);3136static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,3137					enum rpf_event event);3138 3139static void3140bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3141{3142	struct bfa_fcs_rport_s *rport = rpf->rport;3143	struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;3144 3145	bfa_trc(rport->fcs, rport->pwwn);3146	bfa_trc(rport->fcs, rport->pid);3147	bfa_trc(rport->fcs, event);3148 3149	switch (event) {3150	case RPFSM_EVENT_RPORT_ONLINE:3151		/* Send RPSC2 to a Brocade fabric only. */3152		if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&3153			((rport->port->fabric->lps->brcd_switch) ||3154			(bfa_fcs_fabric_get_switch_oui(fabric) ==3155						BFA_FCS_BRCD_SWITCH_OUI))) {3156			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);3157			rpf->rpsc_retries = 0;3158			bfa_fcs_rpf_send_rpsc2(rpf, NULL);3159		}3160		break;3161 3162	case RPFSM_EVENT_RPORT_OFFLINE:3163		break;3164 3165	default:3166		bfa_sm_fault(rport->fcs, event);3167	}3168}3169 3170static void3171bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3172{3173	struct bfa_fcs_rport_s *rport = rpf->rport;3174 3175	bfa_trc(rport->fcs, event);3176 3177	switch (event) {3178	case RPFSM_EVENT_FCXP_SENT:3179		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);3180		break;3181 3182	case RPFSM_EVENT_RPORT_OFFLINE:3183		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3184		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);3185		rpf->rpsc_retries = 0;3186		break;3187 3188	default:3189		bfa_sm_fault(rport->fcs, event);3190	}3191}3192 3193static void3194bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3195{3196	struct bfa_fcs_rport_s *rport = rpf->rport;3197 3198	bfa_trc(rport->fcs, rport->pid);3199	bfa_trc(rport->fcs, event);3200 3201	switch (event) {3202	case RPFSM_EVENT_RPSC_COMP:3203		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);3204		/* Update speed info in f/w via BFA */3205		if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)3206			bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);3207		else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)3208			bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);3209		break;3210 3211	case RPFSM_EVENT_RPSC_FAIL:3212		/* RPSC not supported by rport */3213		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);3214		break;3215 3216	case RPFSM_EVENT_RPSC_ERROR:3217		/* need to retry...delayed a bit. */3218		if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {3219			bfa_timer_start(rport->fcs->bfa, &rpf->timer,3220				    bfa_fcs_rpf_timeout, rpf,3221				    BFA_FCS_RPF_RETRY_TIMEOUT);3222			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);3223		} else {3224			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);3225		}3226		break;3227 3228	case RPFSM_EVENT_RPORT_OFFLINE:3229		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3230		bfa_fcxp_discard(rpf->fcxp);3231		rpf->rpsc_retries = 0;3232		break;3233 3234	default:3235		bfa_sm_fault(rport->fcs, event);3236	}3237}3238 3239static void3240bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3241{3242	struct bfa_fcs_rport_s *rport = rpf->rport;3243 3244	bfa_trc(rport->fcs, rport->pid);3245	bfa_trc(rport->fcs, event);3246 3247	switch (event) {3248	case RPFSM_EVENT_TIMEOUT:3249		/* re-send the RPSC */3250		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);3251		bfa_fcs_rpf_send_rpsc2(rpf, NULL);3252		break;3253 3254	case RPFSM_EVENT_RPORT_OFFLINE:3255		bfa_timer_stop(&rpf->timer);3256		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3257		rpf->rpsc_retries = 0;3258		break;3259 3260	default:3261		bfa_sm_fault(rport->fcs, event);3262	}3263}3264 3265static void3266bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3267{3268	struct bfa_fcs_rport_s *rport = rpf->rport;3269 3270	bfa_trc(rport->fcs, rport->pwwn);3271	bfa_trc(rport->fcs, rport->pid);3272	bfa_trc(rport->fcs, event);3273 3274	switch (event) {3275	case RPFSM_EVENT_RPORT_OFFLINE:3276		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3277		rpf->rpsc_retries = 0;3278		break;3279 3280	default:3281		bfa_sm_fault(rport->fcs, event);3282	}3283}3284 3285static void3286bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3287{3288	struct bfa_fcs_rport_s *rport = rpf->rport;3289 3290	bfa_trc(rport->fcs, rport->pwwn);3291	bfa_trc(rport->fcs, rport->pid);3292	bfa_trc(rport->fcs, event);3293 3294	switch (event) {3295	case RPFSM_EVENT_RPORT_ONLINE:3296		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);3297		bfa_fcs_rpf_send_rpsc2(rpf, NULL);3298		break;3299 3300	case RPFSM_EVENT_RPORT_OFFLINE:3301		break;3302 3303	default:3304		bfa_sm_fault(rport->fcs, event);3305	}3306}3307/*3308 * Called when Rport is created.3309 */3310void3311bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)3312{3313	struct bfa_fcs_rpf_s *rpf = &rport->rpf;3314 3315	bfa_trc(rport->fcs, rport->pid);3316	rpf->rport = rport;3317 3318	bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);3319}3320 3321/*3322 * Called when Rport becomes online3323 */3324void3325bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)3326{3327	bfa_trc(rport->fcs, rport->pid);3328 3329	if (__fcs_min_cfg(rport->port->fcs))3330		return;3331 3332	if (bfa_fcs_fabric_is_switched(rport->port->fabric))3333		bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);3334}3335 3336/*3337 * Called when Rport becomes offline3338 */3339void3340bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)3341{3342	bfa_trc(rport->fcs, rport->pid);3343 3344	if (__fcs_min_cfg(rport->port->fcs))3345		return;3346 3347	rport->rpf.rpsc_speed = 0;3348	bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);3349}3350 3351static void3352bfa_fcs_rpf_timeout(void *arg)3353{3354	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;3355	struct bfa_fcs_rport_s *rport = rpf->rport;3356 3357	bfa_trc(rport->fcs, rport->pid);3358	bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);3359}3360 3361static void3362bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)3363{3364	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;3365	struct bfa_fcs_rport_s *rport = rpf->rport;3366	struct bfa_fcs_lport_s *port = rport->port;3367	struct fchs_s	fchs;3368	int		len;3369	struct bfa_fcxp_s *fcxp;3370 3371	bfa_trc(rport->fcs, rport->pwwn);3372 3373	fcxp = fcxp_alloced ? fcxp_alloced :3374	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);3375	if (!fcxp) {3376		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,3377				bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);3378		return;3379	}3380	rpf->fcxp = fcxp;3381 3382	len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,3383			    bfa_fcs_lport_get_fcid(port), &rport->pid, 1);3384 3385	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,3386			  FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,3387			  rpf, FC_MAX_PDUSZ, FC_ELS_TOV);3388	rport->stats.rpsc_sent++;3389	bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);3390 3391}3392 3393static void3394bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,3395			    bfa_status_t req_status, u32 rsp_len,3396			    u32 resid_len, struct fchs_s *rsp_fchs)3397{3398	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;3399	struct bfa_fcs_rport_s *rport = rpf->rport;3400	struct fc_ls_rjt_s *ls_rjt;3401	struct fc_rpsc2_acc_s *rpsc2_acc;3402	u16	num_ents;3403 3404	bfa_trc(rport->fcs, req_status);3405 3406	if (req_status != BFA_STATUS_OK) {3407		bfa_trc(rport->fcs, req_status);3408		if (req_status == BFA_STATUS_ETIMER)3409			rport->stats.rpsc_failed++;3410		bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);3411		return;3412	}3413 3414	rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);3415	if (rpsc2_acc->els_cmd == FC_ELS_ACC) {3416		rport->stats.rpsc_accs++;3417		num_ents = be16_to_cpu(rpsc2_acc->num_pids);3418		bfa_trc(rport->fcs, num_ents);3419		if (num_ents > 0) {3420			WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) !=3421						bfa_ntoh3b(rport->pid));3422			bfa_trc(rport->fcs,3423				be32_to_cpu(rpsc2_acc->port_info[0].pid));3424			bfa_trc(rport->fcs,3425				be16_to_cpu(rpsc2_acc->port_info[0].speed));3426			bfa_trc(rport->fcs,3427				be16_to_cpu(rpsc2_acc->port_info[0].index));3428			bfa_trc(rport->fcs,3429				rpsc2_acc->port_info[0].type);3430 3431			if (rpsc2_acc->port_info[0].speed == 0) {3432				bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);3433				return;3434			}3435 3436			rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(3437				be16_to_cpu(rpsc2_acc->port_info[0].speed));3438 3439			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);3440		}3441	} else {3442		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);3443		bfa_trc(rport->fcs, ls_rjt->reason_code);3444		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);3445		rport->stats.rpsc_rejects++;3446		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)3447			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);3448		else3449			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);3450	}3451}3452