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