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