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