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