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