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