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