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