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 int 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	if (attr_len < 0)
1891		return;
1892
1893	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1894			  FC_CLASS_3, (len + attr_len), &fchs,
1895			  bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1896			  FC_MAX_PDUSZ, FC_FCCT_TOV);
1897
1898	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1899}
1900
1901static int
1902bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1903{
1904	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1905	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr;
1906	struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1907	struct fdmi_attr_s *attr;
1908	int        len;
1909	u8        *curr_ptr;
1910	u16	templen, count;
1911
1912	fcs_hba_attr = kzalloc(sizeof(*fcs_hba_attr), GFP_KERNEL);
1913	if (!fcs_hba_attr)
1914		return -ENOMEM;
1915
1916	/*
1917	 * get hba attributes
1918	 */
1919	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1920
1921	rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1922	rhba->port_list.num_ports = cpu_to_be32(1);
1923	rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1924
1925	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1926
1927	count = 0;
1928	len += sizeof(rhba->hba_attr_blk.attr_count);
1929
1930	/*
1931	 * fill out the invididual entries of the HBA attrib Block
1932	 */
1933	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1934
1935	/*
1936	 * Node Name
1937	 */
1938	attr = (struct fdmi_attr_s *) curr_ptr;
1939	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1940	templen = sizeof(wwn_t);
1941	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1942	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1943	len += templen;
1944	count++;
1945	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1946			     sizeof(templen));
1947
1948	/*
1949	 * Manufacturer
1950	 */
1951	attr = (struct fdmi_attr_s *) curr_ptr;
1952	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1953	templen = (u16) strlen(fcs_hba_attr->manufacturer);
1954	memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1955	templen = fc_roundup(templen, sizeof(u32));
1956	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1957	len += templen;
1958	count++;
1959	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1960			     sizeof(templen));
1961
1962	/*
1963	 * Serial Number
1964	 */
1965	attr = (struct fdmi_attr_s *) curr_ptr;
1966	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1967	templen = (u16) strlen(fcs_hba_attr->serial_num);
1968	memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1969	templen = fc_roundup(templen, sizeof(u32));
1970	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1971	len += templen;
1972	count++;
1973	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1974			     sizeof(templen));
1975
1976	/*
1977	 * Model
1978	 */
1979	attr = (struct fdmi_attr_s *) curr_ptr;
1980	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1981	templen = (u16) strlen(fcs_hba_attr->model);
1982	memcpy(attr->value, fcs_hba_attr->model, templen);
1983	templen = fc_roundup(templen, sizeof(u32));
1984	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1985	len += templen;
1986	count++;
1987	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1988			     sizeof(templen));
1989
1990	/*
1991	 * Model Desc
1992	 */
1993	attr = (struct fdmi_attr_s *) curr_ptr;
1994	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1995	templen = (u16) strlen(fcs_hba_attr->model_desc);
1996	memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1997	templen = fc_roundup(templen, sizeof(u32));
1998	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1999	len += templen;
2000	count++;
2001	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2002			     sizeof(templen));
2003
2004	/*
2005	 * H/W Version
2006	 */
2007	if (fcs_hba_attr->hw_version[0] != '\0') {
2008		attr = (struct fdmi_attr_s *) curr_ptr;
2009		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
2010		templen = (u16) strlen(fcs_hba_attr->hw_version);
2011		memcpy(attr->value, fcs_hba_attr->hw_version, templen);
2012		templen = fc_roundup(templen, sizeof(u32));
2013		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2014		len += templen;
2015		count++;
2016		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2017					 sizeof(templen));
2018	}
2019
2020	/*
2021	 * Driver Version
2022	 */
2023	attr = (struct fdmi_attr_s *) curr_ptr;
2024	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
2025	templen = (u16) strlen(fcs_hba_attr->driver_version);
2026	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
2027	templen = fc_roundup(templen, sizeof(u32));
2028	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2029	len += templen;
2030	count++;
2031	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2032			     sizeof(templen));
2033
2034	/*
2035	 * Option Rom Version
2036	 */
2037	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
2038		attr = (struct fdmi_attr_s *) curr_ptr;
2039		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
2040		templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
2041		memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
2042		templen = fc_roundup(templen, sizeof(u32));
2043		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2044		len += templen;
2045		count++;
2046		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2047					 sizeof(templen));
2048	}
2049
2050	attr = (struct fdmi_attr_s *) curr_ptr;
2051	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
2052	templen = (u16) strlen(fcs_hba_attr->fw_version);
2053	memcpy(attr->value, fcs_hba_attr->fw_version, templen);
2054	templen = fc_roundup(templen, sizeof(u32));
2055	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2056	len += templen;
2057	count++;
2058	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2059			     sizeof(templen));
2060
2061	/*
2062	 * OS Name
2063	 */
2064	if (fcs_hba_attr->os_name[0] != '\0') {
2065		attr = (struct fdmi_attr_s *) curr_ptr;
2066		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
2067		templen = (u16) strlen(fcs_hba_attr->os_name);
2068		memcpy(attr->value, fcs_hba_attr->os_name, templen);
2069		templen = fc_roundup(templen, sizeof(u32));
2070		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2071		len += templen;
2072		count++;
2073		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2074					sizeof(templen));
2075	}
2076
2077	/*
2078	 * MAX_CT_PAYLOAD
2079	 */
2080	attr = (struct fdmi_attr_s *) curr_ptr;
2081	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
2082	templen = sizeof(fcs_hba_attr->max_ct_pyld);
2083	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
2084	templen = fc_roundup(templen, sizeof(u32));
2085	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2086	len += templen;
2087	count++;
2088	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2089			     sizeof(templen));
2090	/*
2091	 * Send extended attributes ( FOS 7.1 support )
2092	 */
2093	if (fdmi->retry_cnt == 0) {
2094		attr = (struct fdmi_attr_s *) curr_ptr;
2095		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME);
2096		templen = sizeof(fcs_hba_attr->node_sym_name);
2097		memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen);
2098		templen = fc_roundup(templen, sizeof(u32));
2099		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2100		len += templen;
2101		count++;
2102		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2103					sizeof(templen));
2104
2105		attr = (struct fdmi_attr_s *) curr_ptr;
2106		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID);
2107		templen = sizeof(fcs_hba_attr->vendor_info);
2108		memcpy(attr->value, &fcs_hba_attr->vendor_info, templen);
2109		templen = fc_roundup(templen, sizeof(u32));
2110		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2111		len += templen;
2112		count++;
2113		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2114					sizeof(templen));
2115
2116		attr = (struct fdmi_attr_s *) curr_ptr;
2117		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS);
2118		templen = sizeof(fcs_hba_attr->num_ports);
2119		memcpy(attr->value, &fcs_hba_attr->num_ports, templen);
2120		templen = fc_roundup(templen, sizeof(u32));
2121		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2122		len += templen;
2123		count++;
2124		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2125					sizeof(templen));
2126
2127		attr = (struct fdmi_attr_s *) curr_ptr;
2128		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME);
2129		templen = sizeof(fcs_hba_attr->fabric_name);
2130		memcpy(attr->value, &fcs_hba_attr->fabric_name, templen);
2131		templen = fc_roundup(templen, sizeof(u32));
2132		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2133		len += templen;
2134		count++;
2135		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2136					sizeof(templen));
2137
2138		attr = (struct fdmi_attr_s *) curr_ptr;
2139		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER);
2140		templen = sizeof(fcs_hba_attr->bios_ver);
2141		memcpy(attr->value, &fcs_hba_attr->bios_ver, templen);
2142		templen = fc_roundup(attr->len, sizeof(u32));
2143		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2144		len += templen;
2145		count++;
2146		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2147					sizeof(templen));
2148	}
2149
2150	/*
2151	 * Update size of payload
2152	 */
2153	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2154
2155	rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
2156
2157	kfree(fcs_hba_attr);
2158
2159	return len;
2160}
2161
2162static void
2163bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2164				void *cbarg, bfa_status_t req_status,
2165				u32 rsp_len, u32 resid_len,
2166				struct fchs_s *rsp_fchs)
2167{
2168	struct bfa_fcs_lport_fdmi_s *fdmi =
2169				(struct bfa_fcs_lport_fdmi_s *) cbarg;
2170	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2171	struct ct_hdr_s *cthdr = NULL;
2172
2173	bfa_trc(port->fcs, port->port_cfg.pwwn);
2174
2175	/*
2176	 * Sanity Checks
2177	 */
2178	if (req_status != BFA_STATUS_OK) {
2179		bfa_trc(port->fcs, req_status);
2180		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2181		return;
2182	}
2183
2184	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2185	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2186
2187	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2188		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2189		return;
2190	}
2191
2192	bfa_trc(port->fcs, cthdr->reason_code);
2193	bfa_trc(port->fcs, cthdr->exp_code);
2194	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2195}
2196
2197/*
2198*  RPRT : Register Port
2199 */
2200static void
2201bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2202{
2203	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2204	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2205	struct fchs_s fchs;
2206	u16        len, attr_len;
2207	struct bfa_fcxp_s *fcxp;
2208	u8        *pyld;
2209
2210	bfa_trc(port->fcs, port->port_cfg.pwwn);
2211
2212	fcxp = fcxp_alloced ? fcxp_alloced :
2213	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2214	if (!fcxp) {
2215		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2216				bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
2217		return;
2218	}
2219	fdmi->fcxp = fcxp;
2220
2221	pyld = bfa_fcxp_get_reqbuf(fcxp);
2222	memset(pyld, 0, FC_MAX_PDUSZ);
2223
2224	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2225				   FDMI_RPRT);
2226
2227	attr_len =
2228		bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
2229					  (u8 *) ((struct ct_hdr_s *) pyld
2230						       + 1));
2231
2232	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2233			  FC_CLASS_3, len + attr_len, &fchs,
2234			  bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
2235			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2236
2237	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
2238}
2239
2240/*
2241 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
2242 */
2243static          u16
2244bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
2245				       u8 *pyld)
2246{
2247	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
2248	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
2249	struct fdmi_attr_s *attr;
2250	u8        *curr_ptr;
2251	u16        len;
2252	u8	count = 0;
2253	u16	templen;
2254
2255	/*
2256	 * get port attributes
2257	 */
2258	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
2259
2260	len = sizeof(port_attrib->attr_count);
2261
2262	/*
2263	 * fill out the invididual entries
2264	 */
2265	curr_ptr = (u8 *) &port_attrib->port_attr;
2266
2267	/*
2268	 * FC4 Types
2269	 */
2270	attr = (struct fdmi_attr_s *) curr_ptr;
2271	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
2272	templen = sizeof(fcs_port_attr.supp_fc4_types);
2273	memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
2274	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2275	len += templen;
2276	++count;
2277	attr->len =
2278		cpu_to_be16(templen + sizeof(attr->type) +
2279			     sizeof(templen));
2280
2281	/*
2282	 * Supported Speed
2283	 */
2284	attr = (struct fdmi_attr_s *) curr_ptr;
2285	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
2286	templen = sizeof(fcs_port_attr.supp_speed);
2287	memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
2288	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2289	len += templen;
2290	++count;
2291	attr->len =
2292		cpu_to_be16(templen + sizeof(attr->type) +
2293			     sizeof(templen));
2294
2295	/*
2296	 * current Port Speed
2297	 */
2298	attr = (struct fdmi_attr_s *) curr_ptr;
2299	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
2300	templen = sizeof(fcs_port_attr.curr_speed);
2301	memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
2302	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2303	len += templen;
2304	++count;
2305	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2306			     sizeof(templen));
2307
2308	/*
2309	 * max frame size
2310	 */
2311	attr = (struct fdmi_attr_s *) curr_ptr;
2312	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
2313	templen = sizeof(fcs_port_attr.max_frm_size);
2314	memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
2315	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2316	len += templen;
2317	++count;
2318	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2319			     sizeof(templen));
2320
2321	/*
2322	 * OS Device Name
2323	 */
2324	if (fcs_port_attr.os_device_name[0] != '\0') {
2325		attr = (struct fdmi_attr_s *) curr_ptr;
2326		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
2327		templen = (u16) strlen(fcs_port_attr.os_device_name);
2328		memcpy(attr->value, fcs_port_attr.os_device_name, templen);
2329		templen = fc_roundup(templen, sizeof(u32));
2330		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2331		len += templen;
2332		++count;
2333		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2334					sizeof(templen));
2335	}
2336	/*
2337	 * Host Name
2338	 */
2339	if (fcs_port_attr.host_name[0] != '\0') {
2340		attr = (struct fdmi_attr_s *) curr_ptr;
2341		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
2342		templen = (u16) strlen(fcs_port_attr.host_name);
2343		memcpy(attr->value, fcs_port_attr.host_name, templen);
2344		templen = fc_roundup(templen, sizeof(u32));
2345		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2346		len += templen;
2347		++count;
2348		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2349				sizeof(templen));
2350	}
2351
2352	if (fdmi->retry_cnt == 0) {
2353		attr = (struct fdmi_attr_s *) curr_ptr;
2354		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME);
2355		templen = sizeof(fcs_port_attr.node_name);
2356		memcpy(attr->value, &fcs_port_attr.node_name, templen);
2357		templen = fc_roundup(templen, sizeof(u32));
2358		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2359		len += templen;
2360		++count;
2361		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2362				 sizeof(templen));
2363
2364		attr = (struct fdmi_attr_s *) curr_ptr;
2365		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME);
2366		templen = sizeof(fcs_port_attr.port_name);
2367		memcpy(attr->value, &fcs_port_attr.port_name, templen);
2368		templen = fc_roundup(templen, sizeof(u32));
2369		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen;
2370		len += templen;
2371		++count;
2372		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2373				 sizeof(templen));
2374
2375		if (fcs_port_attr.port_sym_name.symname[0] != '\0') {
2376			attr = (struct fdmi_attr_s *) curr_ptr;
2377			attr->type =
2378				cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME);
2379			templen = sizeof(fcs_port_attr.port_sym_name);
2380			memcpy(attr->value,
2381				&fcs_port_attr.port_sym_name, templen);
2382			templen = fc_roundup(templen, sizeof(u32));
2383			curr_ptr += sizeof(attr->type) +
2384					sizeof(templen) + templen;
2385			len += templen;
2386			++count;
2387			attr->len = cpu_to_be16(templen +
2388				sizeof(attr->type) + sizeof(templen));
2389		}
2390
2391		attr = (struct fdmi_attr_s *) curr_ptr;
2392		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE);
2393		templen = sizeof(fcs_port_attr.port_type);
2394		memcpy(attr->value, &fcs_port_attr.port_type, templen);
2395		templen = fc_roundup(templen, sizeof(u32));
2396		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2397		len += templen;
2398		++count;
2399		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2400				 sizeof(templen));
2401
2402		attr = (struct fdmi_attr_s *) curr_ptr;
2403		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS);
2404		templen = sizeof(fcs_port_attr.scos);
2405		memcpy(attr->value, &fcs_port_attr.scos, templen);
2406		templen = fc_roundup(templen, sizeof(u32));
2407		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2408		len += templen;
2409		++count;
2410		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2411				 sizeof(templen));
2412
2413		attr = (struct fdmi_attr_s *) curr_ptr;
2414		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME);
2415		templen = sizeof(fcs_port_attr.port_fabric_name);
2416		memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen);
2417		templen = fc_roundup(templen, sizeof(u32));
2418		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2419		len += templen;
2420		++count;
2421		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2422				 sizeof(templen));
2423
2424		attr = (struct fdmi_attr_s *) curr_ptr;
2425		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE);
2426		templen = sizeof(fcs_port_attr.port_act_fc4_type);
2427		memcpy(attr->value, fcs_port_attr.port_act_fc4_type,
2428				templen);
2429		templen = fc_roundup(templen, sizeof(u32));
2430		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2431		len += templen;
2432		++count;
2433		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2434				 sizeof(templen));
2435
2436		attr = (struct fdmi_attr_s *) curr_ptr;
2437		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE);
2438		templen = sizeof(fcs_port_attr.port_state);
2439		memcpy(attr->value, &fcs_port_attr.port_state, templen);
2440		templen = fc_roundup(templen, sizeof(u32));
2441		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2442		len += templen;
2443		++count;
2444		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2445				 sizeof(templen));
2446
2447		attr = (struct fdmi_attr_s *) curr_ptr;
2448		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT);
2449		templen = sizeof(fcs_port_attr.num_ports);
2450		memcpy(attr->value, &fcs_port_attr.num_ports, templen);
2451		templen = fc_roundup(templen, sizeof(u32));
2452		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2453		len += templen;
2454		++count;
2455		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2456				sizeof(templen));
2457	}
2458
2459	/*
2460	 * Update size of payload
2461	 */
2462	port_attrib->attr_count = cpu_to_be32(count);
2463	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2464	return len;
2465}
2466
2467static          u16
2468bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2469{
2470	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2471	struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2472	u16        len;
2473
2474	rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2475	rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2476
2477	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2478				(u8 *) &rprt->port_attr_blk);
2479
2480	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2481
2482	return len;
2483}
2484
2485static void
2486bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2487				void *cbarg, bfa_status_t req_status,
2488				u32 rsp_len, u32 resid_len,
2489				struct fchs_s *rsp_fchs)
2490{
2491	struct bfa_fcs_lport_fdmi_s *fdmi =
2492			(struct bfa_fcs_lport_fdmi_s *) cbarg;
2493	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2494	struct ct_hdr_s *cthdr = NULL;
2495
2496	bfa_trc(port->fcs, port->port_cfg.pwwn);
2497
2498	/*
2499	 * Sanity Checks
2500	 */
2501	if (req_status != BFA_STATUS_OK) {
2502		bfa_trc(port->fcs, req_status);
2503		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2504		return;
2505	}
2506
2507	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2508	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2509
2510	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2511		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2512		return;
2513	}
2514
2515	bfa_trc(port->fcs, cthdr->reason_code);
2516	bfa_trc(port->fcs, cthdr->exp_code);
2517	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2518}
2519
2520/*
2521*  RPA : Register Port Attributes.
2522 */
2523static void
2524bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2525{
2526	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2527	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2528	struct fchs_s fchs;
2529	u16        len, attr_len;
2530	struct bfa_fcxp_s *fcxp;
2531	u8        *pyld;
2532
2533	bfa_trc(port->fcs, port->port_cfg.pwwn);
2534
2535	fcxp = fcxp_alloced ? fcxp_alloced :
2536	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2537	if (!fcxp) {
2538		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2539				bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
2540		return;
2541	}
2542	fdmi->fcxp = fcxp;
2543
2544	pyld = bfa_fcxp_get_reqbuf(fcxp);
2545	memset(pyld, 0, FC_MAX_PDUSZ);
2546
2547	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2548				   FDMI_RPA);
2549
2550	attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2551				(u8 *) ((struct ct_hdr_s *) pyld + 1));
2552
2553	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2554			  FC_CLASS_3, len + attr_len, &fchs,
2555			  bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2556			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2557
2558	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2559}
2560
2561static          u16
2562bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2563{
2564	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2565	struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2566	u16        len;
2567
2568	rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2569
2570	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2571				(u8 *) &rpa->port_attr_blk);
2572
2573	len += sizeof(rpa->port_name);
2574
2575	return len;
2576}
2577
2578static void
2579bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2580			void *cbarg, bfa_status_t req_status, u32 rsp_len,
2581			u32 resid_len, struct fchs_s *rsp_fchs)
2582{
2583	struct bfa_fcs_lport_fdmi_s *fdmi =
2584				(struct bfa_fcs_lport_fdmi_s *) cbarg;
2585	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2586	struct ct_hdr_s *cthdr = NULL;
2587
2588	bfa_trc(port->fcs, port->port_cfg.pwwn);
2589
2590	/*
2591	 * Sanity Checks
2592	 */
2593	if (req_status != BFA_STATUS_OK) {
2594		bfa_trc(port->fcs, req_status);
2595		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2596		return;
2597	}
2598
2599	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2600	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2601
2602	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2603		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2604		return;
2605	}
2606
2607	bfa_trc(port->fcs, cthdr->reason_code);
2608	bfa_trc(port->fcs, cthdr->exp_code);
2609	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2610}
2611
2612static void
2613bfa_fcs_lport_fdmi_timeout(void *arg)
2614{
2615	struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2616
2617	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2618}
2619
2620static void
2621bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2622			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2623{
2624	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2625	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2626	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
2627
2628	memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2629
2630	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2631					hba_attr->manufacturer);
2632	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2633					hba_attr->serial_num);
2634	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2635					hba_attr->model);
2636	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2637					hba_attr->model_desc);
2638	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2639					hba_attr->hw_version);
2640	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2641					hba_attr->option_rom_ver);
2642	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2643					hba_attr->fw_version);
2644
2645	strscpy(hba_attr->driver_version, (char *)driver_info->version,
2646		sizeof(hba_attr->driver_version));
2647
2648	strscpy(hba_attr->os_name, driver_info->host_os_name,
2649		sizeof(hba_attr->os_name));
2650
2651	/*
2652	 * If there is a patch level, append it
2653	 * to the os name along with a separator
2654	 */
2655	if (driver_info->host_os_patch[0] != '\0') {
2656		strlcat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2657			sizeof(hba_attr->os_name));
2658		strlcat(hba_attr->os_name, driver_info->host_os_patch,
2659				sizeof(hba_attr->os_name));
2660	}
2661
2662	/* Retrieve the max frame size from the port attr */
2663	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
2664	hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
2665
2666	strscpy(hba_attr->node_sym_name.symname,
2667		port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN);
2668	strcpy(hba_attr->vendor_info, "QLogic");
2669	hba_attr->num_ports =
2670		cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc));
2671	hba_attr->fabric_name = port->fabric->lps->pr_nwwn;
2672	strscpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN);
2673
2674}
2675
2676static void
2677bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2678			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
2679{
2680	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2681	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2682	struct bfa_port_attr_s pport_attr;
2683	struct bfa_lport_attr_s lport_attr;
2684
2685	memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2686
2687	/*
2688	 * get pport attributes from hal
2689	 */
2690	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2691
2692	/*
2693	 * get FC4 type Bitmask
2694	 */
2695	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2696
2697	/*
2698	 * Supported Speeds
2699	 */
2700	switch (pport_attr.speed_supported) {
2701	case BFA_PORT_SPEED_16GBPS:
2702		port_attr->supp_speed =
2703			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
2704		break;
2705
2706	case BFA_PORT_SPEED_10GBPS:
2707		port_attr->supp_speed =
2708			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
2709		break;
2710
2711	case BFA_PORT_SPEED_8GBPS:
2712		port_attr->supp_speed =
2713			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
2714		break;
2715
2716	case BFA_PORT_SPEED_4GBPS:
2717		port_attr->supp_speed =
2718			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
2719		break;
2720
2721	default:
2722		bfa_sm_fault(port->fcs, pport_attr.speed_supported);
2723	}
2724
2725	/*
2726	 * Current Speed
2727	 */
2728	port_attr->curr_speed = cpu_to_be32(
2729				bfa_fcs_fdmi_convert_speed(pport_attr.speed));
2730
2731	/*
2732	 * Max PDU Size.
2733	 */
2734	port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize);
2735
2736	/*
2737	 * OS device Name
2738	 */
2739	strscpy(port_attr->os_device_name, driver_info->os_device_name,
2740		sizeof(port_attr->os_device_name));
2741
2742	/*
2743	 * Host name
2744	 */
2745	strscpy(port_attr->host_name, driver_info->host_machine_name,
2746		sizeof(port_attr->host_name));
2747
2748	port_attr->node_name = bfa_fcs_lport_get_nwwn(port);
2749	port_attr->port_name = bfa_fcs_lport_get_pwwn(port);
2750
2751	strscpy(port_attr->port_sym_name.symname,
2752		bfa_fcs_lport_get_psym_name(port).symname, BFA_SYMNAME_MAXLEN);
2753	bfa_fcs_lport_get_attr(port, &lport_attr);
2754	port_attr->port_type = cpu_to_be32(lport_attr.port_type);
2755	port_attr->scos = pport_attr.cos_supported;
2756	port_attr->port_fabric_name = port->fabric->lps->pr_nwwn;
2757	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type);
2758	port_attr->port_state = cpu_to_be32(pport_attr.port_state);
2759	port_attr->num_ports = cpu_to_be32(port->num_rports);
2760}
2761
2762/*
2763 * Convert BFA speed to FDMI format.
2764 */
2765u32
2766bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
2767{
2768	u32	ret;
2769
2770	switch (pport_speed) {
2771	case BFA_PORT_SPEED_1GBPS:
2772	case BFA_PORT_SPEED_2GBPS:
2773		ret = pport_speed;
2774		break;
2775
2776	case BFA_PORT_SPEED_4GBPS:
2777		ret = FDMI_TRANS_SPEED_4G;
2778		break;
2779
2780	case BFA_PORT_SPEED_8GBPS:
2781		ret = FDMI_TRANS_SPEED_8G;
2782		break;
2783
2784	case BFA_PORT_SPEED_10GBPS:
2785		ret = FDMI_TRANS_SPEED_10G;
2786		break;
2787
2788	case BFA_PORT_SPEED_16GBPS:
2789		ret = FDMI_TRANS_SPEED_16G;
2790		break;
2791
2792	default:
2793		ret = FDMI_TRANS_SPEED_UNKNOWN;
2794	}
2795	return ret;
2796}
2797
2798void
2799bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2800{
2801	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2802
2803	fdmi->ms = ms;
2804	if (ms->port->fcs->fdmi_enabled)
2805		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2806	else
2807		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2808}
2809
2810void
2811bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2812{
2813	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2814
2815	fdmi->ms = ms;
2816	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2817}
2818
2819void
2820bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2821{
2822	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2823
2824	fdmi->ms = ms;
2825	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2826}
2827
2828#define BFA_FCS_MS_CMD_MAX_RETRIES  2
2829
2830/*
2831 * forward declarations
2832 */
2833static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2834					   struct bfa_fcxp_s *fcxp_alloced);
2835static void     bfa_fcs_lport_ms_timeout(void *arg);
2836static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2837					       struct bfa_fcxp_s *fcxp,
2838					       void *cbarg,
2839					       bfa_status_t req_status,
2840					       u32 rsp_len,
2841					       u32 resid_len,
2842					       struct fchs_s *rsp_fchs);
2843
2844static void	bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2845					struct bfa_fcxp_s *fcxp_alloced);
2846static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2847					       struct bfa_fcxp_s *fcxp,
2848					       void *cbarg,
2849					       bfa_status_t req_status,
2850					       u32 rsp_len,
2851					       u32 resid_len,
2852					       struct fchs_s *rsp_fchs);
2853static void	bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2854					struct bfa_fcxp_s *fcxp_alloced);
2855static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2856					       struct bfa_fcxp_s *fcxp,
2857					       void *cbarg,
2858					       bfa_status_t req_status,
2859					       u32 rsp_len,
2860					       u32 resid_len,
2861					       struct fchs_s *rsp_fchs);
2862/*
2863 *  fcs_ms_sm FCS MS state machine
2864 */
2865
2866/*
2867 *  MS State Machine events
2868 */
2869enum port_ms_event {
2870	MSSM_EVENT_PORT_ONLINE = 1,
2871	MSSM_EVENT_PORT_OFFLINE = 2,
2872	MSSM_EVENT_RSP_OK = 3,
2873	MSSM_EVENT_RSP_ERROR = 4,
2874	MSSM_EVENT_TIMEOUT = 5,
2875	MSSM_EVENT_FCXP_SENT = 6,
2876	MSSM_EVENT_PORT_FABRIC_RSCN = 7
2877};
2878
2879static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2880					   enum port_ms_event event);
2881static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2882						 enum port_ms_event event);
2883static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2884					 enum port_ms_event event);
2885static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2886					       enum port_ms_event event);
2887static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2888						 enum port_ms_event event);
2889static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2890					 enum port_ms_event event);
2891static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2892					       enum port_ms_event event);
2893static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2894						 enum port_ms_event event);
2895static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2896					 enum port_ms_event event);
2897static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2898					       enum port_ms_event event);
2899static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2900					  enum port_ms_event event);
2901/*
2902 *	Start in offline state - awaiting NS to send start.
2903 */
2904static void
2905bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2906				enum port_ms_event event)
2907{
2908	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2909	bfa_trc(ms->port->fcs, event);
2910
2911	switch (event) {
2912	case MSSM_EVENT_PORT_ONLINE:
2913		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2914		bfa_fcs_lport_ms_send_plogi(ms, NULL);
2915		break;
2916
2917	case MSSM_EVENT_PORT_OFFLINE:
2918		break;
2919
2920	default:
2921		bfa_sm_fault(ms->port->fcs, event);
2922	}
2923}
2924
2925static void
2926bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2927				enum port_ms_event event)
2928{
2929	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2930	bfa_trc(ms->port->fcs, event);
2931
2932	switch (event) {
2933	case MSSM_EVENT_FCXP_SENT:
2934		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2935		break;
2936
2937	case MSSM_EVENT_PORT_OFFLINE:
2938		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2939		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2940					   &ms->fcxp_wqe);
2941		break;
2942
2943	default:
2944		bfa_sm_fault(ms->port->fcs, event);
2945	}
2946}
2947
2948static void
2949bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2950			enum port_ms_event event)
2951{
2952	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2953	bfa_trc(ms->port->fcs, event);
2954
2955	switch (event) {
2956	case MSSM_EVENT_RSP_ERROR:
2957		/*
2958		 * Start timer for a delayed retry
2959		 */
2960		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2961		ms->port->stats.ms_retries++;
2962		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2963				    &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2964				    BFA_FCS_RETRY_TIMEOUT);
2965		break;
2966
2967	case MSSM_EVENT_RSP_OK:
2968		/*
2969		 * since plogi is done, now invoke MS related sub-modules
2970		 */
2971		bfa_fcs_lport_fdmi_online(ms);
2972
2973		/*
2974		 * if this is a Vport, go to online state.
2975		 */
2976		if (ms->port->vport) {
2977			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2978			break;
2979		}
2980
2981		/*
2982		 * For a base port we need to get the
2983		 * switch's IP address.
2984		 */
2985		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2986		bfa_fcs_lport_ms_send_gmal(ms, NULL);
2987		break;
2988
2989	case MSSM_EVENT_PORT_OFFLINE:
2990		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2991		bfa_fcxp_discard(ms->fcxp);
2992		break;
2993
2994	default:
2995		bfa_sm_fault(ms->port->fcs, event);
2996	}
2997}
2998
2999static void
3000bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
3001			enum port_ms_event event)
3002{
3003	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3004	bfa_trc(ms->port->fcs, event);
3005
3006	switch (event) {
3007	case MSSM_EVENT_TIMEOUT:
3008		/*
3009		 * Retry Timer Expired. Re-send
3010		 */
3011		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
3012		bfa_fcs_lport_ms_send_plogi(ms, NULL);
3013		break;
3014
3015	case MSSM_EVENT_PORT_OFFLINE:
3016		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3017		bfa_timer_stop(&ms->timer);
3018		break;
3019
3020	default:
3021		bfa_sm_fault(ms->port->fcs, event);
3022	}
3023}
3024
3025static void
3026bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
3027			enum port_ms_event event)
3028{
3029	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3030	bfa_trc(ms->port->fcs, event);
3031
3032	switch (event) {
3033	case MSSM_EVENT_PORT_OFFLINE:
3034		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3035		break;
3036
3037	case MSSM_EVENT_PORT_FABRIC_RSCN:
3038		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3039		ms->retry_cnt = 0;
3040		bfa_fcs_lport_ms_send_gfn(ms, NULL);
3041		break;
3042
3043	default:
3044		bfa_sm_fault(ms->port->fcs, event);
3045	}
3046}
3047
3048static void
3049bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
3050				enum port_ms_event event)
3051{
3052	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3053	bfa_trc(ms->port->fcs, event);
3054
3055	switch (event) {
3056	case MSSM_EVENT_FCXP_SENT:
3057		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
3058		break;
3059
3060	case MSSM_EVENT_PORT_OFFLINE:
3061		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3062		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3063					   &ms->fcxp_wqe);
3064		break;
3065
3066	default:
3067		bfa_sm_fault(ms->port->fcs, event);
3068	}
3069}
3070
3071static void
3072bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
3073				enum port_ms_event event)
3074{
3075	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3076	bfa_trc(ms->port->fcs, event);
3077
3078	switch (event) {
3079	case MSSM_EVENT_RSP_ERROR:
3080		/*
3081		 * Start timer for a delayed retry
3082		 */
3083		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
3084			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
3085			ms->port->stats.ms_retries++;
3086			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3087				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
3088				BFA_FCS_RETRY_TIMEOUT);
3089		} else {
3090			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3091			bfa_fcs_lport_ms_send_gfn(ms, NULL);
3092			ms->retry_cnt = 0;
3093		}
3094		break;
3095
3096	case MSSM_EVENT_RSP_OK:
3097		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3098		bfa_fcs_lport_ms_send_gfn(ms, NULL);
3099		break;
3100
3101	case MSSM_EVENT_PORT_OFFLINE:
3102		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3103		bfa_fcxp_discard(ms->fcxp);
3104		break;
3105
3106	default:
3107		bfa_sm_fault(ms->port->fcs, event);
3108	}
3109}
3110
3111static void
3112bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
3113				enum port_ms_event event)
3114{
3115	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3116	bfa_trc(ms->port->fcs, event);
3117
3118	switch (event) {
3119	case MSSM_EVENT_TIMEOUT:
3120		/*
3121		 * Retry Timer Expired. Re-send
3122		 */
3123		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
3124		bfa_fcs_lport_ms_send_gmal(ms, NULL);
3125		break;
3126
3127	case MSSM_EVENT_PORT_OFFLINE:
3128		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3129		bfa_timer_stop(&ms->timer);
3130		break;
3131
3132	default:
3133		bfa_sm_fault(ms->port->fcs, event);
3134	}
3135}
3136/*
3137 *  ms_pvt MS local functions
3138 */
3139
3140static void
3141bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3142{
3143	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3144	bfa_fcs_lport_t *port = ms->port;
3145	struct fchs_s	fchs;
3146	int		len;
3147	struct bfa_fcxp_s *fcxp;
3148
3149	bfa_trc(port->fcs, port->pid);
3150
3151	fcxp = fcxp_alloced ? fcxp_alloced :
3152	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3153	if (!fcxp) {
3154		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3155				bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
3156		return;
3157	}
3158	ms->fcxp = fcxp;
3159
3160	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3161			     bfa_fcs_lport_get_fcid(port),
3162				 port->fabric->lps->pr_nwwn);
3163
3164	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3165			  FC_CLASS_3, len, &fchs,
3166			  bfa_fcs_lport_ms_gmal_response, (void *)ms,
3167			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3168
3169	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3170}
3171
3172static void
3173bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3174				void *cbarg, bfa_status_t req_status,
3175				u32 rsp_len, u32 resid_len,
3176				struct fchs_s *rsp_fchs)
3177{
3178	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3179	bfa_fcs_lport_t *port = ms->port;
3180	struct ct_hdr_s		*cthdr = NULL;
3181	struct fcgs_gmal_resp_s *gmal_resp;
3182	struct fcgs_gmal_entry_s *gmal_entry;
3183	u32		num_entries;
3184	u8			*rsp_str;
3185
3186	bfa_trc(port->fcs, req_status);
3187	bfa_trc(port->fcs, port->port_cfg.pwwn);
3188
3189	/*
3190	 * Sanity Checks
3191	 */
3192	if (req_status != BFA_STATUS_OK) {
3193		bfa_trc(port->fcs, req_status);
3194		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3195		return;
3196	}
3197
3198	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3199	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3200
3201	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3202		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
3203
3204		num_entries = be32_to_cpu(gmal_resp->ms_len);
3205		if (num_entries == 0) {
3206			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3207			return;
3208		}
3209		/*
3210		* The response could contain multiple Entries.
3211		* Entries for SNMP interface, etc.
3212		* We look for the entry with a telnet prefix.
3213		* First "http://" entry refers to IP addr
3214		*/
3215
3216		gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
3217		while (num_entries > 0) {
3218			if (strncmp(gmal_entry->prefix,
3219				CT_GMAL_RESP_PREFIX_HTTP,
3220				sizeof(gmal_entry->prefix)) == 0) {
3221
3222				/*
3223				* if the IP address is terminating with a '/',
3224				* remove it.
3225				* Byte 0 consists of the length of the string.
3226				*/
3227				rsp_str = &(gmal_entry->prefix[0]);
3228				if (rsp_str[gmal_entry->len-1] == '/')
3229					rsp_str[gmal_entry->len-1] = 0;
3230
3231				/* copy IP Address to fabric */
3232				strscpy(bfa_fcs_lport_get_fabric_ipaddr(port),
3233					gmal_entry->ip_addr,
3234					BFA_FCS_FABRIC_IPADDR_SZ);
3235				break;
3236			} else {
3237				--num_entries;
3238				++gmal_entry;
3239			}
3240		}
3241
3242		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3243		return;
3244	}
3245
3246	bfa_trc(port->fcs, cthdr->reason_code);
3247	bfa_trc(port->fcs, cthdr->exp_code);
3248	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3249}
3250
3251static void
3252bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
3253			enum port_ms_event event)
3254{
3255	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3256	bfa_trc(ms->port->fcs, event);
3257
3258	switch (event) {
3259	case MSSM_EVENT_FCXP_SENT:
3260		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
3261		break;
3262
3263	case MSSM_EVENT_PORT_OFFLINE:
3264		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3265		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3266					   &ms->fcxp_wqe);
3267		break;
3268
3269	default:
3270		bfa_sm_fault(ms->port->fcs, event);
3271	}
3272}
3273
3274static void
3275bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
3276			enum port_ms_event event)
3277{
3278	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3279	bfa_trc(ms->port->fcs, event);
3280
3281	switch (event) {
3282	case MSSM_EVENT_RSP_ERROR:
3283		/*
3284		 * Start timer for a delayed retry
3285		 */
3286		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
3287			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
3288			ms->port->stats.ms_retries++;
3289			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3290				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
3291				BFA_FCS_RETRY_TIMEOUT);
3292		} else {
3293			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
3294			ms->retry_cnt = 0;
3295		}
3296		break;
3297
3298	case MSSM_EVENT_RSP_OK:
3299		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
3300		break;
3301
3302	case MSSM_EVENT_PORT_OFFLINE:
3303		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3304		bfa_fcxp_discard(ms->fcxp);
3305		break;
3306
3307	default:
3308		bfa_sm_fault(ms->port->fcs, event);
3309	}
3310}
3311
3312static void
3313bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
3314				enum port_ms_event event)
3315{
3316	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3317	bfa_trc(ms->port->fcs, event);
3318
3319	switch (event) {
3320	case MSSM_EVENT_TIMEOUT:
3321		/*
3322		 * Retry Timer Expired. Re-send
3323		 */
3324		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3325		bfa_fcs_lport_ms_send_gfn(ms, NULL);
3326		break;
3327
3328	case MSSM_EVENT_PORT_OFFLINE:
3329		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3330		bfa_timer_stop(&ms->timer);
3331		break;
3332
3333	default:
3334		bfa_sm_fault(ms->port->fcs, event);
3335	}
3336}
3337/*
3338 *  ms_pvt MS local functions
3339 */
3340
3341static void
3342bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3343{
3344	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3345	bfa_fcs_lport_t *port = ms->port;
3346	struct fchs_s		fchs;
3347	int			len;
3348	struct bfa_fcxp_s *fcxp;
3349
3350	bfa_trc(port->fcs, port->pid);
3351
3352	fcxp = fcxp_alloced ? fcxp_alloced :
3353	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3354	if (!fcxp) {
3355		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3356				bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
3357		return;
3358	}
3359	ms->fcxp = fcxp;
3360
3361	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3362			     bfa_fcs_lport_get_fcid(port),
3363				 port->fabric->lps->pr_nwwn);
3364
3365	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3366			  FC_CLASS_3, len, &fchs,
3367			  bfa_fcs_lport_ms_gfn_response, (void *)ms,
3368			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3369
3370	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3371}
3372
3373static void
3374bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3375			void *cbarg, bfa_status_t req_status, u32 rsp_len,
3376			u32 resid_len, struct fchs_s *rsp_fchs)
3377{
3378	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3379	bfa_fcs_lport_t *port = ms->port;
3380	struct ct_hdr_s	*cthdr = NULL;
3381	wwn_t	       *gfn_resp;
3382
3383	bfa_trc(port->fcs, req_status);
3384	bfa_trc(port->fcs, port->port_cfg.pwwn);
3385
3386	/*
3387	 * Sanity Checks
3388	 */
3389	if (req_status != BFA_STATUS_OK) {
3390		bfa_trc(port->fcs, req_status);
3391		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3392		return;
3393	}
3394
3395	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3396	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3397
3398	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3399		gfn_resp = (wwn_t *)(cthdr + 1);
3400		/* check if it has actually changed */
3401		if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
3402				gfn_resp, sizeof(wwn_t)) != 0)) {
3403			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
3404		}
3405		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3406		return;
3407	}
3408
3409	bfa_trc(port->fcs, cthdr->reason_code);
3410	bfa_trc(port->fcs, cthdr->exp_code);
3411	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3412}
3413
3414/*
3415 *  ms_pvt MS local functions
3416 */
3417
3418static void
3419bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3420{
3421	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3422	struct bfa_fcs_lport_s *port = ms->port;
3423	struct fchs_s	fchs;
3424	int	len;
3425	struct bfa_fcxp_s *fcxp;
3426
3427	bfa_trc(port->fcs, port->pid);
3428
3429	fcxp = fcxp_alloced ? fcxp_alloced :
3430	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3431	if (!fcxp) {
3432		port->stats.ms_plogi_alloc_wait++;
3433		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3434				bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
3435		return;
3436	}
3437	ms->fcxp = fcxp;
3438
3439	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3440			     bfa_hton3b(FC_MGMT_SERVER),
3441			     bfa_fcs_lport_get_fcid(port), 0,
3442			     port->port_cfg.pwwn, port->port_cfg.nwwn,
3443			     bfa_fcport_get_maxfrsize(port->fcs->bfa),
3444			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
3445
3446	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3447			  FC_CLASS_3, len, &fchs,
3448			  bfa_fcs_lport_ms_plogi_response, (void *)ms,
3449			  FC_MAX_PDUSZ, FC_ELS_TOV);
3450
3451	port->stats.ms_plogi_sent++;
3452	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3453}
3454
3455static void
3456bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3457			void *cbarg, bfa_status_t req_status,
3458			u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
3459{
3460	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3461	struct bfa_fcs_lport_s *port = ms->port;
3462	struct fc_els_cmd_s *els_cmd;
3463	struct fc_ls_rjt_s *ls_rjt;
3464
3465	bfa_trc(port->fcs, req_status);
3466	bfa_trc(port->fcs, port->port_cfg.pwwn);
3467
3468	/*
3469	 * Sanity Checks
3470	 */
3471	if (req_status != BFA_STATUS_OK) {
3472		port->stats.ms_plogi_rsp_err++;
3473		bfa_trc(port->fcs, req_status);
3474		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3475		return;
3476	}
3477
3478	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3479
3480	switch (els_cmd->els_code) {
3481
3482	case FC_ELS_ACC:
3483		if (rsp_len < sizeof(struct fc_logi_s)) {
3484			bfa_trc(port->fcs, rsp_len);
3485			port->stats.ms_plogi_acc_err++;
3486			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3487			break;
3488		}
3489		port->stats.ms_plogi_accepts++;
3490		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3491		break;
3492
3493	case FC_ELS_LS_RJT:
3494		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3495
3496		bfa_trc(port->fcs, ls_rjt->reason_code);
3497		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3498
3499		port->stats.ms_rejects++;
3500		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3501		break;
3502
3503	default:
3504		port->stats.ms_plogi_unknown_rsp++;
3505		bfa_trc(port->fcs, els_cmd->els_code);
3506		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3507	}
3508}
3509
3510static void
3511bfa_fcs_lport_ms_timeout(void *arg)
3512{
3513	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
3514
3515	ms->port->stats.ms_timeouts++;
3516	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
3517}
3518
3519
3520void
3521bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
3522{
3523	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3524
3525	ms->port = port;
3526	bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3527
3528	/*
3529	 * Invoke init routines of sub modules.
3530	 */
3531	bfa_fcs_lport_fdmi_init(ms);
3532}
3533
3534void
3535bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
3536{
3537	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3538
3539	ms->port = port;
3540	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
3541	bfa_fcs_lport_fdmi_offline(ms);
3542}
3543
3544void
3545bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
3546{
3547	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3548
3549	ms->port = port;
3550	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3551}
3552void
3553bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3554{
3555	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3556
3557	/* todo.  Handle this only  when in Online state */
3558	if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3559		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3560}
3561
3562/*
3563 * @page ns_sm_info VPORT NS State Machine
3564 *
3565 * @section ns_sm_interactions VPORT NS State Machine Interactions
3566 *
3567 * @section ns_sm VPORT NS State Machine
3568 * img ns_sm.jpg
3569 */
3570
3571/*
3572 * forward declarations
3573 */
3574static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3575					   struct bfa_fcxp_s *fcxp_alloced);
3576static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3577					     struct bfa_fcxp_s *fcxp_alloced);
3578static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3579					    struct bfa_fcxp_s *fcxp_alloced);
3580static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3581					    struct bfa_fcxp_s *fcxp_alloced);
3582static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3583					    struct bfa_fcxp_s *fcxp_alloced);
3584static void	bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg,
3585					struct bfa_fcxp_s *fcxp_alloced);
3586static void	bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg,
3587					struct bfa_fcxp_s *fcxp_alloced);
3588static void     bfa_fcs_lport_ns_timeout(void *arg);
3589static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3590					       struct bfa_fcxp_s *fcxp,
3591					       void *cbarg,
3592					       bfa_status_t req_status,
3593					       u32 rsp_len,
3594					       u32 resid_len,
3595					       struct fchs_s *rsp_fchs);
3596static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3597						 struct bfa_fcxp_s *fcxp,
3598						 void *cbarg,
3599						 bfa_status_t req_status,
3600						 u32 rsp_len,
3601						 u32 resid_len,
3602						 struct fchs_s *rsp_fchs);
3603static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
3604						struct bfa_fcxp_s *fcxp,
3605						void *cbarg,
3606						bfa_status_t req_status,
3607						u32 rsp_len,
3608						u32 resid_len,
3609						struct fchs_s *rsp_fchs);
3610static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
3611						struct bfa_fcxp_s *fcxp,
3612						void *cbarg,
3613						bfa_status_t req_status,
3614						u32 rsp_len,
3615						u32 resid_len,
3616						struct fchs_s *rsp_fchs);
3617static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3618						struct bfa_fcxp_s *fcxp,
3619						void *cbarg,
3620						bfa_status_t req_status,
3621						u32 rsp_len,
3622						u32 resid_len,
3623						struct fchs_s *rsp_fchs);
3624static void     bfa_fcs_lport_ns_rnn_id_response(void *fcsarg,
3625						struct bfa_fcxp_s *fcxp,
3626						void *cbarg,
3627						bfa_status_t req_status,
3628						u32 rsp_len,
3629						u32 resid_len,
3630						struct fchs_s *rsp_fchs);
3631static void     bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg,
3632						struct bfa_fcxp_s *fcxp,
3633						void *cbarg,
3634						bfa_status_t req_status,
3635						u32 rsp_len,
3636						u32 resid_len,
3637						struct fchs_s *rsp_fchs);
3638static void     bfa_fcs_lport_ns_process_gidft_pids(
3639				struct bfa_fcs_lport_s *port,
3640				u32 *pid_buf, u32 n_pids);
3641
3642static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3643/*
3644 *  fcs_ns_sm FCS nameserver interface state machine
3645 */
3646
3647/*
3648 * VPort NS State Machine events
3649 */
3650enum vport_ns_event {
3651	NSSM_EVENT_PORT_ONLINE = 1,
3652	NSSM_EVENT_PORT_OFFLINE = 2,
3653	NSSM_EVENT_PLOGI_SENT = 3,
3654	NSSM_EVENT_RSP_OK = 4,
3655	NSSM_EVENT_RSP_ERROR = 5,
3656	NSSM_EVENT_TIMEOUT = 6,
3657	NSSM_EVENT_NS_QUERY = 7,
3658	NSSM_EVENT_RSPNID_SENT = 8,
3659	NSSM_EVENT_RFTID_SENT = 9,
3660	NSSM_EVENT_RFFID_SENT = 10,
3661	NSSM_EVENT_GIDFT_SENT = 11,
3662	NSSM_EVENT_RNNID_SENT = 12,
3663	NSSM_EVENT_RSNN_NN_SENT = 13,
3664};
3665
3666static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3667					   enum vport_ns_event event);
3668static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3669						 enum vport_ns_event event);
3670static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3671					 enum vport_ns_event event);
3672static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3673					       enum vport_ns_event event);
3674static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
3675					struct bfa_fcs_lport_ns_s *ns,
3676					enum vport_ns_event event);
3677static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3678					   enum vport_ns_event event);
3679static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3680						 enum vport_ns_event event);
3681static void     bfa_fcs_lport_ns_sm_sending_rft_id(
3682					struct bfa_fcs_lport_ns_s *ns,
3683					enum vport_ns_event event);
3684static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3685						enum vport_ns_event event);
3686static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3687					  enum vport_ns_event event);
3688static void     bfa_fcs_lport_ns_sm_sending_rff_id(
3689					struct bfa_fcs_lport_ns_s *ns,
3690					enum vport_ns_event event);
3691static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3692						enum vport_ns_event event);
3693static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3694					  enum vport_ns_event event);
3695static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
3696					struct bfa_fcs_lport_ns_s *ns,
3697					enum vport_ns_event event);
3698static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3699					  enum vport_ns_event event);
3700static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3701						enum vport_ns_event event);
3702static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3703					  enum vport_ns_event event);
3704static void     bfa_fcs_lport_ns_sm_sending_rnn_id(
3705					struct bfa_fcs_lport_ns_s *ns,
3706					enum vport_ns_event event);
3707static void     bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3708					enum vport_ns_event event);
3709static void     bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3710						enum vport_ns_event event);
3711static void     bfa_fcs_lport_ns_sm_sending_rsnn_nn(
3712					struct bfa_fcs_lport_ns_s *ns,
3713					enum vport_ns_event event);
3714static void     bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3715						enum vport_ns_event event);
3716static void     bfa_fcs_lport_ns_sm_rsnn_nn_retry(
3717					struct bfa_fcs_lport_ns_s *ns,
3718					enum vport_ns_event event);
3719/*
3720 *	Start in offline state - awaiting linkup
3721 */
3722static void
3723bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3724			enum vport_ns_event event)
3725{
3726	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3727	bfa_trc(ns->port->fcs, event);
3728
3729	switch (event) {
3730	case NSSM_EVENT_PORT_ONLINE:
3731		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3732		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3733		break;
3734
3735	case NSSM_EVENT_PORT_OFFLINE:
3736		break;
3737
3738	default:
3739		bfa_sm_fault(ns->port->fcs, event);
3740	}
3741}
3742
3743static void
3744bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3745			enum vport_ns_event event)
3746{
3747	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3748	bfa_trc(ns->port->fcs, event);
3749
3750	switch (event) {
3751	case NSSM_EVENT_PLOGI_SENT:
3752		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3753		break;
3754
3755	case NSSM_EVENT_PORT_OFFLINE:
3756		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3757		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3758					   &ns->fcxp_wqe);
3759		break;
3760
3761	default:
3762		bfa_sm_fault(ns->port->fcs, event);
3763	}
3764}
3765
3766static void
3767bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3768			enum vport_ns_event event)
3769{
3770	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3771	bfa_trc(ns->port->fcs, event);
3772
3773	switch (event) {
3774	case NSSM_EVENT_RSP_ERROR:
3775		/*
3776		 * Start timer for a delayed retry
3777		 */
3778		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3779		ns->port->stats.ns_retries++;
3780		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3781				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3782				    BFA_FCS_RETRY_TIMEOUT);
3783		break;
3784
3785	case NSSM_EVENT_RSP_OK:
3786		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3787		ns->num_rnnid_retries = 0;
3788		bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3789		break;
3790
3791	case NSSM_EVENT_PORT_OFFLINE:
3792		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3793		bfa_fcxp_discard(ns->fcxp);
3794		break;
3795
3796	default:
3797		bfa_sm_fault(ns->port->fcs, event);
3798	}
3799}
3800
3801static void
3802bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3803				enum vport_ns_event event)
3804{
3805	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3806	bfa_trc(ns->port->fcs, event);
3807
3808	switch (event) {
3809	case NSSM_EVENT_TIMEOUT:
3810		/*
3811		 * Retry Timer Expired. Re-send
3812		 */
3813		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3814		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3815		break;
3816
3817	case NSSM_EVENT_PORT_OFFLINE:
3818		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3819		bfa_timer_stop(&ns->timer);
3820		break;
3821
3822	default:
3823		bfa_sm_fault(ns->port->fcs, event);
3824	}
3825}
3826
3827static void
3828bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3829					enum vport_ns_event event)
3830{
3831	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3832	bfa_trc(ns->port->fcs, event);
3833
3834	switch (event) {
3835	case NSSM_EVENT_RNNID_SENT:
3836		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id);
3837		break;
3838
3839	case NSSM_EVENT_PORT_OFFLINE:
3840		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3841		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3842						&ns->fcxp_wqe);
3843		break;
3844	default:
3845		bfa_sm_fault(ns->port->fcs, event);
3846	}
3847}
3848
3849static void
3850bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3851				enum vport_ns_event event)
3852{
3853	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3854	bfa_trc(ns->port->fcs, event);
3855
3856	switch (event) {
3857	case NSSM_EVENT_RSP_OK:
3858		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3859		ns->num_rnnid_retries = 0;
3860		ns->num_rsnn_nn_retries = 0;
3861		bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3862		break;
3863
3864	case NSSM_EVENT_RSP_ERROR:
3865		if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) {
3866			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry);
3867			ns->port->stats.ns_retries++;
3868			ns->num_rnnid_retries++;
3869			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3870				&ns->timer, bfa_fcs_lport_ns_timeout, ns,
3871				BFA_FCS_RETRY_TIMEOUT);
3872		} else {
3873			bfa_sm_set_state(ns,
3874				bfa_fcs_lport_ns_sm_sending_rspn_id);
3875			bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3876		}
3877		break;
3878
3879	case NSSM_EVENT_PORT_OFFLINE:
3880		bfa_fcxp_discard(ns->fcxp);
3881		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3882		break;
3883
3884	default:
3885		bfa_sm_fault(ns->port->fcs, event);
3886	}
3887}
3888
3889static void
3890bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3891				enum vport_ns_event event)
3892{
3893	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3894	bfa_trc(ns->port->fcs, event);
3895
3896	switch (event) {
3897	case NSSM_EVENT_TIMEOUT:
3898		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3899		bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3900		break;
3901
3902	case NSSM_EVENT_PORT_OFFLINE:
3903		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3904		bfa_timer_stop(&ns->timer);
3905		break;
3906
3907	default:
3908		bfa_sm_fault(ns->port->fcs, event);
3909	}
3910}
3911
3912static void
3913bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3914					enum vport_ns_event event)
3915{
3916	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3917	bfa_trc(ns->port->fcs, event);
3918
3919	switch (event) {
3920	case NSSM_EVENT_RSNN_NN_SENT:
3921		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn);
3922		break;
3923
3924	case NSSM_EVENT_PORT_OFFLINE:
3925		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3926		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3927			&ns->fcxp_wqe);
3928		break;
3929
3930	default:
3931		bfa_sm_fault(ns->port->fcs, event);
3932	}
3933}
3934
3935static void
3936bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3937				enum vport_ns_event event)
3938{
3939	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3940	bfa_trc(ns->port->fcs, event);
3941
3942	switch (event) {
3943	case NSSM_EVENT_RSP_OK:
3944		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3945		ns->num_rsnn_nn_retries = 0;
3946		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3947		break;
3948
3949	case NSSM_EVENT_RSP_ERROR:
3950		if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) {
3951			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry);
3952			ns->port->stats.ns_retries++;
3953			ns->num_rsnn_nn_retries++;
3954			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3955					&ns->timer, bfa_fcs_lport_ns_timeout,
3956					ns, BFA_FCS_RETRY_TIMEOUT);
3957		} else {
3958			bfa_sm_set_state(ns,
3959				bfa_fcs_lport_ns_sm_sending_rspn_id);
3960			bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3961		}
3962		break;
3963
3964	case NSSM_EVENT_PORT_OFFLINE:
3965		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3966		bfa_fcxp_discard(ns->fcxp);
3967		break;
3968
3969	default:
3970		bfa_sm_fault(ns->port->fcs, event);
3971	}
3972}
3973
3974static void
3975bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns,
3976					enum vport_ns_event event)
3977{
3978	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3979	bfa_trc(ns->port->fcs, event);
3980
3981	switch (event) {
3982	case NSSM_EVENT_TIMEOUT:
3983		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3984		bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3985		break;
3986
3987	case NSSM_EVENT_PORT_OFFLINE:
3988		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3989		bfa_timer_stop(&ns->timer);
3990		break;
3991
3992	default:
3993		bfa_sm_fault(ns->port->fcs, event);
3994	}
3995}
3996
3997static void
3998bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3999				   enum vport_ns_event event)
4000{
4001	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4002	bfa_trc(ns->port->fcs, event);
4003
4004	switch (event) {
4005	case NSSM_EVENT_RSPNID_SENT:
4006		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
4007		break;
4008
4009	case NSSM_EVENT_PORT_OFFLINE:
4010		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4011		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4012					   &ns->fcxp_wqe);
4013		break;
4014
4015	default:
4016		bfa_sm_fault(ns->port->fcs, event);
4017	}
4018}
4019
4020static void
4021bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
4022			enum vport_ns_event event)
4023{
4024	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4025	bfa_trc(ns->port->fcs, event);
4026
4027	switch (event) {
4028	case NSSM_EVENT_RSP_ERROR:
4029		/*
4030		 * Start timer for a delayed retry
4031		 */
4032		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
4033		ns->port->stats.ns_retries++;
4034		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4035				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4036				    BFA_FCS_RETRY_TIMEOUT);
4037		break;
4038
4039	case NSSM_EVENT_RSP_OK:
4040		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
4041		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
4042		break;
4043
4044	case NSSM_EVENT_PORT_OFFLINE:
4045		bfa_fcxp_discard(ns->fcxp);
4046		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4047		break;
4048
4049	default:
4050		bfa_sm_fault(ns->port->fcs, event);
4051	}
4052}
4053
4054static void
4055bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
4056				enum vport_ns_event event)
4057{
4058	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4059	bfa_trc(ns->port->fcs, event);
4060
4061	switch (event) {
4062	case NSSM_EVENT_TIMEOUT:
4063		/*
4064		 * Retry Timer Expired. Re-send
4065		 */
4066		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
4067		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
4068		break;
4069
4070	case NSSM_EVENT_PORT_OFFLINE:
4071		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4072		bfa_timer_stop(&ns->timer);
4073		break;
4074
4075	default:
4076		bfa_sm_fault(ns->port->fcs, event);
4077	}
4078}
4079
4080static void
4081bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
4082				  enum vport_ns_event event)
4083{
4084	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4085	bfa_trc(ns->port->fcs, event);
4086
4087	switch (event) {
4088	case NSSM_EVENT_RFTID_SENT:
4089		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
4090		break;
4091
4092	case NSSM_EVENT_PORT_OFFLINE:
4093		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4094		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4095					   &ns->fcxp_wqe);
4096		break;
4097
4098	default:
4099		bfa_sm_fault(ns->port->fcs, event);
4100	}
4101}
4102
4103static void
4104bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
4105			enum vport_ns_event event)
4106{
4107	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4108	bfa_trc(ns->port->fcs, event);
4109
4110	switch (event) {
4111	case NSSM_EVENT_RSP_OK:
4112		/* Now move to register FC4 Features */
4113		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
4114		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
4115		break;
4116
4117	case NSSM_EVENT_RSP_ERROR:
4118		/*
4119		 * Start timer for a delayed retry
4120		 */
4121		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
4122		ns->port->stats.ns_retries++;
4123		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4124				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4125				    BFA_FCS_RETRY_TIMEOUT);
4126		break;
4127
4128	case NSSM_EVENT_PORT_OFFLINE:
4129		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4130		bfa_fcxp_discard(ns->fcxp);
4131		break;
4132
4133	default:
4134		bfa_sm_fault(ns->port->fcs, event);
4135	}
4136}
4137
4138static void
4139bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
4140				enum vport_ns_event event)
4141{
4142	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4143	bfa_trc(ns->port->fcs, event);
4144
4145	switch (event) {
4146	case NSSM_EVENT_TIMEOUT:
4147		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
4148		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
4149		break;
4150
4151	case NSSM_EVENT_PORT_OFFLINE:
4152		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4153		bfa_timer_stop(&ns->timer);
4154		break;
4155
4156	default:
4157		bfa_sm_fault(ns->port->fcs, event);
4158	}
4159}
4160
4161static void
4162bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
4163				  enum vport_ns_event event)
4164{
4165	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4166	bfa_trc(ns->port->fcs, event);
4167
4168	switch (event) {
4169	case NSSM_EVENT_RFFID_SENT:
4170		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
4171		break;
4172
4173	case NSSM_EVENT_PORT_OFFLINE:
4174		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4175		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4176					   &ns->fcxp_wqe);
4177		break;
4178
4179	default:
4180		bfa_sm_fault(ns->port->fcs, event);
4181	}
4182}
4183
4184static void
4185bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
4186			enum vport_ns_event event)
4187{
4188	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4189	bfa_trc(ns->port->fcs, event);
4190
4191	switch (event) {
4192	case NSSM_EVENT_RSP_OK:
4193
4194		/*
4195		 * If min cfg mode is enabled, we donot initiate rport
4196		 * discovery with the fabric. Instead, we will retrieve the
4197		 * boot targets from HAL/FW.
4198		 */
4199		if (__fcs_min_cfg(ns->port->fcs)) {
4200			bfa_fcs_lport_ns_boot_target_disc(ns->port);
4201			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
4202			return;
4203		}
4204
4205		/*
4206		 * If the port role is Initiator Mode issue NS query.
4207		 * If it is Target Mode, skip this and go to online.
4208		 */
4209		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
4210			bfa_sm_set_state(ns,
4211				bfa_fcs_lport_ns_sm_sending_gid_ft);
4212			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4213		}
4214		/*
4215		 * kick off mgmt srvr state machine
4216		 */
4217		bfa_fcs_lport_ms_online(ns->port);
4218		break;
4219
4220	case NSSM_EVENT_RSP_ERROR:
4221		/*
4222		 * Start timer for a delayed retry
4223		 */
4224		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
4225		ns->port->stats.ns_retries++;
4226		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4227				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4228				    BFA_FCS_RETRY_TIMEOUT);
4229		break;
4230
4231	case NSSM_EVENT_PORT_OFFLINE:
4232		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4233		bfa_fcxp_discard(ns->fcxp);
4234		break;
4235
4236	default:
4237		bfa_sm_fault(ns->port->fcs, event);
4238	}
4239}
4240
4241static void
4242bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
4243				enum vport_ns_event event)
4244{
4245	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4246	bfa_trc(ns->port->fcs, event);
4247
4248	switch (event) {
4249	case NSSM_EVENT_TIMEOUT:
4250		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
4251		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
4252		break;
4253
4254	case NSSM_EVENT_PORT_OFFLINE:
4255		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4256		bfa_timer_stop(&ns->timer);
4257		break;
4258
4259	default:
4260		bfa_sm_fault(ns->port->fcs, event);
4261	}
4262}
4263static void
4264bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
4265				  enum vport_ns_event event)
4266{
4267	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4268	bfa_trc(ns->port->fcs, event);
4269
4270	switch (event) {
4271	case NSSM_EVENT_GIDFT_SENT:
4272		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
4273		break;
4274
4275	case NSSM_EVENT_PORT_OFFLINE:
4276		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4277		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4278					   &ns->fcxp_wqe);
4279		break;
4280
4281	default:
4282		bfa_sm_fault(ns->port->fcs, event);
4283	}
4284}
4285
4286static void
4287bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
4288			enum vport_ns_event event)
4289{
4290	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4291	bfa_trc(ns->port->fcs, event);
4292
4293	switch (event) {
4294	case NSSM_EVENT_RSP_OK:
4295		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
4296		break;
4297
4298	case NSSM_EVENT_RSP_ERROR:
4299		/*
4300		 * TBD: for certain reject codes, we don't need to retry
4301		 */
4302		/*
4303		 * Start timer for a delayed retry
4304		 */
4305		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
4306		ns->port->stats.ns_retries++;
4307		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4308				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4309				    BFA_FCS_RETRY_TIMEOUT);
4310		break;
4311
4312	case NSSM_EVENT_PORT_OFFLINE:
4313		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4314		bfa_fcxp_discard(ns->fcxp);
4315		break;
4316
4317	case  NSSM_EVENT_NS_QUERY:
4318		break;
4319
4320	default:
4321		bfa_sm_fault(ns->port->fcs, event);
4322	}
4323}
4324
4325static void
4326bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
4327				enum vport_ns_event event)
4328{
4329	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4330	bfa_trc(ns->port->fcs, event);
4331
4332	switch (event) {
4333	case NSSM_EVENT_TIMEOUT:
4334		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
4335		bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4336		break;
4337
4338	case NSSM_EVENT_PORT_OFFLINE:
4339		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4340		bfa_timer_stop(&ns->timer);
4341		break;
4342
4343	default:
4344		bfa_sm_fault(ns->port->fcs, event);
4345	}
4346}
4347
4348static void
4349bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
4350			enum vport_ns_event event)
4351{
4352	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4353	bfa_trc(ns->port->fcs, event);
4354
4355	switch (event) {
4356	case NSSM_EVENT_PORT_OFFLINE:
4357		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4358		break;
4359
4360	case NSSM_EVENT_NS_QUERY:
4361		/*
4362		 * If the port role is Initiator Mode issue NS query.
4363		 * If it is Target Mode, skip this and go to online.
4364		 */
4365		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
4366			bfa_sm_set_state(ns,
4367				bfa_fcs_lport_ns_sm_sending_gid_ft);
4368			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4369		}
4370		break;
4371
4372	default:
4373		bfa_sm_fault(ns->port->fcs, event);
4374	}
4375}
4376
4377
4378
4379/*
4380 *  ns_pvt Nameserver local functions
4381 */
4382
4383static void
4384bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4385{
4386	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4387	struct bfa_fcs_lport_s *port = ns->port;
4388	struct fchs_s fchs;
4389	int             len;
4390	struct bfa_fcxp_s *fcxp;
4391
4392	bfa_trc(port->fcs, port->pid);
4393
4394	fcxp = fcxp_alloced ? fcxp_alloced :
4395	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4396	if (!fcxp) {
4397		port->stats.ns_plogi_alloc_wait++;
4398		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4399				bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
4400		return;
4401	}
4402	ns->fcxp = fcxp;
4403
4404	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4405			     bfa_hton3b(FC_NAME_SERVER),
4406			     bfa_fcs_lport_get_fcid(port), 0,
4407			     port->port_cfg.pwwn, port->port_cfg.nwwn,
4408			     bfa_fcport_get_maxfrsize(port->fcs->bfa),
4409			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
4410
4411	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4412			  FC_CLASS_3, len, &fchs,
4413			  bfa_fcs_lport_ns_plogi_response, (void *)ns,
4414			  FC_MAX_PDUSZ, FC_ELS_TOV);
4415	port->stats.ns_plogi_sent++;
4416
4417	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
4418}
4419
4420static void
4421bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4422			void *cbarg, bfa_status_t req_status, u32 rsp_len,
4423		       u32 resid_len, struct fchs_s *rsp_fchs)
4424{
4425	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4426	struct bfa_fcs_lport_s *port = ns->port;
4427	/* struct fc_logi_s *plogi_resp; */
4428	struct fc_els_cmd_s *els_cmd;
4429	struct fc_ls_rjt_s *ls_rjt;
4430
4431	bfa_trc(port->fcs, req_status);
4432	bfa_trc(port->fcs, port->port_cfg.pwwn);
4433
4434	/*
4435	 * Sanity Checks
4436	 */
4437	if (req_status != BFA_STATUS_OK) {
4438		bfa_trc(port->fcs, req_status);
4439		port->stats.ns_plogi_rsp_err++;
4440		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4441		return;
4442	}
4443
4444	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4445
4446	switch (els_cmd->els_code) {
4447
4448	case FC_ELS_ACC:
4449		if (rsp_len < sizeof(struct fc_logi_s)) {
4450			bfa_trc(port->fcs, rsp_len);
4451			port->stats.ns_plogi_acc_err++;
4452			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4453			break;
4454		}
4455		port->stats.ns_plogi_accepts++;
4456		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4457		break;
4458
4459	case FC_ELS_LS_RJT:
4460		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4461
4462		bfa_trc(port->fcs, ls_rjt->reason_code);
4463		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4464
4465		port->stats.ns_rejects++;
4466
4467		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4468		break;
4469
4470	default:
4471		port->stats.ns_plogi_unknown_rsp++;
4472		bfa_trc(port->fcs, els_cmd->els_code);
4473		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4474	}
4475}
4476
4477/*
4478 * Register node name for port_id
4479 */
4480static void
4481bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4482{
4483	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4484	struct bfa_fcs_lport_s *port = ns->port;
4485	struct fchs_s  fchs;
4486	int	len;
4487	struct bfa_fcxp_s *fcxp;
4488
4489	bfa_trc(port->fcs, port->port_cfg.pwwn);
4490
4491	fcxp = fcxp_alloced ? fcxp_alloced :
4492			bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4493	if (!fcxp) {
4494		port->stats.ns_rnnid_alloc_wait++;
4495		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4496				bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE);
4497		return;
4498	}
4499
4500	ns->fcxp = fcxp;
4501
4502	len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4503				bfa_fcs_lport_get_fcid(port),
4504				bfa_fcs_lport_get_fcid(port),
4505				bfa_fcs_lport_get_nwwn(port));
4506
4507	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4508			  FC_CLASS_3, len, &fchs,
4509			  bfa_fcs_lport_ns_rnn_id_response, (void *)ns,
4510			  FC_MAX_PDUSZ, FC_FCCT_TOV);
4511
4512	port->stats.ns_rnnid_sent++;
4513	bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT);
4514}
4515
4516static void
4517bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4518				void *cbarg, bfa_status_t req_status,
4519				u32 rsp_len, u32 resid_len,
4520				struct fchs_s *rsp_fchs)
4521
4522{
4523	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4524	struct bfa_fcs_lport_s *port = ns->port;
4525	struct ct_hdr_s	*cthdr = NULL;
4526
4527	bfa_trc(port->fcs, port->port_cfg.pwwn);
4528
4529	/*
4530	 * Sanity Checks
4531	 */
4532	if (req_status != BFA_STATUS_OK) {
4533		bfa_trc(port->fcs, req_status);
4534		port->stats.ns_rnnid_rsp_err++;
4535		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4536		return;
4537	}
4538
4539	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4540	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4541
4542	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4543		port->stats.ns_rnnid_accepts++;
4544		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4545		return;
4546	}
4547
4548	port->stats.ns_rnnid_rejects++;
4549	bfa_trc(port->fcs, cthdr->reason_code);
4550	bfa_trc(port->fcs, cthdr->exp_code);
4551	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4552}
4553
4554/*
4555 * Register the symbolic node name for a given node name.
4556 */
4557static void
4558bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4559{
4560	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4561	struct bfa_fcs_lport_s *port = ns->port;
4562	struct fchs_s  fchs;
4563	int     len;
4564	struct bfa_fcxp_s *fcxp;
4565	u8 *nsymbl;
4566
4567	bfa_trc(port->fcs, port->port_cfg.pwwn);
4568
4569	fcxp = fcxp_alloced ? fcxp_alloced :
4570			bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4571	if (!fcxp) {
4572		port->stats.ns_rsnn_nn_alloc_wait++;
4573		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4574				bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE);
4575		return;
4576	}
4577	ns->fcxp = fcxp;
4578
4579	nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name(
4580					bfa_fcs_get_base_port(port->fcs)));
4581
4582	len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4583				bfa_fcs_lport_get_fcid(port),
4584				bfa_fcs_lport_get_nwwn(port), nsymbl);
4585
4586	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4587			  FC_CLASS_3, len, &fchs,
4588			  bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns,
4589			  FC_MAX_PDUSZ, FC_FCCT_TOV);
4590
4591	port->stats.ns_rsnn_nn_sent++;
4592
4593	bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT);
4594}
4595
4596static void
4597bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4598				void *cbarg, bfa_status_t req_status,
4599				u32 rsp_len, u32 resid_len,
4600				struct fchs_s *rsp_fchs)
4601{
4602	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4603	struct bfa_fcs_lport_s *port = ns->port;
4604	struct ct_hdr_s	*cthdr = NULL;
4605
4606	bfa_trc(port->fcs, port->port_cfg.pwwn);
4607
4608	/*
4609	 * Sanity Checks
4610	 */
4611	if (req_status != BFA_STATUS_OK) {
4612		bfa_trc(port->fcs, req_status);
4613		port->stats.ns_rsnn_nn_rsp_err++;
4614		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4615		return;
4616	}
4617
4618	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4619	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4620
4621	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4622		port->stats.ns_rsnn_nn_accepts++;
4623		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4624		return;
4625	}
4626
4627	port->stats.ns_rsnn_nn_rejects++;
4628	bfa_trc(port->fcs, cthdr->reason_code);
4629	bfa_trc(port->fcs, cthdr->exp_code);
4630	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4631}
4632
4633/*
4634 * Register the symbolic port name.
4635 */
4636static void
4637bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4638{
4639	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4640	struct bfa_fcs_lport_s *port = ns->port;
4641	struct fchs_s fchs;
4642	int             len;
4643	struct bfa_fcxp_s *fcxp;
4644	u8         symbl[256];
4645	u8         *psymbl = &symbl[0];
4646
4647	memset(symbl, 0, sizeof(symbl));
4648
4649	bfa_trc(port->fcs, port->port_cfg.pwwn);
4650
4651	fcxp = fcxp_alloced ? fcxp_alloced :
4652	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4653	if (!fcxp) {
4654		port->stats.ns_rspnid_alloc_wait++;
4655		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4656				bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
4657		return;
4658	}
4659	ns->fcxp = fcxp;
4660
4661	/*
4662	 * for V-Port, form a Port Symbolic Name
4663	 */
4664	if (port->vport) {
4665		/*
4666		 * For Vports, we append the vport's port symbolic name
4667		 * to that of the base port.
4668		 */
4669
4670		strscpy(symbl,
4671			(char *)&(bfa_fcs_lport_get_psym_name
4672			 (bfa_fcs_get_base_port(port->fcs))),
4673			sizeof(symbl));
4674
4675		strlcat(symbl, (char *)&(bfa_fcs_lport_get_psym_name(port)),
4676			sizeof(symbl));
4677	} else {
4678		psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
4679	}
4680
4681	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4682			      bfa_fcs_lport_get_fcid(port), 0, psymbl);
4683
4684	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4685			  FC_CLASS_3, len, &fchs,
4686			  bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
4687			  FC_MAX_PDUSZ, FC_FCCT_TOV);
4688
4689	port->stats.ns_rspnid_sent++;
4690
4691	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
4692}
4693
4694static void
4695bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4696				 void *cbarg, bfa_status_t req_status,
4697				 u32 rsp_len, u32 resid_len,
4698				 struct fchs_s *rsp_fchs)
4699{
4700	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4701	struct bfa_fcs_lport_s *port = ns->port;
4702	struct ct_hdr_s *cthdr = NULL;
4703
4704	bfa_trc(port->fcs, port->port_cfg.pwwn);
4705
4706	/*
4707	 * Sanity Checks
4708	 */
4709	if (req_status != BFA_STATUS_OK) {
4710		bfa_trc(port->fcs, req_status);
4711		port->stats.ns_rspnid_rsp_err++;
4712		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4713		return;
4714	}
4715
4716	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4717	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4718
4719	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4720		port->stats.ns_rspnid_accepts++;
4721		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4722		return;
4723	}
4724
4725	port->stats.ns_rspnid_rejects++;
4726	bfa_trc(port->fcs, cthdr->reason_code);
4727	bfa_trc(port->fcs, cthdr->exp_code);
4728	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4729}
4730
4731/*
4732 * Register FC4-Types
4733 */
4734static void
4735bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4736{
4737	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4738	struct bfa_fcs_lport_s *port = ns->port;
4739	struct fchs_s fchs;
4740	int             len;
4741	struct bfa_fcxp_s *fcxp;
4742
4743	bfa_trc(port->fcs, port->port_cfg.pwwn);
4744
4745	fcxp = fcxp_alloced ? fcxp_alloced :
4746	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4747	if (!fcxp) {
4748		port->stats.ns_rftid_alloc_wait++;
4749		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4750				bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
4751		return;
4752	}
4753	ns->fcxp = fcxp;
4754
4755	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4756		     bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
4757
4758	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4759			  FC_CLASS_3, len, &fchs,
4760			  bfa_fcs_lport_ns_rft_id_response, (void *)ns,
4761			  FC_MAX_PDUSZ, FC_FCCT_TOV);
4762
4763	port->stats.ns_rftid_sent++;
4764	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
4765}
4766
4767static void
4768bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4769				void *cbarg, bfa_status_t req_status,
4770				u32 rsp_len, u32 resid_len,
4771				struct fchs_s *rsp_fchs)
4772{
4773	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4774	struct bfa_fcs_lport_s *port = ns->port;
4775	struct ct_hdr_s *cthdr = NULL;
4776
4777	bfa_trc(port->fcs, port->port_cfg.pwwn);
4778
4779	/*
4780	 * Sanity Checks
4781	 */
4782	if (req_status != BFA_STATUS_OK) {
4783		bfa_trc(port->fcs, req_status);
4784		port->stats.ns_rftid_rsp_err++;
4785		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4786		return;
4787	}
4788
4789	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4790	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4791
4792	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4793		port->stats.ns_rftid_accepts++;
4794		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4795		return;
4796	}
4797
4798	port->stats.ns_rftid_rejects++;
4799	bfa_trc(port->fcs, cthdr->reason_code);
4800	bfa_trc(port->fcs, cthdr->exp_code);
4801	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4802}
4803
4804/*
4805 * Register FC4-Features : Should be done after RFT_ID
4806 */
4807static void
4808bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4809{
4810	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4811	struct bfa_fcs_lport_s *port = ns->port;
4812	struct fchs_s fchs;
4813	int             len;
4814	struct bfa_fcxp_s *fcxp;
4815	u8			fc4_ftrs = 0;
4816
4817	bfa_trc(port->fcs, port->port_cfg.pwwn);
4818
4819	fcxp = fcxp_alloced ? fcxp_alloced :
4820	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4821	if (!fcxp) {
4822		port->stats.ns_rffid_alloc_wait++;
4823		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4824				bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
4825		return;
4826	}
4827	ns->fcxp = fcxp;
4828
4829	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
4830		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
4831
4832	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4833			     bfa_fcs_lport_get_fcid(port), 0,
4834				 FC_TYPE_FCP, fc4_ftrs);
4835
4836	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4837			  FC_CLASS_3, len, &fchs,
4838			  bfa_fcs_lport_ns_rff_id_response, (void *)ns,
4839			  FC_MAX_PDUSZ, FC_FCCT_TOV);
4840
4841	port->stats.ns_rffid_sent++;
4842	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
4843}
4844
4845static void
4846bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4847				void *cbarg, bfa_status_t req_status,
4848				u32 rsp_len, u32 resid_len,
4849				struct fchs_s *rsp_fchs)
4850{
4851	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4852	struct bfa_fcs_lport_s *port = ns->port;
4853	struct ct_hdr_s *cthdr = NULL;
4854
4855	bfa_trc(port->fcs, port->port_cfg.pwwn);
4856
4857	/*
4858	 * Sanity Checks
4859	 */
4860	if (req_status != BFA_STATUS_OK) {
4861		bfa_trc(port->fcs, req_status);
4862		port->stats.ns_rffid_rsp_err++;
4863		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4864		return;
4865	}
4866
4867	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4868	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4869
4870	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4871		port->stats.ns_rffid_accepts++;
4872		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4873		return;
4874	}
4875
4876	port->stats.ns_rffid_rejects++;
4877	bfa_trc(port->fcs, cthdr->reason_code);
4878	bfa_trc(port->fcs, cthdr->exp_code);
4879
4880	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
4881		/* if this command is not supported, we don't retry */
4882		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4883	} else
4884		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4885}
4886/*
4887 * Query Fabric for FC4-Types Devices.
4888 *
4889* TBD : Need to use a local (FCS private) response buffer, since the response
4890 * can be larger than 2K.
4891 */
4892static void
4893bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4894{
4895	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4896	struct bfa_fcs_lport_s *port = ns->port;
4897	struct fchs_s fchs;
4898	int             len;
4899	struct bfa_fcxp_s *fcxp;
4900
4901	bfa_trc(port->fcs, port->pid);
4902
4903	fcxp = fcxp_alloced ? fcxp_alloced :
4904	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4905	if (!fcxp) {
4906		port->stats.ns_gidft_alloc_wait++;
4907		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4908				bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
4909		return;
4910	}
4911	ns->fcxp = fcxp;
4912
4913	/*
4914	 * This query is only initiated for FCP initiator mode.
4915	 */
4916	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4917			      ns->port->pid, FC_TYPE_FCP);
4918
4919	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4920			  FC_CLASS_3, len, &fchs,
4921			  bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
4922			  bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
4923
4924	port->stats.ns_gidft_sent++;
4925
4926	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
4927}
4928
4929static void
4930bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4931				void *cbarg, bfa_status_t req_status,
4932				u32 rsp_len, u32 resid_len,
4933				struct fchs_s *rsp_fchs)
4934{
4935	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4936	struct bfa_fcs_lport_s *port = ns->port;
4937	struct ct_hdr_s *cthdr = NULL;
4938	u32        n_pids;
4939
4940	bfa_trc(port->fcs, port->port_cfg.pwwn);
4941
4942	/*
4943	 * Sanity Checks
4944	 */
4945	if (req_status != BFA_STATUS_OK) {
4946		bfa_trc(port->fcs, req_status);
4947		port->stats.ns_gidft_rsp_err++;
4948		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4949		return;
4950	}
4951
4952	if (resid_len != 0) {
4953		/*
4954		 * TBD : we will need to allocate a larger buffer & retry the
4955		 * command
4956		 */
4957		bfa_trc(port->fcs, rsp_len);
4958		bfa_trc(port->fcs, resid_len);
4959		return;
4960	}
4961
4962	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4963	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4964
4965	switch (cthdr->cmd_rsp_code) {
4966
4967	case CT_RSP_ACCEPT:
4968
4969		port->stats.ns_gidft_accepts++;
4970		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
4971		bfa_trc(port->fcs, n_pids);
4972		bfa_fcs_lport_ns_process_gidft_pids(port,
4973						   (u32 *) (cthdr + 1),
4974						   n_pids);
4975		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4976		break;
4977
4978	case CT_RSP_REJECT:
4979
4980		/*
4981		 * Check the reason code  & explanation.
4982		 * There may not have been any FC4 devices in the fabric
4983		 */
4984		port->stats.ns_gidft_rejects++;
4985		bfa_trc(port->fcs, cthdr->reason_code);
4986		bfa_trc(port->fcs, cthdr->exp_code);
4987
4988		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4989		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4990
4991			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4992		} else {
4993			/*
4994			 * for all other errors, retry
4995			 */
4996			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4997		}
4998		break;
4999
5000	default:
5001		port->stats.ns_gidft_unknown_rsp++;
5002		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
5003		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
5004	}
5005}
5006
5007/*
5008 *     This routine will be called by bfa_timer on timer timeouts.
5009 *
5010 *	param[in]	port - pointer to bfa_fcs_lport_t.
5011 *
5012 *	return
5013 *		void
5014 *
5015 *	Special Considerations:
5016 *
5017 *	note
5018 */
5019static void
5020bfa_fcs_lport_ns_timeout(void *arg)
5021{
5022	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
5023
5024	ns->port->stats.ns_timeouts++;
5025	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
5026}
5027
5028/*
5029 * Process the PID list in GID_FT response
5030 */
5031static void
5032bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
5033				   u32 n_pids)
5034{
5035	struct fcgs_gidft_resp_s *gidft_entry;
5036	struct bfa_fcs_rport_s *rport;
5037	u32        ii;
5038	struct bfa_fcs_fabric_s *fabric = port->fabric;
5039	struct bfa_fcs_vport_s *vport;
5040	struct list_head *qe;
5041	u8 found = 0;
5042
5043	for (ii = 0; ii < n_pids; ii++) {
5044		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
5045
5046		if (gidft_entry->pid == port->pid)
5047			continue;
5048
5049		/*
5050		 * Ignore PID if it is of base port
5051		 * (Avoid vports discovering base port as remote port)
5052		 */
5053		if (gidft_entry->pid == fabric->bport.pid)
5054			continue;
5055
5056		/*
5057		 * Ignore PID if it is of vport created on the same base port
5058		 * (Avoid vport discovering every other vport created on the
5059		 * same port as remote port)
5060		 */
5061		list_for_each(qe, &fabric->vport_q) {
5062			vport = (struct bfa_fcs_vport_s *) qe;
5063			if (vport->lport.pid == gidft_entry->pid)
5064				found = 1;
5065		}
5066
5067		if (found) {
5068			found = 0;
5069			continue;
5070		}
5071
5072		/*
5073		 * Check if this rport already exists
5074		 */
5075		rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
5076		if (rport == NULL) {
5077			/*
5078			 * this is a new device. create rport
5079			 */
5080			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
5081		} else {
5082			/*
5083			 * this rport already exists
5084			 */
5085			bfa_fcs_rport_scn(rport);
5086		}
5087
5088		bfa_trc(port->fcs, gidft_entry->pid);
5089
5090		/*
5091		 * if the last entry bit is set, bail out.
5092		 */
5093		if (gidft_entry->last)
5094			return;
5095	}
5096}
5097
5098/*
5099 *  fcs_ns_public FCS nameserver public interfaces
5100 */
5101
5102/*
5103 * Functions called by port/fab.
5104 * These will send relevant Events to the ns state machine.
5105 */
5106void
5107bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
5108{
5109	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5110
5111	ns->port = port;
5112	bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
5113}
5114
5115void
5116bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
5117{
5118	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5119
5120	ns->port = port;
5121	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
5122}
5123
5124void
5125bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
5126{
5127	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5128
5129	ns->port = port;
5130	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
5131}
5132
5133void
5134bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
5135{
5136	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5137
5138	bfa_trc(port->fcs, port->pid);
5139	if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online))
5140		bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
5141}
5142
5143static void
5144bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
5145{
5146
5147	struct bfa_fcs_rport_s *rport;
5148	u8 nwwns;
5149	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
5150	int ii;
5151
5152	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
5153
5154	for (ii = 0 ; ii < nwwns; ++ii) {
5155		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
5156		WARN_ON(!rport);
5157	}
5158}
5159
5160void
5161bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
5162{
5163	struct bfa_fcs_lport_ns_s *ns = cbarg;
5164	struct bfa_fcs_lport_s *port = ns->port;
5165	struct fchs_s fchs;
5166	struct bfa_fcxp_s *fcxp;
5167	u8 symbl[256];
5168	int len;
5169
5170	/* Avoid sending RSPN in the following states. */
5171	if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
5172	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
5173	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) ||
5174	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) ||
5175	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry))
5176		return;
5177
5178	memset(symbl, 0, sizeof(symbl));
5179	bfa_trc(port->fcs, port->port_cfg.pwwn);
5180
5181	fcxp = fcxp_alloced ? fcxp_alloced :
5182	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
5183	if (!fcxp) {
5184		port->stats.ns_rspnid_alloc_wait++;
5185		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
5186			bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
5187		return;
5188	}
5189
5190	ns->fcxp = fcxp;
5191
5192	if (port->vport) {
5193		/*
5194		 * For Vports, we append the vport's port symbolic name
5195		 * to that of the base port.
5196		 */
5197		strscpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name
5198			(bfa_fcs_get_base_port(port->fcs))),
5199			sizeof(symbl));
5200
5201		strlcat(symbl,
5202			(char *)&(bfa_fcs_lport_get_psym_name(port)),
5203			sizeof(symbl));
5204	}
5205
5206	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5207			      bfa_fcs_lport_get_fcid(port), 0, symbl);
5208
5209	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
5210		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
5211
5212	port->stats.ns_rspnid_sent++;
5213}
5214
5215/*
5216 * FCS SCN
5217 */
5218
5219#define FC_QOS_RSCN_EVENT		0x0c
5220#define FC_FABRIC_NAME_RSCN_EVENT	0x0d
5221
5222/*
5223 * forward declarations
5224 */
5225static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
5226					  struct bfa_fcxp_s *fcxp_alloced);
5227static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
5228					      struct bfa_fcxp_s *fcxp,
5229					      void *cbarg,
5230					      bfa_status_t req_status,
5231					      u32 rsp_len,
5232					      u32 resid_len,
5233					      struct fchs_s *rsp_fchs);
5234static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
5235					     struct fchs_s *rx_fchs);
5236static void     bfa_fcs_lport_scn_timeout(void *arg);
5237
5238/*
5239 *  fcs_scm_sm FCS SCN state machine
5240 */
5241
5242/*
5243 * VPort SCN State Machine events
5244 */
5245enum port_scn_event {
5246	SCNSM_EVENT_PORT_ONLINE = 1,
5247	SCNSM_EVENT_PORT_OFFLINE = 2,
5248	SCNSM_EVENT_RSP_OK = 3,
5249	SCNSM_EVENT_RSP_ERROR = 4,
5250	SCNSM_EVENT_TIMEOUT = 5,
5251	SCNSM_EVENT_SCR_SENT = 6,
5252};
5253
5254static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
5255					    enum port_scn_event event);
5256static void     bfa_fcs_lport_scn_sm_sending_scr(
5257					struct bfa_fcs_lport_scn_s *scn,
5258					enum port_scn_event event);
5259static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
5260					enum port_scn_event event);
5261static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
5262					      enum port_scn_event event);
5263static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
5264					   enum port_scn_event event);
5265
5266/*
5267 *	Starting state - awaiting link up.
5268 */
5269static void
5270bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
5271			enum port_scn_event event)
5272{
5273	switch (event) {
5274	case SCNSM_EVENT_PORT_ONLINE:
5275		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
5276		bfa_fcs_lport_scn_send_scr(scn, NULL);
5277		break;
5278
5279	case SCNSM_EVENT_PORT_OFFLINE:
5280		break;
5281
5282	default:
5283		bfa_sm_fault(scn->port->fcs, event);
5284	}
5285}
5286
5287static void
5288bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
5289				enum port_scn_event event)
5290{
5291	switch (event) {
5292	case SCNSM_EVENT_SCR_SENT:
5293		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
5294		break;
5295
5296	case SCNSM_EVENT_PORT_OFFLINE:
5297		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5298		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
5299		break;
5300
5301	default:
5302		bfa_sm_fault(scn->port->fcs, event);
5303	}
5304}
5305
5306static void
5307bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
5308			enum port_scn_event event)
5309{
5310	struct bfa_fcs_lport_s *port = scn->port;
5311
5312	switch (event) {
5313	case SCNSM_EVENT_RSP_OK:
5314		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
5315		break;
5316
5317	case SCNSM_EVENT_RSP_ERROR:
5318		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
5319		bfa_timer_start(port->fcs->bfa, &scn->timer,
5320				    bfa_fcs_lport_scn_timeout, scn,
5321				    BFA_FCS_RETRY_TIMEOUT);
5322		break;
5323
5324	case SCNSM_EVENT_PORT_OFFLINE:
5325		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5326		bfa_fcxp_discard(scn->fcxp);
5327		break;
5328
5329	default:
5330		bfa_sm_fault(port->fcs, event);
5331	}
5332}
5333
5334static void
5335bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
5336				enum port_scn_event event)
5337{
5338	switch (event) {
5339	case SCNSM_EVENT_TIMEOUT:
5340		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
5341		bfa_fcs_lport_scn_send_scr(scn, NULL);
5342		break;
5343
5344	case SCNSM_EVENT_PORT_OFFLINE:
5345		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5346		bfa_timer_stop(&scn->timer);
5347		break;
5348
5349	default:
5350		bfa_sm_fault(scn->port->fcs, event);
5351	}
5352}
5353
5354static void
5355bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
5356			enum port_scn_event event)
5357{
5358	switch (event) {
5359	case SCNSM_EVENT_PORT_OFFLINE:
5360		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5361		break;
5362
5363	default:
5364		bfa_sm_fault(scn->port->fcs, event);
5365	}
5366}
5367
5368
5369
5370/*
5371 *  fcs_scn_private FCS SCN private functions
5372 */
5373
5374/*
5375 * This routine will be called to send a SCR command.
5376 */
5377static void
5378bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
5379{
5380	struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
5381	struct bfa_fcs_lport_s *port = scn->port;
5382	struct fchs_s fchs;
5383	int             len;
5384	struct bfa_fcxp_s *fcxp;
5385
5386	bfa_trc(port->fcs, port->pid);
5387	bfa_trc(port->fcs, port->port_cfg.pwwn);
5388
5389	fcxp = fcxp_alloced ? fcxp_alloced :
5390	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
5391	if (!fcxp) {
5392		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
5393				bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
5394		return;
5395	}
5396	scn->fcxp = fcxp;
5397
5398	/* Handle VU registrations for Base port only */
5399	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
5400		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5401				port->fabric->lps->brcd_switch,
5402				port->pid, 0);
5403	} else {
5404	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5405				    BFA_FALSE,
5406				    port->pid, 0);
5407	}
5408
5409	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
5410			  FC_CLASS_3, len, &fchs,
5411			  bfa_fcs_lport_scn_scr_response,
5412			  (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
5413
5414	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
5415}
5416
5417static void
5418bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
5419			void *cbarg, bfa_status_t req_status, u32 rsp_len,
5420			      u32 resid_len, struct fchs_s *rsp_fchs)
5421{
5422	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
5423	struct bfa_fcs_lport_s *port = scn->port;
5424	struct fc_els_cmd_s *els_cmd;
5425	struct fc_ls_rjt_s *ls_rjt;
5426
5427	bfa_trc(port->fcs, port->port_cfg.pwwn);
5428
5429	/*
5430	 * Sanity Checks
5431	 */
5432	if (req_status != BFA_STATUS_OK) {
5433		bfa_trc(port->fcs, req_status);
5434		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5435		return;
5436	}
5437
5438	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
5439
5440	switch (els_cmd->els_code) {
5441
5442	case FC_ELS_ACC:
5443		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
5444		break;
5445
5446	case FC_ELS_LS_RJT:
5447
5448		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
5449
5450		bfa_trc(port->fcs, ls_rjt->reason_code);
5451		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
5452
5453		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5454		break;
5455
5456	default:
5457		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5458	}
5459}
5460
5461/*
5462 * Send a LS Accept
5463 */
5464static void
5465bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
5466				struct fchs_s *rx_fchs)
5467{
5468	struct fchs_s fchs;
5469	struct bfa_fcxp_s *fcxp;
5470	struct bfa_rport_s *bfa_rport = NULL;
5471	int             len;
5472
5473	bfa_trc(port->fcs, rx_fchs->s_id);
5474
5475	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
5476	if (!fcxp)
5477		return;
5478
5479	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5480			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
5481			      rx_fchs->ox_id);
5482
5483	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
5484			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
5485			  FC_MAX_PDUSZ, 0);
5486}
5487
5488/*
5489 *     This routine will be called by bfa_timer on timer timeouts.
5490 *
5491 *	param[in]	vport		- pointer to bfa_fcs_lport_t.
5492 *	param[out]	vport_status	- pointer to return vport status in
5493 *
5494 *	return
5495 *		void
5496 *
5497 *	Special Considerations:
5498 *
5499 *	note
5500 */
5501static void
5502bfa_fcs_lport_scn_timeout(void *arg)
5503{
5504	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
5505
5506	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
5507}
5508
5509
5510
5511/*
5512 *  fcs_scn_public FCS state change notification public interfaces
5513 */
5514
5515/*
5516 * Functions called by port/fab
5517 */
5518void
5519bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
5520{
5521	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5522
5523	scn->port = port;
5524	bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5525}
5526
5527void
5528bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
5529{
5530	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5531
5532	scn->port = port;
5533	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
5534}
5535
5536void
5537bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)
5538{
5539	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5540
5541	scn->port = port;
5542	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
5543}
5544
5545static void
5546bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
5547{
5548	struct bfa_fcs_rport_s *rport;
5549	struct bfa_fcs_fabric_s *fabric = port->fabric;
5550	struct bfa_fcs_vport_s *vport;
5551	struct list_head *qe;
5552
5553	bfa_trc(port->fcs, rpid);
5554
5555	/*
5556	 * Ignore PID if it is of base port or of vports created on the
5557	 * same base port. It is to avoid vports discovering base port or
5558	 * other vports created on same base port as remote port
5559	 */
5560	if (rpid == fabric->bport.pid)
5561		return;
5562
5563	list_for_each(qe, &fabric->vport_q) {
5564		vport = (struct bfa_fcs_vport_s *) qe;
5565		if (vport->lport.pid == rpid)
5566			return;
5567	}
5568	/*
5569	 * If this is an unknown device, then it just came online.
5570	 * Otherwise let rport handle the RSCN event.
5571	 */
5572	rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
5573	if (!rport)
5574		rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
5575
5576	if (rport == NULL) {
5577		/*
5578		 * If min cfg mode is enabled, we donot need to
5579		 * discover any new rports.
5580		 */
5581		if (!__fcs_min_cfg(port->fcs))
5582			rport = bfa_fcs_rport_create(port, rpid);
5583	} else
5584		bfa_fcs_rport_scn(rport);
5585}
5586
5587/*
5588 * rscn format based PID comparison
5589 */
5590#define __fc_pid_match(__c0, __c1, __fmt)		\
5591	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
5592	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
5593	  ((__c0)[0] == (__c1)[0])) ||				\
5594	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
5595	  ((__c0)[0] == (__c1)[0]) &&				\
5596	  ((__c0)[1] == (__c1)[1])))
5597
5598static void
5599bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
5600				enum fc_rscn_format format,
5601				u32 rscn_pid)
5602{
5603	struct bfa_fcs_rport_s *rport;
5604	struct list_head        *qe, *qe_next;
5605	u8        *c0, *c1;
5606
5607	bfa_trc(port->fcs, format);
5608	bfa_trc(port->fcs, rscn_pid);
5609
5610	c0 = (u8 *) &rscn_pid;
5611
5612	list_for_each_safe(qe, qe_next, &port->rport_q) {
5613		rport = (struct bfa_fcs_rport_s *) qe;
5614		c1 = (u8 *) &rport->pid;
5615		if (__fc_pid_match(c0, c1, format))
5616			bfa_fcs_rport_scn(rport);
5617	}
5618}
5619
5620
5621void
5622bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
5623			struct fchs_s *fchs, u32 len)
5624{
5625	struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
5626	int             num_entries;
5627	u32        rscn_pid;
5628	bfa_boolean_t   nsquery = BFA_FALSE, found;
5629	int             i = 0, j;
5630
5631	num_entries =
5632		(be16_to_cpu(rscn->payldlen) -
5633		 sizeof(u32)) / sizeof(rscn->event[0]);
5634
5635	bfa_trc(port->fcs, num_entries);
5636
5637	port->stats.num_rscn++;
5638
5639	bfa_fcs_lport_scn_send_ls_acc(port, fchs);
5640
5641	for (i = 0; i < num_entries; i++) {
5642		rscn_pid = rscn->event[i].portid;
5643
5644		bfa_trc(port->fcs, rscn->event[i].format);
5645		bfa_trc(port->fcs, rscn_pid);
5646
5647		/* check for duplicate entries in the list */
5648		found = BFA_FALSE;
5649		for (j = 0; j < i; j++) {
5650			if (rscn->event[j].portid == rscn_pid) {
5651				found = BFA_TRUE;
5652				break;
5653			}
5654		}
5655
5656		/* if found in down the list, pid has been already processed */
5657		if (found) {
5658			bfa_trc(port->fcs, rscn_pid);
5659			continue;
5660		}
5661
5662		switch (rscn->event[i].format) {
5663		case FC_RSCN_FORMAT_PORTID:
5664			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
5665				/*
5666				 * Ignore this event.
5667				 * f/w would have processed it
5668				 */
5669				bfa_trc(port->fcs, rscn_pid);
5670			} else {
5671				port->stats.num_portid_rscn++;
5672				bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
5673			}
5674		break;
5675
5676		case FC_RSCN_FORMAT_FABRIC:
5677			if (rscn->event[i].qualifier ==
5678					FC_FABRIC_NAME_RSCN_EVENT) {
5679				bfa_fcs_lport_ms_fabric_rscn(port);
5680				break;
5681			}
5682			fallthrough;
5683
5684		case FC_RSCN_FORMAT_AREA:
5685		case FC_RSCN_FORMAT_DOMAIN:
5686			nsquery = BFA_TRUE;
5687			bfa_fcs_lport_scn_multiport_rscn(port,
5688							rscn->event[i].format,
5689							rscn_pid);
5690			break;
5691
5692
5693		default:
5694			WARN_ON(1);
5695			nsquery = BFA_TRUE;
5696		}
5697	}
5698
5699	/*
5700	 * If any of area, domain or fabric RSCN is received, do a fresh
5701	 * discovery to find new devices.
5702	 */
5703	if (nsquery)
5704		bfa_fcs_lport_ns_query(port);
5705}
5706
5707/*
5708 * BFA FCS port
5709 */
5710/*
5711 *  fcs_port_api BFA FCS port API
5712 */
5713struct bfa_fcs_lport_s *
5714bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
5715{
5716	return &fcs->fabric.bport;
5717}
5718
5719wwn_t
5720bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
5721		int nrports, bfa_boolean_t bwwn)
5722{
5723	struct list_head	*qh, *qe;
5724	struct bfa_fcs_rport_s *rport = NULL;
5725	int	i;
5726	struct bfa_fcs_s	*fcs;
5727
5728	if (port == NULL || nrports == 0)
5729		return (wwn_t) 0;
5730
5731	fcs = port->fcs;
5732	bfa_trc(fcs, (u32) nrports);
5733
5734	i = 0;
5735	qh = &port->rport_q;
5736	qe = bfa_q_first(qh);
5737
5738	while ((qe != qh) && (i < nrports)) {
5739		rport = (struct bfa_fcs_rport_s *) qe;
5740		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5741			qe = bfa_q_next(qe);
5742			bfa_trc(fcs, (u32) rport->pwwn);
5743			bfa_trc(fcs, rport->pid);
5744			bfa_trc(fcs, i);
5745			continue;
5746		}
5747
5748		if (bwwn) {
5749			if (!memcmp(&wwn, &rport->pwwn, 8))
5750				break;
5751		} else {
5752			if (i == index)
5753				break;
5754		}
5755
5756		i++;
5757		qe = bfa_q_next(qe);
5758	}
5759
5760	bfa_trc(fcs, i);
5761	if (rport)
5762		return rport->pwwn;
5763	else
5764		return (wwn_t) 0;
5765}
5766
5767void
5768bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
5769		struct bfa_rport_qualifier_s rports[], int *nrports)
5770{
5771	struct list_head	*qh, *qe;
5772	struct bfa_fcs_rport_s *rport = NULL;
5773	int	i;
5774	struct bfa_fcs_s	*fcs;
5775
5776	if (port == NULL || rports == NULL || *nrports == 0)
5777		return;
5778
5779	fcs = port->fcs;
5780	bfa_trc(fcs, (u32) *nrports);
5781
5782	i = 0;
5783	qh = &port->rport_q;
5784	qe = bfa_q_first(qh);
5785
5786	while ((qe != qh) && (i < *nrports)) {
5787		rport = (struct bfa_fcs_rport_s *) qe;
5788		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5789			qe = bfa_q_next(qe);
5790			bfa_trc(fcs, (u32) rport->pwwn);
5791			bfa_trc(fcs, rport->pid);
5792			bfa_trc(fcs, i);
5793			continue;
5794		}
5795
5796		if (!rport->pwwn && !rport->pid) {
5797			qe = bfa_q_next(qe);
5798			continue;
5799		}
5800
5801		rports[i].pwwn = rport->pwwn;
5802		rports[i].pid = rport->pid;
5803
5804		i++;
5805		qe = bfa_q_next(qe);
5806	}
5807
5808	bfa_trc(fcs, i);
5809	*nrports = i;
5810}
5811
5812/*
5813 * Iterate's through all the rport's in the given port to
5814 * determine the maximum operating speed.
5815 *
5816 * !!!! To be used in TRL Functionality only !!!!
5817 */
5818bfa_port_speed_t
5819bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
5820{
5821	struct list_head *qh, *qe;
5822	struct bfa_fcs_rport_s *rport = NULL;
5823	struct bfa_fcs_s	*fcs;
5824	bfa_port_speed_t max_speed = 0;
5825	struct bfa_port_attr_s port_attr;
5826	bfa_port_speed_t port_speed, rport_speed;
5827	bfa_boolean_t trl_enabled;
5828
5829	if (port == NULL)
5830		return 0;
5831
5832	fcs = port->fcs;
5833	trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
5834
5835	/* Get Physical port's current speed */
5836	bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
5837	port_speed = port_attr.speed;
5838	bfa_trc(fcs, port_speed);
5839
5840	qh = &port->rport_q;
5841	qe = bfa_q_first(qh);
5842
5843	while (qe != qh) {
5844		rport = (struct bfa_fcs_rport_s *) qe;
5845		if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
5846			(bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
5847			(rport->scsi_function != BFA_RPORT_TARGET)) {
5848			qe = bfa_q_next(qe);
5849			continue;
5850		}
5851
5852		rport_speed = rport->rpf.rpsc_speed;
5853		if ((trl_enabled) && (rport_speed ==
5854			BFA_PORT_SPEED_UNKNOWN)) {
5855			/* Use default ratelim speed setting */
5856			rport_speed =
5857				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
5858		}
5859
5860		if (rport_speed > max_speed)
5861			max_speed = rport_speed;
5862
5863		qe = bfa_q_next(qe);
5864	}
5865
5866	if (max_speed > port_speed)
5867		max_speed = port_speed;
5868
5869	bfa_trc(fcs, max_speed);
5870	return max_speed;
5871}
5872
5873struct bfa_fcs_lport_s *
5874bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
5875{
5876	struct bfa_fcs_vport_s *vport;
5877	bfa_fcs_vf_t   *vf;
5878
5879	WARN_ON(fcs == NULL);
5880
5881	vf = bfa_fcs_vf_lookup(fcs, vf_id);
5882	if (vf == NULL) {
5883		bfa_trc(fcs, vf_id);
5884		return NULL;
5885	}
5886
5887	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
5888		return &vf->bport;
5889
5890	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
5891	if (vport)
5892		return &vport->lport;
5893
5894	return NULL;
5895}
5896
5897/*
5898 *  API corresponding to NPIV_VPORT_GETINFO.
5899 */
5900void
5901bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
5902	 struct bfa_lport_info_s *port_info)
5903{
5904
5905	bfa_trc(port->fcs, port->fabric->fabric_name);
5906
5907	if (port->vport == NULL) {
5908		/*
5909		 * This is a Physical port
5910		 */
5911		port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
5912
5913		/*
5914		 * @todo : need to fix the state & reason
5915		 */
5916		port_info->port_state = 0;
5917		port_info->offline_reason = 0;
5918
5919		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5920		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5921
5922		port_info->max_vports_supp =
5923			bfa_lps_get_max_vport(port->fcs->bfa);
5924		port_info->num_vports_inuse =
5925			port->fabric->num_vports;
5926		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
5927		port_info->num_rports_inuse = port->num_rports;
5928	} else {
5929		/*
5930		 * This is a virtual port
5931		 */
5932		port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
5933
5934		/*
5935		 * @todo : need to fix the state & reason
5936		 */
5937		port_info->port_state = 0;
5938		port_info->offline_reason = 0;
5939
5940		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5941		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5942	}
5943}
5944
5945void
5946bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
5947	 struct bfa_lport_stats_s *port_stats)
5948{
5949	*port_stats = fcs_port->stats;
5950}
5951
5952void
5953bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
5954{
5955	memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
5956}
5957
5958/*
5959 * Let new loop map create missing rports
5960 */
5961void
5962bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port)
5963{
5964	bfa_fcs_lport_loop_online(port);
5965}
5966
5967/*
5968 * FCS virtual port state machine
5969 */
5970
5971#define __vport_fcs(__vp)       ((__vp)->lport.fcs)
5972#define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
5973#define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
5974#define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
5975#define __vport_fcid(__vp)      ((__vp)->lport.pid)
5976#define __vport_fabric(__vp)    ((__vp)->lport.fabric)
5977#define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
5978
5979#define BFA_FCS_VPORT_MAX_RETRIES  5
5980/*
5981 * Forward declarations
5982 */
5983static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
5984static void     bfa_fcs_vport_timeout(void *vport_arg);
5985static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
5986static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
5987
5988/*
5989 *  fcs_vport_sm FCS virtual port state machine
5990 */
5991
5992/*
5993 * VPort State Machine events
5994 */
5995enum bfa_fcs_vport_event {
5996	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
5997	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
5998	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
5999	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
6000	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
6001	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
6002	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
6003	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
6004	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
6005	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
6006	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
6007	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
6008	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
6009	BFA_FCS_VPORT_SM_STOPCOMP = 14,	/* vport delete completion */
6010	BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */
6011};
6012
6013static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
6014					enum bfa_fcs_vport_event event);
6015static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
6016					 enum bfa_fcs_vport_event event);
6017static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
6018					 enum bfa_fcs_vport_event event);
6019static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
6020				       enum bfa_fcs_vport_event event);
6021static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
6022					     enum bfa_fcs_vport_event event);
6023static void	bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
6024					enum bfa_fcs_vport_event event);
6025static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
6026					enum bfa_fcs_vport_event event);
6027static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
6028					  enum bfa_fcs_vport_event event);
6029static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
6030					 enum bfa_fcs_vport_event event);
6031static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
6032				      enum bfa_fcs_vport_event event);
6033static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
6034				      enum bfa_fcs_vport_event event);
6035static void	bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
6036					enum bfa_fcs_vport_event event);
6037static void	bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
6038					enum bfa_fcs_vport_event event);
6039
6040static struct bfa_sm_table_s  vport_sm_table[] = {
6041	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
6042	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
6043	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
6044	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
6045	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
6046	{BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
6047	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
6048	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
6049	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
6050	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
6051	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
6052};
6053
6054/*
6055 * Beginning state.
6056 */
6057static void
6058bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
6059			enum bfa_fcs_vport_event event)
6060{
6061	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6062	bfa_trc(__vport_fcs(vport), event);
6063
6064	switch (event) {
6065	case BFA_FCS_VPORT_SM_CREATE:
6066		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6067		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
6068		break;
6069
6070	default:
6071		bfa_sm_fault(__vport_fcs(vport), event);
6072	}
6073}
6074
6075/*
6076 * Created state - a start event is required to start up the state machine.
6077 */
6078static void
6079bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
6080			enum bfa_fcs_vport_event event)
6081{
6082	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6083	bfa_trc(__vport_fcs(vport), event);
6084
6085	switch (event) {
6086	case BFA_FCS_VPORT_SM_START:
6087		if (bfa_sm_cmp_state(__vport_fabric(vport),
6088					bfa_fcs_fabric_sm_online)
6089		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
6090			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6091			bfa_fcs_vport_do_fdisc(vport);
6092		} else {
6093			/*
6094			 * Fabric is offline or not NPIV capable, stay in
6095			 * offline state.
6096			 */
6097			vport->vport_stats.fab_no_npiv++;
6098			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6099		}
6100		break;
6101
6102	case BFA_FCS_VPORT_SM_DELETE:
6103		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6104		bfa_fcs_lport_delete(&vport->lport);
6105		break;
6106
6107	case BFA_FCS_VPORT_SM_ONLINE:
6108	case BFA_FCS_VPORT_SM_OFFLINE:
6109		/*
6110		 * Ignore ONLINE/OFFLINE events from fabric
6111		 * till vport is started.
6112		 */
6113		break;
6114
6115	default:
6116		bfa_sm_fault(__vport_fcs(vport), event);
6117	}
6118}
6119
6120/*
6121 * Offline state - awaiting ONLINE event from fabric SM.
6122 */
6123static void
6124bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
6125			enum bfa_fcs_vport_event event)
6126{
6127	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6128	bfa_trc(__vport_fcs(vport), event);
6129
6130	switch (event) {
6131	case BFA_FCS_VPORT_SM_DELETE:
6132		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6133		bfa_fcs_lport_delete(&vport->lport);
6134		break;
6135
6136	case BFA_FCS_VPORT_SM_ONLINE:
6137		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6138		vport->fdisc_retries = 0;
6139		bfa_fcs_vport_do_fdisc(vport);
6140		break;
6141
6142	case BFA_FCS_VPORT_SM_STOP:
6143		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6144		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
6145		break;
6146
6147	case BFA_FCS_VPORT_SM_OFFLINE:
6148		/*
6149		 * This can happen if the vport couldn't be initialzied
6150		 * due the fact that the npiv was not enabled on the switch.
6151		 * In that case we will put the vport in offline state.
6152		 * However, the link can go down and cause the this event to
6153		 * be sent when we are already offline. Ignore it.
6154		 */
6155		break;
6156
6157	default:
6158		bfa_sm_fault(__vport_fcs(vport), event);
6159	}
6160}
6161
6162
6163/*
6164 * FDISC is sent and awaiting reply from fabric.
6165 */
6166static void
6167bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
6168			enum bfa_fcs_vport_event event)
6169{
6170	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6171	bfa_trc(__vport_fcs(vport), event);
6172
6173	switch (event) {
6174	case BFA_FCS_VPORT_SM_DELETE:
6175		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
6176		break;
6177
6178	case BFA_FCS_VPORT_SM_OFFLINE:
6179		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6180		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6181		break;
6182
6183	case BFA_FCS_VPORT_SM_RSP_OK:
6184		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
6185		bfa_fcs_lport_online(&vport->lport);
6186		break;
6187
6188	case BFA_FCS_VPORT_SM_RSP_ERROR:
6189		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
6190		bfa_timer_start(__vport_bfa(vport), &vport->timer,
6191				    bfa_fcs_vport_timeout, vport,
6192				    BFA_FCS_RETRY_TIMEOUT);
6193		break;
6194
6195	case BFA_FCS_VPORT_SM_RSP_FAILED:
6196	case BFA_FCS_VPORT_SM_FABRIC_MAX:
6197		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6198		break;
6199
6200	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
6201		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
6202		break;
6203
6204	default:
6205		bfa_sm_fault(__vport_fcs(vport), event);
6206	}
6207}
6208
6209/*
6210 * FDISC attempt failed - a timer is active to retry FDISC.
6211 */
6212static void
6213bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
6214			     enum bfa_fcs_vport_event event)
6215{
6216	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6217	bfa_trc(__vport_fcs(vport), event);
6218
6219	switch (event) {
6220	case BFA_FCS_VPORT_SM_DELETE:
6221		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6222		bfa_timer_stop(&vport->timer);
6223		bfa_fcs_lport_delete(&vport->lport);
6224		break;
6225
6226	case BFA_FCS_VPORT_SM_OFFLINE:
6227		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6228		bfa_timer_stop(&vport->timer);
6229		break;
6230
6231	case BFA_FCS_VPORT_SM_TIMEOUT:
6232		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6233		vport->vport_stats.fdisc_retries++;
6234		vport->fdisc_retries++;
6235		bfa_fcs_vport_do_fdisc(vport);
6236		break;
6237
6238	default:
6239		bfa_sm_fault(__vport_fcs(vport), event);
6240	}
6241}
6242
6243/*
6244 * FDISC is in progress and we got a vport delete request -
6245 * this is a wait state while we wait for fdisc response and
6246 * we will transition to the appropriate state - on rsp status.
6247 */
6248static void
6249bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
6250				enum bfa_fcs_vport_event event)
6251{
6252	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6253	bfa_trc(__vport_fcs(vport), event);
6254
6255	switch (event) {
6256	case BFA_FCS_VPORT_SM_RSP_OK:
6257		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
6258		bfa_fcs_lport_delete(&vport->lport);
6259		break;
6260
6261	case BFA_FCS_VPORT_SM_DELETE:
6262		break;
6263
6264	case BFA_FCS_VPORT_SM_OFFLINE:
6265	case BFA_FCS_VPORT_SM_RSP_ERROR:
6266	case BFA_FCS_VPORT_SM_RSP_FAILED:
6267	case BFA_FCS_VPORT_SM_FABRIC_MAX:
6268	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
6269		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6270		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6271		bfa_fcs_lport_delete(&vport->lport);
6272		break;
6273
6274	default:
6275		bfa_sm_fault(__vport_fcs(vport), event);
6276	}
6277}
6278
6279/*
6280 * Vport is online (FDISC is complete).
6281 */
6282static void
6283bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
6284			enum bfa_fcs_vport_event event)
6285{
6286	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6287	bfa_trc(__vport_fcs(vport), event);
6288
6289	switch (event) {
6290	case BFA_FCS_VPORT_SM_DELETE:
6291		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
6292		bfa_fcs_lport_delete(&vport->lport);
6293		break;
6294
6295	case BFA_FCS_VPORT_SM_STOP:
6296		bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
6297		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
6298		break;
6299
6300	case BFA_FCS_VPORT_SM_OFFLINE:
6301		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6302		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6303		bfa_fcs_lport_offline(&vport->lport);
6304		break;
6305
6306	default:
6307		bfa_sm_fault(__vport_fcs(vport), event);
6308	}
6309}
6310
6311/*
6312 * Vport is being stopped - awaiting lport stop completion to send
6313 * LOGO to fabric.
6314 */
6315static void
6316bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
6317			  enum bfa_fcs_vport_event event)
6318{
6319	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6320	bfa_trc(__vport_fcs(vport), event);
6321
6322	switch (event) {
6323	case BFA_FCS_VPORT_SM_STOPCOMP:
6324		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
6325		bfa_fcs_vport_do_logo(vport);
6326		break;
6327
6328	case BFA_FCS_VPORT_SM_OFFLINE:
6329		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6330		break;
6331
6332	default:
6333		bfa_sm_fault(__vport_fcs(vport), event);
6334	}
6335}
6336
6337/*
6338 * Vport is being deleted - awaiting lport delete completion to send
6339 * LOGO to fabric.
6340 */
6341static void
6342bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
6343			enum bfa_fcs_vport_event event)
6344{
6345	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6346	bfa_trc(__vport_fcs(vport), event);
6347
6348	switch (event) {
6349	case BFA_FCS_VPORT_SM_DELETE:
6350		break;
6351
6352	case BFA_FCS_VPORT_SM_DELCOMP:
6353		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
6354		bfa_fcs_vport_do_logo(vport);
6355		break;
6356
6357	case BFA_FCS_VPORT_SM_OFFLINE:
6358		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6359		break;
6360
6361	default:
6362		bfa_sm_fault(__vport_fcs(vport), event);
6363	}
6364}
6365
6366/*
6367 * Error State.
6368 * This state will be set when the Vport Creation fails due
6369 * to errors like Dup WWN. In this state only operation allowed
6370 * is a Vport Delete.
6371 */
6372static void
6373bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
6374			enum bfa_fcs_vport_event event)
6375{
6376	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6377	bfa_trc(__vport_fcs(vport), event);
6378
6379	switch (event) {
6380	case BFA_FCS_VPORT_SM_DELETE:
6381		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6382		bfa_fcs_lport_delete(&vport->lport);
6383		break;
6384
6385	default:
6386		bfa_trc(__vport_fcs(vport), event);
6387	}
6388}
6389
6390/*
6391 * Lport cleanup is in progress since vport is being deleted. Fabric is
6392 * offline, so no LOGO is needed to complete vport deletion.
6393 */
6394static void
6395bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
6396			enum bfa_fcs_vport_event event)
6397{
6398	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6399	bfa_trc(__vport_fcs(vport), event);
6400
6401	switch (event) {
6402	case BFA_FCS_VPORT_SM_DELCOMP:
6403		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6404		bfa_fcs_vport_free(vport);
6405		break;
6406
6407	case BFA_FCS_VPORT_SM_STOPCOMP:
6408		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6409		break;
6410
6411	case BFA_FCS_VPORT_SM_DELETE:
6412		break;
6413
6414	default:
6415		bfa_sm_fault(__vport_fcs(vport), event);
6416	}
6417}
6418
6419/*
6420 * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
6421 * is done.
6422 */
6423static void
6424bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
6425			       enum bfa_fcs_vport_event event)
6426{
6427	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6428	bfa_trc(__vport_fcs(vport), event);
6429
6430	switch (event) {
6431	case BFA_FCS_VPORT_SM_OFFLINE:
6432		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6433		fallthrough;
6434
6435	case BFA_FCS_VPORT_SM_RSP_OK:
6436	case BFA_FCS_VPORT_SM_RSP_ERROR:
6437		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6438		break;
6439
6440	default:
6441		bfa_sm_fault(__vport_fcs(vport), event);
6442	}
6443}
6444
6445/*
6446 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
6447 * is done.
6448 */
6449static void
6450bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
6451			enum bfa_fcs_vport_event event)
6452{
6453	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6454	bfa_trc(__vport_fcs(vport), event);
6455
6456	switch (event) {
6457	case BFA_FCS_VPORT_SM_OFFLINE:
6458		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6459		fallthrough;
6460
6461	case BFA_FCS_VPORT_SM_RSP_OK:
6462	case BFA_FCS_VPORT_SM_RSP_ERROR:
6463		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6464		bfa_fcs_vport_free(vport);
6465		break;
6466
6467	case BFA_FCS_VPORT_SM_DELETE:
6468		break;
6469
6470	default:
6471		bfa_sm_fault(__vport_fcs(vport), event);
6472	}
6473}
6474
6475
6476
6477/*
6478 *  fcs_vport_private FCS virtual port private functions
6479 */
6480/*
6481 * Send AEN notification
6482 */
6483static void
6484bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port,
6485		       enum bfa_lport_aen_event event)
6486{
6487	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
6488	struct bfa_aen_entry_s  *aen_entry;
6489
6490	bfad_get_aen_entry(bfad, aen_entry);
6491	if (!aen_entry)
6492		return;
6493
6494	aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
6495	aen_entry->aen_data.lport.roles = port->port_cfg.roles;
6496	aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
6497					bfa_fcs_get_base_port(port->fcs));
6498	aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
6499
6500	/* Send the AEN notification */
6501	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
6502				  BFA_AEN_CAT_LPORT, event);
6503}
6504
6505/*
6506 * This routine will be called to send a FDISC command.
6507 */
6508static void
6509bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
6510{
6511	bfa_lps_fdisc(vport->lps, vport,
6512		bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
6513		__vport_pwwn(vport), __vport_nwwn(vport));
6514	vport->vport_stats.fdisc_sent++;
6515}
6516
6517static void
6518bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
6519{
6520	u8		lsrjt_rsn = vport->lps->lsrjt_rsn;
6521	u8		lsrjt_expl = vport->lps->lsrjt_expl;
6522
6523	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
6524	bfa_trc(__vport_fcs(vport), lsrjt_expl);
6525
6526	/* For certain reason codes, we don't want to retry. */
6527	switch (vport->lps->lsrjt_expl) {
6528	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
6529	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
6530		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6531			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6532		else {
6533			bfa_fcs_vport_aen_post(&vport->lport,
6534					BFA_LPORT_AEN_NPIV_DUP_WWN);
6535			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
6536		}
6537		break;
6538
6539	case FC_LS_RJT_EXP_INSUFF_RES:
6540		/*
6541		 * This means max logins per port/switch setting on the
6542		 * switch was exceeded.
6543		 */
6544		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6545			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6546		else {
6547			bfa_fcs_vport_aen_post(&vport->lport,
6548					BFA_LPORT_AEN_NPIV_FABRIC_MAX);
6549			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX);
6550		}
6551		break;
6552
6553	default:
6554		if (vport->fdisc_retries == 0)
6555			bfa_fcs_vport_aen_post(&vport->lport,
6556					BFA_LPORT_AEN_NPIV_UNKNOWN);
6557		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6558	}
6559}
6560
6561/*
6562 *	Called to send a logout to the fabric. Used when a V-Port is
6563 *	deleted/stopped.
6564 */
6565static void
6566bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
6567{
6568	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6569
6570	vport->vport_stats.logo_sent++;
6571	bfa_lps_fdisclogo(vport->lps);
6572}
6573
6574
6575/*
6576 *     This routine will be called by bfa_timer on timer timeouts.
6577 *
6578 *	param[in]	vport		- pointer to bfa_fcs_vport_t.
6579 *	param[out]	vport_status	- pointer to return vport status in
6580 *
6581 *	return
6582 *		void
6583 *
6584 *	Special Considerations:
6585 *
6586 *	note
6587 */
6588static void
6589bfa_fcs_vport_timeout(void *vport_arg)
6590{
6591	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
6592
6593	vport->vport_stats.fdisc_timeouts++;
6594	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
6595}
6596
6597static void
6598bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
6599{
6600	struct bfad_vport_s *vport_drv =
6601			(struct bfad_vport_s *)vport->vport_drv;
6602
6603	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
6604	bfa_lps_delete(vport->lps);
6605
6606	if (vport_drv->comp_del) {
6607		complete(vport_drv->comp_del);
6608		return;
6609	}
6610
6611	/*
6612	 * We queue the vport delete work to the IM work_q from here.
6613	 * The memory for the bfad_vport_s is freed from the FC function
6614	 * template vport_delete entry point.
6615	 */
6616	bfad_im_port_delete(vport_drv->drv_port.bfad, &vport_drv->drv_port);
6617}
6618
6619/*
6620 *  fcs_vport_public FCS virtual port public interfaces
6621 */
6622
6623/*
6624 * Online notification from fabric SM.
6625 */
6626void
6627bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
6628{
6629	vport->vport_stats.fab_online++;
6630	if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
6631		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6632	else
6633		vport->vport_stats.fab_no_npiv++;
6634}
6635
6636/*
6637 * Offline notification from fabric SM.
6638 */
6639void
6640bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
6641{
6642	vport->vport_stats.fab_offline++;
6643	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6644}
6645
6646/*
6647 * Cleanup notification from fabric SM on link timer expiry.
6648 */
6649void
6650bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
6651{
6652	vport->vport_stats.fab_cleanup++;
6653}
6654
6655/*
6656 * Stop notification from fabric SM. To be invoked from within FCS.
6657 */
6658void
6659bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
6660{
6661	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6662}
6663
6664/*
6665 * delete notification from fabric SM. To be invoked from within FCS.
6666 */
6667void
6668bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
6669{
6670	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6671}
6672
6673/*
6674 * Stop completion callback from associated lport
6675 */
6676void
6677bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
6678{
6679	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
6680}
6681
6682/*
6683 * Delete completion callback from associated lport
6684 */
6685void
6686bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
6687{
6688	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
6689}
6690
6691
6692
6693/*
6694 *  fcs_vport_api Virtual port API
6695 */
6696
6697/*
6698 *	Use this function to instantiate a new FCS vport object. This
6699 *	function will not trigger any HW initialization process (which will be
6700 *	done in vport_start() call)
6701 *
6702 *	param[in] vport	-		pointer to bfa_fcs_vport_t. This space
6703 *					needs to be allocated by the driver.
6704 *	param[in] fcs		-	FCS instance
6705 *	param[in] vport_cfg	-	vport configuration
6706 *	param[in] vf_id		-	VF_ID if vport is created within a VF.
6707 *					FC_VF_ID_NULL to specify base fabric.
6708 *	param[in] vport_drv	-	Opaque handle back to the driver's vport
6709 *					structure
6710 *
6711 *	retval BFA_STATUS_OK - on success.
6712 *	retval BFA_STATUS_FAILED - on failure.
6713 */
6714bfa_status_t
6715bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6716		u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6717		struct bfad_vport_s *vport_drv)
6718{
6719	if (vport_cfg->pwwn == 0)
6720		return BFA_STATUS_INVALID_WWN;
6721
6722	if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
6723		return BFA_STATUS_VPORT_WWN_BP;
6724
6725	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
6726		return BFA_STATUS_VPORT_EXISTS;
6727
6728	if (fcs->fabric.num_vports ==
6729			bfa_lps_get_max_vport(fcs->bfa))
6730		return BFA_STATUS_VPORT_MAX;
6731
6732	vport->lps = bfa_lps_alloc(fcs->bfa);
6733	if (!vport->lps)
6734		return BFA_STATUS_VPORT_MAX;
6735
6736	vport->vport_drv = vport_drv;
6737	vport_cfg->preboot_vp = BFA_FALSE;
6738
6739	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6740	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
6741	bfa_fcs_lport_init(&vport->lport, vport_cfg);
6742	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
6743
6744	return BFA_STATUS_OK;
6745}
6746
6747/*
6748 *	Use this function to instantiate a new FCS PBC vport object. This
6749 *	function will not trigger any HW initialization process (which will be
6750 *	done in vport_start() call)
6751 *
6752 *	param[in] vport	-	pointer to bfa_fcs_vport_t. This space
6753 *				needs to be allocated by the driver.
6754 *	param[in] fcs	-	FCS instance
6755 *	param[in] vport_cfg	-	vport configuration
6756 *	param[in] vf_id		-	VF_ID if vport is created within a VF.
6757 *					FC_VF_ID_NULL to specify base fabric.
6758 *	param[in] vport_drv	-	Opaque handle back to the driver's vport
6759 *					structure
6760 *
6761 *	retval BFA_STATUS_OK - on success.
6762 *	retval BFA_STATUS_FAILED - on failure.
6763 */
6764bfa_status_t
6765bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6766			u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6767			struct bfad_vport_s *vport_drv)
6768{
6769	bfa_status_t rc;
6770
6771	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
6772	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
6773
6774	return rc;
6775}
6776
6777/*
6778 *	Use this function to findout if this is a pbc vport or not.
6779 *
6780 * @param[in] vport - pointer to bfa_fcs_vport_t.
6781 *
6782 * @returns None
6783 */
6784bfa_boolean_t
6785bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
6786{
6787
6788	if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
6789		return BFA_TRUE;
6790	else
6791		return BFA_FALSE;
6792
6793}
6794
6795/*
6796 * Use this function initialize the vport.
6797 *
6798 * @param[in] vport - pointer to bfa_fcs_vport_t.
6799 *
6800 * @returns None
6801 */
6802bfa_status_t
6803bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
6804{
6805	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
6806
6807	return BFA_STATUS_OK;
6808}
6809
6810/*
6811 *	Use this function quiese the vport object. This function will return
6812 *	immediately, when the vport is actually stopped, the
6813 *	bfa_drv_vport_stop_cb() will be called.
6814 *
6815 *	param[in] vport - pointer to bfa_fcs_vport_t.
6816 *
6817 *	return None
6818 */
6819bfa_status_t
6820bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
6821{
6822	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6823
6824	return BFA_STATUS_OK;
6825}
6826
6827/*
6828 *	Use this function to delete a vport object. Fabric object should
6829 *	be stopped before this function call.
6830 *
6831 *	!!!!!!! Donot invoke this from within FCS  !!!!!!!
6832 *
6833 *	param[in] vport - pointer to bfa_fcs_vport_t.
6834 *
6835 *	return     None
6836 */
6837bfa_status_t
6838bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
6839{
6840
6841	if (vport->lport.port_cfg.preboot_vp)
6842		return BFA_STATUS_PBC;
6843
6844	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6845
6846	return BFA_STATUS_OK;
6847}
6848
6849/*
6850 *	Use this function to get vport's current status info.
6851 *
6852 *	param[in] vport		pointer to bfa_fcs_vport_t.
6853 *	param[out] attr		pointer to return vport attributes
6854 *
6855 *	return None
6856 */
6857void
6858bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
6859			struct bfa_vport_attr_s *attr)
6860{
6861	if (vport == NULL || attr == NULL)
6862		return;
6863
6864	memset(attr, 0, sizeof(struct bfa_vport_attr_s));
6865
6866	bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
6867	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
6868}
6869
6870
6871/*
6872 *	Lookup a virtual port. Excludes base port from lookup.
6873 */
6874struct bfa_fcs_vport_s *
6875bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
6876{
6877	struct bfa_fcs_vport_s *vport;
6878	struct bfa_fcs_fabric_s *fabric;
6879
6880	bfa_trc(fcs, vf_id);
6881	bfa_trc(fcs, vpwwn);
6882
6883	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
6884	if (!fabric) {
6885		bfa_trc(fcs, vf_id);
6886		return NULL;
6887	}
6888
6889	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
6890	return vport;
6891}
6892
6893/*
6894 * FDISC Response
6895 */
6896void
6897bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
6898{
6899	struct bfa_fcs_vport_s *vport = uarg;
6900
6901	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6902	bfa_trc(__vport_fcs(vport), status);
6903
6904	switch (status) {
6905	case BFA_STATUS_OK:
6906		/*
6907		 * Initialize the V-Port fields
6908		 */
6909		__vport_fcid(vport) = vport->lps->lp_pid;
6910		vport->vport_stats.fdisc_accepts++;
6911		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6912		break;
6913
6914	case BFA_STATUS_INVALID_MAC:
6915		/* Only for CNA */
6916		vport->vport_stats.fdisc_acc_bad++;
6917		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6918
6919		break;
6920
6921	case BFA_STATUS_EPROTOCOL:
6922		switch (vport->lps->ext_status) {
6923		case BFA_EPROTO_BAD_ACCEPT:
6924			vport->vport_stats.fdisc_acc_bad++;
6925			break;
6926
6927		case BFA_EPROTO_UNKNOWN_RSP:
6928			vport->vport_stats.fdisc_unknown_rsp++;
6929			break;
6930
6931		default:
6932			break;
6933		}
6934
6935		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6936			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6937		else
6938			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
6939
6940		break;
6941
6942	case BFA_STATUS_ETIMER:
6943		vport->vport_stats.fdisc_timeouts++;
6944		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6945			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6946		else
6947			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
6948		break;
6949
6950	case BFA_STATUS_FABRIC_RJT:
6951		vport->vport_stats.fdisc_rejects++;
6952		bfa_fcs_vport_fdisc_rejected(vport);
6953		break;
6954
6955	default:
6956		vport->vport_stats.fdisc_rsp_err++;
6957		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6958	}
6959}
6960
6961/*
6962 * LOGO response
6963 */
6964void
6965bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
6966{
6967	struct bfa_fcs_vport_s *vport = uarg;
6968	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6969}
6970
6971/*
6972 * Received clear virtual link
6973 */
6974void
6975bfa_cb_lps_cvl_event(void *bfad, void *uarg)
6976{
6977	struct bfa_fcs_vport_s *vport = uarg;
6978
6979	/* Send an Offline followed by an ONLINE */
6980	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6981	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6982}
6983