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