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