1 /*
2  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17 
18 #include "bfad_drv.h"
19 #include "bfad_im.h"
20 #include "bfa_fcs.h"
21 #include "bfa_fcbuild.h"
22 #include "bfa_fc.h"
23 
24 BFA_TRC_FILE(FCS, PORT);
25 
26 static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
27 					 struct fchs_s *rx_fchs, u8 reason_code,
28 					 u8 reason_code_expl);
29 static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
30 			struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
31 static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
32 static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
33 static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
34 static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
35 static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
36 static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
37 static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
38 			struct fchs_s *rx_fchs,
39 			struct fc_echo_s *echo, u16 len);
40 static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
41 			struct fchs_s *rx_fchs,
42 			struct fc_rnid_cmd_s *rnid, u16 len);
43 static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
44 			struct fc_rnid_general_topology_data_s *gen_topo_data);
45 
46 static void	bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
47 static void	bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
48 static void	bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
49 
50 static void	bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
51 static void	bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
52 static void	bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
53 
54 static struct {
55 	void		(*init) (struct bfa_fcs_lport_s *port);
56 	void		(*online) (struct bfa_fcs_lport_s *port);
57 	void		(*offline) (struct bfa_fcs_lport_s *port);
58 } __port_action[] = {
59 	{
60 	bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
61 			bfa_fcs_lport_unknown_offline}, {
62 	bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
63 			bfa_fcs_lport_fab_offline}, {
64 	bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
65 			bfa_fcs_lport_n2n_offline},
66 	};
67 
68 /*
69  *  fcs_port_sm FCS logical port state machine
70  */
71 
72 enum bfa_fcs_lport_event {
73 	BFA_FCS_PORT_SM_CREATE = 1,
74 	BFA_FCS_PORT_SM_ONLINE = 2,
75 	BFA_FCS_PORT_SM_OFFLINE = 3,
76 	BFA_FCS_PORT_SM_DELETE = 4,
77 	BFA_FCS_PORT_SM_DELRPORT = 5,
78 	BFA_FCS_PORT_SM_STOP = 6,
79 };
80 
81 static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
82 					enum bfa_fcs_lport_event event);
83 static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
84 					enum bfa_fcs_lport_event event);
85 static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
86 					enum bfa_fcs_lport_event event);
87 static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
88 					enum bfa_fcs_lport_event event);
89 static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
90 					enum bfa_fcs_lport_event event);
91 static void	bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
92 					enum bfa_fcs_lport_event event);
93 
94 static void
bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)95 bfa_fcs_lport_sm_uninit(
96 	struct bfa_fcs_lport_s *port,
97 	enum bfa_fcs_lport_event event)
98 {
99 	bfa_trc(port->fcs, port->port_cfg.pwwn);
100 	bfa_trc(port->fcs, event);
101 
102 	switch (event) {
103 	case BFA_FCS_PORT_SM_CREATE:
104 		bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
105 		break;
106 
107 	default:
108 		bfa_sm_fault(port->fcs, event);
109 	}
110 }
111 
112 static void
bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)113 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
114 			enum bfa_fcs_lport_event event)
115 {
116 	bfa_trc(port->fcs, port->port_cfg.pwwn);
117 	bfa_trc(port->fcs, event);
118 
119 	switch (event) {
120 	case BFA_FCS_PORT_SM_ONLINE:
121 		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
122 		bfa_fcs_lport_online_actions(port);
123 		break;
124 
125 	case BFA_FCS_PORT_SM_DELETE:
126 		bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
127 		bfa_fcs_lport_deleted(port);
128 		break;
129 
130 	case BFA_FCS_PORT_SM_STOP:
131 		/* If vport - send completion call back */
132 		if (port->vport)
133 			bfa_fcs_vport_stop_comp(port->vport);
134 		break;
135 
136 	case BFA_FCS_PORT_SM_OFFLINE:
137 		break;
138 
139 	default:
140 		bfa_sm_fault(port->fcs, event);
141 	}
142 }
143 
144 static void
bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)145 bfa_fcs_lport_sm_online(
146 	struct bfa_fcs_lport_s *port,
147 	enum bfa_fcs_lport_event event)
148 {
149 	struct bfa_fcs_rport_s *rport;
150 	struct list_head		*qe, *qen;
151 
152 	bfa_trc(port->fcs, port->port_cfg.pwwn);
153 	bfa_trc(port->fcs, event);
154 
155 	switch (event) {
156 	case BFA_FCS_PORT_SM_OFFLINE:
157 		bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
158 		bfa_fcs_lport_offline_actions(port);
159 		break;
160 
161 	case BFA_FCS_PORT_SM_STOP:
162 		__port_action[port->fabric->fab_type].offline(port);
163 
164 		if (port->num_rports == 0) {
165 			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
166 			/* If vport - send completion call back */
167 			if (port->vport)
168 				bfa_fcs_vport_stop_comp(port->vport);
169 		} else {
170 			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
171 			list_for_each_safe(qe, qen, &port->rport_q) {
172 				rport = (struct bfa_fcs_rport_s *) qe;
173 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
174 			}
175 		}
176 		break;
177 
178 	case BFA_FCS_PORT_SM_DELETE:
179 
180 		__port_action[port->fabric->fab_type].offline(port);
181 
182 		if (port->num_rports == 0) {
183 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
184 			bfa_fcs_lport_deleted(port);
185 		} else {
186 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
187 			list_for_each_safe(qe, qen, &port->rport_q) {
188 				rport = (struct bfa_fcs_rport_s *) qe;
189 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
190 			}
191 		}
192 		break;
193 
194 	case BFA_FCS_PORT_SM_DELRPORT:
195 		break;
196 
197 	default:
198 		bfa_sm_fault(port->fcs, event);
199 	}
200 }
201 
202 static void
bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)203 bfa_fcs_lport_sm_offline(
204 	struct bfa_fcs_lport_s *port,
205 	enum bfa_fcs_lport_event event)
206 {
207 	struct bfa_fcs_rport_s *rport;
208 	struct list_head		*qe, *qen;
209 
210 	bfa_trc(port->fcs, port->port_cfg.pwwn);
211 	bfa_trc(port->fcs, event);
212 
213 	switch (event) {
214 	case BFA_FCS_PORT_SM_ONLINE:
215 		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
216 		bfa_fcs_lport_online_actions(port);
217 		break;
218 
219 	case BFA_FCS_PORT_SM_STOP:
220 		if (port->num_rports == 0) {
221 			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
222 			/* If vport - send completion call back */
223 			if (port->vport)
224 				bfa_fcs_vport_stop_comp(port->vport);
225 		} else {
226 			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
227 			list_for_each_safe(qe, qen, &port->rport_q) {
228 				rport = (struct bfa_fcs_rport_s *) qe;
229 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
230 			}
231 		}
232 		break;
233 
234 	case BFA_FCS_PORT_SM_DELETE:
235 		if (port->num_rports == 0) {
236 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
237 			bfa_fcs_lport_deleted(port);
238 		} else {
239 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
240 			list_for_each_safe(qe, qen, &port->rport_q) {
241 				rport = (struct bfa_fcs_rport_s *) qe;
242 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
243 			}
244 		}
245 		break;
246 
247 	case BFA_FCS_PORT_SM_DELRPORT:
248 	case BFA_FCS_PORT_SM_OFFLINE:
249 		break;
250 
251 	default:
252 		bfa_sm_fault(port->fcs, event);
253 	}
254 }
255 
256 static void
bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)257 bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
258 			  enum bfa_fcs_lport_event event)
259 {
260 	bfa_trc(port->fcs, port->port_cfg.pwwn);
261 	bfa_trc(port->fcs, event);
262 
263 	switch (event) {
264 	case BFA_FCS_PORT_SM_DELRPORT:
265 		if (port->num_rports == 0) {
266 			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
267 			/* If vport - send completion call back */
268 			if (port->vport)
269 				bfa_fcs_vport_stop_comp(port->vport);
270 		}
271 		break;
272 
273 	default:
274 		bfa_sm_fault(port->fcs, event);
275 	}
276 }
277 
278 static void
bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)279 bfa_fcs_lport_sm_deleting(
280 	struct bfa_fcs_lport_s *port,
281 	enum bfa_fcs_lport_event event)
282 {
283 	bfa_trc(port->fcs, port->port_cfg.pwwn);
284 	bfa_trc(port->fcs, event);
285 
286 	switch (event) {
287 	case BFA_FCS_PORT_SM_DELRPORT:
288 		if (port->num_rports == 0) {
289 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
290 			bfa_fcs_lport_deleted(port);
291 		}
292 		break;
293 
294 	default:
295 		bfa_sm_fault(port->fcs, event);
296 	}
297 }
298 
299 /*
300  *  fcs_port_pvt
301  */
302 
303 /*
304  * Send AEN notification
305  */
306 static void
bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s * port,enum bfa_lport_aen_event event)307 bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s *port,
308 			enum bfa_lport_aen_event event)
309 {
310 	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
311 	struct bfa_aen_entry_s  *aen_entry;
312 
313 	bfad_get_aen_entry(bfad, aen_entry);
314 	if (!aen_entry)
315 		return;
316 
317 	aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
318 	aen_entry->aen_data.lport.roles = port->port_cfg.roles;
319 	aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
320 					bfa_fcs_get_base_port(port->fcs));
321 	aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
322 
323 	/* Send the AEN notification */
324 	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
325 				  BFA_AEN_CAT_LPORT, event);
326 }
327 
328 /*
329  * Send a LS reject
330  */
331 static void
bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,u8 reason_code,u8 reason_code_expl)332 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
333 			 u8 reason_code, u8 reason_code_expl)
334 {
335 	struct fchs_s	fchs;
336 	struct bfa_fcxp_s *fcxp;
337 	struct bfa_rport_s *bfa_rport = NULL;
338 	int		len;
339 
340 	bfa_trc(port->fcs, rx_fchs->d_id);
341 	bfa_trc(port->fcs, rx_fchs->s_id);
342 
343 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
344 	if (!fcxp)
345 		return;
346 
347 	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
348 			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
349 			      rx_fchs->ox_id, reason_code, reason_code_expl);
350 
351 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
352 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
353 			  FC_MAX_PDUSZ, 0);
354 }
355 
356 /*
357  * Send a FCCT Reject
358  */
359 static void
bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,u8 reason_code,u8 reason_code_expl)360 bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
361 	struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl)
362 {
363 	struct fchs_s   fchs;
364 	struct bfa_fcxp_s *fcxp;
365 	struct bfa_rport_s *bfa_rport = NULL;
366 	int             len;
367 	struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1);
368 	struct ct_hdr_s *ct_hdr;
369 
370 	bfa_trc(port->fcs, rx_fchs->d_id);
371 	bfa_trc(port->fcs, rx_fchs->s_id);
372 
373 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
374 	if (!fcxp)
375 		return;
376 
377 	ct_hdr = bfa_fcxp_get_reqbuf(fcxp);
378 	ct_hdr->gs_type = rx_cthdr->gs_type;
379 	ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type;
380 
381 	len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id,
382 			bfa_fcs_lport_get_fcid(port),
383 			rx_fchs->ox_id, reason_code, reason_code_expl);
384 
385 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
386 			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
387 			FC_MAX_PDUSZ, 0);
388 }
389 
390 /*
391  * Process incoming plogi from a remote port.
392  */
393 static void
bfa_fcs_lport_plogi(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_logi_s * plogi)394 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
395 		struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
396 {
397 	struct bfa_fcs_rport_s *rport;
398 
399 	bfa_trc(port->fcs, rx_fchs->d_id);
400 	bfa_trc(port->fcs, rx_fchs->s_id);
401 
402 	/*
403 	 * If min cfg mode is enabled, drop any incoming PLOGIs
404 	 */
405 	if (__fcs_min_cfg(port->fcs)) {
406 		bfa_trc(port->fcs, rx_fchs->s_id);
407 		return;
408 	}
409 
410 	if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
411 		bfa_trc(port->fcs, rx_fchs->s_id);
412 		/*
413 		 * send a LS reject
414 		 */
415 		bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
416 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
417 					FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
418 		return;
419 	}
420 
421 	/*
422 	 * Direct Attach P2P mode : verify address assigned by the r-port.
423 	 */
424 	if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
425 		(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
426 			   (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
427 		if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
428 			/* Address assigned to us cannot be a WKA */
429 			bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
430 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
431 					FC_LS_RJT_EXP_INVALID_NPORT_ID);
432 			return;
433 		}
434 		port->pid  = rx_fchs->d_id;
435 		bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
436 	}
437 
438 	/*
439 	 * First, check if we know the device by pwwn.
440 	 */
441 	rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
442 	if (rport) {
443 		/*
444 		 * Direct Attach P2P mode : handle address assigned by r-port.
445 		 */
446 		if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
447 			(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
448 			(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
449 			port->pid  = rx_fchs->d_id;
450 			bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
451 			rport->pid = rx_fchs->s_id;
452 		}
453 		bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
454 		return;
455 	}
456 
457 	/*
458 	 * Next, lookup rport by PID.
459 	 */
460 	rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
461 	if (!rport) {
462 		/*
463 		 * Inbound PLOGI from a new device.
464 		 */
465 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
466 		return;
467 	}
468 
469 	/*
470 	 * Rport is known only by PID.
471 	 */
472 	if (rport->pwwn) {
473 		/*
474 		 * This is a different device with the same pid. Old device
475 		 * disappeared. Send implicit LOGO to old device.
476 		 */
477 		WARN_ON(rport->pwwn == plogi->port_name);
478 		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
479 
480 		/*
481 		 * Inbound PLOGI from a new device (with old PID).
482 		 */
483 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
484 		return;
485 	}
486 
487 	/*
488 	 * PLOGI crossing each other.
489 	 */
490 	WARN_ON(rport->pwwn != WWN_NULL);
491 	bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
492 }
493 
494 /*
495  * Process incoming ECHO.
496  * Since it does not require a login, it is processed here.
497  */
498 static void
bfa_fcs_lport_echo(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_echo_s * echo,u16 rx_len)499 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
500 		struct fc_echo_s *echo, u16 rx_len)
501 {
502 	struct fchs_s		fchs;
503 	struct bfa_fcxp_s	*fcxp;
504 	struct bfa_rport_s	*bfa_rport = NULL;
505 	int			len, pyld_len;
506 
507 	bfa_trc(port->fcs, rx_fchs->s_id);
508 	bfa_trc(port->fcs, rx_fchs->d_id);
509 
510 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
511 	if (!fcxp)
512 		return;
513 
514 	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
515 				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
516 				rx_fchs->ox_id);
517 
518 	/*
519 	 * Copy the payload (if any) from the echo frame
520 	 */
521 	pyld_len = rx_len - sizeof(struct fchs_s);
522 	bfa_trc(port->fcs, rx_len);
523 	bfa_trc(port->fcs, pyld_len);
524 
525 	if (pyld_len > len)
526 		memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
527 			sizeof(struct fc_echo_s), (echo + 1),
528 			(pyld_len - sizeof(struct fc_echo_s)));
529 
530 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
531 			BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
532 			FC_MAX_PDUSZ, 0);
533 }
534 
535 /*
536  * Process incoming RNID.
537  * Since it does not require a login, it is processed here.
538  */
539 static void
bfa_fcs_lport_rnid(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_rnid_cmd_s * rnid,u16 rx_len)540 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
541 		struct fc_rnid_cmd_s *rnid, u16 rx_len)
542 {
543 	struct fc_rnid_common_id_data_s common_id_data;
544 	struct fc_rnid_general_topology_data_s gen_topo_data;
545 	struct fchs_s	fchs;
546 	struct bfa_fcxp_s *fcxp;
547 	struct bfa_rport_s *bfa_rport = NULL;
548 	u16	len;
549 	u32	data_format;
550 
551 	bfa_trc(port->fcs, rx_fchs->s_id);
552 	bfa_trc(port->fcs, rx_fchs->d_id);
553 	bfa_trc(port->fcs, rx_len);
554 
555 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
556 	if (!fcxp)
557 		return;
558 
559 	/*
560 	 * Check Node Indentification Data Format
561 	 * We only support General Topology Discovery Format.
562 	 * For any other requested Data Formats, we return Common Node Id Data
563 	 * only, as per FC-LS.
564 	 */
565 	bfa_trc(port->fcs, rnid->node_id_data_format);
566 	if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
567 		data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
568 		/*
569 		 * Get General topology data for this port
570 		 */
571 		bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
572 	} else {
573 		data_format = RNID_NODEID_DATA_FORMAT_COMMON;
574 	}
575 
576 	/*
577 	 * Copy the Node Id Info
578 	 */
579 	common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
580 	common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
581 
582 	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
583 				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
584 				rx_fchs->ox_id, data_format, &common_id_data,
585 				&gen_topo_data);
586 
587 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
588 			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
589 			FC_MAX_PDUSZ, 0);
590 }
591 
592 /*
593  *  Fill out General Topolpgy Discovery Data for RNID ELS.
594  */
595 static void
bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s * port,struct fc_rnid_general_topology_data_s * gen_topo_data)596 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
597 			struct fc_rnid_general_topology_data_s *gen_topo_data)
598 {
599 	memset(gen_topo_data, 0,
600 		      sizeof(struct fc_rnid_general_topology_data_s));
601 
602 	gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
603 	gen_topo_data->phy_port_num = 0;	/* @todo */
604 	gen_topo_data->num_attached_nodes = cpu_to_be32(1);
605 }
606 
607 static void
bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s * port)608 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
609 {
610 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
611 	char	lpwwn_buf[BFA_STRING_32];
612 
613 	bfa_trc(port->fcs, port->fabric->oper_type);
614 
615 	__port_action[port->fabric->fab_type].init(port);
616 	__port_action[port->fabric->fab_type].online(port);
617 
618 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
619 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
620 		"Logical port online: WWN = %s Role = %s\n",
621 		lpwwn_buf, "Initiator");
622 	bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE);
623 
624 	bfad->bfad_flags |= BFAD_PORT_ONLINE;
625 }
626 
627 static void
bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s * port)628 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
629 {
630 	struct list_head	*qe, *qen;
631 	struct bfa_fcs_rport_s *rport;
632 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
633 	char    lpwwn_buf[BFA_STRING_32];
634 
635 	bfa_trc(port->fcs, port->fabric->oper_type);
636 
637 	__port_action[port->fabric->fab_type].offline(port);
638 
639 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
640 	if (bfa_sm_cmp_state(port->fabric,
641 			bfa_fcs_fabric_sm_online) == BFA_TRUE) {
642 		BFA_LOG(KERN_ERR, bfad, bfa_log_level,
643 		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
644 		lpwwn_buf, "Initiator");
645 		bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
646 	} else {
647 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
648 		"Logical port taken offline: WWN = %s Role = %s\n",
649 		lpwwn_buf, "Initiator");
650 		bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE);
651 	}
652 
653 	list_for_each_safe(qe, qen, &port->rport_q) {
654 		rport = (struct bfa_fcs_rport_s *) qe;
655 		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
656 	}
657 }
658 
659 static void
bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s * port)660 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
661 {
662 	WARN_ON(1);
663 }
664 
665 static void
bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s * port)666 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
667 {
668 	WARN_ON(1);
669 }
670 
671 static void
bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s * port)672 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
673 {
674 	WARN_ON(1);
675 }
676 
677 static void
bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs)678 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
679 {
680 	struct fchs_s fchs;
681 	struct bfa_fcxp_s *fcxp;
682 	int		len;
683 
684 	bfa_trc(port->fcs, rx_fchs->d_id);
685 	bfa_trc(port->fcs, rx_fchs->s_id);
686 
687 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
688 	if (!fcxp)
689 		return;
690 
691 	len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
692 			rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
693 			rx_fchs->ox_id, 0);
694 
695 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
696 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
697 			  FC_MAX_PDUSZ, 0);
698 }
699 static void
bfa_fcs_lport_deleted(struct bfa_fcs_lport_s * port)700 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
701 {
702 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
703 	char    lpwwn_buf[BFA_STRING_32];
704 
705 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
706 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
707 		"Logical port deleted: WWN = %s Role = %s\n",
708 		lpwwn_buf, "Initiator");
709 	bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE);
710 
711 	/* Base port will be deleted by the OS driver */
712 	if (port->vport) {
713 		bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
714 				port->fabric->vf_drv,
715 				port->vport ? port->vport->vport_drv : NULL);
716 		bfa_fcs_vport_delete_comp(port->vport);
717 	} else {
718 		bfa_wc_down(&port->fabric->wc);
719 	}
720 }
721 
722 
723 /*
724  * Unsolicited frame receive handling.
725  */
726 void
bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s * lport,struct fchs_s * fchs,u16 len)727 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
728 			struct fchs_s *fchs, u16 len)
729 {
730 	u32	pid = fchs->s_id;
731 	struct bfa_fcs_rport_s *rport = NULL;
732 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
733 
734 	bfa_stats(lport, uf_recvs);
735 	bfa_trc(lport->fcs, fchs->type);
736 
737 	if (!bfa_fcs_lport_is_online(lport)) {
738 		bfa_stats(lport, uf_recv_drops);
739 		return;
740 	}
741 
742 	/*
743 	 * First, handle ELSs that donot require a login.
744 	 */
745 	/*
746 	 * Handle PLOGI first
747 	 */
748 	if ((fchs->type == FC_TYPE_ELS) &&
749 		(els_cmd->els_code == FC_ELS_PLOGI)) {
750 		bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
751 		return;
752 	}
753 
754 	/*
755 	 * Handle ECHO separately.
756 	 */
757 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
758 		bfa_fcs_lport_echo(lport, fchs,
759 				(struct fc_echo_s *)els_cmd, len);
760 		return;
761 	}
762 
763 	/*
764 	 * Handle RNID separately.
765 	 */
766 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
767 		bfa_fcs_lport_rnid(lport, fchs,
768 			(struct fc_rnid_cmd_s *) els_cmd, len);
769 		return;
770 	}
771 
772 	if (fchs->type == FC_TYPE_BLS) {
773 		if ((fchs->routing == FC_RTG_BASIC_LINK) &&
774 				(fchs->cat_info == FC_CAT_ABTS))
775 			bfa_fcs_lport_abts_acc(lport, fchs);
776 		return;
777 	}
778 
779 	if (fchs->type == FC_TYPE_SERVICES) {
780 		/*
781 		 * Unhandled FC-GS frames. Send a FC-CT Reject
782 		 */
783 		bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP,
784 				CT_NS_EXP_NOADDITIONAL);
785 		return;
786 	}
787 
788 	/*
789 	 * look for a matching remote port ID
790 	 */
791 	rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
792 	if (rport) {
793 		bfa_trc(rport->fcs, fchs->s_id);
794 		bfa_trc(rport->fcs, fchs->d_id);
795 		bfa_trc(rport->fcs, fchs->type);
796 
797 		bfa_fcs_rport_uf_recv(rport, fchs, len);
798 		return;
799 	}
800 
801 	/*
802 	 * Only handles ELS frames for now.
803 	 */
804 	if (fchs->type != FC_TYPE_ELS) {
805 		bfa_trc(lport->fcs, fchs->s_id);
806 		bfa_trc(lport->fcs, fchs->d_id);
807 		/* ignore type FC_TYPE_FC_FSS */
808 		if (fchs->type != FC_TYPE_FC_FSS)
809 			bfa_sm_fault(lport->fcs, fchs->type);
810 		return;
811 	}
812 
813 	bfa_trc(lport->fcs, els_cmd->els_code);
814 	if (els_cmd->els_code == FC_ELS_RSCN) {
815 		bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
816 		return;
817 	}
818 
819 	if (els_cmd->els_code == FC_ELS_LOGO) {
820 		/*
821 		 * @todo Handle LOGO frames received.
822 		 */
823 		return;
824 	}
825 
826 	if (els_cmd->els_code == FC_ELS_PRLI) {
827 		/*
828 		 * @todo Handle PRLI frames received.
829 		 */
830 		return;
831 	}
832 
833 	/*
834 	 * Unhandled ELS frames. Send a LS_RJT.
835 	 */
836 	bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
837 				 FC_LS_RJT_EXP_NO_ADDL_INFO);
838 
839 }
840 
841 /*
842  *   PID based Lookup for a R-Port in the Port R-Port Queue
843  */
844 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s * port,u32 pid)845 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
846 {
847 	struct bfa_fcs_rport_s *rport;
848 	struct list_head	*qe;
849 
850 	list_for_each(qe, &port->rport_q) {
851 		rport = (struct bfa_fcs_rport_s *) qe;
852 		if (rport->pid == pid)
853 			return rport;
854 	}
855 
856 	bfa_trc(port->fcs, pid);
857 	return NULL;
858 }
859 
860 /*
861  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
862  */
863 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s * port,wwn_t pwwn)864 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
865 {
866 	struct bfa_fcs_rport_s *rport;
867 	struct list_head	*qe;
868 
869 	list_for_each(qe, &port->rport_q) {
870 		rport = (struct bfa_fcs_rport_s *) qe;
871 		if (wwn_is_equal(rport->pwwn, pwwn))
872 			return rport;
873 	}
874 
875 	bfa_trc(port->fcs, pwwn);
876 	return NULL;
877 }
878 
879 /*
880  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
881  */
882 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s * port,wwn_t nwwn)883 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
884 {
885 	struct bfa_fcs_rport_s *rport;
886 	struct list_head	*qe;
887 
888 	list_for_each(qe, &port->rport_q) {
889 		rport = (struct bfa_fcs_rport_s *) qe;
890 		if (wwn_is_equal(rport->nwwn, nwwn))
891 			return rport;
892 	}
893 
894 	bfa_trc(port->fcs, nwwn);
895 	return NULL;
896 }
897 
898 /*
899  * Called by rport module when new rports are discovered.
900  */
901 void
bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s * port,struct bfa_fcs_rport_s * rport)902 bfa_fcs_lport_add_rport(
903 	struct bfa_fcs_lport_s *port,
904 	struct bfa_fcs_rport_s *rport)
905 {
906 	list_add_tail(&rport->qe, &port->rport_q);
907 	port->num_rports++;
908 }
909 
910 /*
911  * Called by rport module to when rports are deleted.
912  */
913 void
bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s * port,struct bfa_fcs_rport_s * rport)914 bfa_fcs_lport_del_rport(
915 	struct bfa_fcs_lport_s *port,
916 	struct bfa_fcs_rport_s *rport)
917 {
918 	WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
919 	list_del(&rport->qe);
920 	port->num_rports--;
921 
922 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
923 }
924 
925 /*
926  * Called by fabric for base port when fabric login is complete.
927  * Called by vport for virtual ports when FDISC is complete.
928  */
929 void
bfa_fcs_lport_online(struct bfa_fcs_lport_s * port)930 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
931 {
932 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
933 }
934 
935 /*
936  * Called by fabric for base port when fabric goes offline.
937  * Called by vport for virtual ports when virtual port becomes offline.
938  */
939 void
bfa_fcs_lport_offline(struct bfa_fcs_lport_s * port)940 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
941 {
942 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
943 }
944 
945 /*
946  * Called by fabric to delete base lport and associated resources.
947  *
948  * Called by vport to delete lport and associated resources. Should call
949  * bfa_fcs_vport_delete_comp() for vports on completion.
950  */
951 void
bfa_fcs_lport_delete(struct bfa_fcs_lport_s * port)952 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
953 {
954 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
955 }
956 
957 /*
958  * Return TRUE if port is online, else return FALSE
959  */
960 bfa_boolean_t
bfa_fcs_lport_is_online(struct bfa_fcs_lport_s * port)961 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
962 {
963 	return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
964 }
965 
966 /*
967   * Attach time initialization of logical ports.
968  */
969 void
bfa_fcs_lport_attach(struct bfa_fcs_lport_s * lport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_fcs_vport_s * vport)970 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
971 		   u16 vf_id, struct bfa_fcs_vport_s *vport)
972 {
973 	lport->fcs = fcs;
974 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
975 	lport->vport = vport;
976 	lport->lp_tag = (vport) ? vport->lps->bfa_tag :
977 				  lport->fabric->lps->bfa_tag;
978 
979 	INIT_LIST_HEAD(&lport->rport_q);
980 	lport->num_rports = 0;
981 }
982 
983 /*
984  * Logical port initialization of base or virtual port.
985  * Called by fabric for base port or by vport for virtual ports.
986  */
987 
988 void
bfa_fcs_lport_init(struct bfa_fcs_lport_s * lport,struct bfa_lport_cfg_s * port_cfg)989 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
990 	struct bfa_lport_cfg_s *port_cfg)
991 {
992 	struct bfa_fcs_vport_s *vport = lport->vport;
993 	struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
994 	char    lpwwn_buf[BFA_STRING_32];
995 
996 	lport->port_cfg = *port_cfg;
997 
998 	lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
999 					lport->port_cfg.roles,
1000 					lport->fabric->vf_drv,
1001 					vport ? vport->vport_drv : NULL);
1002 
1003 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
1004 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
1005 		"New logical port created: WWN = %s Role = %s\n",
1006 		lpwwn_buf, "Initiator");
1007 	bfa_fcs_lport_aen_post(lport, BFA_LPORT_AEN_NEW);
1008 
1009 	bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
1010 	bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
1011 }
1012 
1013 /*
1014  *  fcs_lport_api
1015  */
1016 
1017 void
bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s * port,struct bfa_lport_attr_s * port_attr)1018 bfa_fcs_lport_get_attr(
1019 	struct bfa_fcs_lport_s *port,
1020 	struct bfa_lport_attr_s *port_attr)
1021 {
1022 	if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
1023 		port_attr->pid = port->pid;
1024 	else
1025 		port_attr->pid = 0;
1026 
1027 	port_attr->port_cfg = port->port_cfg;
1028 
1029 	if (port->fabric) {
1030 		port_attr->port_type = port->fabric->oper_type;
1031 		port_attr->loopback = bfa_sm_cmp_state(port->fabric,
1032 				bfa_fcs_fabric_sm_loopback);
1033 		port_attr->authfail =
1034 			bfa_sm_cmp_state(port->fabric,
1035 				bfa_fcs_fabric_sm_auth_failed);
1036 		port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
1037 		memcpy(port_attr->fabric_ip_addr,
1038 			bfa_fcs_lport_get_fabric_ipaddr(port),
1039 			BFA_FCS_FABRIC_IPADDR_SZ);
1040 
1041 		if (port->vport != NULL) {
1042 			port_attr->port_type = BFA_PORT_TYPE_VPORT;
1043 			port_attr->fpma_mac =
1044 				port->vport->lps->lp_mac;
1045 		} else {
1046 			port_attr->fpma_mac =
1047 				port->fabric->lps->lp_mac;
1048 		}
1049 	} else {
1050 		port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
1051 		port_attr->state = BFA_LPORT_UNINIT;
1052 	}
1053 }
1054 
1055 /*
1056  *  bfa_fcs_lport_fab port fab functions
1057  */
1058 
1059 /*
1060  *   Called by port to initialize fabric services of the base port.
1061  */
1062 static void
bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s * port)1063 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
1064 {
1065 	bfa_fcs_lport_ns_init(port);
1066 	bfa_fcs_lport_scn_init(port);
1067 	bfa_fcs_lport_ms_init(port);
1068 }
1069 
1070 /*
1071  *   Called by port to notify transition to online state.
1072  */
1073 static void
bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s * port)1074 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
1075 {
1076 	bfa_fcs_lport_ns_online(port);
1077 	bfa_fcs_lport_scn_online(port);
1078 }
1079 
1080 /*
1081  *   Called by port to notify transition to offline state.
1082  */
1083 static void
bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s * port)1084 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
1085 {
1086 	bfa_fcs_lport_ns_offline(port);
1087 	bfa_fcs_lport_scn_offline(port);
1088 	bfa_fcs_lport_ms_offline(port);
1089 }
1090 
1091 /*
1092  *  bfa_fcs_lport_n2n  functions
1093  */
1094 
1095 /*
1096  *   Called by fcs/port to initialize N2N topology.
1097  */
1098 static void
bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s * port)1099 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
1100 {
1101 }
1102 
1103 /*
1104  *   Called by fcs/port to notify transition to online state.
1105  */
1106 static void
bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s * port)1107 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
1108 {
1109 	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1110 	struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
1111 	struct bfa_fcs_rport_s *rport;
1112 
1113 	bfa_trc(port->fcs, pcfg->pwwn);
1114 
1115 	/*
1116 	 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
1117 	 * and assign an Address. if not, we need to wait for its PLOGI.
1118 	 *
1119 	 * If our PWWN is < than that of the remote port, it will send a PLOGI
1120 	 * with the PIDs assigned. The rport state machine take care of this
1121 	 * incoming PLOGI.
1122 	 */
1123 	if (memcmp
1124 	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
1125 	     sizeof(wwn_t)) > 0) {
1126 		port->pid = N2N_LOCAL_PID;
1127 		bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
1128 		/*
1129 		 * First, check if we know the device by pwwn.
1130 		 */
1131 		rport = bfa_fcs_lport_get_rport_by_pwwn(port,
1132 							n2n_port->rem_port_wwn);
1133 		if (rport) {
1134 			bfa_trc(port->fcs, rport->pid);
1135 			bfa_trc(port->fcs, rport->pwwn);
1136 			rport->pid = N2N_REMOTE_PID;
1137 			bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
1138 			return;
1139 		}
1140 
1141 		/*
1142 		 * In n2n there can be only one rport. Delete the old one
1143 		 * whose pid should be zero, because it is offline.
1144 		 */
1145 		if (port->num_rports > 0) {
1146 			rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1147 			WARN_ON(rport == NULL);
1148 			if (rport) {
1149 				bfa_trc(port->fcs, rport->pwwn);
1150 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
1151 			}
1152 		}
1153 		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1154 	}
1155 }
1156 
1157 /*
1158  *   Called by fcs/port to notify transition to offline state.
1159  */
1160 static void
bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s * port)1161 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1162 {
1163 	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1164 
1165 	bfa_trc(port->fcs, port->pid);
1166 	port->pid = 0;
1167 	n2n_port->rem_port_wwn = 0;
1168 	n2n_port->reply_oxid = 0;
1169 }
1170 
1171 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1172 
1173 /*
1174  * forward declarations
1175  */
1176 static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1177 					    struct bfa_fcxp_s *fcxp_alloced);
1178 static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1179 					    struct bfa_fcxp_s *fcxp_alloced);
1180 static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1181 					   struct bfa_fcxp_s *fcxp_alloced);
1182 static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1183 						struct bfa_fcxp_s *fcxp,
1184 						void *cbarg,
1185 						bfa_status_t req_status,
1186 						u32 rsp_len,
1187 						u32 resid_len,
1188 						struct fchs_s *rsp_fchs);
1189 static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1190 						struct bfa_fcxp_s *fcxp,
1191 						void *cbarg,
1192 						bfa_status_t req_status,
1193 						u32 rsp_len,
1194 						u32 resid_len,
1195 						struct fchs_s *rsp_fchs);
1196 static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1197 					       struct bfa_fcxp_s *fcxp,
1198 					       void *cbarg,
1199 					       bfa_status_t req_status,
1200 					       u32 rsp_len,
1201 					       u32 resid_len,
1202 					       struct fchs_s *rsp_fchs);
1203 static void     bfa_fcs_lport_fdmi_timeout(void *arg);
1204 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1205 						  u8 *pyld);
1206 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1207 						  u8 *pyld);
1208 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1209 						 u8 *pyld);
1210 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1211 						       fdmi, u8 *pyld);
1212 static void	bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1213 				 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1214 static void	bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1215 				  struct bfa_fcs_fdmi_port_attr_s *port_attr);
1216 u32	bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed);
1217 
1218 /*
1219  *  fcs_fdmi_sm FCS FDMI state machine
1220  */
1221 
1222 /*
1223  *  FDMI State Machine events
1224  */
1225 enum port_fdmi_event {
1226 	FDMISM_EVENT_PORT_ONLINE = 1,
1227 	FDMISM_EVENT_PORT_OFFLINE = 2,
1228 	FDMISM_EVENT_RSP_OK = 4,
1229 	FDMISM_EVENT_RSP_ERROR = 5,
1230 	FDMISM_EVENT_TIMEOUT = 6,
1231 	FDMISM_EVENT_RHBA_SENT = 7,
1232 	FDMISM_EVENT_RPRT_SENT = 8,
1233 	FDMISM_EVENT_RPA_SENT = 9,
1234 };
1235 
1236 static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1237 					     enum port_fdmi_event event);
1238 static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
1239 				struct bfa_fcs_lport_fdmi_s *fdmi,
1240 				enum port_fdmi_event event);
1241 static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1242 					  enum port_fdmi_event event);
1243 static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
1244 				struct bfa_fcs_lport_fdmi_s *fdmi,
1245 				enum port_fdmi_event event);
1246 static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
1247 				struct bfa_fcs_lport_fdmi_s *fdmi,
1248 				enum port_fdmi_event event);
1249 static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1250 					  enum port_fdmi_event event);
1251 static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
1252 				struct bfa_fcs_lport_fdmi_s *fdmi,
1253 				enum port_fdmi_event event);
1254 static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
1255 				struct bfa_fcs_lport_fdmi_s *fdmi,
1256 				enum port_fdmi_event event);
1257 static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1258 					 enum port_fdmi_event event);
1259 static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
1260 				struct bfa_fcs_lport_fdmi_s *fdmi,
1261 				enum port_fdmi_event event);
1262 static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1263 					    enum port_fdmi_event event);
1264 static void     bfa_fcs_lport_fdmi_sm_disabled(
1265 				struct bfa_fcs_lport_fdmi_s *fdmi,
1266 				enum port_fdmi_event event);
1267 /*
1268  *	Start in offline state - awaiting MS to send start.
1269  */
1270 static void
bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1271 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1272 			     enum port_fdmi_event event)
1273 {
1274 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1275 
1276 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1277 	bfa_trc(port->fcs, event);
1278 
1279 	fdmi->retry_cnt = 0;
1280 
1281 	switch (event) {
1282 	case FDMISM_EVENT_PORT_ONLINE:
1283 		if (port->vport) {
1284 			/*
1285 			 * For Vports, register a new port.
1286 			 */
1287 			bfa_sm_set_state(fdmi,
1288 					 bfa_fcs_lport_fdmi_sm_sending_rprt);
1289 			bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1290 		} else {
1291 			/*
1292 			 * For a base port, we should first register the HBA
1293 			 * attribute. The HBA attribute also contains the base
1294 			 *  port registration.
1295 			 */
1296 			bfa_sm_set_state(fdmi,
1297 					 bfa_fcs_lport_fdmi_sm_sending_rhba);
1298 			bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1299 		}
1300 		break;
1301 
1302 	case FDMISM_EVENT_PORT_OFFLINE:
1303 		break;
1304 
1305 	default:
1306 		bfa_sm_fault(port->fcs, event);
1307 	}
1308 }
1309 
1310 static void
bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1311 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1312 				  enum port_fdmi_event event)
1313 {
1314 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1315 
1316 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1317 	bfa_trc(port->fcs, event);
1318 
1319 	switch (event) {
1320 	case FDMISM_EVENT_RHBA_SENT:
1321 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1322 		break;
1323 
1324 	case FDMISM_EVENT_PORT_OFFLINE:
1325 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1326 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1327 					   &fdmi->fcxp_wqe);
1328 		break;
1329 
1330 	default:
1331 		bfa_sm_fault(port->fcs, event);
1332 	}
1333 }
1334 
1335 static void
bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1336 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1337 			enum port_fdmi_event event)
1338 {
1339 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1340 
1341 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1342 	bfa_trc(port->fcs, event);
1343 
1344 	switch (event) {
1345 	case FDMISM_EVENT_RSP_ERROR:
1346 		/*
1347 		 * if max retries have not been reached, start timer for a
1348 		 * delayed retry
1349 		 */
1350 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1351 			bfa_sm_set_state(fdmi,
1352 					bfa_fcs_lport_fdmi_sm_rhba_retry);
1353 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1354 					    &fdmi->timer,
1355 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1356 					    BFA_FCS_RETRY_TIMEOUT);
1357 		} else {
1358 			/*
1359 			 * set state to offline
1360 			 */
1361 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1362 		}
1363 		break;
1364 
1365 	case FDMISM_EVENT_RSP_OK:
1366 		/*
1367 		 * Initiate Register Port Attributes
1368 		 */
1369 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1370 		fdmi->retry_cnt = 0;
1371 		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1372 		break;
1373 
1374 	case FDMISM_EVENT_PORT_OFFLINE:
1375 		bfa_fcxp_discard(fdmi->fcxp);
1376 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1377 		break;
1378 
1379 	default:
1380 		bfa_sm_fault(port->fcs, event);
1381 	}
1382 }
1383 
1384 static void
bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1385 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1386 				enum port_fdmi_event event)
1387 {
1388 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1389 
1390 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1391 	bfa_trc(port->fcs, event);
1392 
1393 	switch (event) {
1394 	case FDMISM_EVENT_TIMEOUT:
1395 		/*
1396 		 * Retry Timer Expired. Re-send
1397 		 */
1398 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1399 		bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1400 		break;
1401 
1402 	case FDMISM_EVENT_PORT_OFFLINE:
1403 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1404 		bfa_timer_stop(&fdmi->timer);
1405 		break;
1406 
1407 	default:
1408 		bfa_sm_fault(port->fcs, event);
1409 	}
1410 }
1411 
1412 /*
1413 * RPRT : Register Port
1414  */
1415 static void
bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1416 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1417 				  enum port_fdmi_event event)
1418 {
1419 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1420 
1421 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1422 	bfa_trc(port->fcs, event);
1423 
1424 	switch (event) {
1425 	case FDMISM_EVENT_RPRT_SENT:
1426 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1427 		break;
1428 
1429 	case FDMISM_EVENT_PORT_OFFLINE:
1430 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1431 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1432 					   &fdmi->fcxp_wqe);
1433 		break;
1434 
1435 	default:
1436 		bfa_sm_fault(port->fcs, event);
1437 	}
1438 }
1439 
1440 static void
bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1441 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1442 			enum port_fdmi_event event)
1443 {
1444 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1445 
1446 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1447 	bfa_trc(port->fcs, event);
1448 
1449 	switch (event) {
1450 	case FDMISM_EVENT_RSP_ERROR:
1451 		/*
1452 		 * if max retries have not been reached, start timer for a
1453 		 * delayed retry
1454 		 */
1455 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1456 			bfa_sm_set_state(fdmi,
1457 					bfa_fcs_lport_fdmi_sm_rprt_retry);
1458 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1459 					    &fdmi->timer,
1460 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1461 					    BFA_FCS_RETRY_TIMEOUT);
1462 
1463 		} else {
1464 			/*
1465 			 * set state to offline
1466 			 */
1467 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1468 			fdmi->retry_cnt = 0;
1469 		}
1470 		break;
1471 
1472 	case FDMISM_EVENT_RSP_OK:
1473 		fdmi->retry_cnt = 0;
1474 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1475 		break;
1476 
1477 	case FDMISM_EVENT_PORT_OFFLINE:
1478 		bfa_fcxp_discard(fdmi->fcxp);
1479 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1480 		break;
1481 
1482 	default:
1483 		bfa_sm_fault(port->fcs, event);
1484 	}
1485 }
1486 
1487 static void
bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1488 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1489 				enum port_fdmi_event event)
1490 {
1491 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1492 
1493 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1494 	bfa_trc(port->fcs, event);
1495 
1496 	switch (event) {
1497 	case FDMISM_EVENT_TIMEOUT:
1498 		/*
1499 		 * Retry Timer Expired. Re-send
1500 		 */
1501 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1502 		bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1503 		break;
1504 
1505 	case FDMISM_EVENT_PORT_OFFLINE:
1506 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1507 		bfa_timer_stop(&fdmi->timer);
1508 		break;
1509 
1510 	default:
1511 		bfa_sm_fault(port->fcs, event);
1512 	}
1513 }
1514 
1515 /*
1516  * Register Port Attributes
1517  */
1518 static void
bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1519 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1520 				 enum port_fdmi_event event)
1521 {
1522 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1523 
1524 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1525 	bfa_trc(port->fcs, event);
1526 
1527 	switch (event) {
1528 	case FDMISM_EVENT_RPA_SENT:
1529 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1530 		break;
1531 
1532 	case FDMISM_EVENT_PORT_OFFLINE:
1533 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1534 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1535 					   &fdmi->fcxp_wqe);
1536 		break;
1537 
1538 	default:
1539 		bfa_sm_fault(port->fcs, event);
1540 	}
1541 }
1542 
1543 static void
bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1544 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1545 			enum port_fdmi_event event)
1546 {
1547 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1548 
1549 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1550 	bfa_trc(port->fcs, event);
1551 
1552 	switch (event) {
1553 	case FDMISM_EVENT_RSP_ERROR:
1554 		/*
1555 		 * if max retries have not been reached, start timer for a
1556 		 * delayed retry
1557 		 */
1558 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1559 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1560 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1561 					    &fdmi->timer,
1562 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1563 					    BFA_FCS_RETRY_TIMEOUT);
1564 		} else {
1565 			/*
1566 			 * set state to offline
1567 			 */
1568 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1569 			fdmi->retry_cnt = 0;
1570 		}
1571 		break;
1572 
1573 	case FDMISM_EVENT_RSP_OK:
1574 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1575 		fdmi->retry_cnt = 0;
1576 		break;
1577 
1578 	case FDMISM_EVENT_PORT_OFFLINE:
1579 		bfa_fcxp_discard(fdmi->fcxp);
1580 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1581 		break;
1582 
1583 	default:
1584 		bfa_sm_fault(port->fcs, event);
1585 	}
1586 }
1587 
1588 static void
bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1589 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1590 			       enum port_fdmi_event event)
1591 {
1592 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1593 
1594 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1595 	bfa_trc(port->fcs, event);
1596 
1597 	switch (event) {
1598 	case FDMISM_EVENT_TIMEOUT:
1599 		/*
1600 		 * Retry Timer Expired. Re-send
1601 		 */
1602 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1603 		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1604 		break;
1605 
1606 	case FDMISM_EVENT_PORT_OFFLINE:
1607 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1608 		bfa_timer_stop(&fdmi->timer);
1609 		break;
1610 
1611 	default:
1612 		bfa_sm_fault(port->fcs, event);
1613 	}
1614 }
1615 
1616 static void
bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1617 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1618 				enum port_fdmi_event event)
1619 {
1620 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1621 
1622 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1623 	bfa_trc(port->fcs, event);
1624 
1625 	switch (event) {
1626 	case FDMISM_EVENT_PORT_OFFLINE:
1627 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1628 		break;
1629 
1630 	default:
1631 		bfa_sm_fault(port->fcs, event);
1632 	}
1633 }
1634 /*
1635  *  FDMI is disabled state.
1636  */
1637 static void
bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1638 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1639 			     enum port_fdmi_event event)
1640 {
1641 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1642 
1643 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1644 	bfa_trc(port->fcs, event);
1645 
1646 	/* No op State. It can only be enabled at Driver Init. */
1647 }
1648 
1649 /*
1650 *  RHBA : Register HBA Attributes.
1651  */
1652 static void
bfa_fcs_lport_fdmi_send_rhba(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)1653 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1654 {
1655 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1656 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1657 	struct fchs_s fchs;
1658 	int             len, attr_len;
1659 	struct bfa_fcxp_s *fcxp;
1660 	u8        *pyld;
1661 
1662 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1663 
1664 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1665 	if (!fcxp) {
1666 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1667 					bfa_fcs_lport_fdmi_send_rhba, fdmi);
1668 		return;
1669 	}
1670 	fdmi->fcxp = fcxp;
1671 
1672 	pyld = bfa_fcxp_get_reqbuf(fcxp);
1673 	memset(pyld, 0, FC_MAX_PDUSZ);
1674 
1675 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1676 				   FDMI_RHBA);
1677 
1678 	attr_len =
1679 		bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1680 					  (u8 *) ((struct ct_hdr_s *) pyld
1681 						       + 1));
1682 
1683 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1684 			  FC_CLASS_3, (len + attr_len), &fchs,
1685 			  bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1686 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
1687 
1688 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1689 }
1690 
1691 static          u16
bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)1692 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1693 {
1694 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1695 	struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1696 	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1697 	struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1698 	struct fdmi_attr_s *attr;
1699 	u8        *curr_ptr;
1700 	u16        len, count;
1701 	u16	templen;
1702 
1703 	/*
1704 	 * get hba attributes
1705 	 */
1706 	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1707 
1708 	rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1709 	rhba->port_list.num_ports = cpu_to_be32(1);
1710 	rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1711 
1712 	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1713 
1714 	count = 0;
1715 	len += sizeof(rhba->hba_attr_blk.attr_count);
1716 
1717 	/*
1718 	 * fill out the invididual entries of the HBA attrib Block
1719 	 */
1720 	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1721 
1722 	/*
1723 	 * Node Name
1724 	 */
1725 	attr = (struct fdmi_attr_s *) curr_ptr;
1726 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1727 	templen = sizeof(wwn_t);
1728 	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1729 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1730 	len += templen;
1731 	count++;
1732 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1733 			     sizeof(templen));
1734 
1735 	/*
1736 	 * Manufacturer
1737 	 */
1738 	attr = (struct fdmi_attr_s *) curr_ptr;
1739 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1740 	templen = (u16) strlen(fcs_hba_attr->manufacturer);
1741 	memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1742 	templen = fc_roundup(templen, sizeof(u32));
1743 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1744 	len += templen;
1745 	count++;
1746 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1747 			     sizeof(templen));
1748 
1749 	/*
1750 	 * Serial Number
1751 	 */
1752 	attr = (struct fdmi_attr_s *) curr_ptr;
1753 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1754 	templen = (u16) strlen(fcs_hba_attr->serial_num);
1755 	memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1756 	templen = fc_roundup(templen, sizeof(u32));
1757 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1758 	len += templen;
1759 	count++;
1760 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1761 			     sizeof(templen));
1762 
1763 	/*
1764 	 * Model
1765 	 */
1766 	attr = (struct fdmi_attr_s *) curr_ptr;
1767 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1768 	templen = (u16) strlen(fcs_hba_attr->model);
1769 	memcpy(attr->value, fcs_hba_attr->model, templen);
1770 	templen = fc_roundup(templen, sizeof(u32));
1771 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1772 	len += templen;
1773 	count++;
1774 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1775 			     sizeof(templen));
1776 
1777 	/*
1778 	 * Model Desc
1779 	 */
1780 	attr = (struct fdmi_attr_s *) curr_ptr;
1781 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1782 	templen = (u16) strlen(fcs_hba_attr->model_desc);
1783 	memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1784 	templen = fc_roundup(templen, sizeof(u32));
1785 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1786 	len += templen;
1787 	count++;
1788 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1789 			     sizeof(templen));
1790 
1791 	/*
1792 	 * H/W Version
1793 	 */
1794 	if (fcs_hba_attr->hw_version[0] != '\0') {
1795 		attr = (struct fdmi_attr_s *) curr_ptr;
1796 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
1797 		templen = (u16) strlen(fcs_hba_attr->hw_version);
1798 		memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1799 		templen = fc_roundup(templen, sizeof(u32));
1800 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1801 		len += templen;
1802 		count++;
1803 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1804 					 sizeof(templen));
1805 	}
1806 
1807 	/*
1808 	 * Driver Version
1809 	 */
1810 	attr = (struct fdmi_attr_s *) curr_ptr;
1811 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
1812 	templen = (u16) strlen(fcs_hba_attr->driver_version);
1813 	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1814 	templen = fc_roundup(templen, sizeof(u32));
1815 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1816 	len += templen;
1817 	count++;
1818 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1819 			     sizeof(templen));
1820 
1821 	/*
1822 	 * Option Rom Version
1823 	 */
1824 	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1825 		attr = (struct fdmi_attr_s *) curr_ptr;
1826 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
1827 		templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1828 		memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1829 		templen = fc_roundup(templen, sizeof(u32));
1830 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1831 		len += templen;
1832 		count++;
1833 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1834 					 sizeof(templen));
1835 	}
1836 
1837 	/*
1838 	 * f/w Version = driver version
1839 	 */
1840 	attr = (struct fdmi_attr_s *) curr_ptr;
1841 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
1842 	templen = (u16) strlen(fcs_hba_attr->driver_version);
1843 	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1844 	templen = fc_roundup(templen, sizeof(u32));
1845 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1846 	len += templen;
1847 	count++;
1848 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1849 			     sizeof(templen));
1850 
1851 	/*
1852 	 * OS Name
1853 	 */
1854 	if (fcs_hba_attr->os_name[0] != '\0') {
1855 		attr = (struct fdmi_attr_s *) curr_ptr;
1856 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
1857 		templen = (u16) strlen(fcs_hba_attr->os_name);
1858 		memcpy(attr->value, fcs_hba_attr->os_name, templen);
1859 		templen = fc_roundup(templen, sizeof(u32));
1860 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1861 		len += templen;
1862 		count++;
1863 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1864 					sizeof(templen));
1865 	}
1866 
1867 	/*
1868 	 * MAX_CT_PAYLOAD
1869 	 */
1870 	attr = (struct fdmi_attr_s *) curr_ptr;
1871 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
1872 	templen = sizeof(fcs_hba_attr->max_ct_pyld);
1873 	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1874 	len += templen;
1875 	count++;
1876 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1877 			     sizeof(templen));
1878 
1879 	/*
1880 	 * Update size of payload
1881 	 */
1882 	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1883 
1884 	rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
1885 	return len;
1886 }
1887 
1888 static void
bfa_fcs_lport_fdmi_rhba_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)1889 bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1890 				void *cbarg, bfa_status_t req_status,
1891 				u32 rsp_len, u32 resid_len,
1892 				struct fchs_s *rsp_fchs)
1893 {
1894 	struct bfa_fcs_lport_fdmi_s *fdmi =
1895 				(struct bfa_fcs_lport_fdmi_s *) cbarg;
1896 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1897 	struct ct_hdr_s *cthdr = NULL;
1898 
1899 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1900 
1901 	/*
1902 	 * Sanity Checks
1903 	 */
1904 	if (req_status != BFA_STATUS_OK) {
1905 		bfa_trc(port->fcs, req_status);
1906 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1907 		return;
1908 	}
1909 
1910 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1911 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1912 
1913 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1914 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1915 		return;
1916 	}
1917 
1918 	bfa_trc(port->fcs, cthdr->reason_code);
1919 	bfa_trc(port->fcs, cthdr->exp_code);
1920 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1921 }
1922 
1923 /*
1924 *  RPRT : Register Port
1925  */
1926 static void
bfa_fcs_lport_fdmi_send_rprt(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)1927 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1928 {
1929 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1930 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1931 	struct fchs_s fchs;
1932 	u16        len, attr_len;
1933 	struct bfa_fcxp_s *fcxp;
1934 	u8        *pyld;
1935 
1936 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1937 
1938 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1939 	if (!fcxp) {
1940 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1941 					bfa_fcs_lport_fdmi_send_rprt, fdmi);
1942 		return;
1943 	}
1944 	fdmi->fcxp = fcxp;
1945 
1946 	pyld = bfa_fcxp_get_reqbuf(fcxp);
1947 	memset(pyld, 0, FC_MAX_PDUSZ);
1948 
1949 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1950 				   FDMI_RPRT);
1951 
1952 	attr_len =
1953 		bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1954 					  (u8 *) ((struct ct_hdr_s *) pyld
1955 						       + 1));
1956 
1957 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1958 			  FC_CLASS_3, len + attr_len, &fchs,
1959 			  bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1960 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
1961 
1962 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1963 }
1964 
1965 /*
1966  * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1967  */
1968 static          u16
bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)1969 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1970 				       u8 *pyld)
1971 {
1972 	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1973 	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1974 	struct fdmi_attr_s *attr;
1975 	u8        *curr_ptr;
1976 	u16        len;
1977 	u8	count = 0;
1978 	u16	templen;
1979 
1980 	/*
1981 	 * get port attributes
1982 	 */
1983 	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1984 
1985 	len = sizeof(port_attrib->attr_count);
1986 
1987 	/*
1988 	 * fill out the invididual entries
1989 	 */
1990 	curr_ptr = (u8 *) &port_attrib->port_attr;
1991 
1992 	/*
1993 	 * FC4 Types
1994 	 */
1995 	attr = (struct fdmi_attr_s *) curr_ptr;
1996 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
1997 	templen = sizeof(fcs_port_attr.supp_fc4_types);
1998 	memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
1999 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2000 	len += templen;
2001 	++count;
2002 	attr->len =
2003 		cpu_to_be16(templen + sizeof(attr->type) +
2004 			     sizeof(templen));
2005 
2006 	/*
2007 	 * Supported Speed
2008 	 */
2009 	attr = (struct fdmi_attr_s *) curr_ptr;
2010 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
2011 	templen = sizeof(fcs_port_attr.supp_speed);
2012 	memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
2013 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2014 	len += templen;
2015 	++count;
2016 	attr->len =
2017 		cpu_to_be16(templen + sizeof(attr->type) +
2018 			     sizeof(templen));
2019 
2020 	/*
2021 	 * current Port Speed
2022 	 */
2023 	attr = (struct fdmi_attr_s *) curr_ptr;
2024 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
2025 	templen = sizeof(fcs_port_attr.curr_speed);
2026 	memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
2027 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2028 	len += templen;
2029 	++count;
2030 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2031 			     sizeof(templen));
2032 
2033 	/*
2034 	 * max frame size
2035 	 */
2036 	attr = (struct fdmi_attr_s *) curr_ptr;
2037 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
2038 	templen = sizeof(fcs_port_attr.max_frm_size);
2039 	memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
2040 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2041 	len += templen;
2042 	++count;
2043 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2044 			     sizeof(templen));
2045 
2046 	/*
2047 	 * OS Device Name
2048 	 */
2049 	if (fcs_port_attr.os_device_name[0] != '\0') {
2050 		attr = (struct fdmi_attr_s *) curr_ptr;
2051 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
2052 		templen = (u16) strlen(fcs_port_attr.os_device_name);
2053 		memcpy(attr->value, fcs_port_attr.os_device_name, templen);
2054 		templen = fc_roundup(templen, sizeof(u32));
2055 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2056 		len += templen;
2057 		++count;
2058 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2059 					sizeof(templen));
2060 	}
2061 	/*
2062 	 * Host Name
2063 	 */
2064 	if (fcs_port_attr.host_name[0] != '\0') {
2065 		attr = (struct fdmi_attr_s *) curr_ptr;
2066 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
2067 		templen = (u16) strlen(fcs_port_attr.host_name);
2068 		memcpy(attr->value, fcs_port_attr.host_name, templen);
2069 		templen = fc_roundup(templen, sizeof(u32));
2070 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2071 		len += templen;
2072 		++count;
2073 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2074 				sizeof(templen));
2075 	}
2076 
2077 	/*
2078 	 * Update size of payload
2079 	 */
2080 	port_attrib->attr_count = cpu_to_be32(count);
2081 	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2082 	return len;
2083 }
2084 
2085 static          u16
bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)2086 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2087 {
2088 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2089 	struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2090 	u16        len;
2091 
2092 	rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2093 	rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2094 
2095 	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2096 				(u8 *) &rprt->port_attr_blk);
2097 
2098 	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2099 
2100 	return len;
2101 }
2102 
2103 static void
bfa_fcs_lport_fdmi_rprt_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)2104 bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2105 				void *cbarg, bfa_status_t req_status,
2106 				u32 rsp_len, u32 resid_len,
2107 				struct fchs_s *rsp_fchs)
2108 {
2109 	struct bfa_fcs_lport_fdmi_s *fdmi =
2110 			(struct bfa_fcs_lport_fdmi_s *) cbarg;
2111 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2112 	struct ct_hdr_s *cthdr = NULL;
2113 
2114 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2115 
2116 	/*
2117 	 * Sanity Checks
2118 	 */
2119 	if (req_status != BFA_STATUS_OK) {
2120 		bfa_trc(port->fcs, req_status);
2121 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2122 		return;
2123 	}
2124 
2125 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2126 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2127 
2128 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2129 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2130 		return;
2131 	}
2132 
2133 	bfa_trc(port->fcs, cthdr->reason_code);
2134 	bfa_trc(port->fcs, cthdr->exp_code);
2135 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2136 }
2137 
2138 /*
2139 *  RPA : Register Port Attributes.
2140  */
2141 static void
bfa_fcs_lport_fdmi_send_rpa(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)2142 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2143 {
2144 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2145 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2146 	struct fchs_s fchs;
2147 	u16        len, attr_len;
2148 	struct bfa_fcxp_s *fcxp;
2149 	u8        *pyld;
2150 
2151 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2152 
2153 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2154 	if (!fcxp) {
2155 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2156 					bfa_fcs_lport_fdmi_send_rpa, fdmi);
2157 		return;
2158 	}
2159 	fdmi->fcxp = fcxp;
2160 
2161 	pyld = bfa_fcxp_get_reqbuf(fcxp);
2162 	memset(pyld, 0, FC_MAX_PDUSZ);
2163 
2164 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2165 				   FDMI_RPA);
2166 
2167 	attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2168 				(u8 *) ((struct ct_hdr_s *) pyld + 1));
2169 
2170 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2171 			  FC_CLASS_3, len + attr_len, &fchs,
2172 			  bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2173 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2174 
2175 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2176 }
2177 
2178 static          u16
bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)2179 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2180 {
2181 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2182 	struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2183 	u16        len;
2184 
2185 	rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2186 
2187 	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2188 				(u8 *) &rpa->port_attr_blk);
2189 
2190 	len += sizeof(rpa->port_name);
2191 
2192 	return len;
2193 }
2194 
2195 static void
bfa_fcs_lport_fdmi_rpa_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)2196 bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2197 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
2198 			u32 resid_len, struct fchs_s *rsp_fchs)
2199 {
2200 	struct bfa_fcs_lport_fdmi_s *fdmi =
2201 				(struct bfa_fcs_lport_fdmi_s *) cbarg;
2202 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2203 	struct ct_hdr_s *cthdr = NULL;
2204 
2205 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2206 
2207 	/*
2208 	 * Sanity Checks
2209 	 */
2210 	if (req_status != BFA_STATUS_OK) {
2211 		bfa_trc(port->fcs, req_status);
2212 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2213 		return;
2214 	}
2215 
2216 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2217 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2218 
2219 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2220 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2221 		return;
2222 	}
2223 
2224 	bfa_trc(port->fcs, cthdr->reason_code);
2225 	bfa_trc(port->fcs, cthdr->exp_code);
2226 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2227 }
2228 
2229 static void
bfa_fcs_lport_fdmi_timeout(void * arg)2230 bfa_fcs_lport_fdmi_timeout(void *arg)
2231 {
2232 	struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2233 
2234 	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2235 }
2236 
2237 static void
bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s * fdmi,struct bfa_fcs_fdmi_hba_attr_s * hba_attr)2238 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2239 			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2240 {
2241 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2242 	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2243 
2244 	memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2245 
2246 	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2247 					hba_attr->manufacturer);
2248 	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2249 					hba_attr->serial_num);
2250 	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2251 					hba_attr->model);
2252 	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2253 					hba_attr->model_desc);
2254 	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2255 					hba_attr->hw_version);
2256 	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2257 					hba_attr->option_rom_ver);
2258 	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2259 					hba_attr->fw_version);
2260 
2261 	strncpy(hba_attr->driver_version, (char *)driver_info->version,
2262 		sizeof(hba_attr->driver_version));
2263 
2264 	strncpy(hba_attr->os_name, driver_info->host_os_name,
2265 		sizeof(hba_attr->os_name));
2266 
2267 	/*
2268 	 * If there is a patch level, append it
2269 	 * to the os name along with a separator
2270 	 */
2271 	if (driver_info->host_os_patch[0] != '\0') {
2272 		strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2273 			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2274 		strncat(hba_attr->os_name, driver_info->host_os_patch,
2275 				sizeof(driver_info->host_os_patch));
2276 	}
2277 
2278 	hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
2279 }
2280 
2281 static void
bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s * fdmi,struct bfa_fcs_fdmi_port_attr_s * port_attr)2282 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2283 			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
2284 {
2285 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2286 	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2287 	struct bfa_port_attr_s pport_attr;
2288 
2289 	memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2290 
2291 	/*
2292 	 * get pport attributes from hal
2293 	 */
2294 	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2295 
2296 	/*
2297 	 * get FC4 type Bitmask
2298 	 */
2299 	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2300 
2301 	/*
2302 	 * Supported Speeds
2303 	 */
2304 	switch (pport_attr.speed_supported) {
2305 	case BFA_PORT_SPEED_16GBPS:
2306 		port_attr->supp_speed =
2307 			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
2308 		break;
2309 
2310 	case BFA_PORT_SPEED_10GBPS:
2311 		port_attr->supp_speed =
2312 			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
2313 		break;
2314 
2315 	case BFA_PORT_SPEED_8GBPS:
2316 		port_attr->supp_speed =
2317 			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
2318 		break;
2319 
2320 	case BFA_PORT_SPEED_4GBPS:
2321 		port_attr->supp_speed =
2322 			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
2323 		break;
2324 
2325 	default:
2326 		bfa_sm_fault(port->fcs, pport_attr.speed_supported);
2327 	}
2328 
2329 	/*
2330 	 * Current Speed
2331 	 */
2332 	port_attr->curr_speed = cpu_to_be32(
2333 				bfa_fcs_fdmi_convert_speed(pport_attr.speed));
2334 
2335 	/*
2336 	 * Max PDU Size.
2337 	 */
2338 	port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
2339 
2340 	/*
2341 	 * OS device Name
2342 	 */
2343 	strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2344 		sizeof(port_attr->os_device_name));
2345 
2346 	/*
2347 	 * Host name
2348 	 */
2349 	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2350 		sizeof(port_attr->host_name));
2351 
2352 }
2353 
2354 /*
2355  * Convert BFA speed to FDMI format.
2356  */
2357 u32
bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)2358 bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
2359 {
2360 	u32	ret;
2361 
2362 	switch (pport_speed) {
2363 	case BFA_PORT_SPEED_1GBPS:
2364 	case BFA_PORT_SPEED_2GBPS:
2365 		ret = pport_speed;
2366 		break;
2367 
2368 	case BFA_PORT_SPEED_4GBPS:
2369 		ret = FDMI_TRANS_SPEED_4G;
2370 		break;
2371 
2372 	case BFA_PORT_SPEED_8GBPS:
2373 		ret = FDMI_TRANS_SPEED_8G;
2374 		break;
2375 
2376 	case BFA_PORT_SPEED_10GBPS:
2377 		ret = FDMI_TRANS_SPEED_10G;
2378 		break;
2379 
2380 	case BFA_PORT_SPEED_16GBPS:
2381 		ret = FDMI_TRANS_SPEED_16G;
2382 		break;
2383 
2384 	default:
2385 		ret = FDMI_TRANS_SPEED_UNKNOWN;
2386 	}
2387 	return ret;
2388 }
2389 
2390 void
bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s * ms)2391 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2392 {
2393 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2394 
2395 	fdmi->ms = ms;
2396 	if (ms->port->fcs->fdmi_enabled)
2397 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2398 	else
2399 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2400 }
2401 
2402 void
bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s * ms)2403 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2404 {
2405 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2406 
2407 	fdmi->ms = ms;
2408 	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2409 }
2410 
2411 void
bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s * ms)2412 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2413 {
2414 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2415 
2416 	fdmi->ms = ms;
2417 	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2418 }
2419 
2420 #define BFA_FCS_MS_CMD_MAX_RETRIES  2
2421 
2422 /*
2423  * forward declarations
2424  */
2425 static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2426 					   struct bfa_fcxp_s *fcxp_alloced);
2427 static void     bfa_fcs_lport_ms_timeout(void *arg);
2428 static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2429 					       struct bfa_fcxp_s *fcxp,
2430 					       void *cbarg,
2431 					       bfa_status_t req_status,
2432 					       u32 rsp_len,
2433 					       u32 resid_len,
2434 					       struct fchs_s *rsp_fchs);
2435 
2436 static void	bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2437 					struct bfa_fcxp_s *fcxp_alloced);
2438 static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2439 					       struct bfa_fcxp_s *fcxp,
2440 					       void *cbarg,
2441 					       bfa_status_t req_status,
2442 					       u32 rsp_len,
2443 					       u32 resid_len,
2444 					       struct fchs_s *rsp_fchs);
2445 static void	bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2446 					struct bfa_fcxp_s *fcxp_alloced);
2447 static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2448 					       struct bfa_fcxp_s *fcxp,
2449 					       void *cbarg,
2450 					       bfa_status_t req_status,
2451 					       u32 rsp_len,
2452 					       u32 resid_len,
2453 					       struct fchs_s *rsp_fchs);
2454 /*
2455  *  fcs_ms_sm FCS MS state machine
2456  */
2457 
2458 /*
2459  *  MS State Machine events
2460  */
2461 enum port_ms_event {
2462 	MSSM_EVENT_PORT_ONLINE = 1,
2463 	MSSM_EVENT_PORT_OFFLINE = 2,
2464 	MSSM_EVENT_RSP_OK = 3,
2465 	MSSM_EVENT_RSP_ERROR = 4,
2466 	MSSM_EVENT_TIMEOUT = 5,
2467 	MSSM_EVENT_FCXP_SENT = 6,
2468 	MSSM_EVENT_PORT_FABRIC_RSCN = 7
2469 };
2470 
2471 static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2472 					   enum port_ms_event event);
2473 static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2474 						 enum port_ms_event event);
2475 static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2476 					 enum port_ms_event event);
2477 static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2478 					       enum port_ms_event event);
2479 static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2480 						 enum port_ms_event event);
2481 static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2482 					 enum port_ms_event event);
2483 static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2484 					       enum port_ms_event event);
2485 static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2486 						 enum port_ms_event event);
2487 static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2488 					 enum port_ms_event event);
2489 static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2490 					       enum port_ms_event event);
2491 static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2492 					  enum port_ms_event event);
2493 /*
2494  *	Start in offline state - awaiting NS to send start.
2495  */
2496 static void
bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2497 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2498 				enum port_ms_event event)
2499 {
2500 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2501 	bfa_trc(ms->port->fcs, event);
2502 
2503 	switch (event) {
2504 	case MSSM_EVENT_PORT_ONLINE:
2505 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2506 		bfa_fcs_lport_ms_send_plogi(ms, NULL);
2507 		break;
2508 
2509 	case MSSM_EVENT_PORT_OFFLINE:
2510 		break;
2511 
2512 	default:
2513 		bfa_sm_fault(ms->port->fcs, event);
2514 	}
2515 }
2516 
2517 static void
bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2518 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2519 				enum port_ms_event event)
2520 {
2521 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2522 	bfa_trc(ms->port->fcs, event);
2523 
2524 	switch (event) {
2525 	case MSSM_EVENT_FCXP_SENT:
2526 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2527 		break;
2528 
2529 	case MSSM_EVENT_PORT_OFFLINE:
2530 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2531 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2532 					   &ms->fcxp_wqe);
2533 		break;
2534 
2535 	default:
2536 		bfa_sm_fault(ms->port->fcs, event);
2537 	}
2538 }
2539 
2540 static void
bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2541 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2542 			enum port_ms_event event)
2543 {
2544 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2545 	bfa_trc(ms->port->fcs, event);
2546 
2547 	switch (event) {
2548 	case MSSM_EVENT_RSP_ERROR:
2549 		/*
2550 		 * Start timer for a delayed retry
2551 		 */
2552 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2553 		ms->port->stats.ms_retries++;
2554 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2555 				    &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2556 				    BFA_FCS_RETRY_TIMEOUT);
2557 		break;
2558 
2559 	case MSSM_EVENT_RSP_OK:
2560 		/*
2561 		 * since plogi is done, now invoke MS related sub-modules
2562 		 */
2563 		bfa_fcs_lport_fdmi_online(ms);
2564 
2565 		/*
2566 		 * if this is a Vport, go to online state.
2567 		 */
2568 		if (ms->port->vport) {
2569 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2570 			break;
2571 		}
2572 
2573 		/*
2574 		 * For a base port we need to get the
2575 		 * switch's IP address.
2576 		 */
2577 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2578 		bfa_fcs_lport_ms_send_gmal(ms, NULL);
2579 		break;
2580 
2581 	case MSSM_EVENT_PORT_OFFLINE:
2582 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2583 		bfa_fcxp_discard(ms->fcxp);
2584 		break;
2585 
2586 	default:
2587 		bfa_sm_fault(ms->port->fcs, event);
2588 	}
2589 }
2590 
2591 static void
bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2592 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2593 			enum port_ms_event event)
2594 {
2595 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2596 	bfa_trc(ms->port->fcs, event);
2597 
2598 	switch (event) {
2599 	case MSSM_EVENT_TIMEOUT:
2600 		/*
2601 		 * Retry Timer Expired. Re-send
2602 		 */
2603 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2604 		bfa_fcs_lport_ms_send_plogi(ms, NULL);
2605 		break;
2606 
2607 	case MSSM_EVENT_PORT_OFFLINE:
2608 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2609 		bfa_timer_stop(&ms->timer);
2610 		break;
2611 
2612 	default:
2613 		bfa_sm_fault(ms->port->fcs, event);
2614 	}
2615 }
2616 
2617 static void
bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2618 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2619 			enum port_ms_event event)
2620 {
2621 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2622 	bfa_trc(ms->port->fcs, event);
2623 
2624 	switch (event) {
2625 	case MSSM_EVENT_PORT_OFFLINE:
2626 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2627 		break;
2628 
2629 	case MSSM_EVENT_PORT_FABRIC_RSCN:
2630 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2631 		ms->retry_cnt = 0;
2632 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2633 		break;
2634 
2635 	default:
2636 		bfa_sm_fault(ms->port->fcs, event);
2637 	}
2638 }
2639 
2640 static void
bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2641 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2642 				enum port_ms_event event)
2643 {
2644 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2645 	bfa_trc(ms->port->fcs, event);
2646 
2647 	switch (event) {
2648 	case MSSM_EVENT_FCXP_SENT:
2649 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2650 		break;
2651 
2652 	case MSSM_EVENT_PORT_OFFLINE:
2653 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2654 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2655 					   &ms->fcxp_wqe);
2656 		break;
2657 
2658 	default:
2659 		bfa_sm_fault(ms->port->fcs, event);
2660 	}
2661 }
2662 
2663 static void
bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2664 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2665 				enum port_ms_event event)
2666 {
2667 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2668 	bfa_trc(ms->port->fcs, event);
2669 
2670 	switch (event) {
2671 	case MSSM_EVENT_RSP_ERROR:
2672 		/*
2673 		 * Start timer for a delayed retry
2674 		 */
2675 		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2676 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2677 			ms->port->stats.ms_retries++;
2678 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2679 				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
2680 				BFA_FCS_RETRY_TIMEOUT);
2681 		} else {
2682 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2683 			bfa_fcs_lport_ms_send_gfn(ms, NULL);
2684 			ms->retry_cnt = 0;
2685 		}
2686 		break;
2687 
2688 	case MSSM_EVENT_RSP_OK:
2689 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2690 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2691 		break;
2692 
2693 	case MSSM_EVENT_PORT_OFFLINE:
2694 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2695 		bfa_fcxp_discard(ms->fcxp);
2696 		break;
2697 
2698 	default:
2699 		bfa_sm_fault(ms->port->fcs, event);
2700 	}
2701 }
2702 
2703 static void
bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2704 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2705 				enum port_ms_event event)
2706 {
2707 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2708 	bfa_trc(ms->port->fcs, event);
2709 
2710 	switch (event) {
2711 	case MSSM_EVENT_TIMEOUT:
2712 		/*
2713 		 * Retry Timer Expired. Re-send
2714 		 */
2715 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2716 		bfa_fcs_lport_ms_send_gmal(ms, NULL);
2717 		break;
2718 
2719 	case MSSM_EVENT_PORT_OFFLINE:
2720 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2721 		bfa_timer_stop(&ms->timer);
2722 		break;
2723 
2724 	default:
2725 		bfa_sm_fault(ms->port->fcs, event);
2726 	}
2727 }
2728 /*
2729  *  ms_pvt MS local functions
2730  */
2731 
2732 static void
bfa_fcs_lport_ms_send_gmal(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)2733 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2734 {
2735 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2736 	bfa_fcs_lport_t *port = ms->port;
2737 	struct fchs_s	fchs;
2738 	int		len;
2739 	struct bfa_fcxp_s *fcxp;
2740 
2741 	bfa_trc(port->fcs, port->pid);
2742 
2743 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2744 	if (!fcxp) {
2745 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2746 					bfa_fcs_lport_ms_send_gmal, ms);
2747 		return;
2748 	}
2749 	ms->fcxp = fcxp;
2750 
2751 	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2752 			     bfa_fcs_lport_get_fcid(port),
2753 				 port->fabric->lps->pr_nwwn);
2754 
2755 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2756 			  FC_CLASS_3, len, &fchs,
2757 			  bfa_fcs_lport_ms_gmal_response, (void *)ms,
2758 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2759 
2760 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2761 }
2762 
2763 static void
bfa_fcs_lport_ms_gmal_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)2764 bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2765 				void *cbarg, bfa_status_t req_status,
2766 				u32 rsp_len, u32 resid_len,
2767 				struct fchs_s *rsp_fchs)
2768 {
2769 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2770 	bfa_fcs_lport_t *port = ms->port;
2771 	struct ct_hdr_s		*cthdr = NULL;
2772 	struct fcgs_gmal_resp_s *gmal_resp;
2773 	struct fcgs_gmal_entry_s *gmal_entry;
2774 	u32		num_entries;
2775 	u8			*rsp_str;
2776 
2777 	bfa_trc(port->fcs, req_status);
2778 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2779 
2780 	/*
2781 	 * Sanity Checks
2782 	 */
2783 	if (req_status != BFA_STATUS_OK) {
2784 		bfa_trc(port->fcs, req_status);
2785 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2786 		return;
2787 	}
2788 
2789 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2790 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2791 
2792 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2793 		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2794 
2795 		num_entries = be32_to_cpu(gmal_resp->ms_len);
2796 		if (num_entries == 0) {
2797 			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2798 			return;
2799 		}
2800 		/*
2801 		* The response could contain multiple Entries.
2802 		* Entries for SNMP interface, etc.
2803 		* We look for the entry with a telnet prefix.
2804 		* First "http://" entry refers to IP addr
2805 		*/
2806 
2807 		gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2808 		while (num_entries > 0) {
2809 			if (strncmp(gmal_entry->prefix,
2810 				CT_GMAL_RESP_PREFIX_HTTP,
2811 				sizeof(gmal_entry->prefix)) == 0) {
2812 
2813 				/*
2814 				* if the IP address is terminating with a '/',
2815 				* remove it.
2816 				* Byte 0 consists of the length of the string.
2817 				*/
2818 				rsp_str = &(gmal_entry->prefix[0]);
2819 				if (rsp_str[gmal_entry->len-1] == '/')
2820 					rsp_str[gmal_entry->len-1] = 0;
2821 
2822 				/* copy IP Address to fabric */
2823 				strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2824 					gmal_entry->ip_addr,
2825 					BFA_FCS_FABRIC_IPADDR_SZ);
2826 				break;
2827 			} else {
2828 				--num_entries;
2829 				++gmal_entry;
2830 			}
2831 		}
2832 
2833 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2834 		return;
2835 	}
2836 
2837 	bfa_trc(port->fcs, cthdr->reason_code);
2838 	bfa_trc(port->fcs, cthdr->exp_code);
2839 	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2840 }
2841 
2842 static void
bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2843 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2844 			enum port_ms_event event)
2845 {
2846 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2847 	bfa_trc(ms->port->fcs, event);
2848 
2849 	switch (event) {
2850 	case MSSM_EVENT_FCXP_SENT:
2851 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2852 		break;
2853 
2854 	case MSSM_EVENT_PORT_OFFLINE:
2855 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2856 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2857 					   &ms->fcxp_wqe);
2858 		break;
2859 
2860 	default:
2861 		bfa_sm_fault(ms->port->fcs, event);
2862 	}
2863 }
2864 
2865 static void
bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2866 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2867 			enum port_ms_event event)
2868 {
2869 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2870 	bfa_trc(ms->port->fcs, event);
2871 
2872 	switch (event) {
2873 	case MSSM_EVENT_RSP_ERROR:
2874 		/*
2875 		 * Start timer for a delayed retry
2876 		 */
2877 		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2878 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2879 			ms->port->stats.ms_retries++;
2880 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2881 				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
2882 				BFA_FCS_RETRY_TIMEOUT);
2883 		} else {
2884 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2885 			ms->retry_cnt = 0;
2886 		}
2887 		break;
2888 
2889 	case MSSM_EVENT_RSP_OK:
2890 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2891 		break;
2892 
2893 	case MSSM_EVENT_PORT_OFFLINE:
2894 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2895 		bfa_fcxp_discard(ms->fcxp);
2896 		break;
2897 
2898 	default:
2899 		bfa_sm_fault(ms->port->fcs, event);
2900 	}
2901 }
2902 
2903 static void
bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2904 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2905 				enum port_ms_event event)
2906 {
2907 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2908 	bfa_trc(ms->port->fcs, event);
2909 
2910 	switch (event) {
2911 	case MSSM_EVENT_TIMEOUT:
2912 		/*
2913 		 * Retry Timer Expired. Re-send
2914 		 */
2915 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2916 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2917 		break;
2918 
2919 	case MSSM_EVENT_PORT_OFFLINE:
2920 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2921 		bfa_timer_stop(&ms->timer);
2922 		break;
2923 
2924 	default:
2925 		bfa_sm_fault(ms->port->fcs, event);
2926 	}
2927 }
2928 /*
2929  *  ms_pvt MS local functions
2930  */
2931 
2932 static void
bfa_fcs_lport_ms_send_gfn(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)2933 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2934 {
2935 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2936 	bfa_fcs_lport_t *port = ms->port;
2937 	struct fchs_s		fchs;
2938 	int			len;
2939 	struct bfa_fcxp_s *fcxp;
2940 
2941 	bfa_trc(port->fcs, port->pid);
2942 
2943 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2944 	if (!fcxp) {
2945 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2946 					bfa_fcs_lport_ms_send_gfn, ms);
2947 		return;
2948 	}
2949 	ms->fcxp = fcxp;
2950 
2951 	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2952 			     bfa_fcs_lport_get_fcid(port),
2953 				 port->fabric->lps->pr_nwwn);
2954 
2955 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2956 			  FC_CLASS_3, len, &fchs,
2957 			  bfa_fcs_lport_ms_gfn_response, (void *)ms,
2958 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2959 
2960 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2961 }
2962 
2963 static void
bfa_fcs_lport_ms_gfn_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)2964 bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2965 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
2966 			u32 resid_len, struct fchs_s *rsp_fchs)
2967 {
2968 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2969 	bfa_fcs_lport_t *port = ms->port;
2970 	struct ct_hdr_s	*cthdr = NULL;
2971 	wwn_t	       *gfn_resp;
2972 
2973 	bfa_trc(port->fcs, req_status);
2974 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2975 
2976 	/*
2977 	 * Sanity Checks
2978 	 */
2979 	if (req_status != BFA_STATUS_OK) {
2980 		bfa_trc(port->fcs, req_status);
2981 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2982 		return;
2983 	}
2984 
2985 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2986 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2987 
2988 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2989 		gfn_resp = (wwn_t *)(cthdr + 1);
2990 		/* check if it has actually changed */
2991 		if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2992 				gfn_resp, sizeof(wwn_t)) != 0)) {
2993 			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2994 		}
2995 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2996 		return;
2997 	}
2998 
2999 	bfa_trc(port->fcs, cthdr->reason_code);
3000 	bfa_trc(port->fcs, cthdr->exp_code);
3001 	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3002 }
3003 
3004 /*
3005  *  ms_pvt MS local functions
3006  */
3007 
3008 static void
bfa_fcs_lport_ms_send_plogi(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)3009 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3010 {
3011 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3012 	struct bfa_fcs_lport_s *port = ms->port;
3013 	struct fchs_s	fchs;
3014 	int	len;
3015 	struct bfa_fcxp_s *fcxp;
3016 
3017 	bfa_trc(port->fcs, port->pid);
3018 
3019 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3020 	if (!fcxp) {
3021 		port->stats.ms_plogi_alloc_wait++;
3022 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3023 					bfa_fcs_lport_ms_send_plogi, ms);
3024 		return;
3025 	}
3026 	ms->fcxp = fcxp;
3027 
3028 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3029 			     bfa_hton3b(FC_MGMT_SERVER),
3030 			     bfa_fcs_lport_get_fcid(port), 0,
3031 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
3032 			     bfa_fcport_get_maxfrsize(port->fcs->bfa),
3033 			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
3034 
3035 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3036 			  FC_CLASS_3, len, &fchs,
3037 			  bfa_fcs_lport_ms_plogi_response, (void *)ms,
3038 			  FC_MAX_PDUSZ, FC_ELS_TOV);
3039 
3040 	port->stats.ms_plogi_sent++;
3041 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3042 }
3043 
3044 static void
bfa_fcs_lport_ms_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)3045 bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3046 			void *cbarg, bfa_status_t req_status,
3047 			u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
3048 {
3049 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3050 	struct bfa_fcs_lport_s *port = ms->port;
3051 	struct fc_els_cmd_s *els_cmd;
3052 	struct fc_ls_rjt_s *ls_rjt;
3053 
3054 	bfa_trc(port->fcs, req_status);
3055 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3056 
3057 	/*
3058 	 * Sanity Checks
3059 	 */
3060 	if (req_status != BFA_STATUS_OK) {
3061 		port->stats.ms_plogi_rsp_err++;
3062 		bfa_trc(port->fcs, req_status);
3063 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3064 		return;
3065 	}
3066 
3067 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3068 
3069 	switch (els_cmd->els_code) {
3070 
3071 	case FC_ELS_ACC:
3072 		if (rsp_len < sizeof(struct fc_logi_s)) {
3073 			bfa_trc(port->fcs, rsp_len);
3074 			port->stats.ms_plogi_acc_err++;
3075 			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3076 			break;
3077 		}
3078 		port->stats.ms_plogi_accepts++;
3079 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3080 		break;
3081 
3082 	case FC_ELS_LS_RJT:
3083 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3084 
3085 		bfa_trc(port->fcs, ls_rjt->reason_code);
3086 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3087 
3088 		port->stats.ms_rejects++;
3089 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3090 		break;
3091 
3092 	default:
3093 		port->stats.ms_plogi_unknown_rsp++;
3094 		bfa_trc(port->fcs, els_cmd->els_code);
3095 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3096 	}
3097 }
3098 
3099 static void
bfa_fcs_lport_ms_timeout(void * arg)3100 bfa_fcs_lport_ms_timeout(void *arg)
3101 {
3102 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
3103 
3104 	ms->port->stats.ms_timeouts++;
3105 	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
3106 }
3107 
3108 
3109 void
bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s * port)3110 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
3111 {
3112 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3113 
3114 	ms->port = port;
3115 	bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3116 
3117 	/*
3118 	 * Invoke init routines of sub modules.
3119 	 */
3120 	bfa_fcs_lport_fdmi_init(ms);
3121 }
3122 
3123 void
bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s * port)3124 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
3125 {
3126 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3127 
3128 	ms->port = port;
3129 	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
3130 	bfa_fcs_lport_fdmi_offline(ms);
3131 }
3132 
3133 void
bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s * port)3134 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
3135 {
3136 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3137 
3138 	ms->port = port;
3139 	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3140 }
3141 void
bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s * port)3142 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3143 {
3144 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3145 
3146 	/* todo.  Handle this only  when in Online state */
3147 	if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3148 		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3149 }
3150 
3151 /*
3152  * @page ns_sm_info VPORT NS State Machine
3153  *
3154  * @section ns_sm_interactions VPORT NS State Machine Interactions
3155  *
3156  * @section ns_sm VPORT NS State Machine
3157  * img ns_sm.jpg
3158  */
3159 
3160 /*
3161  * forward declarations
3162  */
3163 static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3164 					   struct bfa_fcxp_s *fcxp_alloced);
3165 static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3166 					     struct bfa_fcxp_s *fcxp_alloced);
3167 static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3168 					    struct bfa_fcxp_s *fcxp_alloced);
3169 static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3170 					    struct bfa_fcxp_s *fcxp_alloced);
3171 static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3172 					    struct bfa_fcxp_s *fcxp_alloced);
3173 static void     bfa_fcs_lport_ns_timeout(void *arg);
3174 static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3175 					       struct bfa_fcxp_s *fcxp,
3176 					       void *cbarg,
3177 					       bfa_status_t req_status,
3178 					       u32 rsp_len,
3179 					       u32 resid_len,
3180 					       struct fchs_s *rsp_fchs);
3181 static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3182 						 struct bfa_fcxp_s *fcxp,
3183 						 void *cbarg,
3184 						 bfa_status_t req_status,
3185 						 u32 rsp_len,
3186 						 u32 resid_len,
3187 						 struct fchs_s *rsp_fchs);
3188 static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
3189 						struct bfa_fcxp_s *fcxp,
3190 						void *cbarg,
3191 						bfa_status_t req_status,
3192 						u32 rsp_len,
3193 						u32 resid_len,
3194 						struct fchs_s *rsp_fchs);
3195 static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
3196 						struct bfa_fcxp_s *fcxp,
3197 						void *cbarg,
3198 						bfa_status_t req_status,
3199 						u32 rsp_len,
3200 						u32 resid_len,
3201 						struct fchs_s *rsp_fchs);
3202 static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3203 						struct bfa_fcxp_s *fcxp,
3204 						void *cbarg,
3205 						bfa_status_t req_status,
3206 						u32 rsp_len,
3207 						u32 resid_len,
3208 						struct fchs_s *rsp_fchs);
3209 static void     bfa_fcs_lport_ns_process_gidft_pids(
3210 				struct bfa_fcs_lport_s *port,
3211 				u32 *pid_buf, u32 n_pids);
3212 
3213 static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3214 /*
3215  *  fcs_ns_sm FCS nameserver interface state machine
3216  */
3217 
3218 /*
3219  * VPort NS State Machine events
3220  */
3221 enum vport_ns_event {
3222 	NSSM_EVENT_PORT_ONLINE = 1,
3223 	NSSM_EVENT_PORT_OFFLINE = 2,
3224 	NSSM_EVENT_PLOGI_SENT = 3,
3225 	NSSM_EVENT_RSP_OK = 4,
3226 	NSSM_EVENT_RSP_ERROR = 5,
3227 	NSSM_EVENT_TIMEOUT = 6,
3228 	NSSM_EVENT_NS_QUERY = 7,
3229 	NSSM_EVENT_RSPNID_SENT = 8,
3230 	NSSM_EVENT_RFTID_SENT = 9,
3231 	NSSM_EVENT_RFFID_SENT = 10,
3232 	NSSM_EVENT_GIDFT_SENT = 11,
3233 };
3234 
3235 static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3236 					   enum vport_ns_event event);
3237 static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3238 						 enum vport_ns_event event);
3239 static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3240 					 enum vport_ns_event event);
3241 static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3242 					       enum vport_ns_event event);
3243 static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
3244 					struct bfa_fcs_lport_ns_s *ns,
3245 					enum vport_ns_event event);
3246 static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3247 					   enum vport_ns_event event);
3248 static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3249 						 enum vport_ns_event event);
3250 static void     bfa_fcs_lport_ns_sm_sending_rft_id(
3251 					struct bfa_fcs_lport_ns_s *ns,
3252 					enum vport_ns_event event);
3253 static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3254 						enum vport_ns_event event);
3255 static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3256 					  enum vport_ns_event event);
3257 static void     bfa_fcs_lport_ns_sm_sending_rff_id(
3258 					struct bfa_fcs_lport_ns_s *ns,
3259 					enum vport_ns_event event);
3260 static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3261 						enum vport_ns_event event);
3262 static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3263 					  enum vport_ns_event event);
3264 static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
3265 					struct bfa_fcs_lport_ns_s *ns,
3266 					enum vport_ns_event event);
3267 static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3268 					  enum vport_ns_event event);
3269 static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3270 						enum vport_ns_event event);
3271 static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3272 					  enum vport_ns_event event);
3273 /*
3274  *	Start in offline state - awaiting linkup
3275  */
3276 static void
bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3277 bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3278 			enum vport_ns_event event)
3279 {
3280 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3281 	bfa_trc(ns->port->fcs, event);
3282 
3283 	switch (event) {
3284 	case NSSM_EVENT_PORT_ONLINE:
3285 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3286 		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3287 		break;
3288 
3289 	case NSSM_EVENT_PORT_OFFLINE:
3290 		break;
3291 
3292 	default:
3293 		bfa_sm_fault(ns->port->fcs, event);
3294 	}
3295 }
3296 
3297 static void
bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3298 bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3299 			enum vport_ns_event event)
3300 {
3301 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3302 	bfa_trc(ns->port->fcs, event);
3303 
3304 	switch (event) {
3305 	case NSSM_EVENT_PLOGI_SENT:
3306 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3307 		break;
3308 
3309 	case NSSM_EVENT_PORT_OFFLINE:
3310 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3311 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3312 					   &ns->fcxp_wqe);
3313 		break;
3314 
3315 	default:
3316 		bfa_sm_fault(ns->port->fcs, event);
3317 	}
3318 }
3319 
3320 static void
bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3321 bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3322 			enum vport_ns_event event)
3323 {
3324 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3325 	bfa_trc(ns->port->fcs, event);
3326 
3327 	switch (event) {
3328 	case NSSM_EVENT_RSP_ERROR:
3329 		/*
3330 		 * Start timer for a delayed retry
3331 		 */
3332 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3333 		ns->port->stats.ns_retries++;
3334 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3335 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3336 				    BFA_FCS_RETRY_TIMEOUT);
3337 		break;
3338 
3339 	case NSSM_EVENT_RSP_OK:
3340 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3341 		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3342 		break;
3343 
3344 	case NSSM_EVENT_PORT_OFFLINE:
3345 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3346 		bfa_fcxp_discard(ns->fcxp);
3347 		break;
3348 
3349 	default:
3350 		bfa_sm_fault(ns->port->fcs, event);
3351 	}
3352 }
3353 
3354 static void
bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3355 bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3356 				enum vport_ns_event event)
3357 {
3358 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3359 	bfa_trc(ns->port->fcs, event);
3360 
3361 	switch (event) {
3362 	case NSSM_EVENT_TIMEOUT:
3363 		/*
3364 		 * Retry Timer Expired. Re-send
3365 		 */
3366 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3367 		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3368 		break;
3369 
3370 	case NSSM_EVENT_PORT_OFFLINE:
3371 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3372 		bfa_timer_stop(&ns->timer);
3373 		break;
3374 
3375 	default:
3376 		bfa_sm_fault(ns->port->fcs, event);
3377 	}
3378 }
3379 
3380 static void
bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3381 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3382 				   enum vport_ns_event event)
3383 {
3384 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3385 	bfa_trc(ns->port->fcs, event);
3386 
3387 	switch (event) {
3388 	case NSSM_EVENT_RSPNID_SENT:
3389 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3390 		break;
3391 
3392 	case NSSM_EVENT_PORT_OFFLINE:
3393 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3394 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3395 					   &ns->fcxp_wqe);
3396 		break;
3397 
3398 	default:
3399 		bfa_sm_fault(ns->port->fcs, event);
3400 	}
3401 }
3402 
3403 static void
bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3404 bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3405 			enum vport_ns_event event)
3406 {
3407 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3408 	bfa_trc(ns->port->fcs, event);
3409 
3410 	switch (event) {
3411 	case NSSM_EVENT_RSP_ERROR:
3412 		/*
3413 		 * Start timer for a delayed retry
3414 		 */
3415 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3416 		ns->port->stats.ns_retries++;
3417 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3418 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3419 				    BFA_FCS_RETRY_TIMEOUT);
3420 		break;
3421 
3422 	case NSSM_EVENT_RSP_OK:
3423 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3424 		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3425 		break;
3426 
3427 	case NSSM_EVENT_PORT_OFFLINE:
3428 		bfa_fcxp_discard(ns->fcxp);
3429 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3430 		break;
3431 
3432 	default:
3433 		bfa_sm_fault(ns->port->fcs, event);
3434 	}
3435 }
3436 
3437 static void
bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3438 bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3439 				enum vport_ns_event event)
3440 {
3441 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3442 	bfa_trc(ns->port->fcs, event);
3443 
3444 	switch (event) {
3445 	case NSSM_EVENT_TIMEOUT:
3446 		/*
3447 		 * Retry Timer Expired. Re-send
3448 		 */
3449 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3450 		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3451 		break;
3452 
3453 	case NSSM_EVENT_PORT_OFFLINE:
3454 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3455 		bfa_timer_stop(&ns->timer);
3456 		break;
3457 
3458 	default:
3459 		bfa_sm_fault(ns->port->fcs, event);
3460 	}
3461 }
3462 
3463 static void
bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3464 bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3465 				  enum vport_ns_event event)
3466 {
3467 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3468 	bfa_trc(ns->port->fcs, event);
3469 
3470 	switch (event) {
3471 	case NSSM_EVENT_RFTID_SENT:
3472 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3473 		break;
3474 
3475 	case NSSM_EVENT_PORT_OFFLINE:
3476 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3477 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3478 					   &ns->fcxp_wqe);
3479 		break;
3480 
3481 	default:
3482 		bfa_sm_fault(ns->port->fcs, event);
3483 	}
3484 }
3485 
3486 static void
bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3487 bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3488 			enum vport_ns_event event)
3489 {
3490 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3491 	bfa_trc(ns->port->fcs, event);
3492 
3493 	switch (event) {
3494 	case NSSM_EVENT_RSP_OK:
3495 		/* Now move to register FC4 Features */
3496 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3497 		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3498 		break;
3499 
3500 	case NSSM_EVENT_RSP_ERROR:
3501 		/*
3502 		 * Start timer for a delayed retry
3503 		 */
3504 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3505 		ns->port->stats.ns_retries++;
3506 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3507 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3508 				    BFA_FCS_RETRY_TIMEOUT);
3509 		break;
3510 
3511 	case NSSM_EVENT_PORT_OFFLINE:
3512 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3513 		bfa_fcxp_discard(ns->fcxp);
3514 		break;
3515 
3516 	default:
3517 		bfa_sm_fault(ns->port->fcs, event);
3518 	}
3519 }
3520 
3521 static void
bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3522 bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3523 				enum vport_ns_event event)
3524 {
3525 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3526 	bfa_trc(ns->port->fcs, event);
3527 
3528 	switch (event) {
3529 	case NSSM_EVENT_TIMEOUT:
3530 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3531 		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3532 		break;
3533 
3534 	case NSSM_EVENT_PORT_OFFLINE:
3535 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3536 		bfa_timer_stop(&ns->timer);
3537 		break;
3538 
3539 	default:
3540 		bfa_sm_fault(ns->port->fcs, event);
3541 	}
3542 }
3543 
3544 static void
bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3545 bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3546 				  enum vport_ns_event event)
3547 {
3548 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3549 	bfa_trc(ns->port->fcs, event);
3550 
3551 	switch (event) {
3552 	case NSSM_EVENT_RFFID_SENT:
3553 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3554 		break;
3555 
3556 	case NSSM_EVENT_PORT_OFFLINE:
3557 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3558 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3559 					   &ns->fcxp_wqe);
3560 		break;
3561 
3562 	default:
3563 		bfa_sm_fault(ns->port->fcs, event);
3564 	}
3565 }
3566 
3567 static void
bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3568 bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3569 			enum vport_ns_event event)
3570 {
3571 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3572 	bfa_trc(ns->port->fcs, event);
3573 
3574 	switch (event) {
3575 	case NSSM_EVENT_RSP_OK:
3576 
3577 		/*
3578 		 * If min cfg mode is enabled, we donot initiate rport
3579 		 * discovery with the fabric. Instead, we will retrieve the
3580 		 * boot targets from HAL/FW.
3581 		 */
3582 		if (__fcs_min_cfg(ns->port->fcs)) {
3583 			bfa_fcs_lport_ns_boot_target_disc(ns->port);
3584 			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3585 			return;
3586 		}
3587 
3588 		/*
3589 		 * If the port role is Initiator Mode issue NS query.
3590 		 * If it is Target Mode, skip this and go to online.
3591 		 */
3592 		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3593 			bfa_sm_set_state(ns,
3594 				bfa_fcs_lport_ns_sm_sending_gid_ft);
3595 			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3596 		}
3597 		/*
3598 		 * kick off mgmt srvr state machine
3599 		 */
3600 		bfa_fcs_lport_ms_online(ns->port);
3601 		break;
3602 
3603 	case NSSM_EVENT_RSP_ERROR:
3604 		/*
3605 		 * Start timer for a delayed retry
3606 		 */
3607 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3608 		ns->port->stats.ns_retries++;
3609 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3610 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3611 				    BFA_FCS_RETRY_TIMEOUT);
3612 		break;
3613 
3614 	case NSSM_EVENT_PORT_OFFLINE:
3615 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3616 		bfa_fcxp_discard(ns->fcxp);
3617 		break;
3618 
3619 	default:
3620 		bfa_sm_fault(ns->port->fcs, event);
3621 	}
3622 }
3623 
3624 static void
bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3625 bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3626 				enum vport_ns_event event)
3627 {
3628 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3629 	bfa_trc(ns->port->fcs, event);
3630 
3631 	switch (event) {
3632 	case NSSM_EVENT_TIMEOUT:
3633 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3634 		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3635 		break;
3636 
3637 	case NSSM_EVENT_PORT_OFFLINE:
3638 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3639 		bfa_timer_stop(&ns->timer);
3640 		break;
3641 
3642 	default:
3643 		bfa_sm_fault(ns->port->fcs, event);
3644 	}
3645 }
3646 static void
bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3647 bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3648 				  enum vport_ns_event event)
3649 {
3650 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3651 	bfa_trc(ns->port->fcs, event);
3652 
3653 	switch (event) {
3654 	case NSSM_EVENT_GIDFT_SENT:
3655 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3656 		break;
3657 
3658 	case NSSM_EVENT_PORT_OFFLINE:
3659 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3660 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3661 					   &ns->fcxp_wqe);
3662 		break;
3663 
3664 	default:
3665 		bfa_sm_fault(ns->port->fcs, event);
3666 	}
3667 }
3668 
3669 static void
bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3670 bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3671 			enum vport_ns_event event)
3672 {
3673 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3674 	bfa_trc(ns->port->fcs, event);
3675 
3676 	switch (event) {
3677 	case NSSM_EVENT_RSP_OK:
3678 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3679 		break;
3680 
3681 	case NSSM_EVENT_RSP_ERROR:
3682 		/*
3683 		 * TBD: for certain reject codes, we don't need to retry
3684 		 */
3685 		/*
3686 		 * Start timer for a delayed retry
3687 		 */
3688 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3689 		ns->port->stats.ns_retries++;
3690 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3691 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3692 				    BFA_FCS_RETRY_TIMEOUT);
3693 		break;
3694 
3695 	case NSSM_EVENT_PORT_OFFLINE:
3696 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3697 		bfa_fcxp_discard(ns->fcxp);
3698 		break;
3699 
3700 	case  NSSM_EVENT_NS_QUERY:
3701 		break;
3702 
3703 	default:
3704 		bfa_sm_fault(ns->port->fcs, event);
3705 	}
3706 }
3707 
3708 static void
bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3709 bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3710 				enum vport_ns_event event)
3711 {
3712 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3713 	bfa_trc(ns->port->fcs, event);
3714 
3715 	switch (event) {
3716 	case NSSM_EVENT_TIMEOUT:
3717 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3718 		bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3719 		break;
3720 
3721 	case NSSM_EVENT_PORT_OFFLINE:
3722 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3723 		bfa_timer_stop(&ns->timer);
3724 		break;
3725 
3726 	default:
3727 		bfa_sm_fault(ns->port->fcs, event);
3728 	}
3729 }
3730 
3731 static void
bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3732 bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3733 			enum vport_ns_event event)
3734 {
3735 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3736 	bfa_trc(ns->port->fcs, event);
3737 
3738 	switch (event) {
3739 	case NSSM_EVENT_PORT_OFFLINE:
3740 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3741 		break;
3742 
3743 	case NSSM_EVENT_NS_QUERY:
3744 		/*
3745 		 * If the port role is Initiator Mode issue NS query.
3746 		 * If it is Target Mode, skip this and go to online.
3747 		 */
3748 		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3749 			bfa_sm_set_state(ns,
3750 				bfa_fcs_lport_ns_sm_sending_gid_ft);
3751 			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3752 		};
3753 		break;
3754 
3755 	default:
3756 		bfa_sm_fault(ns->port->fcs, event);
3757 	}
3758 }
3759 
3760 
3761 
3762 /*
3763  *  ns_pvt Nameserver local functions
3764  */
3765 
3766 static void
bfa_fcs_lport_ns_send_plogi(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3767 bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3768 {
3769 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3770 	struct bfa_fcs_lport_s *port = ns->port;
3771 	struct fchs_s fchs;
3772 	int             len;
3773 	struct bfa_fcxp_s *fcxp;
3774 
3775 	bfa_trc(port->fcs, port->pid);
3776 
3777 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3778 	if (!fcxp) {
3779 		port->stats.ns_plogi_alloc_wait++;
3780 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3781 					bfa_fcs_lport_ns_send_plogi, ns);
3782 		return;
3783 	}
3784 	ns->fcxp = fcxp;
3785 
3786 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3787 			     bfa_hton3b(FC_NAME_SERVER),
3788 			     bfa_fcs_lport_get_fcid(port), 0,
3789 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
3790 			     bfa_fcport_get_maxfrsize(port->fcs->bfa),
3791 			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
3792 
3793 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3794 			  FC_CLASS_3, len, &fchs,
3795 			  bfa_fcs_lport_ns_plogi_response, (void *)ns,
3796 			  FC_MAX_PDUSZ, FC_ELS_TOV);
3797 	port->stats.ns_plogi_sent++;
3798 
3799 	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3800 }
3801 
3802 static void
bfa_fcs_lport_ns_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)3803 bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3804 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
3805 		       u32 resid_len, struct fchs_s *rsp_fchs)
3806 {
3807 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3808 	struct bfa_fcs_lport_s *port = ns->port;
3809 	/* struct fc_logi_s *plogi_resp; */
3810 	struct fc_els_cmd_s *els_cmd;
3811 	struct fc_ls_rjt_s *ls_rjt;
3812 
3813 	bfa_trc(port->fcs, req_status);
3814 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3815 
3816 	/*
3817 	 * Sanity Checks
3818 	 */
3819 	if (req_status != BFA_STATUS_OK) {
3820 		bfa_trc(port->fcs, req_status);
3821 		port->stats.ns_plogi_rsp_err++;
3822 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3823 		return;
3824 	}
3825 
3826 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3827 
3828 	switch (els_cmd->els_code) {
3829 
3830 	case FC_ELS_ACC:
3831 		if (rsp_len < sizeof(struct fc_logi_s)) {
3832 			bfa_trc(port->fcs, rsp_len);
3833 			port->stats.ns_plogi_acc_err++;
3834 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3835 			break;
3836 		}
3837 		port->stats.ns_plogi_accepts++;
3838 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3839 		break;
3840 
3841 	case FC_ELS_LS_RJT:
3842 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3843 
3844 		bfa_trc(port->fcs, ls_rjt->reason_code);
3845 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3846 
3847 		port->stats.ns_rejects++;
3848 
3849 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3850 		break;
3851 
3852 	default:
3853 		port->stats.ns_plogi_unknown_rsp++;
3854 		bfa_trc(port->fcs, els_cmd->els_code);
3855 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3856 	}
3857 }
3858 
3859 /*
3860  * Register the symbolic port name.
3861  */
3862 static void
bfa_fcs_lport_ns_send_rspn_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3863 bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3864 {
3865 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3866 	struct bfa_fcs_lport_s *port = ns->port;
3867 	struct fchs_s fchs;
3868 	int             len;
3869 	struct bfa_fcxp_s *fcxp;
3870 	u8         symbl[256];
3871 	u8         *psymbl = &symbl[0];
3872 
3873 	memset(symbl, 0, sizeof(symbl));
3874 
3875 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3876 
3877 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3878 	if (!fcxp) {
3879 		port->stats.ns_rspnid_alloc_wait++;
3880 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3881 					bfa_fcs_lport_ns_send_rspn_id, ns);
3882 		return;
3883 	}
3884 	ns->fcxp = fcxp;
3885 
3886 	/*
3887 	 * for V-Port, form a Port Symbolic Name
3888 	 */
3889 	if (port->vport) {
3890 		/*
3891 		 * For Vports, we append the vport's port symbolic name
3892 		 * to that of the base port.
3893 		 */
3894 
3895 		strncpy((char *)psymbl,
3896 			(char *) &
3897 			(bfa_fcs_lport_get_psym_name
3898 			 (bfa_fcs_get_base_port(port->fcs))),
3899 			strlen((char *) &
3900 			       bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3901 							  (port->fcs))));
3902 
3903 		/* Ensure we have a null terminating string. */
3904 		((char *)psymbl)[strlen((char *) &
3905 			bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3906 						(port->fcs)))] = 0;
3907 		strncat((char *)psymbl,
3908 			(char *) &(bfa_fcs_lport_get_psym_name(port)),
3909 		strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3910 	} else {
3911 		psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3912 	}
3913 
3914 	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3915 			      bfa_fcs_lport_get_fcid(port), 0, psymbl);
3916 
3917 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3918 			  FC_CLASS_3, len, &fchs,
3919 			  bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3920 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3921 
3922 	port->stats.ns_rspnid_sent++;
3923 
3924 	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3925 }
3926 
3927 static void
bfa_fcs_lport_ns_rspn_id_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)3928 bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3929 				 void *cbarg, bfa_status_t req_status,
3930 				 u32 rsp_len, u32 resid_len,
3931 				 struct fchs_s *rsp_fchs)
3932 {
3933 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3934 	struct bfa_fcs_lport_s *port = ns->port;
3935 	struct ct_hdr_s *cthdr = NULL;
3936 
3937 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3938 
3939 	/*
3940 	 * Sanity Checks
3941 	 */
3942 	if (req_status != BFA_STATUS_OK) {
3943 		bfa_trc(port->fcs, req_status);
3944 		port->stats.ns_rspnid_rsp_err++;
3945 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3946 		return;
3947 	}
3948 
3949 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3950 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3951 
3952 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3953 		port->stats.ns_rspnid_accepts++;
3954 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3955 		return;
3956 	}
3957 
3958 	port->stats.ns_rspnid_rejects++;
3959 	bfa_trc(port->fcs, cthdr->reason_code);
3960 	bfa_trc(port->fcs, cthdr->exp_code);
3961 	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3962 }
3963 
3964 /*
3965  * Register FC4-Types
3966  */
3967 static void
bfa_fcs_lport_ns_send_rft_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3968 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3969 {
3970 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3971 	struct bfa_fcs_lport_s *port = ns->port;
3972 	struct fchs_s fchs;
3973 	int             len;
3974 	struct bfa_fcxp_s *fcxp;
3975 
3976 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3977 
3978 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3979 	if (!fcxp) {
3980 		port->stats.ns_rftid_alloc_wait++;
3981 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3982 					bfa_fcs_lport_ns_send_rft_id, ns);
3983 		return;
3984 	}
3985 	ns->fcxp = fcxp;
3986 
3987 	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3988 		     bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3989 
3990 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3991 			  FC_CLASS_3, len, &fchs,
3992 			  bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3993 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3994 
3995 	port->stats.ns_rftid_sent++;
3996 	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3997 }
3998 
3999 static void
bfa_fcs_lport_ns_rft_id_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)4000 bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4001 				void *cbarg, bfa_status_t req_status,
4002 				u32 rsp_len, u32 resid_len,
4003 				struct fchs_s *rsp_fchs)
4004 {
4005 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4006 	struct bfa_fcs_lport_s *port = ns->port;
4007 	struct ct_hdr_s *cthdr = NULL;
4008 
4009 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4010 
4011 	/*
4012 	 * Sanity Checks
4013 	 */
4014 	if (req_status != BFA_STATUS_OK) {
4015 		bfa_trc(port->fcs, req_status);
4016 		port->stats.ns_rftid_rsp_err++;
4017 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4018 		return;
4019 	}
4020 
4021 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4022 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4023 
4024 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4025 		port->stats.ns_rftid_accepts++;
4026 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4027 		return;
4028 	}
4029 
4030 	port->stats.ns_rftid_rejects++;
4031 	bfa_trc(port->fcs, cthdr->reason_code);
4032 	bfa_trc(port->fcs, cthdr->exp_code);
4033 	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4034 }
4035 
4036 /*
4037  * Register FC4-Features : Should be done after RFT_ID
4038  */
4039 static void
bfa_fcs_lport_ns_send_rff_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4040 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4041 {
4042 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4043 	struct bfa_fcs_lport_s *port = ns->port;
4044 	struct fchs_s fchs;
4045 	int             len;
4046 	struct bfa_fcxp_s *fcxp;
4047 	u8			fc4_ftrs = 0;
4048 
4049 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4050 
4051 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4052 	if (!fcxp) {
4053 		port->stats.ns_rffid_alloc_wait++;
4054 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4055 					bfa_fcs_lport_ns_send_rff_id, ns);
4056 		return;
4057 	}
4058 	ns->fcxp = fcxp;
4059 
4060 	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
4061 		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
4062 
4063 	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4064 			     bfa_fcs_lport_get_fcid(port), 0,
4065 				 FC_TYPE_FCP, fc4_ftrs);
4066 
4067 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4068 			  FC_CLASS_3, len, &fchs,
4069 			  bfa_fcs_lport_ns_rff_id_response, (void *)ns,
4070 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
4071 
4072 	port->stats.ns_rffid_sent++;
4073 	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
4074 }
4075 
4076 static void
bfa_fcs_lport_ns_rff_id_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)4077 bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4078 				void *cbarg, bfa_status_t req_status,
4079 				u32 rsp_len, u32 resid_len,
4080 				struct fchs_s *rsp_fchs)
4081 {
4082 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4083 	struct bfa_fcs_lport_s *port = ns->port;
4084 	struct ct_hdr_s *cthdr = NULL;
4085 
4086 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4087 
4088 	/*
4089 	 * Sanity Checks
4090 	 */
4091 	if (req_status != BFA_STATUS_OK) {
4092 		bfa_trc(port->fcs, req_status);
4093 		port->stats.ns_rffid_rsp_err++;
4094 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4095 		return;
4096 	}
4097 
4098 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4099 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4100 
4101 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4102 		port->stats.ns_rffid_accepts++;
4103 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4104 		return;
4105 	}
4106 
4107 	port->stats.ns_rffid_rejects++;
4108 	bfa_trc(port->fcs, cthdr->reason_code);
4109 	bfa_trc(port->fcs, cthdr->exp_code);
4110 
4111 	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
4112 		/* if this command is not supported, we don't retry */
4113 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4114 	} else
4115 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4116 }
4117 /*
4118  * Query Fabric for FC4-Types Devices.
4119  *
4120 * TBD : Need to use a local (FCS private) response buffer, since the response
4121  * can be larger than 2K.
4122  */
4123 static void
bfa_fcs_lport_ns_send_gid_ft(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4124 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4125 {
4126 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4127 	struct bfa_fcs_lport_s *port = ns->port;
4128 	struct fchs_s fchs;
4129 	int             len;
4130 	struct bfa_fcxp_s *fcxp;
4131 
4132 	bfa_trc(port->fcs, port->pid);
4133 
4134 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4135 	if (!fcxp) {
4136 		port->stats.ns_gidft_alloc_wait++;
4137 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4138 					bfa_fcs_lport_ns_send_gid_ft, ns);
4139 		return;
4140 	}
4141 	ns->fcxp = fcxp;
4142 
4143 	/*
4144 	 * This query is only initiated for FCP initiator mode.
4145 	 */
4146 	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4147 			      ns->port->pid, FC_TYPE_FCP);
4148 
4149 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4150 			  FC_CLASS_3, len, &fchs,
4151 			  bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
4152 			  bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
4153 
4154 	port->stats.ns_gidft_sent++;
4155 
4156 	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
4157 }
4158 
4159 static void
bfa_fcs_lport_ns_gid_ft_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)4160 bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4161 				void *cbarg, bfa_status_t req_status,
4162 				u32 rsp_len, u32 resid_len,
4163 				struct fchs_s *rsp_fchs)
4164 {
4165 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4166 	struct bfa_fcs_lport_s *port = ns->port;
4167 	struct ct_hdr_s *cthdr = NULL;
4168 	u32        n_pids;
4169 
4170 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4171 
4172 	/*
4173 	 * Sanity Checks
4174 	 */
4175 	if (req_status != BFA_STATUS_OK) {
4176 		bfa_trc(port->fcs, req_status);
4177 		port->stats.ns_gidft_rsp_err++;
4178 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4179 		return;
4180 	}
4181 
4182 	if (resid_len != 0) {
4183 		/*
4184 		 * TBD : we will need to allocate a larger buffer & retry the
4185 		 * command
4186 		 */
4187 		bfa_trc(port->fcs, rsp_len);
4188 		bfa_trc(port->fcs, resid_len);
4189 		return;
4190 	}
4191 
4192 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4193 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4194 
4195 	switch (cthdr->cmd_rsp_code) {
4196 
4197 	case CT_RSP_ACCEPT:
4198 
4199 		port->stats.ns_gidft_accepts++;
4200 		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
4201 		bfa_trc(port->fcs, n_pids);
4202 		bfa_fcs_lport_ns_process_gidft_pids(port,
4203 						   (u32 *) (cthdr + 1),
4204 						   n_pids);
4205 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4206 		break;
4207 
4208 	case CT_RSP_REJECT:
4209 
4210 		/*
4211 		 * Check the reason code  & explanation.
4212 		 * There may not have been any FC4 devices in the fabric
4213 		 */
4214 		port->stats.ns_gidft_rejects++;
4215 		bfa_trc(port->fcs, cthdr->reason_code);
4216 		bfa_trc(port->fcs, cthdr->exp_code);
4217 
4218 		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4219 		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4220 
4221 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4222 		} else {
4223 			/*
4224 			 * for all other errors, retry
4225 			 */
4226 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4227 		}
4228 		break;
4229 
4230 	default:
4231 		port->stats.ns_gidft_unknown_rsp++;
4232 		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4233 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4234 	}
4235 }
4236 
4237 /*
4238  *     This routine will be called by bfa_timer on timer timeouts.
4239  *
4240  *	param[in]	port - pointer to bfa_fcs_lport_t.
4241  *
4242  *	return
4243  *		void
4244  *
4245  *	Special Considerations:
4246  *
4247  *	note
4248  */
4249 static void
bfa_fcs_lport_ns_timeout(void * arg)4250 bfa_fcs_lport_ns_timeout(void *arg)
4251 {
4252 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4253 
4254 	ns->port->stats.ns_timeouts++;
4255 	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4256 }
4257 
4258 /*
4259  * Process the PID list in GID_FT response
4260  */
4261 static void
bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s * port,u32 * pid_buf,u32 n_pids)4262 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4263 				   u32 n_pids)
4264 {
4265 	struct fcgs_gidft_resp_s *gidft_entry;
4266 	struct bfa_fcs_rport_s *rport;
4267 	u32        ii;
4268 
4269 	for (ii = 0; ii < n_pids; ii++) {
4270 		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4271 
4272 		if (gidft_entry->pid == port->pid)
4273 			continue;
4274 
4275 		/*
4276 		 * Check if this rport already exists
4277 		 */
4278 		rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4279 		if (rport == NULL) {
4280 			/*
4281 			 * this is a new device. create rport
4282 			 */
4283 			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4284 		} else {
4285 			/*
4286 			 * this rport already exists
4287 			 */
4288 			bfa_fcs_rport_scn(rport);
4289 		}
4290 
4291 		bfa_trc(port->fcs, gidft_entry->pid);
4292 
4293 		/*
4294 		 * if the last entry bit is set, bail out.
4295 		 */
4296 		if (gidft_entry->last)
4297 			return;
4298 	}
4299 }
4300 
4301 /*
4302  *  fcs_ns_public FCS nameserver public interfaces
4303  */
4304 
4305 /*
4306  * Functions called by port/fab.
4307  * These will send relevant Events to the ns state machine.
4308  */
4309 void
bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s * port)4310 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4311 {
4312 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4313 
4314 	ns->port = port;
4315 	bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4316 }
4317 
4318 void
bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s * port)4319 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4320 {
4321 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4322 
4323 	ns->port = port;
4324 	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4325 }
4326 
4327 void
bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s * port)4328 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4329 {
4330 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4331 
4332 	ns->port = port;
4333 	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4334 }
4335 
4336 void
bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s * port)4337 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4338 {
4339 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4340 
4341 	bfa_trc(port->fcs, port->pid);
4342 	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4343 }
4344 
4345 static void
bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t * port)4346 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4347 {
4348 
4349 	struct bfa_fcs_rport_s *rport;
4350 	u8 nwwns;
4351 	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
4352 	int ii;
4353 
4354 	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4355 
4356 	for (ii = 0 ; ii < nwwns; ++ii) {
4357 		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4358 		WARN_ON(!rport);
4359 	}
4360 }
4361 
4362 /*
4363  * FCS SCN
4364  */
4365 
4366 #define FC_QOS_RSCN_EVENT		0x0c
4367 #define FC_FABRIC_NAME_RSCN_EVENT	0x0d
4368 
4369 /*
4370  * forward declarations
4371  */
4372 static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4373 					  struct bfa_fcxp_s *fcxp_alloced);
4374 static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
4375 					      struct bfa_fcxp_s *fcxp,
4376 					      void *cbarg,
4377 					      bfa_status_t req_status,
4378 					      u32 rsp_len,
4379 					      u32 resid_len,
4380 					      struct fchs_s *rsp_fchs);
4381 static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4382 					     struct fchs_s *rx_fchs);
4383 static void     bfa_fcs_lport_scn_timeout(void *arg);
4384 
4385 /*
4386  *  fcs_scm_sm FCS SCN state machine
4387  */
4388 
4389 /*
4390  * VPort SCN State Machine events
4391  */
4392 enum port_scn_event {
4393 	SCNSM_EVENT_PORT_ONLINE = 1,
4394 	SCNSM_EVENT_PORT_OFFLINE = 2,
4395 	SCNSM_EVENT_RSP_OK = 3,
4396 	SCNSM_EVENT_RSP_ERROR = 4,
4397 	SCNSM_EVENT_TIMEOUT = 5,
4398 	SCNSM_EVENT_SCR_SENT = 6,
4399 };
4400 
4401 static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4402 					    enum port_scn_event event);
4403 static void     bfa_fcs_lport_scn_sm_sending_scr(
4404 					struct bfa_fcs_lport_scn_s *scn,
4405 					enum port_scn_event event);
4406 static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4407 					enum port_scn_event event);
4408 static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4409 					      enum port_scn_event event);
4410 static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4411 					   enum port_scn_event event);
4412 
4413 /*
4414  *	Starting state - awaiting link up.
4415  */
4416 static void
bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4417 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4418 			enum port_scn_event event)
4419 {
4420 	switch (event) {
4421 	case SCNSM_EVENT_PORT_ONLINE:
4422 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4423 		bfa_fcs_lport_scn_send_scr(scn, NULL);
4424 		break;
4425 
4426 	case SCNSM_EVENT_PORT_OFFLINE:
4427 		break;
4428 
4429 	default:
4430 		bfa_sm_fault(scn->port->fcs, event);
4431 	}
4432 }
4433 
4434 static void
bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4435 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4436 				enum port_scn_event event)
4437 {
4438 	switch (event) {
4439 	case SCNSM_EVENT_SCR_SENT:
4440 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4441 		break;
4442 
4443 	case SCNSM_EVENT_PORT_OFFLINE:
4444 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4445 		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4446 		break;
4447 
4448 	default:
4449 		bfa_sm_fault(scn->port->fcs, event);
4450 	}
4451 }
4452 
4453 static void
bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4454 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4455 			enum port_scn_event event)
4456 {
4457 	struct bfa_fcs_lport_s *port = scn->port;
4458 
4459 	switch (event) {
4460 	case SCNSM_EVENT_RSP_OK:
4461 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4462 		break;
4463 
4464 	case SCNSM_EVENT_RSP_ERROR:
4465 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4466 		bfa_timer_start(port->fcs->bfa, &scn->timer,
4467 				    bfa_fcs_lport_scn_timeout, scn,
4468 				    BFA_FCS_RETRY_TIMEOUT);
4469 		break;
4470 
4471 	case SCNSM_EVENT_PORT_OFFLINE:
4472 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4473 		bfa_fcxp_discard(scn->fcxp);
4474 		break;
4475 
4476 	default:
4477 		bfa_sm_fault(port->fcs, event);
4478 	}
4479 }
4480 
4481 static void
bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4482 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4483 				enum port_scn_event event)
4484 {
4485 	switch (event) {
4486 	case SCNSM_EVENT_TIMEOUT:
4487 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4488 		bfa_fcs_lport_scn_send_scr(scn, NULL);
4489 		break;
4490 
4491 	case SCNSM_EVENT_PORT_OFFLINE:
4492 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4493 		bfa_timer_stop(&scn->timer);
4494 		break;
4495 
4496 	default:
4497 		bfa_sm_fault(scn->port->fcs, event);
4498 	}
4499 }
4500 
4501 static void
bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4502 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4503 			enum port_scn_event event)
4504 {
4505 	switch (event) {
4506 	case SCNSM_EVENT_PORT_OFFLINE:
4507 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4508 		break;
4509 
4510 	default:
4511 		bfa_sm_fault(scn->port->fcs, event);
4512 	}
4513 }
4514 
4515 
4516 
4517 /*
4518  *  fcs_scn_private FCS SCN private functions
4519  */
4520 
4521 /*
4522  * This routine will be called to send a SCR command.
4523  */
4524 static void
bfa_fcs_lport_scn_send_scr(void * scn_cbarg,struct bfa_fcxp_s * fcxp_alloced)4525 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4526 {
4527 	struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4528 	struct bfa_fcs_lport_s *port = scn->port;
4529 	struct fchs_s fchs;
4530 	int             len;
4531 	struct bfa_fcxp_s *fcxp;
4532 
4533 	bfa_trc(port->fcs, port->pid);
4534 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4535 
4536 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4537 	if (!fcxp) {
4538 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4539 					bfa_fcs_lport_scn_send_scr, scn);
4540 		return;
4541 	}
4542 	scn->fcxp = fcxp;
4543 
4544 	/* Handle VU registrations for Base port only */
4545 	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4546 		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4547 				port->fabric->lps->brcd_switch,
4548 				port->pid, 0);
4549 	} else {
4550 	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4551 				    BFA_FALSE,
4552 				    port->pid, 0);
4553 	}
4554 
4555 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4556 			  FC_CLASS_3, len, &fchs,
4557 			  bfa_fcs_lport_scn_scr_response,
4558 			  (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4559 
4560 	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4561 }
4562 
4563 static void
bfa_fcs_lport_scn_scr_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)4564 bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4565 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
4566 			      u32 resid_len, struct fchs_s *rsp_fchs)
4567 {
4568 	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4569 	struct bfa_fcs_lport_s *port = scn->port;
4570 	struct fc_els_cmd_s *els_cmd;
4571 	struct fc_ls_rjt_s *ls_rjt;
4572 
4573 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4574 
4575 	/*
4576 	 * Sanity Checks
4577 	 */
4578 	if (req_status != BFA_STATUS_OK) {
4579 		bfa_trc(port->fcs, req_status);
4580 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4581 		return;
4582 	}
4583 
4584 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4585 
4586 	switch (els_cmd->els_code) {
4587 
4588 	case FC_ELS_ACC:
4589 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4590 		break;
4591 
4592 	case FC_ELS_LS_RJT:
4593 
4594 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4595 
4596 		bfa_trc(port->fcs, ls_rjt->reason_code);
4597 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4598 
4599 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4600 		break;
4601 
4602 	default:
4603 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4604 	}
4605 }
4606 
4607 /*
4608  * Send a LS Accept
4609  */
4610 static void
bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs)4611 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4612 				struct fchs_s *rx_fchs)
4613 {
4614 	struct fchs_s fchs;
4615 	struct bfa_fcxp_s *fcxp;
4616 	struct bfa_rport_s *bfa_rport = NULL;
4617 	int             len;
4618 
4619 	bfa_trc(port->fcs, rx_fchs->s_id);
4620 
4621 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4622 	if (!fcxp)
4623 		return;
4624 
4625 	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4626 			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4627 			      rx_fchs->ox_id);
4628 
4629 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4630 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4631 			  FC_MAX_PDUSZ, 0);
4632 }
4633 
4634 /*
4635  *     This routine will be called by bfa_timer on timer timeouts.
4636  *
4637  *	param[in]	vport		- pointer to bfa_fcs_lport_t.
4638  *	param[out]	vport_status	- pointer to return vport status in
4639  *
4640  *	return
4641  *		void
4642  *
4643  *	Special Considerations:
4644  *
4645  *	note
4646  */
4647 static void
bfa_fcs_lport_scn_timeout(void * arg)4648 bfa_fcs_lport_scn_timeout(void *arg)
4649 {
4650 	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4651 
4652 	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4653 }
4654 
4655 
4656 
4657 /*
4658  *  fcs_scn_public FCS state change notification public interfaces
4659  */
4660 
4661 /*
4662  * Functions called by port/fab
4663  */
4664 void
bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s * port)4665 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4666 {
4667 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4668 
4669 	scn->port = port;
4670 	bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4671 }
4672 
4673 void
bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s * port)4674 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4675 {
4676 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4677 
4678 	scn->port = port;
4679 	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4680 }
4681 
4682 void
bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s * port)4683 bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4684 {
4685 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4686 
4687 	scn->port = port;
4688 	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4689 }
4690 
4691 static void
bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s * port,u32 rpid)4692 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4693 {
4694 	struct bfa_fcs_rport_s *rport;
4695 
4696 	bfa_trc(port->fcs, rpid);
4697 
4698 	/*
4699 	 * If this is an unknown device, then it just came online.
4700 	 * Otherwise let rport handle the RSCN event.
4701 	 */
4702 	rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4703 	if (rport == NULL) {
4704 		/*
4705 		 * If min cfg mode is enabled, we donot need to
4706 		 * discover any new rports.
4707 		 */
4708 		if (!__fcs_min_cfg(port->fcs))
4709 			rport = bfa_fcs_rport_create(port, rpid);
4710 	} else
4711 		bfa_fcs_rport_scn(rport);
4712 }
4713 
4714 /*
4715  * rscn format based PID comparison
4716  */
4717 #define __fc_pid_match(__c0, __c1, __fmt)		\
4718 	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
4719 	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
4720 	  ((__c0)[0] == (__c1)[0])) ||				\
4721 	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
4722 	  ((__c0)[0] == (__c1)[0]) &&				\
4723 	  ((__c0)[1] == (__c1)[1])))
4724 
4725 static void
bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s * port,enum fc_rscn_format format,u32 rscn_pid)4726 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4727 				enum fc_rscn_format format,
4728 				u32 rscn_pid)
4729 {
4730 	struct bfa_fcs_rport_s *rport;
4731 	struct list_head        *qe, *qe_next;
4732 	u8        *c0, *c1;
4733 
4734 	bfa_trc(port->fcs, format);
4735 	bfa_trc(port->fcs, rscn_pid);
4736 
4737 	c0 = (u8 *) &rscn_pid;
4738 
4739 	list_for_each_safe(qe, qe_next, &port->rport_q) {
4740 		rport = (struct bfa_fcs_rport_s *) qe;
4741 		c1 = (u8 *) &rport->pid;
4742 		if (__fc_pid_match(c0, c1, format))
4743 			bfa_fcs_rport_scn(rport);
4744 	}
4745 }
4746 
4747 
4748 void
bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s * port,struct fchs_s * fchs,u32 len)4749 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4750 			struct fchs_s *fchs, u32 len)
4751 {
4752 	struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4753 	int             num_entries;
4754 	u32        rscn_pid;
4755 	bfa_boolean_t   nsquery = BFA_FALSE, found;
4756 	int             i = 0, j;
4757 
4758 	num_entries =
4759 		(be16_to_cpu(rscn->payldlen) -
4760 		 sizeof(u32)) / sizeof(rscn->event[0]);
4761 
4762 	bfa_trc(port->fcs, num_entries);
4763 
4764 	port->stats.num_rscn++;
4765 
4766 	bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4767 
4768 	for (i = 0; i < num_entries; i++) {
4769 		rscn_pid = rscn->event[i].portid;
4770 
4771 		bfa_trc(port->fcs, rscn->event[i].format);
4772 		bfa_trc(port->fcs, rscn_pid);
4773 
4774 		/* check for duplicate entries in the list */
4775 		found = BFA_FALSE;
4776 		for (j = 0; j < i; j++) {
4777 			if (rscn->event[j].portid == rscn_pid) {
4778 				found = BFA_TRUE;
4779 				break;
4780 			}
4781 		}
4782 
4783 		/* if found in down the list, pid has been already processed */
4784 		if (found) {
4785 			bfa_trc(port->fcs, rscn_pid);
4786 			continue;
4787 		}
4788 
4789 		switch (rscn->event[i].format) {
4790 		case FC_RSCN_FORMAT_PORTID:
4791 			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4792 				/*
4793 				 * Ignore this event.
4794 				 * f/w would have processed it
4795 				 */
4796 				bfa_trc(port->fcs, rscn_pid);
4797 			} else {
4798 				port->stats.num_portid_rscn++;
4799 				bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4800 			}
4801 		break;
4802 
4803 		case FC_RSCN_FORMAT_FABRIC:
4804 			if (rscn->event[i].qualifier ==
4805 					FC_FABRIC_NAME_RSCN_EVENT) {
4806 				bfa_fcs_lport_ms_fabric_rscn(port);
4807 				break;
4808 			}
4809 			/* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
4810 
4811 		case FC_RSCN_FORMAT_AREA:
4812 		case FC_RSCN_FORMAT_DOMAIN:
4813 			nsquery = BFA_TRUE;
4814 			bfa_fcs_lport_scn_multiport_rscn(port,
4815 							rscn->event[i].format,
4816 							rscn_pid);
4817 			break;
4818 
4819 
4820 		default:
4821 			WARN_ON(1);
4822 			nsquery = BFA_TRUE;
4823 		}
4824 	}
4825 
4826 	/*
4827 	 * If any of area, domain or fabric RSCN is received, do a fresh
4828 	 * discovery to find new devices.
4829 	 */
4830 	if (nsquery)
4831 		bfa_fcs_lport_ns_query(port);
4832 }
4833 
4834 /*
4835  * BFA FCS port
4836  */
4837 /*
4838  *  fcs_port_api BFA FCS port API
4839  */
4840 struct bfa_fcs_lport_s *
bfa_fcs_get_base_port(struct bfa_fcs_s * fcs)4841 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4842 {
4843 	return &fcs->fabric.bport;
4844 }
4845 
4846 wwn_t
bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s * port,wwn_t wwn,int index,int nrports,bfa_boolean_t bwwn)4847 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4848 		int nrports, bfa_boolean_t bwwn)
4849 {
4850 	struct list_head	*qh, *qe;
4851 	struct bfa_fcs_rport_s *rport = NULL;
4852 	int	i;
4853 	struct bfa_fcs_s	*fcs;
4854 
4855 	if (port == NULL || nrports == 0)
4856 		return (wwn_t) 0;
4857 
4858 	fcs = port->fcs;
4859 	bfa_trc(fcs, (u32) nrports);
4860 
4861 	i = 0;
4862 	qh = &port->rport_q;
4863 	qe = bfa_q_first(qh);
4864 
4865 	while ((qe != qh) && (i < nrports)) {
4866 		rport = (struct bfa_fcs_rport_s *) qe;
4867 		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4868 			qe = bfa_q_next(qe);
4869 			bfa_trc(fcs, (u32) rport->pwwn);
4870 			bfa_trc(fcs, rport->pid);
4871 			bfa_trc(fcs, i);
4872 			continue;
4873 		}
4874 
4875 		if (bwwn) {
4876 			if (!memcmp(&wwn, &rport->pwwn, 8))
4877 				break;
4878 		} else {
4879 			if (i == index)
4880 				break;
4881 		}
4882 
4883 		i++;
4884 		qe = bfa_q_next(qe);
4885 	}
4886 
4887 	bfa_trc(fcs, i);
4888 	if (rport)
4889 		return rport->pwwn;
4890 	else
4891 		return (wwn_t) 0;
4892 }
4893 
4894 void
bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s * port,wwn_t rport_wwns[],int * nrports)4895 bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4896 	 wwn_t rport_wwns[], int *nrports)
4897 {
4898 	struct list_head	*qh, *qe;
4899 	struct bfa_fcs_rport_s *rport = NULL;
4900 	int	i;
4901 	struct bfa_fcs_s	*fcs;
4902 
4903 	if (port == NULL || rport_wwns == NULL || *nrports == 0)
4904 		return;
4905 
4906 	fcs = port->fcs;
4907 	bfa_trc(fcs, (u32) *nrports);
4908 
4909 	i = 0;
4910 	qh = &port->rport_q;
4911 	qe = bfa_q_first(qh);
4912 
4913 	while ((qe != qh) && (i < *nrports)) {
4914 		rport = (struct bfa_fcs_rport_s *) qe;
4915 		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4916 			qe = bfa_q_next(qe);
4917 			bfa_trc(fcs, (u32) rport->pwwn);
4918 			bfa_trc(fcs, rport->pid);
4919 			bfa_trc(fcs, i);
4920 			continue;
4921 		}
4922 
4923 		rport_wwns[i] = rport->pwwn;
4924 
4925 		i++;
4926 		qe = bfa_q_next(qe);
4927 	}
4928 
4929 	bfa_trc(fcs, i);
4930 	*nrports = i;
4931 }
4932 
4933 /*
4934  * Iterate's through all the rport's in the given port to
4935  * determine the maximum operating speed.
4936  *
4937  * !!!! To be used in TRL Functionality only !!!!
4938  */
4939 bfa_port_speed_t
bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t * port)4940 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4941 {
4942 	struct list_head *qh, *qe;
4943 	struct bfa_fcs_rport_s *rport = NULL;
4944 	struct bfa_fcs_s	*fcs;
4945 	bfa_port_speed_t max_speed = 0;
4946 	struct bfa_port_attr_s port_attr;
4947 	bfa_port_speed_t port_speed, rport_speed;
4948 	bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4949 
4950 
4951 	if (port == NULL)
4952 		return 0;
4953 
4954 	fcs = port->fcs;
4955 
4956 	/* Get Physical port's current speed */
4957 	bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4958 	port_speed = port_attr.speed;
4959 	bfa_trc(fcs, port_speed);
4960 
4961 	qh = &port->rport_q;
4962 	qe = bfa_q_first(qh);
4963 
4964 	while (qe != qh) {
4965 		rport = (struct bfa_fcs_rport_s *) qe;
4966 		if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
4967 			(bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
4968 			(rport->scsi_function != BFA_RPORT_TARGET)) {
4969 			qe = bfa_q_next(qe);
4970 			continue;
4971 		}
4972 
4973 		rport_speed = rport->rpf.rpsc_speed;
4974 		if ((trl_enabled) && (rport_speed ==
4975 			BFA_PORT_SPEED_UNKNOWN)) {
4976 			/* Use default ratelim speed setting */
4977 			rport_speed =
4978 				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4979 		}
4980 
4981 		if (rport_speed > max_speed)
4982 			max_speed = rport_speed;
4983 
4984 		qe = bfa_q_next(qe);
4985 	}
4986 
4987 	if (max_speed > port_speed)
4988 		max_speed = port_speed;
4989 
4990 	bfa_trc(fcs, max_speed);
4991 	return max_speed;
4992 }
4993 
4994 struct bfa_fcs_lport_s *
bfa_fcs_lookup_port(struct bfa_fcs_s * fcs,u16 vf_id,wwn_t lpwwn)4995 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4996 {
4997 	struct bfa_fcs_vport_s *vport;
4998 	bfa_fcs_vf_t   *vf;
4999 
5000 	WARN_ON(fcs == NULL);
5001 
5002 	vf = bfa_fcs_vf_lookup(fcs, vf_id);
5003 	if (vf == NULL) {
5004 		bfa_trc(fcs, vf_id);
5005 		return NULL;
5006 	}
5007 
5008 	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
5009 		return &vf->bport;
5010 
5011 	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
5012 	if (vport)
5013 		return &vport->lport;
5014 
5015 	return NULL;
5016 }
5017 
5018 /*
5019  *  API corresponding to NPIV_VPORT_GETINFO.
5020  */
5021 void
bfa_fcs_lport_get_info(struct bfa_fcs_lport_s * port,struct bfa_lport_info_s * port_info)5022 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
5023 	 struct bfa_lport_info_s *port_info)
5024 {
5025 
5026 	bfa_trc(port->fcs, port->fabric->fabric_name);
5027 
5028 	if (port->vport == NULL) {
5029 		/*
5030 		 * This is a Physical port
5031 		 */
5032 		port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
5033 
5034 		/*
5035 		 * @todo : need to fix the state & reason
5036 		 */
5037 		port_info->port_state = 0;
5038 		port_info->offline_reason = 0;
5039 
5040 		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5041 		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5042 
5043 		port_info->max_vports_supp =
5044 			bfa_lps_get_max_vport(port->fcs->bfa);
5045 		port_info->num_vports_inuse =
5046 			port->fabric->num_vports;
5047 		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
5048 		port_info->num_rports_inuse = port->num_rports;
5049 	} else {
5050 		/*
5051 		 * This is a virtual port
5052 		 */
5053 		port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
5054 
5055 		/*
5056 		 * @todo : need to fix the state & reason
5057 		 */
5058 		port_info->port_state = 0;
5059 		port_info->offline_reason = 0;
5060 
5061 		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5062 		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5063 	}
5064 }
5065 
5066 void
bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s * fcs_port,struct bfa_lport_stats_s * port_stats)5067 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
5068 	 struct bfa_lport_stats_s *port_stats)
5069 {
5070 	*port_stats = fcs_port->stats;
5071 }
5072 
5073 void
bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s * fcs_port)5074 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
5075 {
5076 	memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
5077 }
5078 
5079 /*
5080  * FCS virtual port state machine
5081  */
5082 
5083 #define __vport_fcs(__vp)       ((__vp)->lport.fcs)
5084 #define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
5085 #define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
5086 #define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
5087 #define __vport_fcid(__vp)      ((__vp)->lport.pid)
5088 #define __vport_fabric(__vp)    ((__vp)->lport.fabric)
5089 #define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
5090 
5091 #define BFA_FCS_VPORT_MAX_RETRIES  5
5092 /*
5093  * Forward declarations
5094  */
5095 static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
5096 static void     bfa_fcs_vport_timeout(void *vport_arg);
5097 static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
5098 static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
5099 
5100 /*
5101  *  fcs_vport_sm FCS virtual port state machine
5102  */
5103 
5104 /*
5105  * VPort State Machine events
5106  */
5107 enum bfa_fcs_vport_event {
5108 	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
5109 	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
5110 	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
5111 	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
5112 	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
5113 	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
5114 	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
5115 	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
5116 	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
5117 	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
5118 	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
5119 	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
5120 	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
5121 	BFA_FCS_VPORT_SM_STOPCOMP = 14,	/* vport delete completion */
5122 };
5123 
5124 static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
5125 					enum bfa_fcs_vport_event event);
5126 static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
5127 					 enum bfa_fcs_vport_event event);
5128 static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5129 					 enum bfa_fcs_vport_event event);
5130 static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5131 				       enum bfa_fcs_vport_event event);
5132 static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5133 					     enum bfa_fcs_vport_event event);
5134 static void	bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
5135 					enum bfa_fcs_vport_event event);
5136 static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5137 					enum bfa_fcs_vport_event event);
5138 static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5139 					  enum bfa_fcs_vport_event event);
5140 static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5141 					 enum bfa_fcs_vport_event event);
5142 static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5143 				      enum bfa_fcs_vport_event event);
5144 static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5145 				      enum bfa_fcs_vport_event event);
5146 static void	bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
5147 					enum bfa_fcs_vport_event event);
5148 static void	bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
5149 					enum bfa_fcs_vport_event event);
5150 
5151 static struct bfa_sm_table_s  vport_sm_table[] = {
5152 	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
5153 	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
5154 	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
5155 	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
5156 	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
5157 	{BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
5158 	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
5159 	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
5160 	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
5161 	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
5162 	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
5163 };
5164 
5165 /*
5166  * Beginning state.
5167  */
5168 static void
bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5169 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
5170 			enum bfa_fcs_vport_event event)
5171 {
5172 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5173 	bfa_trc(__vport_fcs(vport), event);
5174 
5175 	switch (event) {
5176 	case BFA_FCS_VPORT_SM_CREATE:
5177 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5178 		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
5179 		break;
5180 
5181 	default:
5182 		bfa_sm_fault(__vport_fcs(vport), event);
5183 	}
5184 }
5185 
5186 /*
5187  * Created state - a start event is required to start up the state machine.
5188  */
5189 static void
bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5190 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
5191 			enum bfa_fcs_vport_event event)
5192 {
5193 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5194 	bfa_trc(__vport_fcs(vport), event);
5195 
5196 	switch (event) {
5197 	case BFA_FCS_VPORT_SM_START:
5198 		if (bfa_sm_cmp_state(__vport_fabric(vport),
5199 					bfa_fcs_fabric_sm_online)
5200 		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
5201 			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5202 			bfa_fcs_vport_do_fdisc(vport);
5203 		} else {
5204 			/*
5205 			 * Fabric is offline or not NPIV capable, stay in
5206 			 * offline state.
5207 			 */
5208 			vport->vport_stats.fab_no_npiv++;
5209 			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5210 		}
5211 		break;
5212 
5213 	case BFA_FCS_VPORT_SM_DELETE:
5214 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5215 		bfa_fcs_lport_delete(&vport->lport);
5216 		break;
5217 
5218 	case BFA_FCS_VPORT_SM_ONLINE:
5219 	case BFA_FCS_VPORT_SM_OFFLINE:
5220 		/*
5221 		 * Ignore ONLINE/OFFLINE events from fabric
5222 		 * till vport is started.
5223 		 */
5224 		break;
5225 
5226 	default:
5227 		bfa_sm_fault(__vport_fcs(vport), event);
5228 	}
5229 }
5230 
5231 /*
5232  * Offline state - awaiting ONLINE event from fabric SM.
5233  */
5234 static void
bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5235 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5236 			enum bfa_fcs_vport_event event)
5237 {
5238 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5239 	bfa_trc(__vport_fcs(vport), event);
5240 
5241 	switch (event) {
5242 	case BFA_FCS_VPORT_SM_DELETE:
5243 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5244 		bfa_fcs_lport_delete(&vport->lport);
5245 		break;
5246 
5247 	case BFA_FCS_VPORT_SM_ONLINE:
5248 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5249 		vport->fdisc_retries = 0;
5250 		bfa_fcs_vport_do_fdisc(vport);
5251 		break;
5252 
5253 	case BFA_FCS_VPORT_SM_STOP:
5254 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5255 		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
5256 		break;
5257 
5258 	case BFA_FCS_VPORT_SM_OFFLINE:
5259 		/*
5260 		 * This can happen if the vport couldn't be initialzied
5261 		 * due the fact that the npiv was not enabled on the switch.
5262 		 * In that case we will put the vport in offline state.
5263 		 * However, the link can go down and cause the this event to
5264 		 * be sent when we are already offline. Ignore it.
5265 		 */
5266 		break;
5267 
5268 	default:
5269 		bfa_sm_fault(__vport_fcs(vport), event);
5270 	}
5271 }
5272 
5273 
5274 /*
5275  * FDISC is sent and awaiting reply from fabric.
5276  */
5277 static void
bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5278 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5279 			enum bfa_fcs_vport_event event)
5280 {
5281 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5282 	bfa_trc(__vport_fcs(vport), event);
5283 
5284 	switch (event) {
5285 	case BFA_FCS_VPORT_SM_DELETE:
5286 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
5287 		break;
5288 
5289 	case BFA_FCS_VPORT_SM_OFFLINE:
5290 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5291 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5292 		break;
5293 
5294 	case BFA_FCS_VPORT_SM_RSP_OK:
5295 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5296 		bfa_fcs_lport_online(&vport->lport);
5297 		break;
5298 
5299 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5300 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5301 		bfa_timer_start(__vport_bfa(vport), &vport->timer,
5302 				    bfa_fcs_vport_timeout, vport,
5303 				    BFA_FCS_RETRY_TIMEOUT);
5304 		break;
5305 
5306 	case BFA_FCS_VPORT_SM_RSP_FAILED:
5307 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5308 		break;
5309 
5310 	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5311 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5312 		break;
5313 
5314 	default:
5315 		bfa_sm_fault(__vport_fcs(vport), event);
5316 	}
5317 }
5318 
5319 /*
5320  * FDISC attempt failed - a timer is active to retry FDISC.
5321  */
5322 static void
bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5323 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5324 			     enum bfa_fcs_vport_event event)
5325 {
5326 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5327 	bfa_trc(__vport_fcs(vport), event);
5328 
5329 	switch (event) {
5330 	case BFA_FCS_VPORT_SM_DELETE:
5331 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5332 		bfa_timer_stop(&vport->timer);
5333 		bfa_fcs_lport_delete(&vport->lport);
5334 		break;
5335 
5336 	case BFA_FCS_VPORT_SM_OFFLINE:
5337 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5338 		bfa_timer_stop(&vport->timer);
5339 		break;
5340 
5341 	case BFA_FCS_VPORT_SM_TIMEOUT:
5342 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5343 		vport->vport_stats.fdisc_retries++;
5344 		vport->fdisc_retries++;
5345 		bfa_fcs_vport_do_fdisc(vport);
5346 		break;
5347 
5348 	default:
5349 		bfa_sm_fault(__vport_fcs(vport), event);
5350 	}
5351 }
5352 
5353 /*
5354  * FDISC is in progress and we got a vport delete request -
5355  * this is a wait state while we wait for fdisc response and
5356  * we will transition to the appropriate state - on rsp status.
5357  */
5358 static void
bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5359 bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
5360 				enum bfa_fcs_vport_event event)
5361 {
5362 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5363 	bfa_trc(__vport_fcs(vport), event);
5364 
5365 	switch (event) {
5366 	case BFA_FCS_VPORT_SM_RSP_OK:
5367 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5368 		bfa_fcs_lport_delete(&vport->lport);
5369 		break;
5370 
5371 	case BFA_FCS_VPORT_SM_DELETE:
5372 		break;
5373 
5374 	case BFA_FCS_VPORT_SM_OFFLINE:
5375 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5376 	case BFA_FCS_VPORT_SM_RSP_FAILED:
5377 	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5378 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5379 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5380 		bfa_fcs_lport_delete(&vport->lport);
5381 		break;
5382 
5383 	default:
5384 		bfa_sm_fault(__vport_fcs(vport), event);
5385 	}
5386 }
5387 
5388 /*
5389  * Vport is online (FDISC is complete).
5390  */
5391 static void
bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5392 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5393 			enum bfa_fcs_vport_event event)
5394 {
5395 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5396 	bfa_trc(__vport_fcs(vport), event);
5397 
5398 	switch (event) {
5399 	case BFA_FCS_VPORT_SM_DELETE:
5400 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5401 		bfa_fcs_lport_delete(&vport->lport);
5402 		break;
5403 
5404 	case BFA_FCS_VPORT_SM_STOP:
5405 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
5406 		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
5407 		break;
5408 
5409 	case BFA_FCS_VPORT_SM_OFFLINE:
5410 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5411 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5412 		bfa_fcs_lport_offline(&vport->lport);
5413 		break;
5414 
5415 	default:
5416 		bfa_sm_fault(__vport_fcs(vport), event);
5417 	}
5418 }
5419 
5420 /*
5421  * Vport is being stopped - awaiting lport stop completion to send
5422  * LOGO to fabric.
5423  */
5424 static void
bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5425 bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
5426 			  enum bfa_fcs_vport_event event)
5427 {
5428 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5429 	bfa_trc(__vport_fcs(vport), event);
5430 
5431 	switch (event) {
5432 	case BFA_FCS_VPORT_SM_STOPCOMP:
5433 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
5434 		bfa_fcs_vport_do_logo(vport);
5435 		break;
5436 
5437 	case BFA_FCS_VPORT_SM_OFFLINE:
5438 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5439 		break;
5440 
5441 	default:
5442 		bfa_sm_fault(__vport_fcs(vport), event);
5443 	}
5444 }
5445 
5446 /*
5447  * Vport is being deleted - awaiting lport delete completion to send
5448  * LOGO to fabric.
5449  */
5450 static void
bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5451 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5452 			enum bfa_fcs_vport_event event)
5453 {
5454 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5455 	bfa_trc(__vport_fcs(vport), event);
5456 
5457 	switch (event) {
5458 	case BFA_FCS_VPORT_SM_DELETE:
5459 		break;
5460 
5461 	case BFA_FCS_VPORT_SM_DELCOMP:
5462 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5463 		bfa_fcs_vport_do_logo(vport);
5464 		break;
5465 
5466 	case BFA_FCS_VPORT_SM_OFFLINE:
5467 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5468 		break;
5469 
5470 	default:
5471 		bfa_sm_fault(__vport_fcs(vport), event);
5472 	}
5473 }
5474 
5475 /*
5476  * Error State.
5477  * This state will be set when the Vport Creation fails due
5478  * to errors like Dup WWN. In this state only operation allowed
5479  * is a Vport Delete.
5480  */
5481 static void
bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5482 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5483 			enum bfa_fcs_vport_event event)
5484 {
5485 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5486 	bfa_trc(__vport_fcs(vport), event);
5487 
5488 	switch (event) {
5489 	case BFA_FCS_VPORT_SM_DELETE:
5490 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5491 		bfa_fcs_lport_delete(&vport->lport);
5492 		break;
5493 
5494 	default:
5495 		bfa_trc(__vport_fcs(vport), event);
5496 	}
5497 }
5498 
5499 /*
5500  * Lport cleanup is in progress since vport is being deleted. Fabric is
5501  * offline, so no LOGO is needed to complete vport deletion.
5502  */
5503 static void
bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5504 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5505 			enum bfa_fcs_vport_event event)
5506 {
5507 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5508 	bfa_trc(__vport_fcs(vport), event);
5509 
5510 	switch (event) {
5511 	case BFA_FCS_VPORT_SM_DELCOMP:
5512 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5513 		bfa_fcs_vport_free(vport);
5514 		break;
5515 
5516 	case BFA_FCS_VPORT_SM_STOPCOMP:
5517 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5518 		break;
5519 
5520 	case BFA_FCS_VPORT_SM_DELETE:
5521 		break;
5522 
5523 	default:
5524 		bfa_sm_fault(__vport_fcs(vport), event);
5525 	}
5526 }
5527 
5528 /*
5529  * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
5530  * is done.
5531  */
5532 static void
bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5533 bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
5534 			       enum bfa_fcs_vport_event event)
5535 {
5536 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5537 	bfa_trc(__vport_fcs(vport), event);
5538 
5539 	switch (event) {
5540 	case BFA_FCS_VPORT_SM_OFFLINE:
5541 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5542 		/*
5543 		 * !!! fall through !!!
5544 		 */
5545 
5546 	case BFA_FCS_VPORT_SM_RSP_OK:
5547 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5548 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5549 		break;
5550 
5551 	default:
5552 		bfa_sm_fault(__vport_fcs(vport), event);
5553 	}
5554 }
5555 
5556 /*
5557  * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5558  * is done.
5559  */
5560 static void
bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5561 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5562 			enum bfa_fcs_vport_event event)
5563 {
5564 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5565 	bfa_trc(__vport_fcs(vport), event);
5566 
5567 	switch (event) {
5568 	case BFA_FCS_VPORT_SM_OFFLINE:
5569 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5570 		/*
5571 		 * !!! fall through !!!
5572 		 */
5573 
5574 	case BFA_FCS_VPORT_SM_RSP_OK:
5575 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5576 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5577 		bfa_fcs_vport_free(vport);
5578 		break;
5579 
5580 	case BFA_FCS_VPORT_SM_DELETE:
5581 		break;
5582 
5583 	default:
5584 		bfa_sm_fault(__vport_fcs(vport), event);
5585 	}
5586 }
5587 
5588 
5589 
5590 /*
5591  *  fcs_vport_private FCS virtual port private functions
5592  */
5593 /*
5594  * Send AEN notification
5595  */
5596 static void
bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s * port,enum bfa_lport_aen_event event)5597 bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port,
5598 		       enum bfa_lport_aen_event event)
5599 {
5600 	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
5601 	struct bfa_aen_entry_s  *aen_entry;
5602 
5603 	bfad_get_aen_entry(bfad, aen_entry);
5604 	if (!aen_entry)
5605 		return;
5606 
5607 	aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
5608 	aen_entry->aen_data.lport.roles = port->port_cfg.roles;
5609 	aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
5610 					bfa_fcs_get_base_port(port->fcs));
5611 	aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
5612 
5613 	/* Send the AEN notification */
5614 	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
5615 				  BFA_AEN_CAT_LPORT, event);
5616 }
5617 
5618 /*
5619  * This routine will be called to send a FDISC command.
5620  */
5621 static void
bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s * vport)5622 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5623 {
5624 	bfa_lps_fdisc(vport->lps, vport,
5625 		bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5626 		__vport_pwwn(vport), __vport_nwwn(vport));
5627 	vport->vport_stats.fdisc_sent++;
5628 }
5629 
5630 static void
bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s * vport)5631 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5632 {
5633 	u8		lsrjt_rsn = vport->lps->lsrjt_rsn;
5634 	u8		lsrjt_expl = vport->lps->lsrjt_expl;
5635 
5636 	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5637 	bfa_trc(__vport_fcs(vport), lsrjt_expl);
5638 
5639 	/* For certain reason codes, we don't want to retry. */
5640 	switch (vport->lps->lsrjt_expl) {
5641 	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5642 	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
5643 		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5644 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5645 		else {
5646 			bfa_fcs_vport_aen_post(&vport->lport,
5647 					BFA_LPORT_AEN_NPIV_DUP_WWN);
5648 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5649 		}
5650 		break;
5651 
5652 	case FC_LS_RJT_EXP_INSUFF_RES:
5653 		/*
5654 		 * This means max logins per port/switch setting on the
5655 		 * switch was exceeded.
5656 		 */
5657 		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5658 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5659 		else {
5660 			bfa_fcs_vport_aen_post(&vport->lport,
5661 					BFA_LPORT_AEN_NPIV_FABRIC_MAX);
5662 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5663 		}
5664 		break;
5665 
5666 	default:
5667 		if (vport->fdisc_retries == 0)
5668 			bfa_fcs_vport_aen_post(&vport->lport,
5669 					BFA_LPORT_AEN_NPIV_UNKNOWN);
5670 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5671 	}
5672 }
5673 
5674 /*
5675  *	Called to send a logout to the fabric. Used when a V-Port is
5676  *	deleted/stopped.
5677  */
5678 static void
bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s * vport)5679 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5680 {
5681 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5682 
5683 	vport->vport_stats.logo_sent++;
5684 	bfa_lps_fdisclogo(vport->lps);
5685 }
5686 
5687 
5688 /*
5689  *     This routine will be called by bfa_timer on timer timeouts.
5690  *
5691  *	param[in]	vport		- pointer to bfa_fcs_vport_t.
5692  *	param[out]	vport_status	- pointer to return vport status in
5693  *
5694  *	return
5695  *		void
5696  *
5697  *	Special Considerations:
5698  *
5699  *	note
5700  */
5701 static void
bfa_fcs_vport_timeout(void * vport_arg)5702 bfa_fcs_vport_timeout(void *vport_arg)
5703 {
5704 	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5705 
5706 	vport->vport_stats.fdisc_timeouts++;
5707 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5708 }
5709 
5710 static void
bfa_fcs_vport_free(struct bfa_fcs_vport_s * vport)5711 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5712 {
5713 	struct bfad_vport_s *vport_drv =
5714 			(struct bfad_vport_s *)vport->vport_drv;
5715 
5716 	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5717 
5718 	if (vport_drv->comp_del)
5719 		complete(vport_drv->comp_del);
5720 	else
5721 		kfree(vport_drv);
5722 
5723 	bfa_lps_delete(vport->lps);
5724 }
5725 
5726 
5727 
5728 /*
5729  *  fcs_vport_public FCS virtual port public interfaces
5730  */
5731 
5732 /*
5733  * Online notification from fabric SM.
5734  */
5735 void
bfa_fcs_vport_online(struct bfa_fcs_vport_s * vport)5736 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5737 {
5738 	vport->vport_stats.fab_online++;
5739 	if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
5740 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5741 	else
5742 		vport->vport_stats.fab_no_npiv++;
5743 }
5744 
5745 /*
5746  * Offline notification from fabric SM.
5747  */
5748 void
bfa_fcs_vport_offline(struct bfa_fcs_vport_s * vport)5749 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5750 {
5751 	vport->vport_stats.fab_offline++;
5752 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5753 }
5754 
5755 /*
5756  * Cleanup notification from fabric SM on link timer expiry.
5757  */
5758 void
bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s * vport)5759 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5760 {
5761 	vport->vport_stats.fab_cleanup++;
5762 }
5763 /*
5764  * delete notification from fabric SM. To be invoked from within FCS.
5765  */
5766 void
bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s * vport)5767 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5768 {
5769 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5770 }
5771 
5772 /*
5773  * Stop completion callback from associated lport
5774  */
5775 void
bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s * vport)5776 bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
5777 {
5778 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
5779 }
5780 
5781 /*
5782  * Delete completion callback from associated lport
5783  */
5784 void
bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s * vport)5785 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5786 {
5787 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5788 }
5789 
5790 
5791 
5792 /*
5793  *  fcs_vport_api Virtual port API
5794  */
5795 
5796 /*
5797  *	Use this function to instantiate a new FCS vport object. This
5798  *	function will not trigger any HW initialization process (which will be
5799  *	done in vport_start() call)
5800  *
5801  *	param[in] vport	-		pointer to bfa_fcs_vport_t. This space
5802  *					needs to be allocated by the driver.
5803  *	param[in] fcs		-	FCS instance
5804  *	param[in] vport_cfg	-	vport configuration
5805  *	param[in] vf_id		-	VF_ID if vport is created within a VF.
5806  *					FC_VF_ID_NULL to specify base fabric.
5807  *	param[in] vport_drv	-	Opaque handle back to the driver's vport
5808  *					structure
5809  *
5810  *	retval BFA_STATUS_OK - on success.
5811  *	retval BFA_STATUS_FAILED - on failure.
5812  */
5813 bfa_status_t
bfa_fcs_vport_create(struct bfa_fcs_vport_s * vport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_lport_cfg_s * vport_cfg,struct bfad_vport_s * vport_drv)5814 bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5815 		u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5816 		struct bfad_vport_s *vport_drv)
5817 {
5818 	if (vport_cfg->pwwn == 0)
5819 		return BFA_STATUS_INVALID_WWN;
5820 
5821 	if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5822 		return BFA_STATUS_VPORT_WWN_BP;
5823 
5824 	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5825 		return BFA_STATUS_VPORT_EXISTS;
5826 
5827 	if (fcs->fabric.num_vports ==
5828 			bfa_lps_get_max_vport(fcs->bfa))
5829 		return BFA_STATUS_VPORT_MAX;
5830 
5831 	vport->lps = bfa_lps_alloc(fcs->bfa);
5832 	if (!vport->lps)
5833 		return BFA_STATUS_VPORT_MAX;
5834 
5835 	vport->vport_drv = vport_drv;
5836 	vport_cfg->preboot_vp = BFA_FALSE;
5837 
5838 	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5839 	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5840 	bfa_fcs_lport_init(&vport->lport, vport_cfg);
5841 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5842 
5843 	return BFA_STATUS_OK;
5844 }
5845 
5846 /*
5847  *	Use this function to instantiate a new FCS PBC vport object. This
5848  *	function will not trigger any HW initialization process (which will be
5849  *	done in vport_start() call)
5850  *
5851  *	param[in] vport	-	pointer to bfa_fcs_vport_t. This space
5852  *				needs to be allocated by the driver.
5853  *	param[in] fcs	-	FCS instance
5854  *	param[in] vport_cfg	-	vport configuration
5855  *	param[in] vf_id		-	VF_ID if vport is created within a VF.
5856  *					FC_VF_ID_NULL to specify base fabric.
5857  *	param[in] vport_drv	-	Opaque handle back to the driver's vport
5858  *					structure
5859  *
5860  *	retval BFA_STATUS_OK - on success.
5861  *	retval BFA_STATUS_FAILED - on failure.
5862  */
5863 bfa_status_t
bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s * vport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_lport_cfg_s * vport_cfg,struct bfad_vport_s * vport_drv)5864 bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5865 			u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5866 			struct bfad_vport_s *vport_drv)
5867 {
5868 	bfa_status_t rc;
5869 
5870 	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5871 	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5872 
5873 	return rc;
5874 }
5875 
5876 /*
5877  *	Use this function to findout if this is a pbc vport or not.
5878  *
5879  * @param[in] vport - pointer to bfa_fcs_vport_t.
5880  *
5881  * @returns None
5882  */
5883 bfa_boolean_t
bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s * vport)5884 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5885 {
5886 
5887 	if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5888 		return BFA_TRUE;
5889 	else
5890 		return BFA_FALSE;
5891 
5892 }
5893 
5894 /*
5895  * Use this function initialize the vport.
5896  *
5897  * @param[in] vport - pointer to bfa_fcs_vport_t.
5898  *
5899  * @returns None
5900  */
5901 bfa_status_t
bfa_fcs_vport_start(struct bfa_fcs_vport_s * vport)5902 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5903 {
5904 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5905 
5906 	return BFA_STATUS_OK;
5907 }
5908 
5909 /*
5910  *	Use this function quiese the vport object. This function will return
5911  *	immediately, when the vport is actually stopped, the
5912  *	bfa_drv_vport_stop_cb() will be called.
5913  *
5914  *	param[in] vport - pointer to bfa_fcs_vport_t.
5915  *
5916  *	return None
5917  */
5918 bfa_status_t
bfa_fcs_vport_stop(struct bfa_fcs_vport_s * vport)5919 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5920 {
5921 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5922 
5923 	return BFA_STATUS_OK;
5924 }
5925 
5926 /*
5927  *	Use this function to delete a vport object. Fabric object should
5928  *	be stopped before this function call.
5929  *
5930  *	!!!!!!! Donot invoke this from within FCS  !!!!!!!
5931  *
5932  *	param[in] vport - pointer to bfa_fcs_vport_t.
5933  *
5934  *	return     None
5935  */
5936 bfa_status_t
bfa_fcs_vport_delete(struct bfa_fcs_vport_s * vport)5937 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5938 {
5939 
5940 	if (vport->lport.port_cfg.preboot_vp)
5941 		return BFA_STATUS_PBC;
5942 
5943 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5944 
5945 	return BFA_STATUS_OK;
5946 }
5947 
5948 /*
5949  *	Use this function to get vport's current status info.
5950  *
5951  *	param[in] vport		pointer to bfa_fcs_vport_t.
5952  *	param[out] attr		pointer to return vport attributes
5953  *
5954  *	return None
5955  */
5956 void
bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s * vport,struct bfa_vport_attr_s * attr)5957 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5958 			struct bfa_vport_attr_s *attr)
5959 {
5960 	if (vport == NULL || attr == NULL)
5961 		return;
5962 
5963 	memset(attr, 0, sizeof(struct bfa_vport_attr_s));
5964 
5965 	bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5966 	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5967 }
5968 
5969 
5970 /*
5971  *	Lookup a virtual port. Excludes base port from lookup.
5972  */
5973 struct bfa_fcs_vport_s *
bfa_fcs_vport_lookup(struct bfa_fcs_s * fcs,u16 vf_id,wwn_t vpwwn)5974 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5975 {
5976 	struct bfa_fcs_vport_s *vport;
5977 	struct bfa_fcs_fabric_s *fabric;
5978 
5979 	bfa_trc(fcs, vf_id);
5980 	bfa_trc(fcs, vpwwn);
5981 
5982 	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5983 	if (!fabric) {
5984 		bfa_trc(fcs, vf_id);
5985 		return NULL;
5986 	}
5987 
5988 	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5989 	return vport;
5990 }
5991 
5992 /*
5993  * FDISC Response
5994  */
5995 void
bfa_cb_lps_fdisc_comp(void * bfad,void * uarg,bfa_status_t status)5996 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5997 {
5998 	struct bfa_fcs_vport_s *vport = uarg;
5999 
6000 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6001 	bfa_trc(__vport_fcs(vport), status);
6002 
6003 	switch (status) {
6004 	case BFA_STATUS_OK:
6005 		/*
6006 		 * Initialize the V-Port fields
6007 		 */
6008 		__vport_fcid(vport) = vport->lps->lp_pid;
6009 		vport->vport_stats.fdisc_accepts++;
6010 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6011 		break;
6012 
6013 	case BFA_STATUS_INVALID_MAC:
6014 		/* Only for CNA */
6015 		vport->vport_stats.fdisc_acc_bad++;
6016 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6017 
6018 		break;
6019 
6020 	case BFA_STATUS_EPROTOCOL:
6021 		switch (vport->lps->ext_status) {
6022 		case BFA_EPROTO_BAD_ACCEPT:
6023 			vport->vport_stats.fdisc_acc_bad++;
6024 			break;
6025 
6026 		case BFA_EPROTO_UNKNOWN_RSP:
6027 			vport->vport_stats.fdisc_unknown_rsp++;
6028 			break;
6029 
6030 		default:
6031 			break;
6032 		}
6033 
6034 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6035 		break;
6036 
6037 	case BFA_STATUS_FABRIC_RJT:
6038 		vport->vport_stats.fdisc_rejects++;
6039 		bfa_fcs_vport_fdisc_rejected(vport);
6040 		break;
6041 
6042 	default:
6043 		vport->vport_stats.fdisc_rsp_err++;
6044 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6045 	}
6046 }
6047 
6048 /*
6049  * LOGO response
6050  */
6051 void
bfa_cb_lps_fdisclogo_comp(void * bfad,void * uarg)6052 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
6053 {
6054 	struct bfa_fcs_vport_s *vport = uarg;
6055 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6056 }
6057 
6058 /*
6059  * Received clear virtual link
6060  */
6061 void
bfa_cb_lps_cvl_event(void * bfad,void * uarg)6062 bfa_cb_lps_cvl_event(void *bfad, void *uarg)
6063 {
6064 	struct bfa_fcs_vport_s *vport = uarg;
6065 
6066 	/* Send an Offline followed by an ONLINE */
6067 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6068 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6069 }
6070