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