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