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