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