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