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