xref: /openbmc/linux/drivers/scsi/bfa/bfa_fcs_lport.c (revision ba816ea8)
17725ccfdSJing Huang /*
2a36c61f9SKrishna Gudipati  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
37725ccfdSJing Huang  * All rights reserved
47725ccfdSJing Huang  * www.brocade.com
57725ccfdSJing Huang  *
67725ccfdSJing Huang  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
77725ccfdSJing Huang  *
87725ccfdSJing Huang  * This program is free software; you can redistribute it and/or modify it
97725ccfdSJing Huang  * under the terms of the GNU General Public License (GPL) Version 2 as
107725ccfdSJing Huang  * published by the Free Software Foundation
117725ccfdSJing Huang  *
127725ccfdSJing Huang  * This program is distributed in the hope that it will be useful, but
137725ccfdSJing Huang  * WITHOUT ANY WARRANTY; without even the implied warranty of
147725ccfdSJing Huang  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
157725ccfdSJing Huang  * General Public License for more details.
167725ccfdSJing Huang  */
177725ccfdSJing Huang 
187725ccfdSJing Huang /**
19a36c61f9SKrishna Gudipati  *  bfa_fcs_lport.c BFA FCS port
207725ccfdSJing Huang  */
217725ccfdSJing Huang 
22a36c61f9SKrishna Gudipati #include "bfa_fcs.h"
23a36c61f9SKrishna Gudipati #include "bfa_fcbuild.h"
24a36c61f9SKrishna Gudipati #include "bfa_fc.h"
25a36c61f9SKrishna Gudipati #include "bfad_drv.h"
267725ccfdSJing Huang 
277725ccfdSJing Huang BFA_TRC_FILE(FCS, PORT);
287725ccfdSJing Huang 
297725ccfdSJing Huang /**
307725ccfdSJing Huang  * Forward declarations
317725ccfdSJing Huang  */
327725ccfdSJing Huang 
33a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
347725ccfdSJing Huang 					 struct fchs_s *rx_fchs, u8 reason_code,
357725ccfdSJing Huang 					 u8 reason_code_expl);
36a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
37a36c61f9SKrishna Gudipati 			struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
38a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
39a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
40a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
41a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
42a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
43a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
44a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
457725ccfdSJing Huang 			struct fchs_s *rx_fchs,
467725ccfdSJing Huang 			struct fc_echo_s *echo, u16 len);
47a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
487725ccfdSJing Huang 			struct fchs_s *rx_fchs,
497725ccfdSJing Huang 			struct fc_rnid_cmd_s *rnid, u16 len);
50a36c61f9SKrishna Gudipati static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
517725ccfdSJing Huang 			struct fc_rnid_general_topology_data_s *gen_topo_data);
527725ccfdSJing Huang 
53a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
54a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
55a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
56a36c61f9SKrishna Gudipati 
57a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
58a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
59a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
60a36c61f9SKrishna Gudipati 
617725ccfdSJing Huang static struct {
62a36c61f9SKrishna Gudipati 	void		(*init) (struct bfa_fcs_lport_s *port);
63a36c61f9SKrishna Gudipati 	void		(*online) (struct bfa_fcs_lport_s *port);
64a36c61f9SKrishna Gudipati 	void		(*offline) (struct bfa_fcs_lport_s *port);
657725ccfdSJing Huang } __port_action[] = {
667725ccfdSJing Huang 	{
67a36c61f9SKrishna Gudipati 	bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
68a36c61f9SKrishna Gudipati 			bfa_fcs_lport_unknown_offline}, {
69a36c61f9SKrishna Gudipati 	bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
70a36c61f9SKrishna Gudipati 			bfa_fcs_lport_fab_offline}, {
71a36c61f9SKrishna Gudipati 	bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
72a36c61f9SKrishna Gudipati 			bfa_fcs_lport_n2n_offline},
73a36c61f9SKrishna Gudipati 	};
747725ccfdSJing Huang 
757725ccfdSJing Huang /**
767725ccfdSJing Huang  *  fcs_port_sm FCS logical port state machine
777725ccfdSJing Huang  */
787725ccfdSJing Huang 
79a36c61f9SKrishna Gudipati enum bfa_fcs_lport_event {
807725ccfdSJing Huang 	BFA_FCS_PORT_SM_CREATE = 1,
817725ccfdSJing Huang 	BFA_FCS_PORT_SM_ONLINE = 2,
827725ccfdSJing Huang 	BFA_FCS_PORT_SM_OFFLINE = 3,
837725ccfdSJing Huang 	BFA_FCS_PORT_SM_DELETE = 4,
847725ccfdSJing Huang 	BFA_FCS_PORT_SM_DELRPORT = 5,
857725ccfdSJing Huang };
867725ccfdSJing Huang 
87a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
88a36c61f9SKrishna Gudipati 					enum bfa_fcs_lport_event event);
89a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
90a36c61f9SKrishna Gudipati 					enum bfa_fcs_lport_event event);
91a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
92a36c61f9SKrishna Gudipati 					enum bfa_fcs_lport_event event);
93a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
94a36c61f9SKrishna Gudipati 					enum bfa_fcs_lport_event event);
95a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
96a36c61f9SKrishna Gudipati 					enum bfa_fcs_lport_event event);
977725ccfdSJing Huang 
987725ccfdSJing Huang static void
99a36c61f9SKrishna Gudipati bfa_fcs_lport_sm_uninit(
100a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port,
101a36c61f9SKrishna Gudipati 	enum bfa_fcs_lport_event event)
1027725ccfdSJing Huang {
1037725ccfdSJing Huang 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1047725ccfdSJing Huang 	bfa_trc(port->fcs, event);
1057725ccfdSJing Huang 
1067725ccfdSJing Huang 	switch (event) {
1077725ccfdSJing Huang 	case BFA_FCS_PORT_SM_CREATE:
108a36c61f9SKrishna Gudipati 		bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
1097725ccfdSJing Huang 		break;
1107725ccfdSJing Huang 
1117725ccfdSJing Huang 	default:
112e641de37SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1137725ccfdSJing Huang 	}
1147725ccfdSJing Huang }
1157725ccfdSJing Huang 
1167725ccfdSJing Huang static void
117a36c61f9SKrishna Gudipati bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
118a36c61f9SKrishna Gudipati 			enum bfa_fcs_lport_event event)
1197725ccfdSJing Huang {
1207725ccfdSJing Huang 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1217725ccfdSJing Huang 	bfa_trc(port->fcs, event);
1227725ccfdSJing Huang 
1237725ccfdSJing Huang 	switch (event) {
1247725ccfdSJing Huang 	case BFA_FCS_PORT_SM_ONLINE:
125a36c61f9SKrishna Gudipati 		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
126a36c61f9SKrishna Gudipati 		bfa_fcs_lport_online_actions(port);
1277725ccfdSJing Huang 		break;
1287725ccfdSJing Huang 
1297725ccfdSJing Huang 	case BFA_FCS_PORT_SM_DELETE:
130a36c61f9SKrishna Gudipati 		bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
131a36c61f9SKrishna Gudipati 		bfa_fcs_lport_deleted(port);
1327725ccfdSJing Huang 		break;
1337725ccfdSJing Huang 
1343e98cc01SJing Huang 	case BFA_FCS_PORT_SM_OFFLINE:
1353e98cc01SJing Huang 		break;
1363e98cc01SJing Huang 
1377725ccfdSJing Huang 	default:
138e641de37SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1397725ccfdSJing Huang 	}
1407725ccfdSJing Huang }
1417725ccfdSJing Huang 
1427725ccfdSJing Huang static void
143a36c61f9SKrishna Gudipati bfa_fcs_lport_sm_online(
144a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port,
145a36c61f9SKrishna Gudipati 	enum bfa_fcs_lport_event event)
1467725ccfdSJing Huang {
1477725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport;
1487725ccfdSJing Huang 	struct list_head		*qe, *qen;
1497725ccfdSJing Huang 
1507725ccfdSJing Huang 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1517725ccfdSJing Huang 	bfa_trc(port->fcs, event);
1527725ccfdSJing Huang 
1537725ccfdSJing Huang 	switch (event) {
1547725ccfdSJing Huang 	case BFA_FCS_PORT_SM_OFFLINE:
155a36c61f9SKrishna Gudipati 		bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
156a36c61f9SKrishna Gudipati 		bfa_fcs_lport_offline_actions(port);
1577725ccfdSJing Huang 		break;
1587725ccfdSJing Huang 
1597725ccfdSJing Huang 	case BFA_FCS_PORT_SM_DELETE:
1607725ccfdSJing Huang 
1617725ccfdSJing Huang 		__port_action[port->fabric->fab_type].offline(port);
1627725ccfdSJing Huang 
1637725ccfdSJing Huang 		if (port->num_rports == 0) {
164a36c61f9SKrishna Gudipati 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
165a36c61f9SKrishna Gudipati 			bfa_fcs_lport_deleted(port);
1667725ccfdSJing Huang 		} else {
167a36c61f9SKrishna Gudipati 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
1687725ccfdSJing Huang 			list_for_each_safe(qe, qen, &port->rport_q) {
1697725ccfdSJing Huang 				rport = (struct bfa_fcs_rport_s *) qe;
1707725ccfdSJing Huang 				bfa_fcs_rport_delete(rport);
1717725ccfdSJing Huang 			}
1727725ccfdSJing Huang 		}
1737725ccfdSJing Huang 		break;
1747725ccfdSJing Huang 
1757725ccfdSJing Huang 	case BFA_FCS_PORT_SM_DELRPORT:
1767725ccfdSJing Huang 		break;
1777725ccfdSJing Huang 
1787725ccfdSJing Huang 	default:
179e641de37SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1807725ccfdSJing Huang 	}
1817725ccfdSJing Huang }
1827725ccfdSJing Huang 
1837725ccfdSJing Huang static void
184a36c61f9SKrishna Gudipati bfa_fcs_lport_sm_offline(
185a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port,
186a36c61f9SKrishna Gudipati 	enum bfa_fcs_lport_event event)
1877725ccfdSJing Huang {
1887725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport;
1897725ccfdSJing Huang 	struct list_head		*qe, *qen;
1907725ccfdSJing Huang 
1917725ccfdSJing Huang 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1927725ccfdSJing Huang 	bfa_trc(port->fcs, event);
1937725ccfdSJing Huang 
1947725ccfdSJing Huang 	switch (event) {
1957725ccfdSJing Huang 	case BFA_FCS_PORT_SM_ONLINE:
196a36c61f9SKrishna Gudipati 		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
197a36c61f9SKrishna Gudipati 		bfa_fcs_lport_online_actions(port);
1987725ccfdSJing Huang 		break;
1997725ccfdSJing Huang 
2007725ccfdSJing Huang 	case BFA_FCS_PORT_SM_DELETE:
2017725ccfdSJing Huang 		if (port->num_rports == 0) {
202a36c61f9SKrishna Gudipati 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
203a36c61f9SKrishna Gudipati 			bfa_fcs_lport_deleted(port);
2047725ccfdSJing Huang 		} else {
205a36c61f9SKrishna Gudipati 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
2067725ccfdSJing Huang 			list_for_each_safe(qe, qen, &port->rport_q) {
2077725ccfdSJing Huang 				rport = (struct bfa_fcs_rport_s *) qe;
2087725ccfdSJing Huang 				bfa_fcs_rport_delete(rport);
2097725ccfdSJing Huang 			}
2107725ccfdSJing Huang 		}
2117725ccfdSJing Huang 		break;
2127725ccfdSJing Huang 
2137725ccfdSJing Huang 	case BFA_FCS_PORT_SM_DELRPORT:
2147725ccfdSJing Huang 	case BFA_FCS_PORT_SM_OFFLINE:
2157725ccfdSJing Huang 		break;
2167725ccfdSJing Huang 
2177725ccfdSJing Huang 	default:
218e641de37SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
2197725ccfdSJing Huang 	}
2207725ccfdSJing Huang }
2217725ccfdSJing Huang 
2227725ccfdSJing Huang static void
223a36c61f9SKrishna Gudipati bfa_fcs_lport_sm_deleting(
224a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port,
225a36c61f9SKrishna Gudipati 	enum bfa_fcs_lport_event event)
2267725ccfdSJing Huang {
2277725ccfdSJing Huang 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2287725ccfdSJing Huang 	bfa_trc(port->fcs, event);
2297725ccfdSJing Huang 
2307725ccfdSJing Huang 	switch (event) {
2317725ccfdSJing Huang 	case BFA_FCS_PORT_SM_DELRPORT:
2327725ccfdSJing Huang 		if (port->num_rports == 0) {
233a36c61f9SKrishna Gudipati 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
234a36c61f9SKrishna Gudipati 			bfa_fcs_lport_deleted(port);
2357725ccfdSJing Huang 		}
2367725ccfdSJing Huang 		break;
2377725ccfdSJing Huang 
2387725ccfdSJing Huang 	default:
239e641de37SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
2407725ccfdSJing Huang 	}
2417725ccfdSJing Huang }
2427725ccfdSJing Huang 
2437725ccfdSJing Huang /**
2447725ccfdSJing Huang  *  fcs_port_pvt
2457725ccfdSJing Huang  */
2467725ccfdSJing Huang 
2477725ccfdSJing Huang /*
2487725ccfdSJing Huang  * Send a LS reject
2497725ccfdSJing Huang  */
2507725ccfdSJing Huang static void
251a36c61f9SKrishna Gudipati bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
2527725ccfdSJing Huang 			 u8 reason_code, u8 reason_code_expl)
2537725ccfdSJing Huang {
2547725ccfdSJing Huang 	struct fchs_s	fchs;
2557725ccfdSJing Huang 	struct bfa_fcxp_s *fcxp;
2567725ccfdSJing Huang 	struct bfa_rport_s *bfa_rport = NULL;
2577725ccfdSJing Huang 	int		len;
2587725ccfdSJing Huang 
259a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, rx_fchs->d_id);
2607725ccfdSJing Huang 	bfa_trc(port->fcs, rx_fchs->s_id);
2617725ccfdSJing Huang 
2627725ccfdSJing Huang 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
2637725ccfdSJing Huang 	if (!fcxp)
2647725ccfdSJing Huang 		return;
2657725ccfdSJing Huang 
266a36c61f9SKrishna Gudipati 	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
267a36c61f9SKrishna Gudipati 			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
268a36c61f9SKrishna Gudipati 			      rx_fchs->ox_id, reason_code, reason_code_expl);
2697725ccfdSJing Huang 
2707725ccfdSJing Huang 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
2717725ccfdSJing Huang 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2727725ccfdSJing Huang 			  FC_MAX_PDUSZ, 0);
2737725ccfdSJing Huang }
2747725ccfdSJing Huang 
2757725ccfdSJing Huang /**
2767725ccfdSJing Huang  * Process incoming plogi from a remote port.
2777725ccfdSJing Huang  */
2787725ccfdSJing Huang static void
279a36c61f9SKrishna Gudipati bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
280a36c61f9SKrishna Gudipati 		struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
2817725ccfdSJing Huang {
2827725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport;
2837725ccfdSJing Huang 
2847725ccfdSJing Huang 	bfa_trc(port->fcs, rx_fchs->d_id);
2857725ccfdSJing Huang 	bfa_trc(port->fcs, rx_fchs->s_id);
2867725ccfdSJing Huang 
2877725ccfdSJing Huang 	/*
2887725ccfdSJing Huang 	 * If min cfg mode is enabled, drop any incoming PLOGIs
2897725ccfdSJing Huang 	 */
2907725ccfdSJing Huang 	if (__fcs_min_cfg(port->fcs)) {
2917725ccfdSJing Huang 		bfa_trc(port->fcs, rx_fchs->s_id);
2927725ccfdSJing Huang 		return;
2937725ccfdSJing Huang 	}
2947725ccfdSJing Huang 
2957725ccfdSJing Huang 	if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
2967725ccfdSJing Huang 		bfa_trc(port->fcs, rx_fchs->s_id);
2977725ccfdSJing Huang 		/*
2987725ccfdSJing Huang 		 * send a LS reject
2997725ccfdSJing Huang 		 */
300a36c61f9SKrishna Gudipati 		bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
3017725ccfdSJing Huang 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
3027725ccfdSJing Huang 					FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
3037725ccfdSJing Huang 		return;
3047725ccfdSJing Huang 	}
3057725ccfdSJing Huang 
3067725ccfdSJing Huang 	/**
3077725ccfdSJing Huang 	 * Direct Attach P2P mode : verify address assigned by the r-port.
3087725ccfdSJing Huang 	 */
309a36c61f9SKrishna Gudipati 	if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
310a36c61f9SKrishna Gudipati 		(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
311a36c61f9SKrishna Gudipati 			   (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
3127725ccfdSJing Huang 		if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
313a36c61f9SKrishna Gudipati 			/* Address assigned to us cannot be a WKA */
314a36c61f9SKrishna Gudipati 			bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
3157725ccfdSJing Huang 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
3167725ccfdSJing Huang 					FC_LS_RJT_EXP_INVALID_NPORT_ID);
3177725ccfdSJing Huang 			return;
3187725ccfdSJing Huang 		}
3197725ccfdSJing Huang 		port->pid  = rx_fchs->d_id;
3207725ccfdSJing Huang 	}
3217725ccfdSJing Huang 
3227725ccfdSJing Huang 	/**
3237725ccfdSJing Huang 	 * First, check if we know the device by pwwn.
3247725ccfdSJing Huang 	 */
325a36c61f9SKrishna Gudipati 	rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
3267725ccfdSJing Huang 	if (rport) {
3277725ccfdSJing Huang 		/**
328a36c61f9SKrishna Gudipati 		 * Direct Attach P2P mode : handle address assigned by r-port.
3297725ccfdSJing Huang 		 */
330a36c61f9SKrishna Gudipati 		if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
331a36c61f9SKrishna Gudipati 			(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
3327725ccfdSJing Huang 			(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
3337725ccfdSJing Huang 			port->pid  = rx_fchs->d_id;
3347725ccfdSJing Huang 			rport->pid = rx_fchs->s_id;
3357725ccfdSJing Huang 		}
3367725ccfdSJing Huang 		bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
3377725ccfdSJing Huang 		return;
3387725ccfdSJing Huang 	}
3397725ccfdSJing Huang 
3407725ccfdSJing Huang 	/**
3417725ccfdSJing Huang 	 * Next, lookup rport by PID.
3427725ccfdSJing Huang 	 */
343a36c61f9SKrishna Gudipati 	rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
3447725ccfdSJing Huang 	if (!rport) {
3457725ccfdSJing Huang 		/**
3467725ccfdSJing Huang 		 * Inbound PLOGI from a new device.
3477725ccfdSJing Huang 		 */
3487725ccfdSJing Huang 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
3497725ccfdSJing Huang 		return;
3507725ccfdSJing Huang 	}
3517725ccfdSJing Huang 
3527725ccfdSJing Huang 	/**
3537725ccfdSJing Huang 	 * Rport is known only by PID.
3547725ccfdSJing Huang 	 */
3557725ccfdSJing Huang 	if (rport->pwwn) {
3567725ccfdSJing Huang 		/**
3577725ccfdSJing Huang 		 * This is a different device with the same pid. Old device
3587725ccfdSJing Huang 		 * disappeared. Send implicit LOGO to old device.
3597725ccfdSJing Huang 		 */
3607725ccfdSJing Huang 		bfa_assert(rport->pwwn != plogi->port_name);
3617725ccfdSJing Huang 		bfa_fcs_rport_logo_imp(rport);
3627725ccfdSJing Huang 
3637725ccfdSJing Huang 		/**
3647725ccfdSJing Huang 		 * Inbound PLOGI from a new device (with old PID).
3657725ccfdSJing Huang 		 */
3667725ccfdSJing Huang 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
3677725ccfdSJing Huang 		return;
3687725ccfdSJing Huang 	}
3697725ccfdSJing Huang 
3707725ccfdSJing Huang 	/**
3717725ccfdSJing Huang 	 * PLOGI crossing each other.
3727725ccfdSJing Huang 	 */
3737725ccfdSJing Huang 	bfa_assert(rport->pwwn == WWN_NULL);
3747725ccfdSJing Huang 	bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
3757725ccfdSJing Huang }
3767725ccfdSJing Huang 
3777725ccfdSJing Huang /*
3787725ccfdSJing Huang  * Process incoming ECHO.
3797725ccfdSJing Huang  * Since it does not require a login, it is processed here.
3807725ccfdSJing Huang  */
3817725ccfdSJing Huang static void
382a36c61f9SKrishna Gudipati bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
3837725ccfdSJing Huang 		struct fc_echo_s *echo, u16 rx_len)
3847725ccfdSJing Huang {
3857725ccfdSJing Huang 	struct fchs_s		fchs;
3867725ccfdSJing Huang 	struct bfa_fcxp_s	*fcxp;
3877725ccfdSJing Huang 	struct bfa_rport_s	*bfa_rport = NULL;
3887725ccfdSJing Huang 	int			len, pyld_len;
3897725ccfdSJing Huang 
3907725ccfdSJing Huang 	bfa_trc(port->fcs, rx_fchs->s_id);
3917725ccfdSJing Huang 	bfa_trc(port->fcs, rx_fchs->d_id);
3927725ccfdSJing Huang 
3937725ccfdSJing Huang 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
3947725ccfdSJing Huang 	if (!fcxp)
3957725ccfdSJing Huang 		return;
3967725ccfdSJing Huang 
397a36c61f9SKrishna Gudipati 	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
398a36c61f9SKrishna Gudipati 				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
399a36c61f9SKrishna Gudipati 				rx_fchs->ox_id);
4007725ccfdSJing Huang 
4017725ccfdSJing Huang 	/*
4027725ccfdSJing Huang 	 * Copy the payload (if any) from the echo frame
4037725ccfdSJing Huang 	 */
4047725ccfdSJing Huang 	pyld_len = rx_len - sizeof(struct fchs_s);
405a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, rx_len);
4067725ccfdSJing Huang 	bfa_trc(port->fcs, pyld_len);
4077725ccfdSJing Huang 
4087725ccfdSJing Huang 	if (pyld_len > len)
4097725ccfdSJing Huang 		memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
4107725ccfdSJing Huang 			sizeof(struct fc_echo_s), (echo + 1),
4117725ccfdSJing Huang 			(pyld_len - sizeof(struct fc_echo_s)));
4127725ccfdSJing Huang 
4137725ccfdSJing Huang 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4147725ccfdSJing Huang 			BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
4157725ccfdSJing Huang 			FC_MAX_PDUSZ, 0);
4167725ccfdSJing Huang }
4177725ccfdSJing Huang 
4187725ccfdSJing Huang /*
4197725ccfdSJing Huang  * Process incoming RNID.
4207725ccfdSJing Huang  * Since it does not require a login, it is processed here.
4217725ccfdSJing Huang  */
4227725ccfdSJing Huang static void
423a36c61f9SKrishna Gudipati bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
4247725ccfdSJing Huang 		struct fc_rnid_cmd_s *rnid, u16 rx_len)
4257725ccfdSJing Huang {
4267725ccfdSJing Huang 	struct fc_rnid_common_id_data_s common_id_data;
4277725ccfdSJing Huang 	struct fc_rnid_general_topology_data_s gen_topo_data;
4287725ccfdSJing Huang 	struct fchs_s	fchs;
4297725ccfdSJing Huang 	struct bfa_fcxp_s *fcxp;
4307725ccfdSJing Huang 	struct bfa_rport_s *bfa_rport = NULL;
4317725ccfdSJing Huang 	u16	len;
4327725ccfdSJing Huang 	u32	data_format;
4337725ccfdSJing Huang 
4347725ccfdSJing Huang 	bfa_trc(port->fcs, rx_fchs->s_id);
4357725ccfdSJing Huang 	bfa_trc(port->fcs, rx_fchs->d_id);
4367725ccfdSJing Huang 	bfa_trc(port->fcs, rx_len);
4377725ccfdSJing Huang 
4387725ccfdSJing Huang 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4397725ccfdSJing Huang 	if (!fcxp)
4407725ccfdSJing Huang 		return;
4417725ccfdSJing Huang 
4427725ccfdSJing Huang 	/*
4437725ccfdSJing Huang 	 * Check Node Indentification Data Format
4447725ccfdSJing Huang 	 * We only support General Topology Discovery Format.
4457725ccfdSJing Huang 	 * For any other requested Data Formats, we return Common Node Id Data
4467725ccfdSJing Huang 	 * only, as per FC-LS.
4477725ccfdSJing Huang 	 */
4487725ccfdSJing Huang 	bfa_trc(port->fcs, rnid->node_id_data_format);
4497725ccfdSJing Huang 	if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
4507725ccfdSJing Huang 		data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
4517725ccfdSJing Huang 		/*
4527725ccfdSJing Huang 		 * Get General topology data for this port
4537725ccfdSJing Huang 		 */
4547725ccfdSJing Huang 		bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
4557725ccfdSJing Huang 	} else {
4567725ccfdSJing Huang 		data_format = RNID_NODEID_DATA_FORMAT_COMMON;
4577725ccfdSJing Huang 	}
4587725ccfdSJing Huang 
4597725ccfdSJing Huang 	/*
4607725ccfdSJing Huang 	 * Copy the Node Id Info
4617725ccfdSJing Huang 	 */
462a36c61f9SKrishna Gudipati 	common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
463a36c61f9SKrishna Gudipati 	common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
4647725ccfdSJing Huang 
465a36c61f9SKrishna Gudipati 	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
466a36c61f9SKrishna Gudipati 				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
467a36c61f9SKrishna Gudipati 				rx_fchs->ox_id, data_format, &common_id_data,
468a36c61f9SKrishna Gudipati 				&gen_topo_data);
4697725ccfdSJing Huang 
4707725ccfdSJing Huang 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4717725ccfdSJing Huang 			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4727725ccfdSJing Huang 			FC_MAX_PDUSZ, 0);
4737725ccfdSJing Huang }
4747725ccfdSJing Huang 
4757725ccfdSJing Huang /*
4767725ccfdSJing Huang  *  Fill out General Topolpgy Discovery Data for RNID ELS.
4777725ccfdSJing Huang  */
4787725ccfdSJing Huang static void
479a36c61f9SKrishna Gudipati bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
4807725ccfdSJing Huang 			struct fc_rnid_general_topology_data_s *gen_topo_data)
4817725ccfdSJing Huang {
4826a18b167SJing Huang 	memset(gen_topo_data, 0,
4837725ccfdSJing Huang 		      sizeof(struct fc_rnid_general_topology_data_s));
4847725ccfdSJing Huang 
485ba816ea8SJing Huang 	gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
4867725ccfdSJing Huang 	gen_topo_data->phy_port_num = 0;	/* @todo */
487ba816ea8SJing Huang 	gen_topo_data->num_attached_nodes = cpu_to_be32(1);
4887725ccfdSJing Huang }
4897725ccfdSJing Huang 
4907725ccfdSJing Huang static void
491a36c61f9SKrishna Gudipati bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
4927725ccfdSJing Huang {
493a36c61f9SKrishna Gudipati 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
494a36c61f9SKrishna Gudipati 	char	lpwwn_buf[BFA_STRING_32];
495a36c61f9SKrishna Gudipati 
4967725ccfdSJing Huang 	bfa_trc(port->fcs, port->fabric->oper_type);
4977725ccfdSJing Huang 
4987725ccfdSJing Huang 	__port_action[port->fabric->fab_type].init(port);
4997725ccfdSJing Huang 	__port_action[port->fabric->fab_type].online(port);
5007725ccfdSJing Huang 
501a36c61f9SKrishna Gudipati 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
502a36c61f9SKrishna Gudipati 	BFA_LOG(KERN_INFO, bfad, log_level,
503a36c61f9SKrishna Gudipati 		"Logical port online: WWN = %s Role = %s\n",
504a36c61f9SKrishna Gudipati 		lpwwn_buf, "Initiator");
505a36c61f9SKrishna Gudipati 
506a36c61f9SKrishna Gudipati 	bfad->bfad_flags |= BFAD_PORT_ONLINE;
5077725ccfdSJing Huang }
5087725ccfdSJing Huang 
5097725ccfdSJing Huang static void
510a36c61f9SKrishna Gudipati bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
5117725ccfdSJing Huang {
5127725ccfdSJing Huang 	struct list_head	*qe, *qen;
5137725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport;
514a36c61f9SKrishna Gudipati 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
515a36c61f9SKrishna Gudipati 	char    lpwwn_buf[BFA_STRING_32];
5167725ccfdSJing Huang 
5177725ccfdSJing Huang 	bfa_trc(port->fcs, port->fabric->oper_type);
5187725ccfdSJing Huang 
5197725ccfdSJing Huang 	__port_action[port->fabric->fab_type].offline(port);
5207725ccfdSJing Huang 
521a36c61f9SKrishna Gudipati 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
522f8ceafdeSJing Huang 	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
523a36c61f9SKrishna Gudipati 		BFA_LOG(KERN_ERR, bfad, log_level,
524a36c61f9SKrishna Gudipati 		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
525a36c61f9SKrishna Gudipati 		lpwwn_buf, "Initiator");
526f8ceafdeSJing Huang 	else
527a36c61f9SKrishna Gudipati 		BFA_LOG(KERN_INFO, bfad, log_level,
528a36c61f9SKrishna Gudipati 		"Logical port taken offline: WWN = %s Role = %s\n",
529a36c61f9SKrishna Gudipati 		lpwwn_buf, "Initiator");
5307725ccfdSJing Huang 
5317725ccfdSJing Huang 	list_for_each_safe(qe, qen, &port->rport_q) {
5327725ccfdSJing Huang 		rport = (struct bfa_fcs_rport_s *) qe;
5337725ccfdSJing Huang 		bfa_fcs_rport_offline(rport);
5347725ccfdSJing Huang 	}
5357725ccfdSJing Huang }
5367725ccfdSJing Huang 
5377725ccfdSJing Huang static void
538a36c61f9SKrishna Gudipati bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
5397725ccfdSJing Huang {
5407725ccfdSJing Huang 	bfa_assert(0);
5417725ccfdSJing Huang }
5427725ccfdSJing Huang 
5437725ccfdSJing Huang static void
544a36c61f9SKrishna Gudipati bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
5457725ccfdSJing Huang {
5467725ccfdSJing Huang 	bfa_assert(0);
5477725ccfdSJing Huang }
5487725ccfdSJing Huang 
5497725ccfdSJing Huang static void
550a36c61f9SKrishna Gudipati bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
5517725ccfdSJing Huang {
5527725ccfdSJing Huang 	bfa_assert(0);
5537725ccfdSJing Huang }
5547725ccfdSJing Huang 
5557725ccfdSJing Huang static void
556a36c61f9SKrishna Gudipati bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
5577725ccfdSJing Huang {
558a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
559a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
560a36c61f9SKrishna Gudipati 	int		len;
5617725ccfdSJing Huang 
562a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, rx_fchs->d_id);
563a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, rx_fchs->s_id);
564a36c61f9SKrishna Gudipati 
565a36c61f9SKrishna Gudipati 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
566a36c61f9SKrishna Gudipati 	if (!fcxp)
567a36c61f9SKrishna Gudipati 		return;
568a36c61f9SKrishna Gudipati 
569a36c61f9SKrishna Gudipati 	len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
570a36c61f9SKrishna Gudipati 			rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
571a36c61f9SKrishna Gudipati 			rx_fchs->ox_id, 0);
572a36c61f9SKrishna Gudipati 
573a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
574a36c61f9SKrishna Gudipati 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
575a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, 0);
576a36c61f9SKrishna Gudipati }
577a36c61f9SKrishna Gudipati static void
578a36c61f9SKrishna Gudipati bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
579a36c61f9SKrishna Gudipati {
580a36c61f9SKrishna Gudipati 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
581a36c61f9SKrishna Gudipati 	char    lpwwn_buf[BFA_STRING_32];
582a36c61f9SKrishna Gudipati 
583a36c61f9SKrishna Gudipati 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
584a36c61f9SKrishna Gudipati 	BFA_LOG(KERN_INFO, bfad, log_level,
585a36c61f9SKrishna Gudipati 		"Logical port deleted: WWN = %s Role = %s\n",
586a36c61f9SKrishna Gudipati 		lpwwn_buf, "Initiator");
587a36c61f9SKrishna Gudipati 
588a36c61f9SKrishna Gudipati 	/* Base port will be deleted by the OS driver */
5897725ccfdSJing Huang 	if (port->vport) {
590a36c61f9SKrishna Gudipati 		bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
5917725ccfdSJing Huang 				port->fabric->vf_drv,
5927725ccfdSJing Huang 				port->vport ? port->vport->vport_drv : NULL);
5937725ccfdSJing Huang 		bfa_fcs_vport_delete_comp(port->vport);
5947725ccfdSJing Huang 	} else {
5957725ccfdSJing Huang 		 bfa_fcs_fabric_port_delete_comp(port->fabric);
5967725ccfdSJing Huang 	}
5977725ccfdSJing Huang }
5987725ccfdSJing Huang 
5997725ccfdSJing Huang 
6007725ccfdSJing Huang 
6017725ccfdSJing Huang /**
6027725ccfdSJing Huang  *  fcs_lport_api BFA FCS port API
6037725ccfdSJing Huang  */
6047725ccfdSJing Huang /**
6057725ccfdSJing Huang  *   Module initialization
6067725ccfdSJing Huang  */
6077725ccfdSJing Huang void
608a36c61f9SKrishna Gudipati bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs)
6097725ccfdSJing Huang {
6107725ccfdSJing Huang 
6117725ccfdSJing Huang }
6127725ccfdSJing Huang 
6137725ccfdSJing Huang /**
6147725ccfdSJing Huang  *   Module cleanup
6157725ccfdSJing Huang  */
6167725ccfdSJing Huang void
617a36c61f9SKrishna Gudipati bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs)
6187725ccfdSJing Huang {
6197725ccfdSJing Huang 	bfa_fcs_modexit_comp(fcs);
6207725ccfdSJing Huang }
6217725ccfdSJing Huang 
6227725ccfdSJing Huang /**
6237725ccfdSJing Huang  * Unsolicited frame receive handling.
6247725ccfdSJing Huang  */
6257725ccfdSJing Huang void
626a36c61f9SKrishna Gudipati bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
627a36c61f9SKrishna Gudipati 			struct fchs_s *fchs, u16 len)
6287725ccfdSJing Huang {
6297725ccfdSJing Huang 	u32	pid = fchs->s_id;
6307725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport = NULL;
6317725ccfdSJing Huang 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
6327725ccfdSJing Huang 
6337725ccfdSJing Huang 	bfa_stats(lport, uf_recvs);
6347725ccfdSJing Huang 
635a36c61f9SKrishna Gudipati 	if (!bfa_fcs_lport_is_online(lport)) {
6367725ccfdSJing Huang 		bfa_stats(lport, uf_recv_drops);
6377725ccfdSJing Huang 		return;
6387725ccfdSJing Huang 	}
6397725ccfdSJing Huang 
6407725ccfdSJing Huang 	/**
6417725ccfdSJing Huang 	 * First, handle ELSs that donot require a login.
6427725ccfdSJing Huang 	 */
6437725ccfdSJing Huang 	/*
6447725ccfdSJing Huang 	 * Handle PLOGI first
6457725ccfdSJing Huang 	 */
6467725ccfdSJing Huang 	if ((fchs->type == FC_TYPE_ELS) &&
6477725ccfdSJing Huang 		(els_cmd->els_code == FC_ELS_PLOGI)) {
648a36c61f9SKrishna Gudipati 		bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
6497725ccfdSJing Huang 		return;
6507725ccfdSJing Huang 	}
6517725ccfdSJing Huang 
6527725ccfdSJing Huang 	/*
6537725ccfdSJing Huang 	 * Handle ECHO separately.
6547725ccfdSJing Huang 	 */
6557725ccfdSJing Huang 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
656a36c61f9SKrishna Gudipati 		bfa_fcs_lport_echo(lport, fchs,
6577725ccfdSJing Huang 				(struct fc_echo_s *)els_cmd, len);
6587725ccfdSJing Huang 		return;
6597725ccfdSJing Huang 	}
6607725ccfdSJing Huang 
6617725ccfdSJing Huang 	/*
6627725ccfdSJing Huang 	 * Handle RNID separately.
6637725ccfdSJing Huang 	 */
6647725ccfdSJing Huang 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
665a36c61f9SKrishna Gudipati 		bfa_fcs_lport_rnid(lport, fchs,
6667725ccfdSJing Huang 			(struct fc_rnid_cmd_s *) els_cmd, len);
6677725ccfdSJing Huang 		return;
6687725ccfdSJing Huang 	}
6697725ccfdSJing Huang 
670a36c61f9SKrishna Gudipati 	if (fchs->type == FC_TYPE_BLS) {
671a36c61f9SKrishna Gudipati 		if ((fchs->routing == FC_RTG_BASIC_LINK) &&
672a36c61f9SKrishna Gudipati 				(fchs->cat_info == FC_CAT_ABTS))
673a36c61f9SKrishna Gudipati 			bfa_fcs_lport_abts_acc(lport, fchs);
674a36c61f9SKrishna Gudipati 		return;
675a36c61f9SKrishna Gudipati 	}
6767725ccfdSJing Huang 	/**
6777725ccfdSJing Huang 	 * look for a matching remote port ID
6787725ccfdSJing Huang 	 */
679a36c61f9SKrishna Gudipati 	rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
6807725ccfdSJing Huang 	if (rport) {
6817725ccfdSJing Huang 		bfa_trc(rport->fcs, fchs->s_id);
6827725ccfdSJing Huang 		bfa_trc(rport->fcs, fchs->d_id);
6837725ccfdSJing Huang 		bfa_trc(rport->fcs, fchs->type);
6847725ccfdSJing Huang 
6857725ccfdSJing Huang 		bfa_fcs_rport_uf_recv(rport, fchs, len);
6867725ccfdSJing Huang 		return;
6877725ccfdSJing Huang 	}
6887725ccfdSJing Huang 
6897725ccfdSJing Huang 	/**
6907725ccfdSJing Huang 	 * Only handles ELS frames for now.
6917725ccfdSJing Huang 	 */
6927725ccfdSJing Huang 	if (fchs->type != FC_TYPE_ELS) {
6937725ccfdSJing Huang 		bfa_trc(lport->fcs, fchs->type);
6947725ccfdSJing Huang 		bfa_assert(0);
6957725ccfdSJing Huang 		return;
6967725ccfdSJing Huang 	}
6977725ccfdSJing Huang 
6987725ccfdSJing Huang 	bfa_trc(lport->fcs, els_cmd->els_code);
6997725ccfdSJing Huang 	if (els_cmd->els_code == FC_ELS_RSCN) {
700a36c61f9SKrishna Gudipati 		bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
7017725ccfdSJing Huang 		return;
7027725ccfdSJing Huang 	}
7037725ccfdSJing Huang 
7047725ccfdSJing Huang 	if (els_cmd->els_code == FC_ELS_LOGO) {
7057725ccfdSJing Huang 		/**
7067725ccfdSJing Huang 		 * @todo Handle LOGO frames received.
7077725ccfdSJing Huang 		 */
7087725ccfdSJing Huang 		return;
7097725ccfdSJing Huang 	}
7107725ccfdSJing Huang 
7117725ccfdSJing Huang 	if (els_cmd->els_code == FC_ELS_PRLI) {
7127725ccfdSJing Huang 		/**
7137725ccfdSJing Huang 		 * @todo Handle PRLI frames received.
7147725ccfdSJing Huang 		 */
7157725ccfdSJing Huang 		return;
7167725ccfdSJing Huang 	}
7177725ccfdSJing Huang 
7187725ccfdSJing Huang 	/**
7197725ccfdSJing Huang 	 * Unhandled ELS frames. Send a LS_RJT.
7207725ccfdSJing Huang 	 */
721a36c61f9SKrishna Gudipati 	bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
7227725ccfdSJing Huang 				 FC_LS_RJT_EXP_NO_ADDL_INFO);
7237725ccfdSJing Huang 
7247725ccfdSJing Huang }
7257725ccfdSJing Huang 
7267725ccfdSJing Huang /**
7277725ccfdSJing Huang  *   PID based Lookup for a R-Port in the Port R-Port Queue
7287725ccfdSJing Huang  */
7297725ccfdSJing Huang struct bfa_fcs_rport_s *
730a36c61f9SKrishna Gudipati bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
7317725ccfdSJing Huang {
7327725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport;
7337725ccfdSJing Huang 	struct list_head	*qe;
7347725ccfdSJing Huang 
7357725ccfdSJing Huang 	list_for_each(qe, &port->rport_q) {
7367725ccfdSJing Huang 		rport = (struct bfa_fcs_rport_s *) qe;
7377725ccfdSJing Huang 		if (rport->pid == pid)
7387725ccfdSJing Huang 			return rport;
7397725ccfdSJing Huang 	}
7407725ccfdSJing Huang 
7417725ccfdSJing Huang 	bfa_trc(port->fcs, pid);
7427725ccfdSJing Huang 	return NULL;
7437725ccfdSJing Huang }
7447725ccfdSJing Huang 
7457725ccfdSJing Huang /**
7467725ccfdSJing Huang  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
7477725ccfdSJing Huang  */
7487725ccfdSJing Huang struct bfa_fcs_rport_s *
749a36c61f9SKrishna Gudipati bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
7507725ccfdSJing Huang {
7517725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport;
7527725ccfdSJing Huang 	struct list_head	*qe;
7537725ccfdSJing Huang 
7547725ccfdSJing Huang 	list_for_each(qe, &port->rport_q) {
7557725ccfdSJing Huang 		rport = (struct bfa_fcs_rport_s *) qe;
7567725ccfdSJing Huang 		if (wwn_is_equal(rport->pwwn, pwwn))
7577725ccfdSJing Huang 			return rport;
7587725ccfdSJing Huang 	}
7597725ccfdSJing Huang 
7607725ccfdSJing Huang 	bfa_trc(port->fcs, pwwn);
761f8ceafdeSJing Huang 	return NULL;
7627725ccfdSJing Huang }
7637725ccfdSJing Huang 
7647725ccfdSJing Huang /**
7657725ccfdSJing Huang  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
7667725ccfdSJing Huang  */
7677725ccfdSJing Huang struct bfa_fcs_rport_s *
768a36c61f9SKrishna Gudipati bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
7697725ccfdSJing Huang {
7707725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport;
7717725ccfdSJing Huang 	struct list_head	*qe;
7727725ccfdSJing Huang 
7737725ccfdSJing Huang 	list_for_each(qe, &port->rport_q) {
7747725ccfdSJing Huang 		rport = (struct bfa_fcs_rport_s *) qe;
7757725ccfdSJing Huang 		if (wwn_is_equal(rport->nwwn, nwwn))
7767725ccfdSJing Huang 			return rport;
7777725ccfdSJing Huang 	}
7787725ccfdSJing Huang 
7797725ccfdSJing Huang 	bfa_trc(port->fcs, nwwn);
780f8ceafdeSJing Huang 	return NULL;
7817725ccfdSJing Huang }
7827725ccfdSJing Huang 
7837725ccfdSJing Huang /**
7847725ccfdSJing Huang  * Called by rport module when new rports are discovered.
7857725ccfdSJing Huang  */
7867725ccfdSJing Huang void
787a36c61f9SKrishna Gudipati bfa_fcs_lport_add_rport(
788a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port,
7897725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport)
7907725ccfdSJing Huang {
7917725ccfdSJing Huang 	list_add_tail(&rport->qe, &port->rport_q);
7927725ccfdSJing Huang 	port->num_rports++;
7937725ccfdSJing Huang }
7947725ccfdSJing Huang 
7957725ccfdSJing Huang /**
7967725ccfdSJing Huang  * Called by rport module to when rports are deleted.
7977725ccfdSJing Huang  */
7987725ccfdSJing Huang void
799a36c61f9SKrishna Gudipati bfa_fcs_lport_del_rport(
800a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port,
8017725ccfdSJing Huang 	struct bfa_fcs_rport_s *rport)
8027725ccfdSJing Huang {
8037725ccfdSJing Huang 	bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
8047725ccfdSJing Huang 	list_del(&rport->qe);
8057725ccfdSJing Huang 	port->num_rports--;
8067725ccfdSJing Huang 
8077725ccfdSJing Huang 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
8087725ccfdSJing Huang }
8097725ccfdSJing Huang 
8107725ccfdSJing Huang /**
8117725ccfdSJing Huang  * Called by fabric for base port when fabric login is complete.
8127725ccfdSJing Huang  * Called by vport for virtual ports when FDISC is complete.
8137725ccfdSJing Huang  */
8147725ccfdSJing Huang void
815a36c61f9SKrishna Gudipati bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
8167725ccfdSJing Huang {
8177725ccfdSJing Huang 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
8187725ccfdSJing Huang }
8197725ccfdSJing Huang 
8207725ccfdSJing Huang /**
8217725ccfdSJing Huang  * Called by fabric for base port when fabric goes offline.
8227725ccfdSJing Huang  * Called by vport for virtual ports when virtual port becomes offline.
8237725ccfdSJing Huang  */
8247725ccfdSJing Huang void
825a36c61f9SKrishna Gudipati bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
8267725ccfdSJing Huang {
8277725ccfdSJing Huang 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
8287725ccfdSJing Huang }
8297725ccfdSJing Huang 
8307725ccfdSJing Huang /**
8317725ccfdSJing Huang  * Called by fabric to delete base lport and associated resources.
8327725ccfdSJing Huang  *
8337725ccfdSJing Huang  * Called by vport to delete lport and associated resources. Should call
8347725ccfdSJing Huang  * bfa_fcs_vport_delete_comp() for vports on completion.
8357725ccfdSJing Huang  */
8367725ccfdSJing Huang void
837a36c61f9SKrishna Gudipati bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
8387725ccfdSJing Huang {
8397725ccfdSJing Huang 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
8407725ccfdSJing Huang }
8417725ccfdSJing Huang 
8427725ccfdSJing Huang /**
8437725ccfdSJing Huang  * Return TRUE if port is online, else return FALSE
8447725ccfdSJing Huang  */
8457725ccfdSJing Huang bfa_boolean_t
846a36c61f9SKrishna Gudipati bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
8477725ccfdSJing Huang {
848a36c61f9SKrishna Gudipati 	return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
8497725ccfdSJing Huang }
8507725ccfdSJing Huang 
8517725ccfdSJing Huang /**
852e6714324SKrishna Gudipati   * Attach time initialization of logical ports.
8537725ccfdSJing Huang  */
8547725ccfdSJing Huang void
855a36c61f9SKrishna Gudipati bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
856a36c61f9SKrishna Gudipati 		   u16 vf_id, struct bfa_fcs_vport_s *vport)
8577725ccfdSJing Huang {
8587725ccfdSJing Huang 	lport->fcs = fcs;
8597725ccfdSJing Huang 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
8607725ccfdSJing Huang 	lport->vport = vport;
8617725ccfdSJing Huang 	lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
8627725ccfdSJing Huang 				  bfa_lps_get_tag(lport->fabric->lps);
8637725ccfdSJing Huang 
8647725ccfdSJing Huang 	INIT_LIST_HEAD(&lport->rport_q);
8657725ccfdSJing Huang 	lport->num_rports = 0;
866e6714324SKrishna Gudipati }
8677725ccfdSJing Huang 
868e6714324SKrishna Gudipati /**
869e6714324SKrishna Gudipati  * Logical port initialization of base or virtual port.
870e6714324SKrishna Gudipati  * Called by fabric for base port or by vport for virtual ports.
871e6714324SKrishna Gudipati  */
872e6714324SKrishna Gudipati 
873e6714324SKrishna Gudipati void
874a36c61f9SKrishna Gudipati bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
875a36c61f9SKrishna Gudipati 	struct bfa_lport_cfg_s *port_cfg)
876e6714324SKrishna Gudipati {
877e6714324SKrishna Gudipati 	struct bfa_fcs_vport_s *vport = lport->vport;
878a36c61f9SKrishna Gudipati 	struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
879a36c61f9SKrishna Gudipati 	char    lpwwn_buf[BFA_STRING_32];
880e6714324SKrishna Gudipati 
8816a18b167SJing Huang 	lport->port_cfg = *port_cfg;
882e6714324SKrishna Gudipati 
883a36c61f9SKrishna Gudipati 	lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
884e6714324SKrishna Gudipati 					lport->port_cfg.roles,
8857725ccfdSJing Huang 					lport->fabric->vf_drv,
8867725ccfdSJing Huang 					vport ? vport->vport_drv : NULL);
887e6714324SKrishna Gudipati 
888a36c61f9SKrishna Gudipati 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
889a36c61f9SKrishna Gudipati 	BFA_LOG(KERN_INFO, bfad, log_level,
890a36c61f9SKrishna Gudipati 		"New logical port created: WWN = %s Role = %s\n",
891a36c61f9SKrishna Gudipati 		lpwwn_buf, "Initiator");
8927725ccfdSJing Huang 
893a36c61f9SKrishna Gudipati 	bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
8947725ccfdSJing Huang 	bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
8957725ccfdSJing Huang }
8967725ccfdSJing Huang 
8977725ccfdSJing Huang /**
8987725ccfdSJing Huang  *  fcs_lport_api
8997725ccfdSJing Huang  */
9007725ccfdSJing Huang 
9017725ccfdSJing Huang void
902a36c61f9SKrishna Gudipati bfa_fcs_lport_get_attr(
903a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port,
904a36c61f9SKrishna Gudipati 	struct bfa_lport_attr_s *port_attr)
9057725ccfdSJing Huang {
906a36c61f9SKrishna Gudipati 	if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
9077725ccfdSJing Huang 		port_attr->pid = port->pid;
9087725ccfdSJing Huang 	else
9097725ccfdSJing Huang 		port_attr->pid = 0;
9107725ccfdSJing Huang 
9117725ccfdSJing Huang 	port_attr->port_cfg = port->port_cfg;
9127725ccfdSJing Huang 
9137725ccfdSJing Huang 	if (port->fabric) {
9147725ccfdSJing Huang 		port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
9157725ccfdSJing Huang 		port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
916f926a05fSKrishna Gudipati 		port_attr->authfail =
917f926a05fSKrishna Gudipati 			bfa_fcs_fabric_is_auth_failed(port->fabric);
918a36c61f9SKrishna Gudipati 		port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
9197725ccfdSJing Huang 		memcpy(port_attr->fabric_ip_addr,
920a36c61f9SKrishna Gudipati 			bfa_fcs_lport_get_fabric_ipaddr(port),
9217725ccfdSJing Huang 			BFA_FCS_FABRIC_IPADDR_SZ);
9227725ccfdSJing Huang 
92386e32dabSKrishna Gudipati 		if (port->vport != NULL) {
924a36c61f9SKrishna Gudipati 			port_attr->port_type = BFA_PORT_TYPE_VPORT;
92586e32dabSKrishna Gudipati 			port_attr->fpma_mac =
92686e32dabSKrishna Gudipati 				bfa_lps_get_lp_mac(port->vport->lps);
927a36c61f9SKrishna Gudipati 		} else {
92886e32dabSKrishna Gudipati 			port_attr->fpma_mac =
92986e32dabSKrishna Gudipati 				bfa_lps_get_lp_mac(port->fabric->lps);
930a36c61f9SKrishna Gudipati 		}
931a36c61f9SKrishna Gudipati 	} else {
932a36c61f9SKrishna Gudipati 		port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
933a36c61f9SKrishna Gudipati 		port_attr->state = BFA_LPORT_UNINIT;
934a36c61f9SKrishna Gudipati 	}
935a36c61f9SKrishna Gudipati }
936a36c61f9SKrishna Gudipati 
937a36c61f9SKrishna Gudipati /**
938a36c61f9SKrishna Gudipati  *  bfa_fcs_lport_fab port fab functions
939a36c61f9SKrishna Gudipati  */
940a36c61f9SKrishna Gudipati 
941a36c61f9SKrishna Gudipati /**
942a36c61f9SKrishna Gudipati  *   Called by port to initialize fabric services of the base port.
943a36c61f9SKrishna Gudipati  */
944a36c61f9SKrishna Gudipati static void
945a36c61f9SKrishna Gudipati bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
946a36c61f9SKrishna Gudipati {
947a36c61f9SKrishna Gudipati 	bfa_fcs_lport_ns_init(port);
948a36c61f9SKrishna Gudipati 	bfa_fcs_lport_scn_init(port);
949a36c61f9SKrishna Gudipati 	bfa_fcs_lport_ms_init(port);
950a36c61f9SKrishna Gudipati }
951a36c61f9SKrishna Gudipati 
952a36c61f9SKrishna Gudipati /**
953a36c61f9SKrishna Gudipati  *   Called by port to notify transition to online state.
954a36c61f9SKrishna Gudipati  */
955a36c61f9SKrishna Gudipati static void
956a36c61f9SKrishna Gudipati bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
957a36c61f9SKrishna Gudipati {
958a36c61f9SKrishna Gudipati 	bfa_fcs_lport_ns_online(port);
959a36c61f9SKrishna Gudipati 	bfa_fcs_lport_scn_online(port);
960a36c61f9SKrishna Gudipati }
961a36c61f9SKrishna Gudipati 
962a36c61f9SKrishna Gudipati /**
963a36c61f9SKrishna Gudipati  *   Called by port to notify transition to offline state.
964a36c61f9SKrishna Gudipati  */
965a36c61f9SKrishna Gudipati static void
966a36c61f9SKrishna Gudipati bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
967a36c61f9SKrishna Gudipati {
968a36c61f9SKrishna Gudipati 	bfa_fcs_lport_ns_offline(port);
969a36c61f9SKrishna Gudipati 	bfa_fcs_lport_scn_offline(port);
970a36c61f9SKrishna Gudipati 	bfa_fcs_lport_ms_offline(port);
971a36c61f9SKrishna Gudipati }
972a36c61f9SKrishna Gudipati 
973a36c61f9SKrishna Gudipati /**
974a36c61f9SKrishna Gudipati  *  bfa_fcs_lport_n2n  functions
975a36c61f9SKrishna Gudipati  */
976a36c61f9SKrishna Gudipati 
977a36c61f9SKrishna Gudipati /**
978a36c61f9SKrishna Gudipati  *   Called by fcs/port to initialize N2N topology.
979a36c61f9SKrishna Gudipati  */
980a36c61f9SKrishna Gudipati static void
981a36c61f9SKrishna Gudipati bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
982a36c61f9SKrishna Gudipati {
983a36c61f9SKrishna Gudipati }
984a36c61f9SKrishna Gudipati 
985a36c61f9SKrishna Gudipati /**
986a36c61f9SKrishna Gudipati  *   Called by fcs/port to notify transition to online state.
987a36c61f9SKrishna Gudipati  */
988a36c61f9SKrishna Gudipati static void
989a36c61f9SKrishna Gudipati bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
990a36c61f9SKrishna Gudipati {
991a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
992a36c61f9SKrishna Gudipati 	struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
993a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport;
994a36c61f9SKrishna Gudipati 
995a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, pcfg->pwwn);
996a36c61f9SKrishna Gudipati 
997a36c61f9SKrishna Gudipati 	/*
998a36c61f9SKrishna Gudipati 	 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
999a36c61f9SKrishna Gudipati 	 * and assign an Address. if not, we need to wait for its PLOGI.
1000a36c61f9SKrishna Gudipati 	 *
1001a36c61f9SKrishna Gudipati 	 * If our PWWN is < than that of the remote port, it will send a PLOGI
1002a36c61f9SKrishna Gudipati 	 * with the PIDs assigned. The rport state machine take care of this
1003a36c61f9SKrishna Gudipati 	 * incoming PLOGI.
1004a36c61f9SKrishna Gudipati 	 */
1005a36c61f9SKrishna Gudipati 	if (memcmp
1006a36c61f9SKrishna Gudipati 	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
1007a36c61f9SKrishna Gudipati 	     sizeof(wwn_t)) > 0) {
1008a36c61f9SKrishna Gudipati 		port->pid = N2N_LOCAL_PID;
1009a36c61f9SKrishna Gudipati 		/**
1010a36c61f9SKrishna Gudipati 		 * First, check if we know the device by pwwn.
1011a36c61f9SKrishna Gudipati 		 */
1012a36c61f9SKrishna Gudipati 		rport = bfa_fcs_lport_get_rport_by_pwwn(port,
1013a36c61f9SKrishna Gudipati 							n2n_port->rem_port_wwn);
1014a36c61f9SKrishna Gudipati 		if (rport) {
1015a36c61f9SKrishna Gudipati 			bfa_trc(port->fcs, rport->pid);
1016a36c61f9SKrishna Gudipati 			bfa_trc(port->fcs, rport->pwwn);
1017a36c61f9SKrishna Gudipati 			rport->pid = N2N_REMOTE_PID;
1018a36c61f9SKrishna Gudipati 			bfa_fcs_rport_online(rport);
1019a36c61f9SKrishna Gudipati 			return;
1020a36c61f9SKrishna Gudipati 		}
1021a36c61f9SKrishna Gudipati 
1022a36c61f9SKrishna Gudipati 		/*
1023a36c61f9SKrishna Gudipati 		 * In n2n there can be only one rport. Delete the old one
1024a36c61f9SKrishna Gudipati 		 * whose pid should be zero, because it is offline.
1025a36c61f9SKrishna Gudipati 		 */
1026a36c61f9SKrishna Gudipati 		if (port->num_rports > 0) {
1027a36c61f9SKrishna Gudipati 			rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1028a36c61f9SKrishna Gudipati 			bfa_assert(rport != NULL);
1029a36c61f9SKrishna Gudipati 			if (rport) {
1030a36c61f9SKrishna Gudipati 				bfa_trc(port->fcs, rport->pwwn);
1031a36c61f9SKrishna Gudipati 				bfa_fcs_rport_delete(rport);
1032a36c61f9SKrishna Gudipati 			}
1033a36c61f9SKrishna Gudipati 		}
1034a36c61f9SKrishna Gudipati 		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1035a36c61f9SKrishna Gudipati 	}
1036a36c61f9SKrishna Gudipati }
1037a36c61f9SKrishna Gudipati 
1038a36c61f9SKrishna Gudipati /**
1039a36c61f9SKrishna Gudipati  *   Called by fcs/port to notify transition to offline state.
1040a36c61f9SKrishna Gudipati  */
1041a36c61f9SKrishna Gudipati static void
1042a36c61f9SKrishna Gudipati bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1043a36c61f9SKrishna Gudipati {
1044a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1045a36c61f9SKrishna Gudipati 
1046a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
1047a36c61f9SKrishna Gudipati 	port->pid = 0;
1048a36c61f9SKrishna Gudipati 	n2n_port->rem_port_wwn = 0;
1049a36c61f9SKrishna Gudipati 	n2n_port->reply_oxid = 0;
1050a36c61f9SKrishna Gudipati }
1051a36c61f9SKrishna Gudipati 
1052a36c61f9SKrishna Gudipati #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1053a36c61f9SKrishna Gudipati 
1054a36c61f9SKrishna Gudipati /*
1055a36c61f9SKrishna Gudipati  * forward declarations
1056a36c61f9SKrishna Gudipati  */
1057a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1058a36c61f9SKrishna Gudipati 					    struct bfa_fcxp_s *fcxp_alloced);
1059a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1060a36c61f9SKrishna Gudipati 					    struct bfa_fcxp_s *fcxp_alloced);
1061a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1062a36c61f9SKrishna Gudipati 					   struct bfa_fcxp_s *fcxp_alloced);
1063a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1064a36c61f9SKrishna Gudipati 						struct bfa_fcxp_s *fcxp,
1065a36c61f9SKrishna Gudipati 						void *cbarg,
1066a36c61f9SKrishna Gudipati 						bfa_status_t req_status,
1067a36c61f9SKrishna Gudipati 						u32 rsp_len,
1068a36c61f9SKrishna Gudipati 						u32 resid_len,
1069a36c61f9SKrishna Gudipati 						struct fchs_s *rsp_fchs);
1070a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1071a36c61f9SKrishna Gudipati 						struct bfa_fcxp_s *fcxp,
1072a36c61f9SKrishna Gudipati 						void *cbarg,
1073a36c61f9SKrishna Gudipati 						bfa_status_t req_status,
1074a36c61f9SKrishna Gudipati 						u32 rsp_len,
1075a36c61f9SKrishna Gudipati 						u32 resid_len,
1076a36c61f9SKrishna Gudipati 						struct fchs_s *rsp_fchs);
1077a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1078a36c61f9SKrishna Gudipati 					       struct bfa_fcxp_s *fcxp,
1079a36c61f9SKrishna Gudipati 					       void *cbarg,
1080a36c61f9SKrishna Gudipati 					       bfa_status_t req_status,
1081a36c61f9SKrishna Gudipati 					       u32 rsp_len,
1082a36c61f9SKrishna Gudipati 					       u32 resid_len,
1083a36c61f9SKrishna Gudipati 					       struct fchs_s *rsp_fchs);
1084a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_timeout(void *arg);
1085a36c61f9SKrishna Gudipati static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1086a36c61f9SKrishna Gudipati 						  u8 *pyld);
1087a36c61f9SKrishna Gudipati static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1088a36c61f9SKrishna Gudipati 						  u8 *pyld);
1089a36c61f9SKrishna Gudipati static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1090a36c61f9SKrishna Gudipati 						 u8 *pyld);
1091a36c61f9SKrishna Gudipati static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1092a36c61f9SKrishna Gudipati 						       fdmi, u8 *pyld);
1093a36c61f9SKrishna Gudipati static void	bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1094a36c61f9SKrishna Gudipati 				 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1095a36c61f9SKrishna Gudipati static void	bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1096a36c61f9SKrishna Gudipati 				  struct bfa_fcs_fdmi_port_attr_s *port_attr);
1097a36c61f9SKrishna Gudipati /**
1098a36c61f9SKrishna Gudipati  *  fcs_fdmi_sm FCS FDMI state machine
1099a36c61f9SKrishna Gudipati  */
1100a36c61f9SKrishna Gudipati 
1101a36c61f9SKrishna Gudipati /**
1102a36c61f9SKrishna Gudipati  *  FDMI State Machine events
1103a36c61f9SKrishna Gudipati  */
1104a36c61f9SKrishna Gudipati enum port_fdmi_event {
1105a36c61f9SKrishna Gudipati 	FDMISM_EVENT_PORT_ONLINE = 1,
1106a36c61f9SKrishna Gudipati 	FDMISM_EVENT_PORT_OFFLINE = 2,
1107a36c61f9SKrishna Gudipati 	FDMISM_EVENT_RSP_OK = 4,
1108a36c61f9SKrishna Gudipati 	FDMISM_EVENT_RSP_ERROR = 5,
1109a36c61f9SKrishna Gudipati 	FDMISM_EVENT_TIMEOUT = 6,
1110a36c61f9SKrishna Gudipati 	FDMISM_EVENT_RHBA_SENT = 7,
1111a36c61f9SKrishna Gudipati 	FDMISM_EVENT_RPRT_SENT = 8,
1112a36c61f9SKrishna Gudipati 	FDMISM_EVENT_RPA_SENT = 9,
1113a36c61f9SKrishna Gudipati };
1114a36c61f9SKrishna Gudipati 
1115a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1116a36c61f9SKrishna Gudipati 					     enum port_fdmi_event event);
1117a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
1118a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_fdmi_s *fdmi,
1119a36c61f9SKrishna Gudipati 				enum port_fdmi_event event);
1120a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1121a36c61f9SKrishna Gudipati 					  enum port_fdmi_event event);
1122a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
1123a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_fdmi_s *fdmi,
1124a36c61f9SKrishna Gudipati 				enum port_fdmi_event event);
1125a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
1126a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_fdmi_s *fdmi,
1127a36c61f9SKrishna Gudipati 				enum port_fdmi_event event);
1128a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1129a36c61f9SKrishna Gudipati 					  enum port_fdmi_event event);
1130a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
1131a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_fdmi_s *fdmi,
1132a36c61f9SKrishna Gudipati 				enum port_fdmi_event event);
1133a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
1134a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_fdmi_s *fdmi,
1135a36c61f9SKrishna Gudipati 				enum port_fdmi_event event);
1136a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1137a36c61f9SKrishna Gudipati 					 enum port_fdmi_event event);
1138a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
1139a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_fdmi_s *fdmi,
1140a36c61f9SKrishna Gudipati 				enum port_fdmi_event event);
1141a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1142a36c61f9SKrishna Gudipati 					    enum port_fdmi_event event);
1143a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_fdmi_sm_disabled(
1144a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_fdmi_s *fdmi,
1145a36c61f9SKrishna Gudipati 				enum port_fdmi_event event);
1146a36c61f9SKrishna Gudipati /**
1147a36c61f9SKrishna Gudipati  *	Start in offline state - awaiting MS to send start.
1148a36c61f9SKrishna Gudipati  */
1149a36c61f9SKrishna Gudipati static void
1150a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1151a36c61f9SKrishna Gudipati 			     enum port_fdmi_event event)
1152a36c61f9SKrishna Gudipati {
1153a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1154a36c61f9SKrishna Gudipati 
1155a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1156a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1157a36c61f9SKrishna Gudipati 
1158a36c61f9SKrishna Gudipati 	fdmi->retry_cnt = 0;
1159a36c61f9SKrishna Gudipati 
1160a36c61f9SKrishna Gudipati 	switch (event) {
1161a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_ONLINE:
1162a36c61f9SKrishna Gudipati 		if (port->vport) {
1163a36c61f9SKrishna Gudipati 			/*
1164a36c61f9SKrishna Gudipati 			 * For Vports, register a new port.
1165a36c61f9SKrishna Gudipati 			 */
1166a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi,
1167a36c61f9SKrishna Gudipati 					 bfa_fcs_lport_fdmi_sm_sending_rprt);
1168a36c61f9SKrishna Gudipati 			bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1169a36c61f9SKrishna Gudipati 		} else {
1170a36c61f9SKrishna Gudipati 			/*
1171a36c61f9SKrishna Gudipati 			 * For a base port, we should first register the HBA
1172a36c61f9SKrishna Gudipati 			 * atribute. The HBA attribute also contains the base
1173a36c61f9SKrishna Gudipati 			 *  port registration.
1174a36c61f9SKrishna Gudipati 			 */
1175a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi,
1176a36c61f9SKrishna Gudipati 					 bfa_fcs_lport_fdmi_sm_sending_rhba);
1177a36c61f9SKrishna Gudipati 			bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1178a36c61f9SKrishna Gudipati 		}
1179a36c61f9SKrishna Gudipati 		break;
1180a36c61f9SKrishna Gudipati 
1181a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1182a36c61f9SKrishna Gudipati 		break;
1183a36c61f9SKrishna Gudipati 
1184a36c61f9SKrishna Gudipati 	default:
1185a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1186a36c61f9SKrishna Gudipati 	}
1187a36c61f9SKrishna Gudipati }
1188a36c61f9SKrishna Gudipati 
1189a36c61f9SKrishna Gudipati static void
1190a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1191a36c61f9SKrishna Gudipati 				  enum port_fdmi_event event)
1192a36c61f9SKrishna Gudipati {
1193a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1194a36c61f9SKrishna Gudipati 
1195a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1196a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1197a36c61f9SKrishna Gudipati 
1198a36c61f9SKrishna Gudipati 	switch (event) {
1199a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RHBA_SENT:
1200a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1201a36c61f9SKrishna Gudipati 		break;
1202a36c61f9SKrishna Gudipati 
1203a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1204a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1205a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1206a36c61f9SKrishna Gudipati 					   &fdmi->fcxp_wqe);
1207a36c61f9SKrishna Gudipati 		break;
1208a36c61f9SKrishna Gudipati 
1209a36c61f9SKrishna Gudipati 	default:
1210a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1211a36c61f9SKrishna Gudipati 	}
1212a36c61f9SKrishna Gudipati }
1213a36c61f9SKrishna Gudipati 
1214a36c61f9SKrishna Gudipati static void
1215a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1216a36c61f9SKrishna Gudipati 			enum port_fdmi_event event)
1217a36c61f9SKrishna Gudipati {
1218a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1219a36c61f9SKrishna Gudipati 
1220a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1221a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1222a36c61f9SKrishna Gudipati 
1223a36c61f9SKrishna Gudipati 	switch (event) {
1224a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RSP_ERROR:
1225a36c61f9SKrishna Gudipati 		/*
1226a36c61f9SKrishna Gudipati 		 * if max retries have not been reached, start timer for a
1227a36c61f9SKrishna Gudipati 		 * delayed retry
1228a36c61f9SKrishna Gudipati 		 */
1229a36c61f9SKrishna Gudipati 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1230a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi,
1231a36c61f9SKrishna Gudipati 					bfa_fcs_lport_fdmi_sm_rhba_retry);
1232a36c61f9SKrishna Gudipati 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1233a36c61f9SKrishna Gudipati 					    &fdmi->timer,
1234a36c61f9SKrishna Gudipati 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1235a36c61f9SKrishna Gudipati 					    BFA_FCS_RETRY_TIMEOUT);
1236a36c61f9SKrishna Gudipati 		} else {
1237a36c61f9SKrishna Gudipati 			/*
1238a36c61f9SKrishna Gudipati 			 * set state to offline
1239a36c61f9SKrishna Gudipati 			 */
1240a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1241a36c61f9SKrishna Gudipati 		}
1242a36c61f9SKrishna Gudipati 		break;
1243a36c61f9SKrishna Gudipati 
1244a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RSP_OK:
1245a36c61f9SKrishna Gudipati 		/*
1246a36c61f9SKrishna Gudipati 		 * Initiate Register Port Attributes
1247a36c61f9SKrishna Gudipati 		 */
1248a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1249a36c61f9SKrishna Gudipati 		fdmi->retry_cnt = 0;
1250a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1251a36c61f9SKrishna Gudipati 		break;
1252a36c61f9SKrishna Gudipati 
1253a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1254a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(fdmi->fcxp);
1255a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1256a36c61f9SKrishna Gudipati 		break;
1257a36c61f9SKrishna Gudipati 
1258a36c61f9SKrishna Gudipati 	default:
1259a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1260a36c61f9SKrishna Gudipati 	}
1261a36c61f9SKrishna Gudipati }
1262a36c61f9SKrishna Gudipati 
1263a36c61f9SKrishna Gudipati static void
1264a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1265a36c61f9SKrishna Gudipati 				enum port_fdmi_event event)
1266a36c61f9SKrishna Gudipati {
1267a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1268a36c61f9SKrishna Gudipati 
1269a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1270a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1271a36c61f9SKrishna Gudipati 
1272a36c61f9SKrishna Gudipati 	switch (event) {
1273a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_TIMEOUT:
1274a36c61f9SKrishna Gudipati 		/*
1275a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
1276a36c61f9SKrishna Gudipati 		 */
1277a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1278a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1279a36c61f9SKrishna Gudipati 		break;
1280a36c61f9SKrishna Gudipati 
1281a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1282a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1283a36c61f9SKrishna Gudipati 		bfa_timer_stop(&fdmi->timer);
1284a36c61f9SKrishna Gudipati 		break;
1285a36c61f9SKrishna Gudipati 
1286a36c61f9SKrishna Gudipati 	default:
1287a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1288a36c61f9SKrishna Gudipati 	}
1289a36c61f9SKrishna Gudipati }
1290a36c61f9SKrishna Gudipati 
1291a36c61f9SKrishna Gudipati /*
1292a36c61f9SKrishna Gudipati * RPRT : Register Port
1293a36c61f9SKrishna Gudipati  */
1294a36c61f9SKrishna Gudipati static void
1295a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1296a36c61f9SKrishna Gudipati 				  enum port_fdmi_event event)
1297a36c61f9SKrishna Gudipati {
1298a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1299a36c61f9SKrishna Gudipati 
1300a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1301a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1302a36c61f9SKrishna Gudipati 
1303a36c61f9SKrishna Gudipati 	switch (event) {
1304a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RPRT_SENT:
1305a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1306a36c61f9SKrishna Gudipati 		break;
1307a36c61f9SKrishna Gudipati 
1308a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1309a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1310a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1311a36c61f9SKrishna Gudipati 					   &fdmi->fcxp_wqe);
1312a36c61f9SKrishna Gudipati 		break;
1313a36c61f9SKrishna Gudipati 
1314a36c61f9SKrishna Gudipati 	default:
1315a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1316a36c61f9SKrishna Gudipati 	}
1317a36c61f9SKrishna Gudipati }
1318a36c61f9SKrishna Gudipati 
1319a36c61f9SKrishna Gudipati static void
1320a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1321a36c61f9SKrishna Gudipati 			enum port_fdmi_event event)
1322a36c61f9SKrishna Gudipati {
1323a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1324a36c61f9SKrishna Gudipati 
1325a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1326a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1327a36c61f9SKrishna Gudipati 
1328a36c61f9SKrishna Gudipati 	switch (event) {
1329a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RSP_ERROR:
1330a36c61f9SKrishna Gudipati 		/*
1331a36c61f9SKrishna Gudipati 		 * if max retries have not been reached, start timer for a
1332a36c61f9SKrishna Gudipati 		 * delayed retry
1333a36c61f9SKrishna Gudipati 		 */
1334a36c61f9SKrishna Gudipati 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1335a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi,
1336a36c61f9SKrishna Gudipati 					bfa_fcs_lport_fdmi_sm_rprt_retry);
1337a36c61f9SKrishna Gudipati 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1338a36c61f9SKrishna Gudipati 					    &fdmi->timer,
1339a36c61f9SKrishna Gudipati 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1340a36c61f9SKrishna Gudipati 					    BFA_FCS_RETRY_TIMEOUT);
13417725ccfdSJing Huang 
13427725ccfdSJing Huang 		} else {
1343a36c61f9SKrishna Gudipati 			/*
1344a36c61f9SKrishna Gudipati 			 * set state to offline
1345a36c61f9SKrishna Gudipati 			 */
1346a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1347a36c61f9SKrishna Gudipati 			fdmi->retry_cnt = 0;
13487725ccfdSJing Huang 		}
1349a36c61f9SKrishna Gudipati 		break;
1350a36c61f9SKrishna Gudipati 
1351a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RSP_OK:
1352a36c61f9SKrishna Gudipati 		fdmi->retry_cnt = 0;
1353a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1354a36c61f9SKrishna Gudipati 		break;
1355a36c61f9SKrishna Gudipati 
1356a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1357a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(fdmi->fcxp);
1358a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1359a36c61f9SKrishna Gudipati 		break;
1360a36c61f9SKrishna Gudipati 
1361a36c61f9SKrishna Gudipati 	default:
1362a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1363a36c61f9SKrishna Gudipati 	}
1364a36c61f9SKrishna Gudipati }
1365a36c61f9SKrishna Gudipati 
1366a36c61f9SKrishna Gudipati static void
1367a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1368a36c61f9SKrishna Gudipati 				enum port_fdmi_event event)
1369a36c61f9SKrishna Gudipati {
1370a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1371a36c61f9SKrishna Gudipati 
1372a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1373a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1374a36c61f9SKrishna Gudipati 
1375a36c61f9SKrishna Gudipati 	switch (event) {
1376a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_TIMEOUT:
1377a36c61f9SKrishna Gudipati 		/*
1378a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
1379a36c61f9SKrishna Gudipati 		 */
1380a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1381a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1382a36c61f9SKrishna Gudipati 		break;
1383a36c61f9SKrishna Gudipati 
1384a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1385a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1386a36c61f9SKrishna Gudipati 		bfa_timer_stop(&fdmi->timer);
1387a36c61f9SKrishna Gudipati 		break;
1388a36c61f9SKrishna Gudipati 
1389a36c61f9SKrishna Gudipati 	default:
1390a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1391a36c61f9SKrishna Gudipati 	}
1392a36c61f9SKrishna Gudipati }
1393a36c61f9SKrishna Gudipati 
1394a36c61f9SKrishna Gudipati /*
1395a36c61f9SKrishna Gudipati  * Register Port Attributes
1396a36c61f9SKrishna Gudipati  */
1397a36c61f9SKrishna Gudipati static void
1398a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1399a36c61f9SKrishna Gudipati 				 enum port_fdmi_event event)
1400a36c61f9SKrishna Gudipati {
1401a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1402a36c61f9SKrishna Gudipati 
1403a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1404a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1405a36c61f9SKrishna Gudipati 
1406a36c61f9SKrishna Gudipati 	switch (event) {
1407a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RPA_SENT:
1408a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1409a36c61f9SKrishna Gudipati 		break;
1410a36c61f9SKrishna Gudipati 
1411a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1412a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1413a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1414a36c61f9SKrishna Gudipati 					   &fdmi->fcxp_wqe);
1415a36c61f9SKrishna Gudipati 		break;
1416a36c61f9SKrishna Gudipati 
1417a36c61f9SKrishna Gudipati 	default:
1418a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1419a36c61f9SKrishna Gudipati 	}
1420a36c61f9SKrishna Gudipati }
1421a36c61f9SKrishna Gudipati 
1422a36c61f9SKrishna Gudipati static void
1423a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1424a36c61f9SKrishna Gudipati 			enum port_fdmi_event event)
1425a36c61f9SKrishna Gudipati {
1426a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1427a36c61f9SKrishna Gudipati 
1428a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1429a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1430a36c61f9SKrishna Gudipati 
1431a36c61f9SKrishna Gudipati 	switch (event) {
1432a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RSP_ERROR:
1433a36c61f9SKrishna Gudipati 		/*
1434a36c61f9SKrishna Gudipati 		 * if max retries have not been reached, start timer for a
1435a36c61f9SKrishna Gudipati 		 * delayed retry
1436a36c61f9SKrishna Gudipati 		 */
1437a36c61f9SKrishna Gudipati 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1438a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1439a36c61f9SKrishna Gudipati 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1440a36c61f9SKrishna Gudipati 					    &fdmi->timer,
1441a36c61f9SKrishna Gudipati 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1442a36c61f9SKrishna Gudipati 					    BFA_FCS_RETRY_TIMEOUT);
1443a36c61f9SKrishna Gudipati 		} else {
1444a36c61f9SKrishna Gudipati 			/*
1445a36c61f9SKrishna Gudipati 			 * set state to offline
1446a36c61f9SKrishna Gudipati 			 */
1447a36c61f9SKrishna Gudipati 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1448a36c61f9SKrishna Gudipati 			fdmi->retry_cnt = 0;
1449a36c61f9SKrishna Gudipati 		}
1450a36c61f9SKrishna Gudipati 		break;
1451a36c61f9SKrishna Gudipati 
1452a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_RSP_OK:
1453a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1454a36c61f9SKrishna Gudipati 		fdmi->retry_cnt = 0;
1455a36c61f9SKrishna Gudipati 		break;
1456a36c61f9SKrishna Gudipati 
1457a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1458a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(fdmi->fcxp);
1459a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1460a36c61f9SKrishna Gudipati 		break;
1461a36c61f9SKrishna Gudipati 
1462a36c61f9SKrishna Gudipati 	default:
1463a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1464a36c61f9SKrishna Gudipati 	}
1465a36c61f9SKrishna Gudipati }
1466a36c61f9SKrishna Gudipati 
1467a36c61f9SKrishna Gudipati static void
1468a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1469a36c61f9SKrishna Gudipati 			       enum port_fdmi_event event)
1470a36c61f9SKrishna Gudipati {
1471a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1472a36c61f9SKrishna Gudipati 
1473a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1474a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1475a36c61f9SKrishna Gudipati 
1476a36c61f9SKrishna Gudipati 	switch (event) {
1477a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_TIMEOUT:
1478a36c61f9SKrishna Gudipati 		/*
1479a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
1480a36c61f9SKrishna Gudipati 		 */
1481a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1482a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1483a36c61f9SKrishna Gudipati 		break;
1484a36c61f9SKrishna Gudipati 
1485a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1486a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1487a36c61f9SKrishna Gudipati 		bfa_timer_stop(&fdmi->timer);
1488a36c61f9SKrishna Gudipati 		break;
1489a36c61f9SKrishna Gudipati 
1490a36c61f9SKrishna Gudipati 	default:
1491a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1492a36c61f9SKrishna Gudipati 	}
1493a36c61f9SKrishna Gudipati }
1494a36c61f9SKrishna Gudipati 
1495a36c61f9SKrishna Gudipati static void
1496a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1497a36c61f9SKrishna Gudipati 				enum port_fdmi_event event)
1498a36c61f9SKrishna Gudipati {
1499a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1500a36c61f9SKrishna Gudipati 
1501a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1502a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1503a36c61f9SKrishna Gudipati 
1504a36c61f9SKrishna Gudipati 	switch (event) {
1505a36c61f9SKrishna Gudipati 	case FDMISM_EVENT_PORT_OFFLINE:
1506a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1507a36c61f9SKrishna Gudipati 		break;
1508a36c61f9SKrishna Gudipati 
1509a36c61f9SKrishna Gudipati 	default:
1510a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
1511a36c61f9SKrishna Gudipati 	}
1512a36c61f9SKrishna Gudipati }
1513a36c61f9SKrishna Gudipati /**
1514a36c61f9SKrishna Gudipati  *  FDMI is disabled state.
1515a36c61f9SKrishna Gudipati  */
1516a36c61f9SKrishna Gudipati static void
1517a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1518a36c61f9SKrishna Gudipati 			     enum port_fdmi_event event)
1519a36c61f9SKrishna Gudipati {
1520a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1521a36c61f9SKrishna Gudipati 
1522a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1523a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, event);
1524a36c61f9SKrishna Gudipati 
1525a36c61f9SKrishna Gudipati 	/* No op State. It can only be enabled at Driver Init. */
1526a36c61f9SKrishna Gudipati }
1527a36c61f9SKrishna Gudipati 
1528a36c61f9SKrishna Gudipati /**
1529a36c61f9SKrishna Gudipati *  RHBA : Register HBA Attributes.
1530a36c61f9SKrishna Gudipati  */
1531a36c61f9SKrishna Gudipati static void
1532a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1533a36c61f9SKrishna Gudipati {
1534a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1535a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1536a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
1537a36c61f9SKrishna Gudipati 	int             len, attr_len;
1538a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
1539a36c61f9SKrishna Gudipati 	u8        *pyld;
1540a36c61f9SKrishna Gudipati 
1541a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1542a36c61f9SKrishna Gudipati 
1543a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1544a36c61f9SKrishna Gudipati 	if (!fcxp) {
1545a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1546a36c61f9SKrishna Gudipati 					bfa_fcs_lport_fdmi_send_rhba, fdmi);
1547a36c61f9SKrishna Gudipati 		return;
1548a36c61f9SKrishna Gudipati 	}
1549a36c61f9SKrishna Gudipati 	fdmi->fcxp = fcxp;
1550a36c61f9SKrishna Gudipati 
1551a36c61f9SKrishna Gudipati 	pyld = bfa_fcxp_get_reqbuf(fcxp);
15526a18b167SJing Huang 	memset(pyld, 0, FC_MAX_PDUSZ);
1553a36c61f9SKrishna Gudipati 
1554a36c61f9SKrishna Gudipati 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1555a36c61f9SKrishna Gudipati 				   FDMI_RHBA);
1556a36c61f9SKrishna Gudipati 
1557a36c61f9SKrishna Gudipati 	attr_len =
1558a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1559a36c61f9SKrishna Gudipati 					  (u8 *) ((struct ct_hdr_s *) pyld
1560a36c61f9SKrishna Gudipati 						       + 1));
1561a36c61f9SKrishna Gudipati 
1562a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1563a36c61f9SKrishna Gudipati 			  FC_CLASS_3, (len + attr_len), &fchs,
1564a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1565a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
1566a36c61f9SKrishna Gudipati 
1567a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1568a36c61f9SKrishna Gudipati }
1569a36c61f9SKrishna Gudipati 
1570a36c61f9SKrishna Gudipati static          u16
1571a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1572a36c61f9SKrishna Gudipati {
1573a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1574a36c61f9SKrishna Gudipati 	struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1575a36c61f9SKrishna Gudipati 	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1576a36c61f9SKrishna Gudipati 	struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1577a36c61f9SKrishna Gudipati 	struct fdmi_attr_s *attr;
1578a36c61f9SKrishna Gudipati 	u8        *curr_ptr;
1579a36c61f9SKrishna Gudipati 	u16        len, count;
1580a36c61f9SKrishna Gudipati 
1581a36c61f9SKrishna Gudipati 	/*
1582a36c61f9SKrishna Gudipati 	 * get hba attributes
1583a36c61f9SKrishna Gudipati 	 */
1584a36c61f9SKrishna Gudipati 	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1585a36c61f9SKrishna Gudipati 
1586a36c61f9SKrishna Gudipati 	rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1587ba816ea8SJing Huang 	rhba->port_list.num_ports = cpu_to_be32(1);
1588a36c61f9SKrishna Gudipati 	rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1589a36c61f9SKrishna Gudipati 
1590a36c61f9SKrishna Gudipati 	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1591a36c61f9SKrishna Gudipati 
1592a36c61f9SKrishna Gudipati 	count = 0;
1593a36c61f9SKrishna Gudipati 	len += sizeof(rhba->hba_attr_blk.attr_count);
1594a36c61f9SKrishna Gudipati 
1595a36c61f9SKrishna Gudipati 	/*
1596a36c61f9SKrishna Gudipati 	 * fill out the invididual entries of the HBA attrib Block
1597a36c61f9SKrishna Gudipati 	 */
1598a36c61f9SKrishna Gudipati 	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1599a36c61f9SKrishna Gudipati 
1600a36c61f9SKrishna Gudipati 	/*
1601a36c61f9SKrishna Gudipati 	 * Node Name
1602a36c61f9SKrishna Gudipati 	 */
1603a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1604ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1605a36c61f9SKrishna Gudipati 	attr->len = sizeof(wwn_t);
1606a36c61f9SKrishna Gudipati 	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len);
1607a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1608a36c61f9SKrishna Gudipati 	len += attr->len;
1609a36c61f9SKrishna Gudipati 	count++;
1610a36c61f9SKrishna Gudipati 	attr->len =
1611ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1612a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1613a36c61f9SKrishna Gudipati 
1614a36c61f9SKrishna Gudipati 	/*
1615a36c61f9SKrishna Gudipati 	 * Manufacturer
1616a36c61f9SKrishna Gudipati 	 */
1617a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1618ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1619a36c61f9SKrishna Gudipati 	attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
1620a36c61f9SKrishna Gudipati 	memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
1621a36c61f9SKrishna Gudipati 	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1622a36c61f9SKrishna Gudipati 								 *fields need
1623a36c61f9SKrishna Gudipati 								 *to be 4 byte
1624a36c61f9SKrishna Gudipati 								 *aligned */
1625a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1626a36c61f9SKrishna Gudipati 	len += attr->len;
1627a36c61f9SKrishna Gudipati 	count++;
1628a36c61f9SKrishna Gudipati 	attr->len =
1629ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1630a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1631a36c61f9SKrishna Gudipati 
1632a36c61f9SKrishna Gudipati 	/*
1633a36c61f9SKrishna Gudipati 	 * Serial Number
1634a36c61f9SKrishna Gudipati 	 */
1635a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1636ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1637a36c61f9SKrishna Gudipati 	attr->len = (u16) strlen(fcs_hba_attr->serial_num);
1638a36c61f9SKrishna Gudipati 	memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
1639a36c61f9SKrishna Gudipati 	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1640a36c61f9SKrishna Gudipati 								 *fields need
1641a36c61f9SKrishna Gudipati 								 *to be 4 byte
1642a36c61f9SKrishna Gudipati 								 *aligned */
1643a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1644a36c61f9SKrishna Gudipati 	len += attr->len;
1645a36c61f9SKrishna Gudipati 	count++;
1646a36c61f9SKrishna Gudipati 	attr->len =
1647ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1648a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1649a36c61f9SKrishna Gudipati 
1650a36c61f9SKrishna Gudipati 	/*
1651a36c61f9SKrishna Gudipati 	 * Model
1652a36c61f9SKrishna Gudipati 	 */
1653a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1654ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1655a36c61f9SKrishna Gudipati 	attr->len = (u16) strlen(fcs_hba_attr->model);
1656a36c61f9SKrishna Gudipati 	memcpy(attr->value, fcs_hba_attr->model, attr->len);
1657a36c61f9SKrishna Gudipati 	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1658a36c61f9SKrishna Gudipati 								 *fields need
1659a36c61f9SKrishna Gudipati 								 *to be 4 byte
1660a36c61f9SKrishna Gudipati 								 *aligned */
1661a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1662a36c61f9SKrishna Gudipati 	len += attr->len;
1663a36c61f9SKrishna Gudipati 	count++;
1664a36c61f9SKrishna Gudipati 	attr->len =
1665ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1666a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1667a36c61f9SKrishna Gudipati 
1668a36c61f9SKrishna Gudipati 	/*
1669a36c61f9SKrishna Gudipati 	 * Model Desc
1670a36c61f9SKrishna Gudipati 	 */
1671a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1672ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1673a36c61f9SKrishna Gudipati 	attr->len = (u16) strlen(fcs_hba_attr->model_desc);
1674a36c61f9SKrishna Gudipati 	memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
1675a36c61f9SKrishna Gudipati 	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1676a36c61f9SKrishna Gudipati 							 *fields need
1677a36c61f9SKrishna Gudipati 							 *to be 4 byte
1678a36c61f9SKrishna Gudipati 							 *aligned */
1679a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1680a36c61f9SKrishna Gudipati 	len += attr->len;
1681a36c61f9SKrishna Gudipati 	count++;
1682a36c61f9SKrishna Gudipati 	attr->len =
1683ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1684a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1685a36c61f9SKrishna Gudipati 
1686a36c61f9SKrishna Gudipati 	/*
1687a36c61f9SKrishna Gudipati 	 * H/W Version
1688a36c61f9SKrishna Gudipati 	 */
1689a36c61f9SKrishna Gudipati 	if (fcs_hba_attr->hw_version[0] != '\0') {
1690a36c61f9SKrishna Gudipati 		attr = (struct fdmi_attr_s *) curr_ptr;
1691ba816ea8SJing Huang 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
1692a36c61f9SKrishna Gudipati 		attr->len = (u16) strlen(fcs_hba_attr->hw_version);
1693a36c61f9SKrishna Gudipati 		memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
1694a36c61f9SKrishna Gudipati 		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1695a36c61f9SKrishna Gudipati 								 *fields need
1696a36c61f9SKrishna Gudipati 								 *to be 4 byte
1697a36c61f9SKrishna Gudipati 								 *aligned */
1698a36c61f9SKrishna Gudipati 		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1699a36c61f9SKrishna Gudipati 		len += attr->len;
1700a36c61f9SKrishna Gudipati 		count++;
1701a36c61f9SKrishna Gudipati 		attr->len =
1702ba816ea8SJing Huang 			cpu_to_be16(attr->len + sizeof(attr->type) +
1703a36c61f9SKrishna Gudipati 					 sizeof(attr->len));
1704a36c61f9SKrishna Gudipati 	}
1705a36c61f9SKrishna Gudipati 
1706a36c61f9SKrishna Gudipati 	/*
1707a36c61f9SKrishna Gudipati 	 * Driver Version
1708a36c61f9SKrishna Gudipati 	 */
1709a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1710ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
1711a36c61f9SKrishna Gudipati 	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
1712a36c61f9SKrishna Gudipati 	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
1713a36c61f9SKrishna Gudipati 	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1714a36c61f9SKrishna Gudipati 							 *fields need
1715a36c61f9SKrishna Gudipati 							 *to be 4 byte
1716a36c61f9SKrishna Gudipati 							 *aligned */
1717a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1718a36c61f9SKrishna Gudipati 	len += attr->len;;
1719a36c61f9SKrishna Gudipati 	count++;
1720a36c61f9SKrishna Gudipati 	attr->len =
1721ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1722a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1723a36c61f9SKrishna Gudipati 
1724a36c61f9SKrishna Gudipati 	/*
1725a36c61f9SKrishna Gudipati 	 * Option Rom Version
1726a36c61f9SKrishna Gudipati 	 */
1727a36c61f9SKrishna Gudipati 	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1728a36c61f9SKrishna Gudipati 		attr = (struct fdmi_attr_s *) curr_ptr;
1729ba816ea8SJing Huang 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
1730a36c61f9SKrishna Gudipati 		attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
1731a36c61f9SKrishna Gudipati 		memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
1732a36c61f9SKrishna Gudipati 		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1733a36c61f9SKrishna Gudipati 								 *fields need
1734a36c61f9SKrishna Gudipati 								 *to be 4 byte
1735a36c61f9SKrishna Gudipati 								 *aligned */
1736a36c61f9SKrishna Gudipati 		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1737a36c61f9SKrishna Gudipati 		len += attr->len;
1738a36c61f9SKrishna Gudipati 		count++;
1739a36c61f9SKrishna Gudipati 		attr->len =
1740ba816ea8SJing Huang 			cpu_to_be16(attr->len + sizeof(attr->type) +
1741a36c61f9SKrishna Gudipati 					 sizeof(attr->len));
1742a36c61f9SKrishna Gudipati 	}
1743a36c61f9SKrishna Gudipati 
1744a36c61f9SKrishna Gudipati 	/*
1745a36c61f9SKrishna Gudipati 	 * f/w Version = driver version
1746a36c61f9SKrishna Gudipati 	 */
1747a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1748ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
1749a36c61f9SKrishna Gudipati 	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
1750a36c61f9SKrishna Gudipati 	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
1751a36c61f9SKrishna Gudipati 	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1752a36c61f9SKrishna Gudipati 							 *fields need
1753a36c61f9SKrishna Gudipati 							 *to be 4 byte
1754a36c61f9SKrishna Gudipati 							 *aligned */
1755a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1756a36c61f9SKrishna Gudipati 	len += attr->len;
1757a36c61f9SKrishna Gudipati 	count++;
1758a36c61f9SKrishna Gudipati 	attr->len =
1759ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1760a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1761a36c61f9SKrishna Gudipati 
1762a36c61f9SKrishna Gudipati 	/*
1763a36c61f9SKrishna Gudipati 	 * OS Name
1764a36c61f9SKrishna Gudipati 	 */
1765a36c61f9SKrishna Gudipati 	if (fcs_hba_attr->os_name[0] != '\0') {
1766a36c61f9SKrishna Gudipati 		attr = (struct fdmi_attr_s *) curr_ptr;
1767ba816ea8SJing Huang 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
1768a36c61f9SKrishna Gudipati 		attr->len = (u16) strlen(fcs_hba_attr->os_name);
1769a36c61f9SKrishna Gudipati 		memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
1770a36c61f9SKrishna Gudipati 		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1771a36c61f9SKrishna Gudipati 							     *fields need
1772a36c61f9SKrishna Gudipati 							     *to be 4 byte
1773a36c61f9SKrishna Gudipati 							     *aligned */
1774a36c61f9SKrishna Gudipati 		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1775a36c61f9SKrishna Gudipati 		len += attr->len;
1776a36c61f9SKrishna Gudipati 		count++;
1777a36c61f9SKrishna Gudipati 		attr->len =
1778ba816ea8SJing Huang 			cpu_to_be16(attr->len + sizeof(attr->type) +
1779a36c61f9SKrishna Gudipati 					sizeof(attr->len));
1780a36c61f9SKrishna Gudipati 	}
1781a36c61f9SKrishna Gudipati 
1782a36c61f9SKrishna Gudipati 	/*
1783a36c61f9SKrishna Gudipati 	 * MAX_CT_PAYLOAD
1784a36c61f9SKrishna Gudipati 	 */
1785a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1786ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
1787a36c61f9SKrishna Gudipati 	attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
1788a36c61f9SKrishna Gudipati 	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
1789a36c61f9SKrishna Gudipati 	len += attr->len;
1790a36c61f9SKrishna Gudipati 	count++;
1791a36c61f9SKrishna Gudipati 	attr->len =
1792ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1793a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1794a36c61f9SKrishna Gudipati 
1795a36c61f9SKrishna Gudipati 	/*
1796a36c61f9SKrishna Gudipati 	 * Update size of payload
1797a36c61f9SKrishna Gudipati 	 */
1798a36c61f9SKrishna Gudipati 	len += ((sizeof(attr->type) +
1799a36c61f9SKrishna Gudipati 		 sizeof(attr->len)) * count);
1800a36c61f9SKrishna Gudipati 
1801ba816ea8SJing Huang 	rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
1802a36c61f9SKrishna Gudipati 	return len;
1803a36c61f9SKrishna Gudipati }
1804a36c61f9SKrishna Gudipati 
1805a36c61f9SKrishna Gudipati static void
1806a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1807a36c61f9SKrishna Gudipati 				void *cbarg, bfa_status_t req_status,
1808a36c61f9SKrishna Gudipati 				u32 rsp_len, u32 resid_len,
1809a36c61f9SKrishna Gudipati 				struct fchs_s *rsp_fchs)
1810a36c61f9SKrishna Gudipati {
1811a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi =
1812a36c61f9SKrishna Gudipati 				(struct bfa_fcs_lport_fdmi_s *) cbarg;
1813a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1814a36c61f9SKrishna Gudipati 	struct ct_hdr_s *cthdr = NULL;
1815a36c61f9SKrishna Gudipati 
1816a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1817a36c61f9SKrishna Gudipati 
1818a36c61f9SKrishna Gudipati 	/*
1819a36c61f9SKrishna Gudipati 	 * Sanity Checks
1820a36c61f9SKrishna Gudipati 	 */
1821a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
1822a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
1823a36c61f9SKrishna Gudipati 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1824a36c61f9SKrishna Gudipati 		return;
1825a36c61f9SKrishna Gudipati 	}
1826a36c61f9SKrishna Gudipati 
1827a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1828ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1829a36c61f9SKrishna Gudipati 
1830a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1831a36c61f9SKrishna Gudipati 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1832a36c61f9SKrishna Gudipati 		return;
1833a36c61f9SKrishna Gudipati 	}
1834a36c61f9SKrishna Gudipati 
1835a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
1836a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
1837a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1838a36c61f9SKrishna Gudipati }
1839a36c61f9SKrishna Gudipati 
1840a36c61f9SKrishna Gudipati /**
1841a36c61f9SKrishna Gudipati *  RPRT : Register Port
1842a36c61f9SKrishna Gudipati  */
1843a36c61f9SKrishna Gudipati static void
1844a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1845a36c61f9SKrishna Gudipati {
1846a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1847a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1848a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
1849a36c61f9SKrishna Gudipati 	u16        len, attr_len;
1850a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
1851a36c61f9SKrishna Gudipati 	u8        *pyld;
1852a36c61f9SKrishna Gudipati 
1853a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1854a36c61f9SKrishna Gudipati 
1855a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1856a36c61f9SKrishna Gudipati 	if (!fcxp) {
1857a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1858a36c61f9SKrishna Gudipati 					bfa_fcs_lport_fdmi_send_rprt, fdmi);
1859a36c61f9SKrishna Gudipati 		return;
1860a36c61f9SKrishna Gudipati 	}
1861a36c61f9SKrishna Gudipati 	fdmi->fcxp = fcxp;
1862a36c61f9SKrishna Gudipati 
1863a36c61f9SKrishna Gudipati 	pyld = bfa_fcxp_get_reqbuf(fcxp);
18646a18b167SJing Huang 	memset(pyld, 0, FC_MAX_PDUSZ);
1865a36c61f9SKrishna Gudipati 
1866a36c61f9SKrishna Gudipati 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1867a36c61f9SKrishna Gudipati 				   FDMI_RPRT);
1868a36c61f9SKrishna Gudipati 
1869a36c61f9SKrishna Gudipati 	attr_len =
1870a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1871a36c61f9SKrishna Gudipati 					  (u8 *) ((struct ct_hdr_s *) pyld
1872a36c61f9SKrishna Gudipati 						       + 1));
1873a36c61f9SKrishna Gudipati 
1874a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1875a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len + attr_len, &fchs,
1876a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1877a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
1878a36c61f9SKrishna Gudipati 
1879a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1880a36c61f9SKrishna Gudipati }
1881a36c61f9SKrishna Gudipati 
1882a36c61f9SKrishna Gudipati /**
1883a36c61f9SKrishna Gudipati  * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1884a36c61f9SKrishna Gudipati  */
1885a36c61f9SKrishna Gudipati static          u16
1886a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1887a36c61f9SKrishna Gudipati 				       u8 *pyld)
1888a36c61f9SKrishna Gudipati {
1889a36c61f9SKrishna Gudipati 	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1890a36c61f9SKrishna Gudipati 	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1891a36c61f9SKrishna Gudipati 	struct fdmi_attr_s *attr;
1892a36c61f9SKrishna Gudipati 	u8        *curr_ptr;
1893a36c61f9SKrishna Gudipati 	u16        len;
1894a36c61f9SKrishna Gudipati 	u8	count = 0;
1895a36c61f9SKrishna Gudipati 
1896a36c61f9SKrishna Gudipati 	/*
1897a36c61f9SKrishna Gudipati 	 * get port attributes
1898a36c61f9SKrishna Gudipati 	 */
1899a36c61f9SKrishna Gudipati 	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1900a36c61f9SKrishna Gudipati 
1901a36c61f9SKrishna Gudipati 	len = sizeof(port_attrib->attr_count);
1902a36c61f9SKrishna Gudipati 
1903a36c61f9SKrishna Gudipati 	/*
1904a36c61f9SKrishna Gudipati 	 * fill out the invididual entries
1905a36c61f9SKrishna Gudipati 	 */
1906a36c61f9SKrishna Gudipati 	curr_ptr = (u8 *) &port_attrib->port_attr;
1907a36c61f9SKrishna Gudipati 
1908a36c61f9SKrishna Gudipati 	/*
1909a36c61f9SKrishna Gudipati 	 * FC4 Types
1910a36c61f9SKrishna Gudipati 	 */
1911a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1912ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
1913a36c61f9SKrishna Gudipati 	attr->len = sizeof(fcs_port_attr.supp_fc4_types);
1914a36c61f9SKrishna Gudipati 	memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
1915a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1916a36c61f9SKrishna Gudipati 	len += attr->len;
1917a36c61f9SKrishna Gudipati 	++count;
1918a36c61f9SKrishna Gudipati 	attr->len =
1919ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1920a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1921a36c61f9SKrishna Gudipati 
1922a36c61f9SKrishna Gudipati 	/*
1923a36c61f9SKrishna Gudipati 	 * Supported Speed
1924a36c61f9SKrishna Gudipati 	 */
1925a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1926ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
1927a36c61f9SKrishna Gudipati 	attr->len = sizeof(fcs_port_attr.supp_speed);
1928a36c61f9SKrishna Gudipati 	memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
1929a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1930a36c61f9SKrishna Gudipati 	len += attr->len;
1931a36c61f9SKrishna Gudipati 	++count;
1932a36c61f9SKrishna Gudipati 	attr->len =
1933ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1934a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1935a36c61f9SKrishna Gudipati 
1936a36c61f9SKrishna Gudipati 	/*
1937a36c61f9SKrishna Gudipati 	 * current Port Speed
1938a36c61f9SKrishna Gudipati 	 */
1939a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1940ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
1941a36c61f9SKrishna Gudipati 	attr->len = sizeof(fcs_port_attr.curr_speed);
1942a36c61f9SKrishna Gudipati 	memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
1943a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1944a36c61f9SKrishna Gudipati 	len += attr->len;
1945a36c61f9SKrishna Gudipati 	++count;
1946a36c61f9SKrishna Gudipati 	attr->len =
1947ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1948a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1949a36c61f9SKrishna Gudipati 
1950a36c61f9SKrishna Gudipati 	/*
1951a36c61f9SKrishna Gudipati 	 * max frame size
1952a36c61f9SKrishna Gudipati 	 */
1953a36c61f9SKrishna Gudipati 	attr = (struct fdmi_attr_s *) curr_ptr;
1954ba816ea8SJing Huang 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
1955a36c61f9SKrishna Gudipati 	attr->len = sizeof(fcs_port_attr.max_frm_size);
1956a36c61f9SKrishna Gudipati 	memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
1957a36c61f9SKrishna Gudipati 	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1958a36c61f9SKrishna Gudipati 	len += attr->len;
1959a36c61f9SKrishna Gudipati 	++count;
1960a36c61f9SKrishna Gudipati 	attr->len =
1961ba816ea8SJing Huang 		cpu_to_be16(attr->len + sizeof(attr->type) +
1962a36c61f9SKrishna Gudipati 			     sizeof(attr->len));
1963a36c61f9SKrishna Gudipati 
1964a36c61f9SKrishna Gudipati 	/*
1965a36c61f9SKrishna Gudipati 	 * OS Device Name
1966a36c61f9SKrishna Gudipati 	 */
1967a36c61f9SKrishna Gudipati 	if (fcs_port_attr.os_device_name[0] != '\0') {
1968a36c61f9SKrishna Gudipati 		attr = (struct fdmi_attr_s *) curr_ptr;
1969ba816ea8SJing Huang 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
1970a36c61f9SKrishna Gudipati 		attr->len = (u16) strlen(fcs_port_attr.os_device_name);
1971a36c61f9SKrishna Gudipati 		memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
1972a36c61f9SKrishna Gudipati 		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1973a36c61f9SKrishna Gudipati 							     *fields need
1974a36c61f9SKrishna Gudipati 							     *to be 4 byte
1975a36c61f9SKrishna Gudipati 							     *aligned */
1976a36c61f9SKrishna Gudipati 		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1977a36c61f9SKrishna Gudipati 		len += attr->len;
1978a36c61f9SKrishna Gudipati 		++count;
1979a36c61f9SKrishna Gudipati 		attr->len =
1980ba816ea8SJing Huang 			cpu_to_be16(attr->len + sizeof(attr->type) +
1981a36c61f9SKrishna Gudipati 					sizeof(attr->len));
1982a36c61f9SKrishna Gudipati 	}
1983a36c61f9SKrishna Gudipati 	/*
1984a36c61f9SKrishna Gudipati 	 * Host Name
1985a36c61f9SKrishna Gudipati 	 */
1986a36c61f9SKrishna Gudipati 	if (fcs_port_attr.host_name[0] != '\0') {
1987a36c61f9SKrishna Gudipati 		attr = (struct fdmi_attr_s *) curr_ptr;
1988ba816ea8SJing Huang 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
1989a36c61f9SKrishna Gudipati 		attr->len = (u16) strlen(fcs_port_attr.host_name);
1990a36c61f9SKrishna Gudipati 		memcpy(attr->value, fcs_port_attr.host_name, attr->len);
1991a36c61f9SKrishna Gudipati 		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
1992a36c61f9SKrishna Gudipati 							     *fields need
1993a36c61f9SKrishna Gudipati 							     *to be 4 byte
1994a36c61f9SKrishna Gudipati 							     *aligned */
1995a36c61f9SKrishna Gudipati 		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1996a36c61f9SKrishna Gudipati 		len += attr->len;
1997a36c61f9SKrishna Gudipati 		++count;
1998a36c61f9SKrishna Gudipati 		attr->len =
1999ba816ea8SJing Huang 			cpu_to_be16(attr->len + sizeof(attr->type) +
2000a36c61f9SKrishna Gudipati 				sizeof(attr->len));
2001a36c61f9SKrishna Gudipati 	}
2002a36c61f9SKrishna Gudipati 
2003a36c61f9SKrishna Gudipati 	/*
2004a36c61f9SKrishna Gudipati 	 * Update size of payload
2005a36c61f9SKrishna Gudipati 	 */
2006ba816ea8SJing Huang 	port_attrib->attr_count = cpu_to_be32(count);
2007a36c61f9SKrishna Gudipati 	len += ((sizeof(attr->type) +
2008a36c61f9SKrishna Gudipati 		 sizeof(attr->len)) * count);
2009a36c61f9SKrishna Gudipati 	return len;
2010a36c61f9SKrishna Gudipati }
2011a36c61f9SKrishna Gudipati 
2012a36c61f9SKrishna Gudipati static          u16
2013a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2014a36c61f9SKrishna Gudipati {
2015a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2016a36c61f9SKrishna Gudipati 	struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2017a36c61f9SKrishna Gudipati 	u16        len;
2018a36c61f9SKrishna Gudipati 
2019a36c61f9SKrishna Gudipati 	rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2020a36c61f9SKrishna Gudipati 	rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2021a36c61f9SKrishna Gudipati 
2022a36c61f9SKrishna Gudipati 	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2023a36c61f9SKrishna Gudipati 				(u8 *) &rprt->port_attr_blk);
2024a36c61f9SKrishna Gudipati 
2025a36c61f9SKrishna Gudipati 	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2026a36c61f9SKrishna Gudipati 
2027a36c61f9SKrishna Gudipati 	return len;
2028a36c61f9SKrishna Gudipati }
2029a36c61f9SKrishna Gudipati 
2030a36c61f9SKrishna Gudipati static void
2031a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2032a36c61f9SKrishna Gudipati 				void *cbarg, bfa_status_t req_status,
2033a36c61f9SKrishna Gudipati 				u32 rsp_len, u32 resid_len,
2034a36c61f9SKrishna Gudipati 				struct fchs_s *rsp_fchs)
2035a36c61f9SKrishna Gudipati {
2036a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi =
2037a36c61f9SKrishna Gudipati 			(struct bfa_fcs_lport_fdmi_s *) cbarg;
2038a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2039a36c61f9SKrishna Gudipati 	struct ct_hdr_s *cthdr = NULL;
2040a36c61f9SKrishna Gudipati 
2041a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2042a36c61f9SKrishna Gudipati 
2043a36c61f9SKrishna Gudipati 	/*
2044a36c61f9SKrishna Gudipati 	 * Sanity Checks
2045a36c61f9SKrishna Gudipati 	 */
2046a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
2047a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
2048a36c61f9SKrishna Gudipati 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2049a36c61f9SKrishna Gudipati 		return;
2050a36c61f9SKrishna Gudipati 	}
2051a36c61f9SKrishna Gudipati 
2052a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2053ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2054a36c61f9SKrishna Gudipati 
2055a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2056a36c61f9SKrishna Gudipati 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2057a36c61f9SKrishna Gudipati 		return;
2058a36c61f9SKrishna Gudipati 	}
2059a36c61f9SKrishna Gudipati 
2060a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
2061a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
2062a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2063a36c61f9SKrishna Gudipati }
2064a36c61f9SKrishna Gudipati 
2065a36c61f9SKrishna Gudipati /**
2066a36c61f9SKrishna Gudipati *  RPA : Register Port Attributes.
2067a36c61f9SKrishna Gudipati  */
2068a36c61f9SKrishna Gudipati static void
2069a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2070a36c61f9SKrishna Gudipati {
2071a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2072a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2073a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
2074a36c61f9SKrishna Gudipati 	u16        len, attr_len;
2075a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
2076a36c61f9SKrishna Gudipati 	u8        *pyld;
2077a36c61f9SKrishna Gudipati 
2078a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2079a36c61f9SKrishna Gudipati 
2080a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2081a36c61f9SKrishna Gudipati 	if (!fcxp) {
2082a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2083a36c61f9SKrishna Gudipati 					bfa_fcs_lport_fdmi_send_rpa, fdmi);
2084a36c61f9SKrishna Gudipati 		return;
2085a36c61f9SKrishna Gudipati 	}
2086a36c61f9SKrishna Gudipati 	fdmi->fcxp = fcxp;
2087a36c61f9SKrishna Gudipati 
2088a36c61f9SKrishna Gudipati 	pyld = bfa_fcxp_get_reqbuf(fcxp);
20896a18b167SJing Huang 	memset(pyld, 0, FC_MAX_PDUSZ);
2090a36c61f9SKrishna Gudipati 
2091a36c61f9SKrishna Gudipati 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2092a36c61f9SKrishna Gudipati 				   FDMI_RPA);
2093a36c61f9SKrishna Gudipati 
2094a36c61f9SKrishna Gudipati 	attr_len =
2095a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2096a36c61f9SKrishna Gudipati 					 (u8 *) ((struct ct_hdr_s *) pyld
2097a36c61f9SKrishna Gudipati 						      + 1));
2098a36c61f9SKrishna Gudipati 
2099a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2100a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len + attr_len, &fchs,
2101a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2102a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2103a36c61f9SKrishna Gudipati 
2104a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2105a36c61f9SKrishna Gudipati }
2106a36c61f9SKrishna Gudipati 
2107a36c61f9SKrishna Gudipati static          u16
2108a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2109a36c61f9SKrishna Gudipati {
2110a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2111a36c61f9SKrishna Gudipati 	struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2112a36c61f9SKrishna Gudipati 	u16        len;
2113a36c61f9SKrishna Gudipati 
2114a36c61f9SKrishna Gudipati 	rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2115a36c61f9SKrishna Gudipati 
2116a36c61f9SKrishna Gudipati 	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2117a36c61f9SKrishna Gudipati 				(u8 *) &rpa->port_attr_blk);
2118a36c61f9SKrishna Gudipati 
2119a36c61f9SKrishna Gudipati 	len += sizeof(rpa->port_name);
2120a36c61f9SKrishna Gudipati 
2121a36c61f9SKrishna Gudipati 	return len;
2122a36c61f9SKrishna Gudipati }
2123a36c61f9SKrishna Gudipati 
2124a36c61f9SKrishna Gudipati static void
2125a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2126a36c61f9SKrishna Gudipati 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
2127a36c61f9SKrishna Gudipati 			u32 resid_len, struct fchs_s *rsp_fchs)
2128a36c61f9SKrishna Gudipati {
2129a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi =
2130a36c61f9SKrishna Gudipati 				(struct bfa_fcs_lport_fdmi_s *) cbarg;
2131a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2132a36c61f9SKrishna Gudipati 	struct ct_hdr_s *cthdr = NULL;
2133a36c61f9SKrishna Gudipati 
2134a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2135a36c61f9SKrishna Gudipati 
2136a36c61f9SKrishna Gudipati 	/*
2137a36c61f9SKrishna Gudipati 	 * Sanity Checks
2138a36c61f9SKrishna Gudipati 	 */
2139a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
2140a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
2141a36c61f9SKrishna Gudipati 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2142a36c61f9SKrishna Gudipati 		return;
2143a36c61f9SKrishna Gudipati 	}
2144a36c61f9SKrishna Gudipati 
2145a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2146ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2147a36c61f9SKrishna Gudipati 
2148a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2149a36c61f9SKrishna Gudipati 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2150a36c61f9SKrishna Gudipati 		return;
2151a36c61f9SKrishna Gudipati 	}
2152a36c61f9SKrishna Gudipati 
2153a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
2154a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
2155a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2156a36c61f9SKrishna Gudipati }
2157a36c61f9SKrishna Gudipati 
2158a36c61f9SKrishna Gudipati static void
2159a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_timeout(void *arg)
2160a36c61f9SKrishna Gudipati {
2161a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2162a36c61f9SKrishna Gudipati 
2163a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2164a36c61f9SKrishna Gudipati }
2165a36c61f9SKrishna Gudipati 
2166a36c61f9SKrishna Gudipati void
2167a36c61f9SKrishna Gudipati bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2168a36c61f9SKrishna Gudipati 			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2169a36c61f9SKrishna Gudipati {
2170a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2171a36c61f9SKrishna Gudipati 	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2172a36c61f9SKrishna Gudipati 
21736a18b167SJing Huang 	memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2174a36c61f9SKrishna Gudipati 
2175a36c61f9SKrishna Gudipati 	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2176a36c61f9SKrishna Gudipati 					hba_attr->manufacturer);
2177a36c61f9SKrishna Gudipati 	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2178a36c61f9SKrishna Gudipati 					hba_attr->serial_num);
2179a36c61f9SKrishna Gudipati 	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2180a36c61f9SKrishna Gudipati 					hba_attr->model);
2181a36c61f9SKrishna Gudipati 	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2182a36c61f9SKrishna Gudipati 					hba_attr->model_desc);
2183a36c61f9SKrishna Gudipati 	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2184a36c61f9SKrishna Gudipati 					hba_attr->hw_version);
2185a36c61f9SKrishna Gudipati 	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2186a36c61f9SKrishna Gudipati 					hba_attr->option_rom_ver);
2187a36c61f9SKrishna Gudipati 	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2188a36c61f9SKrishna Gudipati 					hba_attr->fw_version);
2189a36c61f9SKrishna Gudipati 
2190a36c61f9SKrishna Gudipati 	strncpy(hba_attr->driver_version, (char *)driver_info->version,
2191a36c61f9SKrishna Gudipati 		sizeof(hba_attr->driver_version));
2192a36c61f9SKrishna Gudipati 
2193a36c61f9SKrishna Gudipati 	strncpy(hba_attr->os_name, driver_info->host_os_name,
2194a36c61f9SKrishna Gudipati 		sizeof(hba_attr->os_name));
2195a36c61f9SKrishna Gudipati 
2196a36c61f9SKrishna Gudipati 	/*
2197a36c61f9SKrishna Gudipati 	 * If there is a patch level, append it
2198a36c61f9SKrishna Gudipati 	 * to the os name along with a separator
2199a36c61f9SKrishna Gudipati 	 */
2200a36c61f9SKrishna Gudipati 	if (driver_info->host_os_patch[0] != '\0') {
2201a36c61f9SKrishna Gudipati 		strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2202a36c61f9SKrishna Gudipati 			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2203a36c61f9SKrishna Gudipati 		strncat(hba_attr->os_name, driver_info->host_os_patch,
2204a36c61f9SKrishna Gudipati 				sizeof(driver_info->host_os_patch));
2205a36c61f9SKrishna Gudipati 	}
2206a36c61f9SKrishna Gudipati 
2207ba816ea8SJing Huang 	hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
2208a36c61f9SKrishna Gudipati }
2209a36c61f9SKrishna Gudipati 
2210a36c61f9SKrishna Gudipati void
2211a36c61f9SKrishna Gudipati bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2212a36c61f9SKrishna Gudipati 			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
2213a36c61f9SKrishna Gudipati {
2214a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2215a36c61f9SKrishna Gudipati 	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2216a36c61f9SKrishna Gudipati 	struct bfa_port_attr_s pport_attr;
2217a36c61f9SKrishna Gudipati 
22186a18b167SJing Huang 	memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2219a36c61f9SKrishna Gudipati 
2220a36c61f9SKrishna Gudipati 	/*
2221a36c61f9SKrishna Gudipati 	 * get pport attributes from hal
2222a36c61f9SKrishna Gudipati 	 */
2223a36c61f9SKrishna Gudipati 	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2224a36c61f9SKrishna Gudipati 
2225a36c61f9SKrishna Gudipati 	/*
2226a36c61f9SKrishna Gudipati 	 * get FC4 type Bitmask
2227a36c61f9SKrishna Gudipati 	 */
2228a36c61f9SKrishna Gudipati 	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2229a36c61f9SKrishna Gudipati 
2230a36c61f9SKrishna Gudipati 	/*
2231a36c61f9SKrishna Gudipati 	 * Supported Speeds
2232a36c61f9SKrishna Gudipati 	 */
2233ba816ea8SJing Huang 	port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
2234a36c61f9SKrishna Gudipati 
2235a36c61f9SKrishna Gudipati 	/*
2236a36c61f9SKrishna Gudipati 	 * Current Speed
2237a36c61f9SKrishna Gudipati 	 */
2238ba816ea8SJing Huang 	port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
2239a36c61f9SKrishna Gudipati 
2240a36c61f9SKrishna Gudipati 	/*
2241a36c61f9SKrishna Gudipati 	 * Max PDU Size.
2242a36c61f9SKrishna Gudipati 	 */
2243ba816ea8SJing Huang 	port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
2244a36c61f9SKrishna Gudipati 
2245a36c61f9SKrishna Gudipati 	/*
2246a36c61f9SKrishna Gudipati 	 * OS device Name
2247a36c61f9SKrishna Gudipati 	 */
2248a36c61f9SKrishna Gudipati 	strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2249a36c61f9SKrishna Gudipati 		sizeof(port_attr->os_device_name));
2250a36c61f9SKrishna Gudipati 
2251a36c61f9SKrishna Gudipati 	/*
2252a36c61f9SKrishna Gudipati 	 * Host name
2253a36c61f9SKrishna Gudipati 	 */
2254a36c61f9SKrishna Gudipati 	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2255a36c61f9SKrishna Gudipati 		sizeof(port_attr->host_name));
22567725ccfdSJing Huang 
22577725ccfdSJing Huang }
22587725ccfdSJing Huang 
22597725ccfdSJing Huang 
2260a36c61f9SKrishna Gudipati void
2261a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2262a36c61f9SKrishna Gudipati {
2263a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2264a36c61f9SKrishna Gudipati 
2265a36c61f9SKrishna Gudipati 	fdmi->ms = ms;
2266a36c61f9SKrishna Gudipati 	if (ms->port->fcs->fdmi_enabled)
2267a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2268a36c61f9SKrishna Gudipati 	else
2269a36c61f9SKrishna Gudipati 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2270a36c61f9SKrishna Gudipati }
2271a36c61f9SKrishna Gudipati 
2272a36c61f9SKrishna Gudipati void
2273a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2274a36c61f9SKrishna Gudipati {
2275a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2276a36c61f9SKrishna Gudipati 
2277a36c61f9SKrishna Gudipati 	fdmi->ms = ms;
2278a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2279a36c61f9SKrishna Gudipati }
2280a36c61f9SKrishna Gudipati 
2281a36c61f9SKrishna Gudipati void
2282a36c61f9SKrishna Gudipati bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2283a36c61f9SKrishna Gudipati {
2284a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2285a36c61f9SKrishna Gudipati 
2286a36c61f9SKrishna Gudipati 	fdmi->ms = ms;
2287a36c61f9SKrishna Gudipati 	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2288a36c61f9SKrishna Gudipati }
2289a36c61f9SKrishna Gudipati 
2290a36c61f9SKrishna Gudipati #define BFA_FCS_MS_CMD_MAX_RETRIES  2
2291a36c61f9SKrishna Gudipati 
2292a36c61f9SKrishna Gudipati /*
2293a36c61f9SKrishna Gudipati  * forward declarations
2294a36c61f9SKrishna Gudipati  */
2295a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2296a36c61f9SKrishna Gudipati 					   struct bfa_fcxp_s *fcxp_alloced);
2297a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_timeout(void *arg);
2298a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2299a36c61f9SKrishna Gudipati 					       struct bfa_fcxp_s *fcxp,
2300a36c61f9SKrishna Gudipati 					       void *cbarg,
2301a36c61f9SKrishna Gudipati 					       bfa_status_t req_status,
2302a36c61f9SKrishna Gudipati 					       u32 rsp_len,
2303a36c61f9SKrishna Gudipati 					       u32 resid_len,
2304a36c61f9SKrishna Gudipati 					       struct fchs_s *rsp_fchs);
2305a36c61f9SKrishna Gudipati 
2306a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2307a36c61f9SKrishna Gudipati 					struct bfa_fcxp_s *fcxp_alloced);
2308a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2309a36c61f9SKrishna Gudipati 					       struct bfa_fcxp_s *fcxp,
2310a36c61f9SKrishna Gudipati 					       void *cbarg,
2311a36c61f9SKrishna Gudipati 					       bfa_status_t req_status,
2312a36c61f9SKrishna Gudipati 					       u32 rsp_len,
2313a36c61f9SKrishna Gudipati 					       u32 resid_len,
2314a36c61f9SKrishna Gudipati 					       struct fchs_s *rsp_fchs);
2315a36c61f9SKrishna Gudipati static void	bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2316a36c61f9SKrishna Gudipati 					struct bfa_fcxp_s *fcxp_alloced);
2317a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2318a36c61f9SKrishna Gudipati 					       struct bfa_fcxp_s *fcxp,
2319a36c61f9SKrishna Gudipati 					       void *cbarg,
2320a36c61f9SKrishna Gudipati 					       bfa_status_t req_status,
2321a36c61f9SKrishna Gudipati 					       u32 rsp_len,
2322a36c61f9SKrishna Gudipati 					       u32 resid_len,
2323a36c61f9SKrishna Gudipati 					       struct fchs_s *rsp_fchs);
2324a36c61f9SKrishna Gudipati /**
2325a36c61f9SKrishna Gudipati  *  fcs_ms_sm FCS MS state machine
2326a36c61f9SKrishna Gudipati  */
2327a36c61f9SKrishna Gudipati 
2328a36c61f9SKrishna Gudipati /**
2329a36c61f9SKrishna Gudipati  *  MS State Machine events
2330a36c61f9SKrishna Gudipati  */
2331a36c61f9SKrishna Gudipati enum port_ms_event {
2332a36c61f9SKrishna Gudipati 	MSSM_EVENT_PORT_ONLINE = 1,
2333a36c61f9SKrishna Gudipati 	MSSM_EVENT_PORT_OFFLINE = 2,
2334a36c61f9SKrishna Gudipati 	MSSM_EVENT_RSP_OK = 3,
2335a36c61f9SKrishna Gudipati 	MSSM_EVENT_RSP_ERROR = 4,
2336a36c61f9SKrishna Gudipati 	MSSM_EVENT_TIMEOUT = 5,
2337a36c61f9SKrishna Gudipati 	MSSM_EVENT_FCXP_SENT = 6,
2338a36c61f9SKrishna Gudipati 	MSSM_EVENT_PORT_FABRIC_RSCN = 7
2339a36c61f9SKrishna Gudipati };
2340a36c61f9SKrishna Gudipati 
2341a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2342a36c61f9SKrishna Gudipati 					   enum port_ms_event event);
2343a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2344a36c61f9SKrishna Gudipati 						 enum port_ms_event event);
2345a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2346a36c61f9SKrishna Gudipati 					 enum port_ms_event event);
2347a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2348a36c61f9SKrishna Gudipati 					       enum port_ms_event event);
2349a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2350a36c61f9SKrishna Gudipati 						 enum port_ms_event event);
2351a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2352a36c61f9SKrishna Gudipati 					 enum port_ms_event event);
2353a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2354a36c61f9SKrishna Gudipati 					       enum port_ms_event event);
2355a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2356a36c61f9SKrishna Gudipati 						 enum port_ms_event event);
2357a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2358a36c61f9SKrishna Gudipati 					 enum port_ms_event event);
2359a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2360a36c61f9SKrishna Gudipati 					       enum port_ms_event event);
2361a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2362a36c61f9SKrishna Gudipati 					  enum port_ms_event event);
2363a36c61f9SKrishna Gudipati /**
2364a36c61f9SKrishna Gudipati  *	Start in offline state - awaiting NS to send start.
2365a36c61f9SKrishna Gudipati  */
2366a36c61f9SKrishna Gudipati static void
2367a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2368a36c61f9SKrishna Gudipati 				enum port_ms_event event)
2369a36c61f9SKrishna Gudipati {
2370a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2371a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2372a36c61f9SKrishna Gudipati 
2373a36c61f9SKrishna Gudipati 	switch (event) {
2374a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_ONLINE:
2375a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2376a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_send_plogi(ms, NULL);
2377a36c61f9SKrishna Gudipati 		break;
2378a36c61f9SKrishna Gudipati 
2379a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2380a36c61f9SKrishna Gudipati 		break;
2381a36c61f9SKrishna Gudipati 
2382a36c61f9SKrishna Gudipati 	default:
2383a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2384a36c61f9SKrishna Gudipati 	}
2385a36c61f9SKrishna Gudipati }
2386a36c61f9SKrishna Gudipati 
2387a36c61f9SKrishna Gudipati static void
2388a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2389a36c61f9SKrishna Gudipati 				enum port_ms_event event)
2390a36c61f9SKrishna Gudipati {
2391a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2392a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2393a36c61f9SKrishna Gudipati 
2394a36c61f9SKrishna Gudipati 	switch (event) {
2395a36c61f9SKrishna Gudipati 	case MSSM_EVENT_FCXP_SENT:
2396a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2397a36c61f9SKrishna Gudipati 		break;
2398a36c61f9SKrishna Gudipati 
2399a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2400a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2401a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2402a36c61f9SKrishna Gudipati 					   &ms->fcxp_wqe);
2403a36c61f9SKrishna Gudipati 		break;
2404a36c61f9SKrishna Gudipati 
2405a36c61f9SKrishna Gudipati 	default:
2406a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2407a36c61f9SKrishna Gudipati 	}
2408a36c61f9SKrishna Gudipati }
2409a36c61f9SKrishna Gudipati 
2410a36c61f9SKrishna Gudipati static void
2411a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2412a36c61f9SKrishna Gudipati 			enum port_ms_event event)
2413a36c61f9SKrishna Gudipati {
2414a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2415a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2416a36c61f9SKrishna Gudipati 
2417a36c61f9SKrishna Gudipati 	switch (event) {
2418a36c61f9SKrishna Gudipati 	case MSSM_EVENT_RSP_ERROR:
2419a36c61f9SKrishna Gudipati 		/*
2420a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
2421a36c61f9SKrishna Gudipati 		 */
2422a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2423a36c61f9SKrishna Gudipati 		ms->port->stats.ms_retries++;
2424a36c61f9SKrishna Gudipati 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2425a36c61f9SKrishna Gudipati 				    &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2426a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
2427a36c61f9SKrishna Gudipati 		break;
2428a36c61f9SKrishna Gudipati 
2429a36c61f9SKrishna Gudipati 	case MSSM_EVENT_RSP_OK:
2430a36c61f9SKrishna Gudipati 		/*
2431a36c61f9SKrishna Gudipati 		 * since plogi is done, now invoke MS related sub-modules
2432a36c61f9SKrishna Gudipati 		 */
2433a36c61f9SKrishna Gudipati 		bfa_fcs_lport_fdmi_online(ms);
2434a36c61f9SKrishna Gudipati 
2435a36c61f9SKrishna Gudipati 		/**
2436a36c61f9SKrishna Gudipati 		 * if this is a Vport, go to online state.
2437a36c61f9SKrishna Gudipati 		 */
2438a36c61f9SKrishna Gudipati 		if (ms->port->vport) {
2439a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2440a36c61f9SKrishna Gudipati 			break;
2441a36c61f9SKrishna Gudipati 		}
2442a36c61f9SKrishna Gudipati 
2443a36c61f9SKrishna Gudipati 		/*
2444a36c61f9SKrishna Gudipati 		 * For a base port we need to get the
2445a36c61f9SKrishna Gudipati 		 * switch's IP address.
2446a36c61f9SKrishna Gudipati 		 */
2447a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2448a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_send_gmal(ms, NULL);
2449a36c61f9SKrishna Gudipati 		break;
2450a36c61f9SKrishna Gudipati 
2451a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2452a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2453a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ms->fcxp);
2454a36c61f9SKrishna Gudipati 		break;
2455a36c61f9SKrishna Gudipati 
2456a36c61f9SKrishna Gudipati 	default:
2457a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2458a36c61f9SKrishna Gudipati 	}
2459a36c61f9SKrishna Gudipati }
2460a36c61f9SKrishna Gudipati 
2461a36c61f9SKrishna Gudipati static void
2462a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2463a36c61f9SKrishna Gudipati 			enum port_ms_event event)
2464a36c61f9SKrishna Gudipati {
2465a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2466a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2467a36c61f9SKrishna Gudipati 
2468a36c61f9SKrishna Gudipati 	switch (event) {
2469a36c61f9SKrishna Gudipati 	case MSSM_EVENT_TIMEOUT:
2470a36c61f9SKrishna Gudipati 		/*
2471a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
2472a36c61f9SKrishna Gudipati 		 */
2473a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2474a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_send_plogi(ms, NULL);
2475a36c61f9SKrishna Gudipati 		break;
2476a36c61f9SKrishna Gudipati 
2477a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2478a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2479a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ms->timer);
2480a36c61f9SKrishna Gudipati 		break;
2481a36c61f9SKrishna Gudipati 
2482a36c61f9SKrishna Gudipati 	default:
2483a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2484a36c61f9SKrishna Gudipati 	}
2485a36c61f9SKrishna Gudipati }
2486a36c61f9SKrishna Gudipati 
2487a36c61f9SKrishna Gudipati static void
2488a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2489a36c61f9SKrishna Gudipati 			enum port_ms_event event)
2490a36c61f9SKrishna Gudipati {
2491a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2492a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2493a36c61f9SKrishna Gudipati 
2494a36c61f9SKrishna Gudipati 	switch (event) {
2495a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2496a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2497a36c61f9SKrishna Gudipati 		break;
2498a36c61f9SKrishna Gudipati 
2499a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_FABRIC_RSCN:
2500a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2501a36c61f9SKrishna Gudipati 		ms->retry_cnt = 0;
2502a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2503a36c61f9SKrishna Gudipati 		break;
2504a36c61f9SKrishna Gudipati 
2505a36c61f9SKrishna Gudipati 	default:
2506a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2507a36c61f9SKrishna Gudipati 	}
2508a36c61f9SKrishna Gudipati }
2509a36c61f9SKrishna Gudipati 
2510a36c61f9SKrishna Gudipati static void
2511a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2512a36c61f9SKrishna Gudipati 				enum port_ms_event event)
2513a36c61f9SKrishna Gudipati {
2514a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2515a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2516a36c61f9SKrishna Gudipati 
2517a36c61f9SKrishna Gudipati 	switch (event) {
2518a36c61f9SKrishna Gudipati 	case MSSM_EVENT_FCXP_SENT:
2519a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2520a36c61f9SKrishna Gudipati 		break;
2521a36c61f9SKrishna Gudipati 
2522a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2523a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2524a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2525a36c61f9SKrishna Gudipati 					   &ms->fcxp_wqe);
2526a36c61f9SKrishna Gudipati 		break;
2527a36c61f9SKrishna Gudipati 
2528a36c61f9SKrishna Gudipati 	default:
2529a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2530a36c61f9SKrishna Gudipati 	}
2531a36c61f9SKrishna Gudipati }
2532a36c61f9SKrishna Gudipati 
2533a36c61f9SKrishna Gudipati static void
2534a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2535a36c61f9SKrishna Gudipati 				enum port_ms_event event)
2536a36c61f9SKrishna Gudipati {
2537a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2538a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2539a36c61f9SKrishna Gudipati 
2540a36c61f9SKrishna Gudipati 	switch (event) {
2541a36c61f9SKrishna Gudipati 	case MSSM_EVENT_RSP_ERROR:
2542a36c61f9SKrishna Gudipati 		/*
2543a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
2544a36c61f9SKrishna Gudipati 		 */
2545a36c61f9SKrishna Gudipati 		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2546a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2547a36c61f9SKrishna Gudipati 			ms->port->stats.ms_retries++;
2548a36c61f9SKrishna Gudipati 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2549a36c61f9SKrishna Gudipati 				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
2550a36c61f9SKrishna Gudipati 				BFA_FCS_RETRY_TIMEOUT);
2551a36c61f9SKrishna Gudipati 		} else {
2552a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2553a36c61f9SKrishna Gudipati 			bfa_fcs_lport_ms_send_gfn(ms, NULL);
2554a36c61f9SKrishna Gudipati 			ms->retry_cnt = 0;
2555a36c61f9SKrishna Gudipati 		}
2556a36c61f9SKrishna Gudipati 		break;
2557a36c61f9SKrishna Gudipati 
2558a36c61f9SKrishna Gudipati 	case MSSM_EVENT_RSP_OK:
2559a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2560a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2561a36c61f9SKrishna Gudipati 		break;
2562a36c61f9SKrishna Gudipati 
2563a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2564a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2565a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ms->fcxp);
2566a36c61f9SKrishna Gudipati 		break;
2567a36c61f9SKrishna Gudipati 
2568a36c61f9SKrishna Gudipati 	default:
2569a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2570a36c61f9SKrishna Gudipati 	}
2571a36c61f9SKrishna Gudipati }
2572a36c61f9SKrishna Gudipati 
2573a36c61f9SKrishna Gudipati static void
2574a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2575a36c61f9SKrishna Gudipati 				enum port_ms_event event)
2576a36c61f9SKrishna Gudipati {
2577a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2578a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2579a36c61f9SKrishna Gudipati 
2580a36c61f9SKrishna Gudipati 	switch (event) {
2581a36c61f9SKrishna Gudipati 	case MSSM_EVENT_TIMEOUT:
2582a36c61f9SKrishna Gudipati 		/*
2583a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
2584a36c61f9SKrishna Gudipati 		 */
2585a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2586a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_send_gmal(ms, NULL);
2587a36c61f9SKrishna Gudipati 		break;
2588a36c61f9SKrishna Gudipati 
2589a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2590a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2591a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ms->timer);
2592a36c61f9SKrishna Gudipati 		break;
2593a36c61f9SKrishna Gudipati 
2594a36c61f9SKrishna Gudipati 	default:
2595a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2596a36c61f9SKrishna Gudipati 	}
2597a36c61f9SKrishna Gudipati }
2598a36c61f9SKrishna Gudipati /**
2599a36c61f9SKrishna Gudipati  *  ms_pvt MS local functions
2600a36c61f9SKrishna Gudipati  */
2601a36c61f9SKrishna Gudipati 
2602a36c61f9SKrishna Gudipati static void
2603a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2604a36c61f9SKrishna Gudipati {
2605a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2606a36c61f9SKrishna Gudipati 	bfa_fcs_lport_t *port = ms->port;
2607a36c61f9SKrishna Gudipati 	struct fchs_s	fchs;
2608a36c61f9SKrishna Gudipati 	int		len;
2609a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
2610a36c61f9SKrishna Gudipati 
2611a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
2612a36c61f9SKrishna Gudipati 
2613a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2614a36c61f9SKrishna Gudipati 	if (!fcxp) {
2615a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2616a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ms_send_gmal, ms);
2617a36c61f9SKrishna Gudipati 		return;
2618a36c61f9SKrishna Gudipati 	}
2619a36c61f9SKrishna Gudipati 	ms->fcxp = fcxp;
2620a36c61f9SKrishna Gudipati 
2621a36c61f9SKrishna Gudipati 	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2622a36c61f9SKrishna Gudipati 			     bfa_fcs_lport_get_fcid(port),
2623a36c61f9SKrishna Gudipati 				 bfa_lps_get_peer_nwwn(port->fabric->lps));
2624a36c61f9SKrishna Gudipati 
2625a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2626a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
2627a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ms_gmal_response, (void *)ms,
2628a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2629a36c61f9SKrishna Gudipati 
2630a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2631a36c61f9SKrishna Gudipati }
2632a36c61f9SKrishna Gudipati 
2633a36c61f9SKrishna Gudipati static void
2634a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2635a36c61f9SKrishna Gudipati 				void *cbarg, bfa_status_t req_status,
2636a36c61f9SKrishna Gudipati 				u32 rsp_len, u32 resid_len,
2637a36c61f9SKrishna Gudipati 				struct fchs_s *rsp_fchs)
2638a36c61f9SKrishna Gudipati {
2639a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2640a36c61f9SKrishna Gudipati 	bfa_fcs_lport_t *port = ms->port;
2641a36c61f9SKrishna Gudipati 	struct ct_hdr_s		*cthdr = NULL;
2642a36c61f9SKrishna Gudipati 	struct fcgs_gmal_resp_s *gmal_resp;
2643a36c61f9SKrishna Gudipati 	struct fcgs_gmal_entry_s *gmal_entry;
2644a36c61f9SKrishna Gudipati 	u32		num_entries;
2645a36c61f9SKrishna Gudipati 	u8			*rsp_str;
2646a36c61f9SKrishna Gudipati 
2647a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, req_status);
2648a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2649a36c61f9SKrishna Gudipati 
2650a36c61f9SKrishna Gudipati 	/*
2651a36c61f9SKrishna Gudipati 	 * Sanity Checks
2652a36c61f9SKrishna Gudipati 	 */
2653a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
2654a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
2655a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2656a36c61f9SKrishna Gudipati 		return;
2657a36c61f9SKrishna Gudipati 	}
2658a36c61f9SKrishna Gudipati 
2659a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2660ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2661a36c61f9SKrishna Gudipati 
2662a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2663a36c61f9SKrishna Gudipati 		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2664a36c61f9SKrishna Gudipati 
2665ba816ea8SJing Huang 		num_entries = be32_to_cpu(gmal_resp->ms_len);
2666a36c61f9SKrishna Gudipati 		if (num_entries == 0) {
2667a36c61f9SKrishna Gudipati 			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2668a36c61f9SKrishna Gudipati 			return;
2669a36c61f9SKrishna Gudipati 		}
2670a36c61f9SKrishna Gudipati 		/*
2671a36c61f9SKrishna Gudipati 		* The response could contain multiple Entries.
2672a36c61f9SKrishna Gudipati 		* Entries for SNMP interface, etc.
2673a36c61f9SKrishna Gudipati 		* We look for the entry with a telnet prefix.
2674a36c61f9SKrishna Gudipati 		* First "http://" entry refers to IP addr
2675a36c61f9SKrishna Gudipati 		*/
2676a36c61f9SKrishna Gudipati 
2677a36c61f9SKrishna Gudipati 		gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2678a36c61f9SKrishna Gudipati 		while (num_entries > 0) {
2679a36c61f9SKrishna Gudipati 			if (strncmp(gmal_entry->prefix,
2680a36c61f9SKrishna Gudipati 				CT_GMAL_RESP_PREFIX_HTTP,
2681a36c61f9SKrishna Gudipati 				sizeof(gmal_entry->prefix)) == 0) {
2682a36c61f9SKrishna Gudipati 
2683a36c61f9SKrishna Gudipati 				/*
2684a36c61f9SKrishna Gudipati 				* if the IP address is terminating with a '/',
2685a36c61f9SKrishna Gudipati 				* remove it.
2686a36c61f9SKrishna Gudipati 				* Byte 0 consists of the length of the string.
2687a36c61f9SKrishna Gudipati 				*/
2688a36c61f9SKrishna Gudipati 				rsp_str = &(gmal_entry->prefix[0]);
2689a36c61f9SKrishna Gudipati 				if (rsp_str[gmal_entry->len-1] == '/')
2690a36c61f9SKrishna Gudipati 					rsp_str[gmal_entry->len-1] = 0;
2691a36c61f9SKrishna Gudipati 
2692a36c61f9SKrishna Gudipati 				/* copy IP Address to fabric */
2693a36c61f9SKrishna Gudipati 				strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2694a36c61f9SKrishna Gudipati 					gmal_entry->ip_addr,
2695a36c61f9SKrishna Gudipati 					BFA_FCS_FABRIC_IPADDR_SZ);
2696a36c61f9SKrishna Gudipati 				break;
2697a36c61f9SKrishna Gudipati 			} else {
2698a36c61f9SKrishna Gudipati 				--num_entries;
2699a36c61f9SKrishna Gudipati 				++gmal_entry;
2700a36c61f9SKrishna Gudipati 			}
2701a36c61f9SKrishna Gudipati 		}
2702a36c61f9SKrishna Gudipati 
2703a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2704a36c61f9SKrishna Gudipati 		return;
2705a36c61f9SKrishna Gudipati 	}
2706a36c61f9SKrishna Gudipati 
2707a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
2708a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
2709a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2710a36c61f9SKrishna Gudipati }
2711a36c61f9SKrishna Gudipati 
2712a36c61f9SKrishna Gudipati static void
2713a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2714a36c61f9SKrishna Gudipati 			enum port_ms_event event)
2715a36c61f9SKrishna Gudipati {
2716a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2717a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2718a36c61f9SKrishna Gudipati 
2719a36c61f9SKrishna Gudipati 	switch (event) {
2720a36c61f9SKrishna Gudipati 	case MSSM_EVENT_FCXP_SENT:
2721a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2722a36c61f9SKrishna Gudipati 		break;
2723a36c61f9SKrishna Gudipati 
2724a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2725a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2726a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2727a36c61f9SKrishna Gudipati 					   &ms->fcxp_wqe);
2728a36c61f9SKrishna Gudipati 		break;
2729a36c61f9SKrishna Gudipati 
2730a36c61f9SKrishna Gudipati 	default:
2731a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2732a36c61f9SKrishna Gudipati 	}
2733a36c61f9SKrishna Gudipati }
2734a36c61f9SKrishna Gudipati 
2735a36c61f9SKrishna Gudipati static void
2736a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2737a36c61f9SKrishna Gudipati 			enum port_ms_event event)
2738a36c61f9SKrishna Gudipati {
2739a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2740a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2741a36c61f9SKrishna Gudipati 
2742a36c61f9SKrishna Gudipati 	switch (event) {
2743a36c61f9SKrishna Gudipati 	case MSSM_EVENT_RSP_ERROR:
2744a36c61f9SKrishna Gudipati 		/*
2745a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
2746a36c61f9SKrishna Gudipati 		 */
2747a36c61f9SKrishna Gudipati 		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2748a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2749a36c61f9SKrishna Gudipati 			ms->port->stats.ms_retries++;
2750a36c61f9SKrishna Gudipati 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2751a36c61f9SKrishna Gudipati 				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
2752a36c61f9SKrishna Gudipati 				BFA_FCS_RETRY_TIMEOUT);
2753a36c61f9SKrishna Gudipati 		} else {
2754a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2755a36c61f9SKrishna Gudipati 			ms->retry_cnt = 0;
2756a36c61f9SKrishna Gudipati 		}
2757a36c61f9SKrishna Gudipati 		break;
2758a36c61f9SKrishna Gudipati 
2759a36c61f9SKrishna Gudipati 	case MSSM_EVENT_RSP_OK:
2760a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2761a36c61f9SKrishna Gudipati 		break;
2762a36c61f9SKrishna Gudipati 
2763a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2764a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2765a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ms->fcxp);
2766a36c61f9SKrishna Gudipati 		break;
2767a36c61f9SKrishna Gudipati 
2768a36c61f9SKrishna Gudipati 	default:
2769a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2770a36c61f9SKrishna Gudipati 	}
2771a36c61f9SKrishna Gudipati }
2772a36c61f9SKrishna Gudipati 
2773a36c61f9SKrishna Gudipati static void
2774a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2775a36c61f9SKrishna Gudipati 				enum port_ms_event event)
2776a36c61f9SKrishna Gudipati {
2777a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2778a36c61f9SKrishna Gudipati 	bfa_trc(ms->port->fcs, event);
2779a36c61f9SKrishna Gudipati 
2780a36c61f9SKrishna Gudipati 	switch (event) {
2781a36c61f9SKrishna Gudipati 	case MSSM_EVENT_TIMEOUT:
2782a36c61f9SKrishna Gudipati 		/*
2783a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
2784a36c61f9SKrishna Gudipati 		 */
2785a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2786a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2787a36c61f9SKrishna Gudipati 		break;
2788a36c61f9SKrishna Gudipati 
2789a36c61f9SKrishna Gudipati 	case MSSM_EVENT_PORT_OFFLINE:
2790a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2791a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ms->timer);
2792a36c61f9SKrishna Gudipati 		break;
2793a36c61f9SKrishna Gudipati 
2794a36c61f9SKrishna Gudipati 	default:
2795a36c61f9SKrishna Gudipati 		bfa_sm_fault(ms->port->fcs, event);
2796a36c61f9SKrishna Gudipati 	}
2797a36c61f9SKrishna Gudipati }
2798a36c61f9SKrishna Gudipati /**
2799a36c61f9SKrishna Gudipati  *  ms_pvt MS local functions
2800a36c61f9SKrishna Gudipati  */
2801a36c61f9SKrishna Gudipati 
2802a36c61f9SKrishna Gudipati static void
2803a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2804a36c61f9SKrishna Gudipati {
2805a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2806a36c61f9SKrishna Gudipati 	bfa_fcs_lport_t *port = ms->port;
2807a36c61f9SKrishna Gudipati 	struct fchs_s		fchs;
2808a36c61f9SKrishna Gudipati 	int			len;
2809a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
2810a36c61f9SKrishna Gudipati 
2811a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
2812a36c61f9SKrishna Gudipati 
2813a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2814a36c61f9SKrishna Gudipati 	if (!fcxp) {
2815a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2816a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ms_send_gfn, ms);
2817a36c61f9SKrishna Gudipati 		return;
2818a36c61f9SKrishna Gudipati 	}
2819a36c61f9SKrishna Gudipati 	ms->fcxp = fcxp;
2820a36c61f9SKrishna Gudipati 
2821a36c61f9SKrishna Gudipati 	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2822a36c61f9SKrishna Gudipati 			     bfa_fcs_lport_get_fcid(port),
2823a36c61f9SKrishna Gudipati 				 bfa_lps_get_peer_nwwn(port->fabric->lps));
2824a36c61f9SKrishna Gudipati 
2825a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2826a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
2827a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ms_gfn_response, (void *)ms,
2828a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2829a36c61f9SKrishna Gudipati 
2830a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2831a36c61f9SKrishna Gudipati }
2832a36c61f9SKrishna Gudipati 
2833a36c61f9SKrishna Gudipati static void
2834a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2835a36c61f9SKrishna Gudipati 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
2836a36c61f9SKrishna Gudipati 			u32 resid_len, struct fchs_s *rsp_fchs)
2837a36c61f9SKrishna Gudipati {
2838a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2839a36c61f9SKrishna Gudipati 	bfa_fcs_lport_t *port = ms->port;
2840a36c61f9SKrishna Gudipati 	struct ct_hdr_s	*cthdr = NULL;
2841a36c61f9SKrishna Gudipati 	wwn_t	       *gfn_resp;
2842a36c61f9SKrishna Gudipati 
2843a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, req_status);
2844a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2845a36c61f9SKrishna Gudipati 
2846a36c61f9SKrishna Gudipati 	/*
2847a36c61f9SKrishna Gudipati 	 * Sanity Checks
2848a36c61f9SKrishna Gudipati 	 */
2849a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
2850a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
2851a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2852a36c61f9SKrishna Gudipati 		return;
2853a36c61f9SKrishna Gudipati 	}
2854a36c61f9SKrishna Gudipati 
2855a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2856ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2857a36c61f9SKrishna Gudipati 
2858a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2859a36c61f9SKrishna Gudipati 		gfn_resp = (wwn_t *)(cthdr + 1);
2860a36c61f9SKrishna Gudipati 		/* check if it has actually changed */
2861a36c61f9SKrishna Gudipati 		if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2862a36c61f9SKrishna Gudipati 				gfn_resp, sizeof(wwn_t)) != 0)) {
2863a36c61f9SKrishna Gudipati 			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2864a36c61f9SKrishna Gudipati 		}
2865a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2866a36c61f9SKrishna Gudipati 		return;
2867a36c61f9SKrishna Gudipati 	}
2868a36c61f9SKrishna Gudipati 
2869a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
2870a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
2871a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2872a36c61f9SKrishna Gudipati }
2873a36c61f9SKrishna Gudipati 
2874a36c61f9SKrishna Gudipati /**
2875a36c61f9SKrishna Gudipati  *  ms_pvt MS local functions
2876a36c61f9SKrishna Gudipati  */
2877a36c61f9SKrishna Gudipati 
2878a36c61f9SKrishna Gudipati static void
2879a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2880a36c61f9SKrishna Gudipati {
2881a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2882a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ms->port;
2883a36c61f9SKrishna Gudipati 	struct fchs_s	fchs;
2884a36c61f9SKrishna Gudipati 	int	len;
2885a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
2886a36c61f9SKrishna Gudipati 
2887a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
2888a36c61f9SKrishna Gudipati 
2889a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2890a36c61f9SKrishna Gudipati 	if (!fcxp) {
2891a36c61f9SKrishna Gudipati 		port->stats.ms_plogi_alloc_wait++;
2892a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2893a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ms_send_plogi, ms);
2894a36c61f9SKrishna Gudipati 		return;
2895a36c61f9SKrishna Gudipati 	}
2896a36c61f9SKrishna Gudipati 	ms->fcxp = fcxp;
2897a36c61f9SKrishna Gudipati 
2898a36c61f9SKrishna Gudipati 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2899a36c61f9SKrishna Gudipati 			     bfa_os_hton3b(FC_MGMT_SERVER),
2900a36c61f9SKrishna Gudipati 			     bfa_fcs_lport_get_fcid(port), 0,
2901a36c61f9SKrishna Gudipati 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
2902a36c61f9SKrishna Gudipati 				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
2903a36c61f9SKrishna Gudipati 
2904a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2905a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
2906a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ms_plogi_response, (void *)ms,
2907a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_ELS_TOV);
2908a36c61f9SKrishna Gudipati 
2909a36c61f9SKrishna Gudipati 	port->stats.ms_plogi_sent++;
2910a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2911a36c61f9SKrishna Gudipati }
2912a36c61f9SKrishna Gudipati 
2913a36c61f9SKrishna Gudipati static void
2914a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2915a36c61f9SKrishna Gudipati 			void *cbarg, bfa_status_t req_status,
2916a36c61f9SKrishna Gudipati 			u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2917a36c61f9SKrishna Gudipati {
2918a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2919a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ms->port;
2920a36c61f9SKrishna Gudipati 	struct fc_els_cmd_s *els_cmd;
2921a36c61f9SKrishna Gudipati 	struct fc_ls_rjt_s *ls_rjt;
2922a36c61f9SKrishna Gudipati 
2923a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, req_status);
2924a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2925a36c61f9SKrishna Gudipati 
2926a36c61f9SKrishna Gudipati 	/*
2927a36c61f9SKrishna Gudipati 	 * Sanity Checks
2928a36c61f9SKrishna Gudipati 	 */
2929a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
2930a36c61f9SKrishna Gudipati 		port->stats.ms_plogi_rsp_err++;
2931a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
2932a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2933a36c61f9SKrishna Gudipati 		return;
2934a36c61f9SKrishna Gudipati 	}
2935a36c61f9SKrishna Gudipati 
2936a36c61f9SKrishna Gudipati 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2937a36c61f9SKrishna Gudipati 
2938a36c61f9SKrishna Gudipati 	switch (els_cmd->els_code) {
2939a36c61f9SKrishna Gudipati 
2940a36c61f9SKrishna Gudipati 	case FC_ELS_ACC:
2941a36c61f9SKrishna Gudipati 		if (rsp_len < sizeof(struct fc_logi_s)) {
2942a36c61f9SKrishna Gudipati 			bfa_trc(port->fcs, rsp_len);
2943a36c61f9SKrishna Gudipati 			port->stats.ms_plogi_acc_err++;
2944a36c61f9SKrishna Gudipati 			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2945a36c61f9SKrishna Gudipati 			break;
2946a36c61f9SKrishna Gudipati 		}
2947a36c61f9SKrishna Gudipati 		port->stats.ms_plogi_accepts++;
2948a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2949a36c61f9SKrishna Gudipati 		break;
2950a36c61f9SKrishna Gudipati 
2951a36c61f9SKrishna Gudipati 	case FC_ELS_LS_RJT:
2952a36c61f9SKrishna Gudipati 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2953a36c61f9SKrishna Gudipati 
2954a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, ls_rjt->reason_code);
2955a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2956a36c61f9SKrishna Gudipati 
2957a36c61f9SKrishna Gudipati 		port->stats.ms_rejects++;
2958a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2959a36c61f9SKrishna Gudipati 		break;
2960a36c61f9SKrishna Gudipati 
2961a36c61f9SKrishna Gudipati 	default:
2962a36c61f9SKrishna Gudipati 		port->stats.ms_plogi_unknown_rsp++;
2963a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, els_cmd->els_code);
2964a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2965a36c61f9SKrishna Gudipati 	}
2966a36c61f9SKrishna Gudipati }
2967a36c61f9SKrishna Gudipati 
2968a36c61f9SKrishna Gudipati static void
2969a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_timeout(void *arg)
2970a36c61f9SKrishna Gudipati {
2971a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2972a36c61f9SKrishna Gudipati 
2973a36c61f9SKrishna Gudipati 	ms->port->stats.ms_timeouts++;
2974a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2975a36c61f9SKrishna Gudipati }
2976a36c61f9SKrishna Gudipati 
2977a36c61f9SKrishna Gudipati 
2978a36c61f9SKrishna Gudipati void
2979a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2980a36c61f9SKrishna Gudipati {
2981a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2982a36c61f9SKrishna Gudipati 
2983a36c61f9SKrishna Gudipati 	ms->port = port;
2984a36c61f9SKrishna Gudipati 	bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2985a36c61f9SKrishna Gudipati 
2986a36c61f9SKrishna Gudipati 	/*
2987a36c61f9SKrishna Gudipati 	 * Invoke init routines of sub modules.
2988a36c61f9SKrishna Gudipati 	 */
2989a36c61f9SKrishna Gudipati 	bfa_fcs_lport_fdmi_init(ms);
2990a36c61f9SKrishna Gudipati }
2991a36c61f9SKrishna Gudipati 
2992a36c61f9SKrishna Gudipati void
2993a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2994a36c61f9SKrishna Gudipati {
2995a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2996a36c61f9SKrishna Gudipati 
2997a36c61f9SKrishna Gudipati 	ms->port = port;
2998a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2999a36c61f9SKrishna Gudipati 	bfa_fcs_lport_fdmi_offline(ms);
3000a36c61f9SKrishna Gudipati }
3001a36c61f9SKrishna Gudipati 
3002a36c61f9SKrishna Gudipati void
3003a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
3004a36c61f9SKrishna Gudipati {
3005a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3006a36c61f9SKrishna Gudipati 
3007a36c61f9SKrishna Gudipati 	ms->port = port;
3008a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3009a36c61f9SKrishna Gudipati }
3010a36c61f9SKrishna Gudipati void
3011a36c61f9SKrishna Gudipati bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3012a36c61f9SKrishna Gudipati {
3013a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3014a36c61f9SKrishna Gudipati 
3015a36c61f9SKrishna Gudipati 	/* todo.  Handle this only  when in Online state */
3016a36c61f9SKrishna Gudipati 	if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3017a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3018a36c61f9SKrishna Gudipati }
3019a36c61f9SKrishna Gudipati 
3020a36c61f9SKrishna Gudipati /**
3021a36c61f9SKrishna Gudipati  * @page ns_sm_info VPORT NS State Machine
3022a36c61f9SKrishna Gudipati  *
3023a36c61f9SKrishna Gudipati  * @section ns_sm_interactions VPORT NS State Machine Interactions
3024a36c61f9SKrishna Gudipati  *
3025a36c61f9SKrishna Gudipati  * @section ns_sm VPORT NS State Machine
3026a36c61f9SKrishna Gudipati  * img ns_sm.jpg
3027a36c61f9SKrishna Gudipati  */
3028a36c61f9SKrishna Gudipati 
3029a36c61f9SKrishna Gudipati /*
3030a36c61f9SKrishna Gudipati  * forward declarations
3031a36c61f9SKrishna Gudipati  */
3032a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3033a36c61f9SKrishna Gudipati 					   struct bfa_fcxp_s *fcxp_alloced);
3034a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3035a36c61f9SKrishna Gudipati 					     struct bfa_fcxp_s *fcxp_alloced);
3036a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3037a36c61f9SKrishna Gudipati 					    struct bfa_fcxp_s *fcxp_alloced);
3038a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3039a36c61f9SKrishna Gudipati 					    struct bfa_fcxp_s *fcxp_alloced);
3040a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3041a36c61f9SKrishna Gudipati 					    struct bfa_fcxp_s *fcxp_alloced);
3042a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_timeout(void *arg);
3043a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3044a36c61f9SKrishna Gudipati 					       struct bfa_fcxp_s *fcxp,
3045a36c61f9SKrishna Gudipati 					       void *cbarg,
3046a36c61f9SKrishna Gudipati 					       bfa_status_t req_status,
3047a36c61f9SKrishna Gudipati 					       u32 rsp_len,
3048a36c61f9SKrishna Gudipati 					       u32 resid_len,
3049a36c61f9SKrishna Gudipati 					       struct fchs_s *rsp_fchs);
3050a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3051a36c61f9SKrishna Gudipati 						 struct bfa_fcxp_s *fcxp,
3052a36c61f9SKrishna Gudipati 						 void *cbarg,
3053a36c61f9SKrishna Gudipati 						 bfa_status_t req_status,
3054a36c61f9SKrishna Gudipati 						 u32 rsp_len,
3055a36c61f9SKrishna Gudipati 						 u32 resid_len,
3056a36c61f9SKrishna Gudipati 						 struct fchs_s *rsp_fchs);
3057a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
3058a36c61f9SKrishna Gudipati 						struct bfa_fcxp_s *fcxp,
3059a36c61f9SKrishna Gudipati 						void *cbarg,
3060a36c61f9SKrishna Gudipati 						bfa_status_t req_status,
3061a36c61f9SKrishna Gudipati 						u32 rsp_len,
3062a36c61f9SKrishna Gudipati 						u32 resid_len,
3063a36c61f9SKrishna Gudipati 						struct fchs_s *rsp_fchs);
3064a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
3065a36c61f9SKrishna Gudipati 						struct bfa_fcxp_s *fcxp,
3066a36c61f9SKrishna Gudipati 						void *cbarg,
3067a36c61f9SKrishna Gudipati 						bfa_status_t req_status,
3068a36c61f9SKrishna Gudipati 						u32 rsp_len,
3069a36c61f9SKrishna Gudipati 						u32 resid_len,
3070a36c61f9SKrishna Gudipati 						struct fchs_s *rsp_fchs);
3071a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3072a36c61f9SKrishna Gudipati 						struct bfa_fcxp_s *fcxp,
3073a36c61f9SKrishna Gudipati 						void *cbarg,
3074a36c61f9SKrishna Gudipati 						bfa_status_t req_status,
3075a36c61f9SKrishna Gudipati 						u32 rsp_len,
3076a36c61f9SKrishna Gudipati 						u32 resid_len,
3077a36c61f9SKrishna Gudipati 						struct fchs_s *rsp_fchs);
3078a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_process_gidft_pids(
3079a36c61f9SKrishna Gudipati 				struct bfa_fcs_lport_s *port,
3080a36c61f9SKrishna Gudipati 				u32 *pid_buf, u32 n_pids);
3081a36c61f9SKrishna Gudipati 
3082a36c61f9SKrishna Gudipati static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3083a36c61f9SKrishna Gudipati /**
3084a36c61f9SKrishna Gudipati  *  fcs_ns_sm FCS nameserver interface state machine
3085a36c61f9SKrishna Gudipati  */
3086a36c61f9SKrishna Gudipati 
3087a36c61f9SKrishna Gudipati /**
3088a36c61f9SKrishna Gudipati  * VPort NS State Machine events
3089a36c61f9SKrishna Gudipati  */
3090a36c61f9SKrishna Gudipati enum vport_ns_event {
3091a36c61f9SKrishna Gudipati 	NSSM_EVENT_PORT_ONLINE = 1,
3092a36c61f9SKrishna Gudipati 	NSSM_EVENT_PORT_OFFLINE = 2,
3093a36c61f9SKrishna Gudipati 	NSSM_EVENT_PLOGI_SENT = 3,
3094a36c61f9SKrishna Gudipati 	NSSM_EVENT_RSP_OK = 4,
3095a36c61f9SKrishna Gudipati 	NSSM_EVENT_RSP_ERROR = 5,
3096a36c61f9SKrishna Gudipati 	NSSM_EVENT_TIMEOUT = 6,
3097a36c61f9SKrishna Gudipati 	NSSM_EVENT_NS_QUERY = 7,
3098a36c61f9SKrishna Gudipati 	NSSM_EVENT_RSPNID_SENT = 8,
3099a36c61f9SKrishna Gudipati 	NSSM_EVENT_RFTID_SENT = 9,
3100a36c61f9SKrishna Gudipati 	NSSM_EVENT_RFFID_SENT = 10,
3101a36c61f9SKrishna Gudipati 	NSSM_EVENT_GIDFT_SENT = 11,
3102a36c61f9SKrishna Gudipati };
3103a36c61f9SKrishna Gudipati 
3104a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3105a36c61f9SKrishna Gudipati 					   enum vport_ns_event event);
3106a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3107a36c61f9SKrishna Gudipati 						 enum vport_ns_event event);
3108a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3109a36c61f9SKrishna Gudipati 					 enum vport_ns_event event);
3110a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3111a36c61f9SKrishna Gudipati 					       enum vport_ns_event event);
3112a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
3113a36c61f9SKrishna Gudipati 					struct bfa_fcs_lport_ns_s *ns,
3114a36c61f9SKrishna Gudipati 					enum vport_ns_event event);
3115a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3116a36c61f9SKrishna Gudipati 					   enum vport_ns_event event);
3117a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3118a36c61f9SKrishna Gudipati 						 enum vport_ns_event event);
3119a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_sending_rft_id(
3120a36c61f9SKrishna Gudipati 					struct bfa_fcs_lport_ns_s *ns,
3121a36c61f9SKrishna Gudipati 					enum vport_ns_event event);
3122a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3123a36c61f9SKrishna Gudipati 						enum vport_ns_event event);
3124a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3125a36c61f9SKrishna Gudipati 					  enum vport_ns_event event);
3126a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_sending_rff_id(
3127a36c61f9SKrishna Gudipati 					struct bfa_fcs_lport_ns_s *ns,
3128a36c61f9SKrishna Gudipati 					enum vport_ns_event event);
3129a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3130a36c61f9SKrishna Gudipati 						enum vport_ns_event event);
3131a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3132a36c61f9SKrishna Gudipati 					  enum vport_ns_event event);
3133a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
3134a36c61f9SKrishna Gudipati 					struct bfa_fcs_lport_ns_s *ns,
3135a36c61f9SKrishna Gudipati 					enum vport_ns_event event);
3136a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3137a36c61f9SKrishna Gudipati 					  enum vport_ns_event event);
3138a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3139a36c61f9SKrishna Gudipati 						enum vport_ns_event event);
3140a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3141a36c61f9SKrishna Gudipati 					  enum vport_ns_event event);
3142a36c61f9SKrishna Gudipati /**
3143a36c61f9SKrishna Gudipati  *	Start in offline state - awaiting linkup
3144a36c61f9SKrishna Gudipati  */
3145a36c61f9SKrishna Gudipati static void
3146a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3147a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3148a36c61f9SKrishna Gudipati {
3149a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3150a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3151a36c61f9SKrishna Gudipati 
3152a36c61f9SKrishna Gudipati 	switch (event) {
3153a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_ONLINE:
3154a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3155a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3156a36c61f9SKrishna Gudipati 		break;
3157a36c61f9SKrishna Gudipati 
3158a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3159a36c61f9SKrishna Gudipati 		break;
3160a36c61f9SKrishna Gudipati 
3161a36c61f9SKrishna Gudipati 	default:
3162a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3163a36c61f9SKrishna Gudipati 	}
3164a36c61f9SKrishna Gudipati }
3165a36c61f9SKrishna Gudipati 
3166a36c61f9SKrishna Gudipati static void
3167a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3168a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3169a36c61f9SKrishna Gudipati {
3170a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3171a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3172a36c61f9SKrishna Gudipati 
3173a36c61f9SKrishna Gudipati 	switch (event) {
3174a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PLOGI_SENT:
3175a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3176a36c61f9SKrishna Gudipati 		break;
3177a36c61f9SKrishna Gudipati 
3178a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3179a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3180a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3181a36c61f9SKrishna Gudipati 					   &ns->fcxp_wqe);
3182a36c61f9SKrishna Gudipati 		break;
3183a36c61f9SKrishna Gudipati 
3184a36c61f9SKrishna Gudipati 	default:
3185a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3186a36c61f9SKrishna Gudipati 	}
3187a36c61f9SKrishna Gudipati }
3188a36c61f9SKrishna Gudipati 
3189a36c61f9SKrishna Gudipati static void
3190a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3191a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3192a36c61f9SKrishna Gudipati {
3193a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3194a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3195a36c61f9SKrishna Gudipati 
3196a36c61f9SKrishna Gudipati 	switch (event) {
3197a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_ERROR:
3198a36c61f9SKrishna Gudipati 		/*
3199a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
3200a36c61f9SKrishna Gudipati 		 */
3201a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3202a36c61f9SKrishna Gudipati 		ns->port->stats.ns_retries++;
3203a36c61f9SKrishna Gudipati 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3204a36c61f9SKrishna Gudipati 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3205a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
3206a36c61f9SKrishna Gudipati 		break;
3207a36c61f9SKrishna Gudipati 
3208a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_OK:
3209a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3210a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3211a36c61f9SKrishna Gudipati 		break;
3212a36c61f9SKrishna Gudipati 
3213a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3214a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3215a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ns->fcxp);
3216a36c61f9SKrishna Gudipati 		break;
3217a36c61f9SKrishna Gudipati 
3218a36c61f9SKrishna Gudipati 	default:
3219a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3220a36c61f9SKrishna Gudipati 	}
3221a36c61f9SKrishna Gudipati }
3222a36c61f9SKrishna Gudipati 
3223a36c61f9SKrishna Gudipati static void
3224a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3225a36c61f9SKrishna Gudipati 				enum vport_ns_event event)
3226a36c61f9SKrishna Gudipati {
3227a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3228a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3229a36c61f9SKrishna Gudipati 
3230a36c61f9SKrishna Gudipati 	switch (event) {
3231a36c61f9SKrishna Gudipati 	case NSSM_EVENT_TIMEOUT:
3232a36c61f9SKrishna Gudipati 		/*
3233a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
3234a36c61f9SKrishna Gudipati 		 */
3235a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3236a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3237a36c61f9SKrishna Gudipati 		break;
3238a36c61f9SKrishna Gudipati 
3239a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3240a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3241a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ns->timer);
3242a36c61f9SKrishna Gudipati 		break;
3243a36c61f9SKrishna Gudipati 
3244a36c61f9SKrishna Gudipati 	default:
3245a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3246a36c61f9SKrishna Gudipati 	}
3247a36c61f9SKrishna Gudipati }
3248a36c61f9SKrishna Gudipati 
3249a36c61f9SKrishna Gudipati static void
3250a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3251a36c61f9SKrishna Gudipati 				   enum vport_ns_event event)
3252a36c61f9SKrishna Gudipati {
3253a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3254a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3255a36c61f9SKrishna Gudipati 
3256a36c61f9SKrishna Gudipati 	switch (event) {
3257a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSPNID_SENT:
3258a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3259a36c61f9SKrishna Gudipati 		break;
3260a36c61f9SKrishna Gudipati 
3261a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3262a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3263a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3264a36c61f9SKrishna Gudipati 					   &ns->fcxp_wqe);
3265a36c61f9SKrishna Gudipati 		break;
3266a36c61f9SKrishna Gudipati 
3267a36c61f9SKrishna Gudipati 	default:
3268a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3269a36c61f9SKrishna Gudipati 	}
3270a36c61f9SKrishna Gudipati }
3271a36c61f9SKrishna Gudipati 
3272a36c61f9SKrishna Gudipati static void
3273a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3274a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3275a36c61f9SKrishna Gudipati {
3276a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3277a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3278a36c61f9SKrishna Gudipati 
3279a36c61f9SKrishna Gudipati 	switch (event) {
3280a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_ERROR:
3281a36c61f9SKrishna Gudipati 		/*
3282a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
3283a36c61f9SKrishna Gudipati 		 */
3284a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3285a36c61f9SKrishna Gudipati 		ns->port->stats.ns_retries++;
3286a36c61f9SKrishna Gudipati 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3287a36c61f9SKrishna Gudipati 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3288a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
3289a36c61f9SKrishna Gudipati 		break;
3290a36c61f9SKrishna Gudipati 
3291a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_OK:
3292a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3293a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3294a36c61f9SKrishna Gudipati 		break;
3295a36c61f9SKrishna Gudipati 
3296a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3297a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ns->fcxp);
3298a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3299a36c61f9SKrishna Gudipati 		break;
3300a36c61f9SKrishna Gudipati 
3301a36c61f9SKrishna Gudipati 	default:
3302a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3303a36c61f9SKrishna Gudipati 	}
3304a36c61f9SKrishna Gudipati }
3305a36c61f9SKrishna Gudipati 
3306a36c61f9SKrishna Gudipati static void
3307a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3308a36c61f9SKrishna Gudipati 				enum vport_ns_event event)
3309a36c61f9SKrishna Gudipati {
3310a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3311a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3312a36c61f9SKrishna Gudipati 
3313a36c61f9SKrishna Gudipati 	switch (event) {
3314a36c61f9SKrishna Gudipati 	case NSSM_EVENT_TIMEOUT:
3315a36c61f9SKrishna Gudipati 		/*
3316a36c61f9SKrishna Gudipati 		 * Retry Timer Expired. Re-send
3317a36c61f9SKrishna Gudipati 		 */
3318a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3319a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3320a36c61f9SKrishna Gudipati 		break;
3321a36c61f9SKrishna Gudipati 
3322a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3323a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3324a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ns->timer);
3325a36c61f9SKrishna Gudipati 		break;
3326a36c61f9SKrishna Gudipati 
3327a36c61f9SKrishna Gudipati 	default:
3328a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3329a36c61f9SKrishna Gudipati 	}
3330a36c61f9SKrishna Gudipati }
3331a36c61f9SKrishna Gudipati 
3332a36c61f9SKrishna Gudipati static void
3333a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3334a36c61f9SKrishna Gudipati 				  enum vport_ns_event event)
3335a36c61f9SKrishna Gudipati {
3336a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3337a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3338a36c61f9SKrishna Gudipati 
3339a36c61f9SKrishna Gudipati 	switch (event) {
3340a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RFTID_SENT:
3341a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3342a36c61f9SKrishna Gudipati 		break;
3343a36c61f9SKrishna Gudipati 
3344a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3345a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3346a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3347a36c61f9SKrishna Gudipati 					   &ns->fcxp_wqe);
3348a36c61f9SKrishna Gudipati 		break;
3349a36c61f9SKrishna Gudipati 
3350a36c61f9SKrishna Gudipati 	default:
3351a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3352a36c61f9SKrishna Gudipati 	}
3353a36c61f9SKrishna Gudipati }
3354a36c61f9SKrishna Gudipati 
3355a36c61f9SKrishna Gudipati static void
3356a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3357a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3358a36c61f9SKrishna Gudipati {
3359a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3360a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3361a36c61f9SKrishna Gudipati 
3362a36c61f9SKrishna Gudipati 	switch (event) {
3363a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_OK:
3364a36c61f9SKrishna Gudipati 		/* Now move to register FC4 Features */
3365a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3366a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3367a36c61f9SKrishna Gudipati 		break;
3368a36c61f9SKrishna Gudipati 
3369a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_ERROR:
3370a36c61f9SKrishna Gudipati 		/*
3371a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
3372a36c61f9SKrishna Gudipati 		 */
3373a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3374a36c61f9SKrishna Gudipati 		ns->port->stats.ns_retries++;
3375a36c61f9SKrishna Gudipati 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3376a36c61f9SKrishna Gudipati 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3377a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
3378a36c61f9SKrishna Gudipati 		break;
3379a36c61f9SKrishna Gudipati 
3380a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3381a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3382a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ns->fcxp);
3383a36c61f9SKrishna Gudipati 		break;
3384a36c61f9SKrishna Gudipati 
3385a36c61f9SKrishna Gudipati 	default:
3386a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3387a36c61f9SKrishna Gudipati 	}
3388a36c61f9SKrishna Gudipati }
3389a36c61f9SKrishna Gudipati 
3390a36c61f9SKrishna Gudipati static void
3391a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3392a36c61f9SKrishna Gudipati 				enum vport_ns_event event)
3393a36c61f9SKrishna Gudipati {
3394a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3395a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3396a36c61f9SKrishna Gudipati 
3397a36c61f9SKrishna Gudipati 	switch (event) {
3398a36c61f9SKrishna Gudipati 	case NSSM_EVENT_TIMEOUT:
3399a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3400a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3401a36c61f9SKrishna Gudipati 		break;
3402a36c61f9SKrishna Gudipati 
3403a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3404a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3405a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ns->timer);
3406a36c61f9SKrishna Gudipati 		break;
3407a36c61f9SKrishna Gudipati 
3408a36c61f9SKrishna Gudipati 	default:
3409a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3410a36c61f9SKrishna Gudipati 	}
3411a36c61f9SKrishna Gudipati }
3412a36c61f9SKrishna Gudipati 
3413a36c61f9SKrishna Gudipati static void
3414a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3415a36c61f9SKrishna Gudipati 				  enum vport_ns_event event)
3416a36c61f9SKrishna Gudipati {
3417a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3418a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3419a36c61f9SKrishna Gudipati 
3420a36c61f9SKrishna Gudipati 	switch (event) {
3421a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RFFID_SENT:
3422a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3423a36c61f9SKrishna Gudipati 		break;
3424a36c61f9SKrishna Gudipati 
3425a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3426a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3427a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3428a36c61f9SKrishna Gudipati 					   &ns->fcxp_wqe);
3429a36c61f9SKrishna Gudipati 		break;
3430a36c61f9SKrishna Gudipati 
3431a36c61f9SKrishna Gudipati 	default:
3432a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3433a36c61f9SKrishna Gudipati 	}
3434a36c61f9SKrishna Gudipati }
3435a36c61f9SKrishna Gudipati 
3436a36c61f9SKrishna Gudipati static void
3437a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3438a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3439a36c61f9SKrishna Gudipati {
3440a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3441a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3442a36c61f9SKrishna Gudipati 
3443a36c61f9SKrishna Gudipati 	switch (event) {
3444a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_OK:
3445a36c61f9SKrishna Gudipati 
3446a36c61f9SKrishna Gudipati 		/*
3447a36c61f9SKrishna Gudipati 		 * If min cfg mode is enabled, we donot initiate rport
3448a36c61f9SKrishna Gudipati 		 * discovery with the fabric. Instead, we will retrieve the
3449a36c61f9SKrishna Gudipati 		 * boot targets from HAL/FW.
3450a36c61f9SKrishna Gudipati 		 */
3451a36c61f9SKrishna Gudipati 		if (__fcs_min_cfg(ns->port->fcs)) {
3452a36c61f9SKrishna Gudipati 			bfa_fcs_lport_ns_boot_target_disc(ns->port);
3453a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3454a36c61f9SKrishna Gudipati 			return;
3455a36c61f9SKrishna Gudipati 		}
3456a36c61f9SKrishna Gudipati 
3457a36c61f9SKrishna Gudipati 		/*
3458a36c61f9SKrishna Gudipati 		 * If the port role is Initiator Mode issue NS query.
3459a36c61f9SKrishna Gudipati 		 * If it is Target Mode, skip this and go to online.
3460a36c61f9SKrishna Gudipati 		 */
3461a36c61f9SKrishna Gudipati 		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3462a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ns,
3463a36c61f9SKrishna Gudipati 				bfa_fcs_lport_ns_sm_sending_gid_ft);
3464a36c61f9SKrishna Gudipati 			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3465a36c61f9SKrishna Gudipati 		}
3466a36c61f9SKrishna Gudipati 		/*
3467a36c61f9SKrishna Gudipati 		 * kick off mgmt srvr state machine
3468a36c61f9SKrishna Gudipati 		 */
3469a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ms_online(ns->port);
3470a36c61f9SKrishna Gudipati 		break;
3471a36c61f9SKrishna Gudipati 
3472a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_ERROR:
3473a36c61f9SKrishna Gudipati 		/*
3474a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
3475a36c61f9SKrishna Gudipati 		 */
3476a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3477a36c61f9SKrishna Gudipati 		ns->port->stats.ns_retries++;
3478a36c61f9SKrishna Gudipati 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3479a36c61f9SKrishna Gudipati 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3480a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
3481a36c61f9SKrishna Gudipati 		break;
3482a36c61f9SKrishna Gudipati 
3483a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3484a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3485a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ns->fcxp);
3486a36c61f9SKrishna Gudipati 		break;
3487a36c61f9SKrishna Gudipati 
3488a36c61f9SKrishna Gudipati 	default:
3489a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3490a36c61f9SKrishna Gudipati 	}
3491a36c61f9SKrishna Gudipati }
3492a36c61f9SKrishna Gudipati 
3493a36c61f9SKrishna Gudipati static void
3494a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3495a36c61f9SKrishna Gudipati 				enum vport_ns_event event)
3496a36c61f9SKrishna Gudipati {
3497a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3498a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3499a36c61f9SKrishna Gudipati 
3500a36c61f9SKrishna Gudipati 	switch (event) {
3501a36c61f9SKrishna Gudipati 	case NSSM_EVENT_TIMEOUT:
3502a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3503a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3504a36c61f9SKrishna Gudipati 		break;
3505a36c61f9SKrishna Gudipati 
3506a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3507a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3508a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ns->timer);
3509a36c61f9SKrishna Gudipati 		break;
3510a36c61f9SKrishna Gudipati 
3511a36c61f9SKrishna Gudipati 	default:
3512a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3513a36c61f9SKrishna Gudipati 	}
3514a36c61f9SKrishna Gudipati }
3515a36c61f9SKrishna Gudipati static void
3516a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3517a36c61f9SKrishna Gudipati 				  enum vport_ns_event event)
3518a36c61f9SKrishna Gudipati {
3519a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3520a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3521a36c61f9SKrishna Gudipati 
3522a36c61f9SKrishna Gudipati 	switch (event) {
3523a36c61f9SKrishna Gudipati 	case NSSM_EVENT_GIDFT_SENT:
3524a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3525a36c61f9SKrishna Gudipati 		break;
3526a36c61f9SKrishna Gudipati 
3527a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3528a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3529a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3530a36c61f9SKrishna Gudipati 					   &ns->fcxp_wqe);
3531a36c61f9SKrishna Gudipati 		break;
3532a36c61f9SKrishna Gudipati 
3533a36c61f9SKrishna Gudipati 	default:
3534a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3535a36c61f9SKrishna Gudipati 	}
3536a36c61f9SKrishna Gudipati }
3537a36c61f9SKrishna Gudipati 
3538a36c61f9SKrishna Gudipati static void
3539a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3540a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3541a36c61f9SKrishna Gudipati {
3542a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3543a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3544a36c61f9SKrishna Gudipati 
3545a36c61f9SKrishna Gudipati 	switch (event) {
3546a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_OK:
3547a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3548a36c61f9SKrishna Gudipati 		break;
3549a36c61f9SKrishna Gudipati 
3550a36c61f9SKrishna Gudipati 	case NSSM_EVENT_RSP_ERROR:
3551a36c61f9SKrishna Gudipati 		/*
3552a36c61f9SKrishna Gudipati 		 * TBD: for certain reject codes, we don't need to retry
3553a36c61f9SKrishna Gudipati 		 */
3554a36c61f9SKrishna Gudipati 		/*
3555a36c61f9SKrishna Gudipati 		 * Start timer for a delayed retry
3556a36c61f9SKrishna Gudipati 		 */
3557a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3558a36c61f9SKrishna Gudipati 		ns->port->stats.ns_retries++;
3559a36c61f9SKrishna Gudipati 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3560a36c61f9SKrishna Gudipati 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3561a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
3562a36c61f9SKrishna Gudipati 		break;
3563a36c61f9SKrishna Gudipati 
3564a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3565a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3566a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(ns->fcxp);
3567a36c61f9SKrishna Gudipati 		break;
3568a36c61f9SKrishna Gudipati 
3569a36c61f9SKrishna Gudipati 	case  NSSM_EVENT_NS_QUERY:
3570a36c61f9SKrishna Gudipati 		break;
3571a36c61f9SKrishna Gudipati 
3572a36c61f9SKrishna Gudipati 	default:
3573a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3574a36c61f9SKrishna Gudipati 	}
3575a36c61f9SKrishna Gudipati }
3576a36c61f9SKrishna Gudipati 
3577a36c61f9SKrishna Gudipati static void
3578a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3579a36c61f9SKrishna Gudipati 				enum vport_ns_event event)
3580a36c61f9SKrishna Gudipati {
3581a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3582a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3583a36c61f9SKrishna Gudipati 
3584a36c61f9SKrishna Gudipati 	switch (event) {
3585a36c61f9SKrishna Gudipati 	case NSSM_EVENT_TIMEOUT:
3586a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3587a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3588a36c61f9SKrishna Gudipati 		break;
3589a36c61f9SKrishna Gudipati 
3590a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3591a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3592a36c61f9SKrishna Gudipati 		bfa_timer_stop(&ns->timer);
3593a36c61f9SKrishna Gudipati 		break;
3594a36c61f9SKrishna Gudipati 
3595a36c61f9SKrishna Gudipati 	default:
3596a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3597a36c61f9SKrishna Gudipati 	}
3598a36c61f9SKrishna Gudipati }
3599a36c61f9SKrishna Gudipati 
3600a36c61f9SKrishna Gudipati static void
3601a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3602a36c61f9SKrishna Gudipati 			enum vport_ns_event event)
3603a36c61f9SKrishna Gudipati {
3604a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3605a36c61f9SKrishna Gudipati 	bfa_trc(ns->port->fcs, event);
3606a36c61f9SKrishna Gudipati 
3607a36c61f9SKrishna Gudipati 	switch (event) {
3608a36c61f9SKrishna Gudipati 	case NSSM_EVENT_PORT_OFFLINE:
3609a36c61f9SKrishna Gudipati 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3610a36c61f9SKrishna Gudipati 		break;
3611a36c61f9SKrishna Gudipati 
3612a36c61f9SKrishna Gudipati 	case NSSM_EVENT_NS_QUERY:
3613a36c61f9SKrishna Gudipati 		/*
3614a36c61f9SKrishna Gudipati 		 * If the port role is Initiator Mode issue NS query.
3615a36c61f9SKrishna Gudipati 		 * If it is Target Mode, skip this and go to online.
3616a36c61f9SKrishna Gudipati 		 */
3617a36c61f9SKrishna Gudipati 		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3618a36c61f9SKrishna Gudipati 			bfa_sm_set_state(ns,
3619a36c61f9SKrishna Gudipati 				bfa_fcs_lport_ns_sm_sending_gid_ft);
3620a36c61f9SKrishna Gudipati 			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3621a36c61f9SKrishna Gudipati 		};
3622a36c61f9SKrishna Gudipati 		break;
3623a36c61f9SKrishna Gudipati 
3624a36c61f9SKrishna Gudipati 	default:
3625a36c61f9SKrishna Gudipati 		bfa_sm_fault(ns->port->fcs, event);
3626a36c61f9SKrishna Gudipati 	}
3627a36c61f9SKrishna Gudipati }
3628a36c61f9SKrishna Gudipati 
3629a36c61f9SKrishna Gudipati 
3630a36c61f9SKrishna Gudipati 
3631a36c61f9SKrishna Gudipati /**
3632a36c61f9SKrishna Gudipati  *  ns_pvt Nameserver local functions
3633a36c61f9SKrishna Gudipati  */
3634a36c61f9SKrishna Gudipati 
3635a36c61f9SKrishna Gudipati static void
3636a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3637a36c61f9SKrishna Gudipati {
3638a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3639a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3640a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
3641a36c61f9SKrishna Gudipati 	int             len;
3642a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
3643a36c61f9SKrishna Gudipati 
3644a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
3645a36c61f9SKrishna Gudipati 
3646a36c61f9SKrishna Gudipati fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3647a36c61f9SKrishna Gudipati 	if (!fcxp) {
3648a36c61f9SKrishna Gudipati 		port->stats.ns_plogi_alloc_wait++;
3649a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3650a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ns_send_plogi, ns);
3651a36c61f9SKrishna Gudipati 		return;
3652a36c61f9SKrishna Gudipati 	}
3653a36c61f9SKrishna Gudipati 	ns->fcxp = fcxp;
3654a36c61f9SKrishna Gudipati 
3655a36c61f9SKrishna Gudipati 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3656a36c61f9SKrishna Gudipati 			     bfa_os_hton3b(FC_NAME_SERVER),
3657a36c61f9SKrishna Gudipati 			     bfa_fcs_lport_get_fcid(port), 0,
3658a36c61f9SKrishna Gudipati 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
3659a36c61f9SKrishna Gudipati 				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
3660a36c61f9SKrishna Gudipati 
3661a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3662a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
3663a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ns_plogi_response, (void *)ns,
3664a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_ELS_TOV);
3665a36c61f9SKrishna Gudipati 	port->stats.ns_plogi_sent++;
3666a36c61f9SKrishna Gudipati 
3667a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3668a36c61f9SKrishna Gudipati }
3669a36c61f9SKrishna Gudipati 
3670a36c61f9SKrishna Gudipati static void
3671a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3672a36c61f9SKrishna Gudipati 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
3673a36c61f9SKrishna Gudipati 		       u32 resid_len, struct fchs_s *rsp_fchs)
3674a36c61f9SKrishna Gudipati {
3675a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3676a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3677a36c61f9SKrishna Gudipati 	/* struct fc_logi_s *plogi_resp; */
3678a36c61f9SKrishna Gudipati 	struct fc_els_cmd_s *els_cmd;
3679a36c61f9SKrishna Gudipati 	struct fc_ls_rjt_s *ls_rjt;
3680a36c61f9SKrishna Gudipati 
3681a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, req_status);
3682a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3683a36c61f9SKrishna Gudipati 
3684a36c61f9SKrishna Gudipati 	/*
3685a36c61f9SKrishna Gudipati 	 * Sanity Checks
3686a36c61f9SKrishna Gudipati 	 */
3687a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
3688a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
3689a36c61f9SKrishna Gudipati 		port->stats.ns_plogi_rsp_err++;
3690a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3691a36c61f9SKrishna Gudipati 		return;
3692a36c61f9SKrishna Gudipati 	}
3693a36c61f9SKrishna Gudipati 
3694a36c61f9SKrishna Gudipati 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3695a36c61f9SKrishna Gudipati 
3696a36c61f9SKrishna Gudipati 	switch (els_cmd->els_code) {
3697a36c61f9SKrishna Gudipati 
3698a36c61f9SKrishna Gudipati 	case FC_ELS_ACC:
3699a36c61f9SKrishna Gudipati 		if (rsp_len < sizeof(struct fc_logi_s)) {
3700a36c61f9SKrishna Gudipati 			bfa_trc(port->fcs, rsp_len);
3701a36c61f9SKrishna Gudipati 			port->stats.ns_plogi_acc_err++;
3702a36c61f9SKrishna Gudipati 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3703a36c61f9SKrishna Gudipati 			break;
3704a36c61f9SKrishna Gudipati 		}
3705a36c61f9SKrishna Gudipati 		port->stats.ns_plogi_accepts++;
3706a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3707a36c61f9SKrishna Gudipati 		break;
3708a36c61f9SKrishna Gudipati 
3709a36c61f9SKrishna Gudipati 	case FC_ELS_LS_RJT:
3710a36c61f9SKrishna Gudipati 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3711a36c61f9SKrishna Gudipati 
3712a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, ls_rjt->reason_code);
3713a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3714a36c61f9SKrishna Gudipati 
3715a36c61f9SKrishna Gudipati 		port->stats.ns_rejects++;
3716a36c61f9SKrishna Gudipati 
3717a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3718a36c61f9SKrishna Gudipati 		break;
3719a36c61f9SKrishna Gudipati 
3720a36c61f9SKrishna Gudipati 	default:
3721a36c61f9SKrishna Gudipati 		port->stats.ns_plogi_unknown_rsp++;
3722a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, els_cmd->els_code);
3723a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3724a36c61f9SKrishna Gudipati 	}
3725a36c61f9SKrishna Gudipati }
3726a36c61f9SKrishna Gudipati 
3727a36c61f9SKrishna Gudipati /**
3728a36c61f9SKrishna Gudipati  * Register the symbolic port name.
3729a36c61f9SKrishna Gudipati  */
3730a36c61f9SKrishna Gudipati static void
3731a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3732a36c61f9SKrishna Gudipati {
3733a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3734a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3735a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
3736a36c61f9SKrishna Gudipati 	int             len;
3737a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
3738a36c61f9SKrishna Gudipati 	u8         symbl[256];
3739a36c61f9SKrishna Gudipati 	u8         *psymbl = &symbl[0];
3740a36c61f9SKrishna Gudipati 
37416a18b167SJing Huang 	memset(symbl, 0, sizeof(symbl));
3742a36c61f9SKrishna Gudipati 
3743a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3744a36c61f9SKrishna Gudipati 
3745a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3746a36c61f9SKrishna Gudipati 	if (!fcxp) {
3747a36c61f9SKrishna Gudipati 		port->stats.ns_rspnid_alloc_wait++;
3748a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3749a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ns_send_rspn_id, ns);
3750a36c61f9SKrishna Gudipati 		return;
3751a36c61f9SKrishna Gudipati 	}
3752a36c61f9SKrishna Gudipati 	ns->fcxp = fcxp;
3753a36c61f9SKrishna Gudipati 
3754a36c61f9SKrishna Gudipati 	/*
3755a36c61f9SKrishna Gudipati 	 * for V-Port, form a Port Symbolic Name
3756a36c61f9SKrishna Gudipati 	 */
3757a36c61f9SKrishna Gudipati 	if (port->vport) {
3758a36c61f9SKrishna Gudipati 		/**
3759a36c61f9SKrishna Gudipati 		 * For Vports, we append the vport's port symbolic name
3760a36c61f9SKrishna Gudipati 		 * to that of the base port.
3761a36c61f9SKrishna Gudipati 		 */
3762a36c61f9SKrishna Gudipati 
3763a36c61f9SKrishna Gudipati 		strncpy((char *)psymbl,
3764a36c61f9SKrishna Gudipati 			(char *) &
3765a36c61f9SKrishna Gudipati 			(bfa_fcs_lport_get_psym_name
3766a36c61f9SKrishna Gudipati 			 (bfa_fcs_get_base_port(port->fcs))),
3767a36c61f9SKrishna Gudipati 			strlen((char *) &
3768a36c61f9SKrishna Gudipati 			       bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3769a36c61f9SKrishna Gudipati 							  (port->fcs))));
3770a36c61f9SKrishna Gudipati 
3771a36c61f9SKrishna Gudipati 		/* Ensure we have a null terminating string. */
3772a36c61f9SKrishna Gudipati 		((char *)psymbl)[strlen((char *) &
3773a36c61f9SKrishna Gudipati 			bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3774a36c61f9SKrishna Gudipati 						(port->fcs)))] = 0;
3775a36c61f9SKrishna Gudipati 		strncat((char *)psymbl,
3776a36c61f9SKrishna Gudipati 			(char *) &(bfa_fcs_lport_get_psym_name(port)),
3777a36c61f9SKrishna Gudipati 		strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3778a36c61f9SKrishna Gudipati 	} else {
3779a36c61f9SKrishna Gudipati 		psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3780a36c61f9SKrishna Gudipati 	}
3781a36c61f9SKrishna Gudipati 
3782a36c61f9SKrishna Gudipati 	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3783a36c61f9SKrishna Gudipati 			      bfa_fcs_lport_get_fcid(port), 0, psymbl);
3784a36c61f9SKrishna Gudipati 
3785a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3786a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
3787a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3788a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3789a36c61f9SKrishna Gudipati 
3790a36c61f9SKrishna Gudipati 	port->stats.ns_rspnid_sent++;
3791a36c61f9SKrishna Gudipati 
3792a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3793a36c61f9SKrishna Gudipati }
3794a36c61f9SKrishna Gudipati 
3795a36c61f9SKrishna Gudipati static void
3796a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3797a36c61f9SKrishna Gudipati 				 void *cbarg, bfa_status_t req_status,
3798a36c61f9SKrishna Gudipati 				 u32 rsp_len, u32 resid_len,
3799a36c61f9SKrishna Gudipati 				 struct fchs_s *rsp_fchs)
3800a36c61f9SKrishna Gudipati {
3801a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3802a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3803a36c61f9SKrishna Gudipati 	struct ct_hdr_s *cthdr = NULL;
3804a36c61f9SKrishna Gudipati 
3805a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3806a36c61f9SKrishna Gudipati 
3807a36c61f9SKrishna Gudipati 	/*
3808a36c61f9SKrishna Gudipati 	 * Sanity Checks
3809a36c61f9SKrishna Gudipati 	 */
3810a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
3811a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
3812a36c61f9SKrishna Gudipati 		port->stats.ns_rspnid_rsp_err++;
3813a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3814a36c61f9SKrishna Gudipati 		return;
3815a36c61f9SKrishna Gudipati 	}
3816a36c61f9SKrishna Gudipati 
3817a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3818ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3819a36c61f9SKrishna Gudipati 
3820a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3821a36c61f9SKrishna Gudipati 		port->stats.ns_rspnid_accepts++;
3822a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3823a36c61f9SKrishna Gudipati 		return;
3824a36c61f9SKrishna Gudipati 	}
3825a36c61f9SKrishna Gudipati 
3826a36c61f9SKrishna Gudipati 	port->stats.ns_rspnid_rejects++;
3827a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
3828a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
3829a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3830a36c61f9SKrishna Gudipati }
3831a36c61f9SKrishna Gudipati 
3832a36c61f9SKrishna Gudipati /**
3833a36c61f9SKrishna Gudipati  * Register FC4-Types
3834a36c61f9SKrishna Gudipati  */
3835a36c61f9SKrishna Gudipati static void
3836a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3837a36c61f9SKrishna Gudipati {
3838a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3839a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3840a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
3841a36c61f9SKrishna Gudipati 	int             len;
3842a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
3843a36c61f9SKrishna Gudipati 
3844a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3845a36c61f9SKrishna Gudipati 
3846a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3847a36c61f9SKrishna Gudipati 	if (!fcxp) {
3848a36c61f9SKrishna Gudipati 		port->stats.ns_rftid_alloc_wait++;
3849a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3850a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ns_send_rft_id, ns);
3851a36c61f9SKrishna Gudipati 		return;
3852a36c61f9SKrishna Gudipati 	}
3853a36c61f9SKrishna Gudipati 	ns->fcxp = fcxp;
3854a36c61f9SKrishna Gudipati 
3855a36c61f9SKrishna Gudipati 	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3856a36c61f9SKrishna Gudipati 		     bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3857a36c61f9SKrishna Gudipati 
3858a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3859a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
3860a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3861a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3862a36c61f9SKrishna Gudipati 
3863a36c61f9SKrishna Gudipati 	port->stats.ns_rftid_sent++;
3864a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3865a36c61f9SKrishna Gudipati }
3866a36c61f9SKrishna Gudipati 
3867a36c61f9SKrishna Gudipati static void
3868a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3869a36c61f9SKrishna Gudipati 				void *cbarg, bfa_status_t req_status,
3870a36c61f9SKrishna Gudipati 				u32 rsp_len, u32 resid_len,
3871a36c61f9SKrishna Gudipati 				struct fchs_s *rsp_fchs)
3872a36c61f9SKrishna Gudipati {
3873a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3874a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3875a36c61f9SKrishna Gudipati 	struct ct_hdr_s *cthdr = NULL;
3876a36c61f9SKrishna Gudipati 
3877a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3878a36c61f9SKrishna Gudipati 
3879a36c61f9SKrishna Gudipati 	/*
3880a36c61f9SKrishna Gudipati 	 * Sanity Checks
3881a36c61f9SKrishna Gudipati 	 */
3882a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
3883a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
3884a36c61f9SKrishna Gudipati 		port->stats.ns_rftid_rsp_err++;
3885a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3886a36c61f9SKrishna Gudipati 		return;
3887a36c61f9SKrishna Gudipati 	}
3888a36c61f9SKrishna Gudipati 
3889a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3890ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3891a36c61f9SKrishna Gudipati 
3892a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3893a36c61f9SKrishna Gudipati 		port->stats.ns_rftid_accepts++;
3894a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3895a36c61f9SKrishna Gudipati 		return;
3896a36c61f9SKrishna Gudipati 	}
3897a36c61f9SKrishna Gudipati 
3898a36c61f9SKrishna Gudipati 	port->stats.ns_rftid_rejects++;
3899a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
3900a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
3901a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3902a36c61f9SKrishna Gudipati }
3903a36c61f9SKrishna Gudipati 
3904a36c61f9SKrishna Gudipati /**
3905a36c61f9SKrishna Gudipati  * Register FC4-Features : Should be done after RFT_ID
3906a36c61f9SKrishna Gudipati  */
3907a36c61f9SKrishna Gudipati static void
3908a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3909a36c61f9SKrishna Gudipati {
3910a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3911a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3912a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
3913a36c61f9SKrishna Gudipati 	int             len;
3914a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
3915a36c61f9SKrishna Gudipati 	u8			fc4_ftrs = 0;
3916a36c61f9SKrishna Gudipati 
3917a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3918a36c61f9SKrishna Gudipati 
3919a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3920a36c61f9SKrishna Gudipati 	if (!fcxp) {
3921a36c61f9SKrishna Gudipati 		port->stats.ns_rffid_alloc_wait++;
3922a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3923a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ns_send_rff_id, ns);
3924a36c61f9SKrishna Gudipati 		return;
3925a36c61f9SKrishna Gudipati 	}
3926a36c61f9SKrishna Gudipati 	ns->fcxp = fcxp;
3927a36c61f9SKrishna Gudipati 
3928a36c61f9SKrishna Gudipati 	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3929a36c61f9SKrishna Gudipati 		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
3930a36c61f9SKrishna Gudipati 
3931a36c61f9SKrishna Gudipati 	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3932a36c61f9SKrishna Gudipati 			     bfa_fcs_lport_get_fcid(port), 0,
3933a36c61f9SKrishna Gudipati 				 FC_TYPE_FCP, fc4_ftrs);
3934a36c61f9SKrishna Gudipati 
3935a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3936a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
3937a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ns_rff_id_response, (void *)ns,
3938a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3939a36c61f9SKrishna Gudipati 
3940a36c61f9SKrishna Gudipati 	port->stats.ns_rffid_sent++;
3941a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3942a36c61f9SKrishna Gudipati }
3943a36c61f9SKrishna Gudipati 
3944a36c61f9SKrishna Gudipati static void
3945a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3946a36c61f9SKrishna Gudipati 				void *cbarg, bfa_status_t req_status,
3947a36c61f9SKrishna Gudipati 				u32 rsp_len, u32 resid_len,
3948a36c61f9SKrishna Gudipati 				struct fchs_s *rsp_fchs)
3949a36c61f9SKrishna Gudipati {
3950a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3951a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3952a36c61f9SKrishna Gudipati 	struct ct_hdr_s *cthdr = NULL;
3953a36c61f9SKrishna Gudipati 
3954a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3955a36c61f9SKrishna Gudipati 
3956a36c61f9SKrishna Gudipati 	/*
3957a36c61f9SKrishna Gudipati 	 * Sanity Checks
3958a36c61f9SKrishna Gudipati 	 */
3959a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
3960a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
3961a36c61f9SKrishna Gudipati 		port->stats.ns_rffid_rsp_err++;
3962a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3963a36c61f9SKrishna Gudipati 		return;
3964a36c61f9SKrishna Gudipati 	}
3965a36c61f9SKrishna Gudipati 
3966a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3967ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3968a36c61f9SKrishna Gudipati 
3969a36c61f9SKrishna Gudipati 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3970a36c61f9SKrishna Gudipati 		port->stats.ns_rffid_accepts++;
3971a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3972a36c61f9SKrishna Gudipati 		return;
3973a36c61f9SKrishna Gudipati 	}
3974a36c61f9SKrishna Gudipati 
3975a36c61f9SKrishna Gudipati 	port->stats.ns_rffid_rejects++;
3976a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->reason_code);
3977a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, cthdr->exp_code);
3978a36c61f9SKrishna Gudipati 
3979a36c61f9SKrishna Gudipati 	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3980a36c61f9SKrishna Gudipati 		/* if this command is not supported, we don't retry */
3981a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3982a36c61f9SKrishna Gudipati 	} else
3983a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3984a36c61f9SKrishna Gudipati }
3985a36c61f9SKrishna Gudipati /**
3986a36c61f9SKrishna Gudipati  * Query Fabric for FC4-Types Devices.
3987a36c61f9SKrishna Gudipati  *
3988a36c61f9SKrishna Gudipati * TBD : Need to use a local (FCS private) response buffer, since the response
3989a36c61f9SKrishna Gudipati  * can be larger than 2K.
3990a36c61f9SKrishna Gudipati  */
3991a36c61f9SKrishna Gudipati static void
3992a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3993a36c61f9SKrishna Gudipati {
3994a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3995a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
3996a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
3997a36c61f9SKrishna Gudipati 	int             len;
3998a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
3999a36c61f9SKrishna Gudipati 
4000a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
4001a36c61f9SKrishna Gudipati 
4002a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4003a36c61f9SKrishna Gudipati 	if (!fcxp) {
4004a36c61f9SKrishna Gudipati 		port->stats.ns_gidft_alloc_wait++;
4005a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4006a36c61f9SKrishna Gudipati 					bfa_fcs_lport_ns_send_gid_ft, ns);
4007a36c61f9SKrishna Gudipati 		return;
4008a36c61f9SKrishna Gudipati 	}
4009a36c61f9SKrishna Gudipati 	ns->fcxp = fcxp;
4010a36c61f9SKrishna Gudipati 
4011a36c61f9SKrishna Gudipati 	/*
4012a36c61f9SKrishna Gudipati 	 * This query is only initiated for FCP initiator mode.
4013a36c61f9SKrishna Gudipati 	 */
4014a36c61f9SKrishna Gudipati 	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4015a36c61f9SKrishna Gudipati 			      ns->port->pid, FC_TYPE_FCP);
4016a36c61f9SKrishna Gudipati 
4017a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4018a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
4019a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
4020a36c61f9SKrishna Gudipati 			  bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
4021a36c61f9SKrishna Gudipati 
4022a36c61f9SKrishna Gudipati 	port->stats.ns_gidft_sent++;
4023a36c61f9SKrishna Gudipati 
4024a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
4025a36c61f9SKrishna Gudipati }
4026a36c61f9SKrishna Gudipati 
4027a36c61f9SKrishna Gudipati static void
4028a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4029a36c61f9SKrishna Gudipati 				void *cbarg, bfa_status_t req_status,
4030a36c61f9SKrishna Gudipati 				u32 rsp_len, u32 resid_len,
4031a36c61f9SKrishna Gudipati 				struct fchs_s *rsp_fchs)
4032a36c61f9SKrishna Gudipati {
4033a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4034a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = ns->port;
4035a36c61f9SKrishna Gudipati 	struct ct_hdr_s *cthdr = NULL;
4036a36c61f9SKrishna Gudipati 	u32        n_pids;
4037a36c61f9SKrishna Gudipati 
4038a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4039a36c61f9SKrishna Gudipati 
4040a36c61f9SKrishna Gudipati 	/*
4041a36c61f9SKrishna Gudipati 	 * Sanity Checks
4042a36c61f9SKrishna Gudipati 	 */
4043a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
4044a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
4045a36c61f9SKrishna Gudipati 		port->stats.ns_gidft_rsp_err++;
4046a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4047a36c61f9SKrishna Gudipati 		return;
4048a36c61f9SKrishna Gudipati 	}
4049a36c61f9SKrishna Gudipati 
4050a36c61f9SKrishna Gudipati 	if (resid_len != 0) {
4051a36c61f9SKrishna Gudipati 		/*
4052a36c61f9SKrishna Gudipati 		 * TBD : we will need to allocate a larger buffer & retry the
4053a36c61f9SKrishna Gudipati 		 * command
4054a36c61f9SKrishna Gudipati 		 */
4055a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, rsp_len);
4056a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, resid_len);
4057a36c61f9SKrishna Gudipati 		return;
4058a36c61f9SKrishna Gudipati 	}
4059a36c61f9SKrishna Gudipati 
4060a36c61f9SKrishna Gudipati 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4061ba816ea8SJing Huang 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4062a36c61f9SKrishna Gudipati 
4063a36c61f9SKrishna Gudipati 	switch (cthdr->cmd_rsp_code) {
4064a36c61f9SKrishna Gudipati 
4065a36c61f9SKrishna Gudipati 	case CT_RSP_ACCEPT:
4066a36c61f9SKrishna Gudipati 
4067a36c61f9SKrishna Gudipati 		port->stats.ns_gidft_accepts++;
4068a36c61f9SKrishna Gudipati 		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
4069a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, n_pids);
4070a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_process_gidft_pids(port,
4071a36c61f9SKrishna Gudipati 						   (u32 *) (cthdr + 1),
4072a36c61f9SKrishna Gudipati 						   n_pids);
4073a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4074a36c61f9SKrishna Gudipati 		break;
4075a36c61f9SKrishna Gudipati 
4076a36c61f9SKrishna Gudipati 	case CT_RSP_REJECT:
4077a36c61f9SKrishna Gudipati 
4078a36c61f9SKrishna Gudipati 		/*
4079a36c61f9SKrishna Gudipati 		 * Check the reason code  & explanation.
4080a36c61f9SKrishna Gudipati 		 * There may not have been any FC4 devices in the fabric
4081a36c61f9SKrishna Gudipati 		 */
4082a36c61f9SKrishna Gudipati 		port->stats.ns_gidft_rejects++;
4083a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, cthdr->reason_code);
4084a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, cthdr->exp_code);
4085a36c61f9SKrishna Gudipati 
4086a36c61f9SKrishna Gudipati 		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4087a36c61f9SKrishna Gudipati 		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4088a36c61f9SKrishna Gudipati 
4089a36c61f9SKrishna Gudipati 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4090a36c61f9SKrishna Gudipati 		} else {
4091a36c61f9SKrishna Gudipati 			/*
4092a36c61f9SKrishna Gudipati 			 * for all other errors, retry
4093a36c61f9SKrishna Gudipati 			 */
4094a36c61f9SKrishna Gudipati 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4095a36c61f9SKrishna Gudipati 		}
4096a36c61f9SKrishna Gudipati 		break;
4097a36c61f9SKrishna Gudipati 
4098a36c61f9SKrishna Gudipati 	default:
4099a36c61f9SKrishna Gudipati 		port->stats.ns_gidft_unknown_rsp++;
4100a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4101a36c61f9SKrishna Gudipati 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4102a36c61f9SKrishna Gudipati 	}
4103a36c61f9SKrishna Gudipati }
4104a36c61f9SKrishna Gudipati 
4105a36c61f9SKrishna Gudipati /**
4106a36c61f9SKrishna Gudipati  *     This routine will be called by bfa_timer on timer timeouts.
4107a36c61f9SKrishna Gudipati  *
4108a36c61f9SKrishna Gudipati  *	param[in]	port - pointer to bfa_fcs_lport_t.
4109a36c61f9SKrishna Gudipati  *
4110a36c61f9SKrishna Gudipati  *	return
4111a36c61f9SKrishna Gudipati  *		void
4112a36c61f9SKrishna Gudipati  *
4113a36c61f9SKrishna Gudipati  *	Special Considerations:
4114a36c61f9SKrishna Gudipati  *
4115a36c61f9SKrishna Gudipati  *	note
4116a36c61f9SKrishna Gudipati  */
4117a36c61f9SKrishna Gudipati static void
4118a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_timeout(void *arg)
4119a36c61f9SKrishna Gudipati {
4120a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4121a36c61f9SKrishna Gudipati 
4122a36c61f9SKrishna Gudipati 	ns->port->stats.ns_timeouts++;
4123a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4124a36c61f9SKrishna Gudipati }
4125a36c61f9SKrishna Gudipati 
4126a36c61f9SKrishna Gudipati /*
4127a36c61f9SKrishna Gudipati  * Process the PID list in GID_FT response
4128a36c61f9SKrishna Gudipati  */
4129a36c61f9SKrishna Gudipati static void
4130a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4131a36c61f9SKrishna Gudipati 				   u32 n_pids)
4132a36c61f9SKrishna Gudipati {
4133a36c61f9SKrishna Gudipati 	struct fcgs_gidft_resp_s *gidft_entry;
4134a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport;
4135a36c61f9SKrishna Gudipati 	u32        ii;
4136a36c61f9SKrishna Gudipati 
4137a36c61f9SKrishna Gudipati 	for (ii = 0; ii < n_pids; ii++) {
4138a36c61f9SKrishna Gudipati 		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4139a36c61f9SKrishna Gudipati 
4140a36c61f9SKrishna Gudipati 		if (gidft_entry->pid == port->pid)
4141a36c61f9SKrishna Gudipati 			continue;
4142a36c61f9SKrishna Gudipati 
4143a36c61f9SKrishna Gudipati 		/*
4144a36c61f9SKrishna Gudipati 		 * Check if this rport already exists
4145a36c61f9SKrishna Gudipati 		 */
4146a36c61f9SKrishna Gudipati 		rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4147a36c61f9SKrishna Gudipati 		if (rport == NULL) {
4148a36c61f9SKrishna Gudipati 			/*
4149a36c61f9SKrishna Gudipati 			 * this is a new device. create rport
4150a36c61f9SKrishna Gudipati 			 */
4151a36c61f9SKrishna Gudipati 			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4152a36c61f9SKrishna Gudipati 		} else {
4153a36c61f9SKrishna Gudipati 			/*
4154a36c61f9SKrishna Gudipati 			 * this rport already exists
4155a36c61f9SKrishna Gudipati 			 */
4156a36c61f9SKrishna Gudipati 			bfa_fcs_rport_scn(rport);
4157a36c61f9SKrishna Gudipati 		}
4158a36c61f9SKrishna Gudipati 
4159a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, gidft_entry->pid);
4160a36c61f9SKrishna Gudipati 
4161a36c61f9SKrishna Gudipati 		/*
4162a36c61f9SKrishna Gudipati 		 * if the last entry bit is set, bail out.
4163a36c61f9SKrishna Gudipati 		 */
4164a36c61f9SKrishna Gudipati 		if (gidft_entry->last)
4165a36c61f9SKrishna Gudipati 			return;
4166a36c61f9SKrishna Gudipati 	}
4167a36c61f9SKrishna Gudipati }
4168a36c61f9SKrishna Gudipati 
4169a36c61f9SKrishna Gudipati /**
4170a36c61f9SKrishna Gudipati  *  fcs_ns_public FCS nameserver public interfaces
4171a36c61f9SKrishna Gudipati  */
4172a36c61f9SKrishna Gudipati 
4173a36c61f9SKrishna Gudipati /*
4174a36c61f9SKrishna Gudipati  * Functions called by port/fab.
4175a36c61f9SKrishna Gudipati  * These will send relevant Events to the ns state machine.
4176a36c61f9SKrishna Gudipati  */
4177a36c61f9SKrishna Gudipati void
4178a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4179a36c61f9SKrishna Gudipati {
4180a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4181a36c61f9SKrishna Gudipati 
4182a36c61f9SKrishna Gudipati 	ns->port = port;
4183a36c61f9SKrishna Gudipati 	bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4184a36c61f9SKrishna Gudipati }
4185a36c61f9SKrishna Gudipati 
4186a36c61f9SKrishna Gudipati void
4187a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4188a36c61f9SKrishna Gudipati {
4189a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4190a36c61f9SKrishna Gudipati 
4191a36c61f9SKrishna Gudipati 	ns->port = port;
4192a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4193a36c61f9SKrishna Gudipati }
4194a36c61f9SKrishna Gudipati 
4195a36c61f9SKrishna Gudipati void
4196a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4197a36c61f9SKrishna Gudipati {
4198a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4199a36c61f9SKrishna Gudipati 
4200a36c61f9SKrishna Gudipati 	ns->port = port;
4201a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4202a36c61f9SKrishna Gudipati }
4203a36c61f9SKrishna Gudipati 
4204a36c61f9SKrishna Gudipati void
4205a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4206a36c61f9SKrishna Gudipati {
4207a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4208a36c61f9SKrishna Gudipati 
4209a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
4210a36c61f9SKrishna Gudipati 	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4211a36c61f9SKrishna Gudipati }
4212a36c61f9SKrishna Gudipati 
4213a36c61f9SKrishna Gudipati void
4214a36c61f9SKrishna Gudipati bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4215a36c61f9SKrishna Gudipati {
4216a36c61f9SKrishna Gudipati 
4217a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport;
4218a36c61f9SKrishna Gudipati 	u8 nwwns;
4219a36c61f9SKrishna Gudipati 	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
4220a36c61f9SKrishna Gudipati 	int ii;
4221a36c61f9SKrishna Gudipati 
4222a36c61f9SKrishna Gudipati 	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4223a36c61f9SKrishna Gudipati 
4224a36c61f9SKrishna Gudipati 	for (ii = 0 ; ii < nwwns; ++ii) {
4225a36c61f9SKrishna Gudipati 		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4226a36c61f9SKrishna Gudipati 		bfa_assert(rport);
4227a36c61f9SKrishna Gudipati 	}
4228a36c61f9SKrishna Gudipati }
4229a36c61f9SKrishna Gudipati 
4230a36c61f9SKrishna Gudipati /**
4231a36c61f9SKrishna Gudipati  * FCS SCN
4232a36c61f9SKrishna Gudipati  */
4233a36c61f9SKrishna Gudipati 
4234a36c61f9SKrishna Gudipati #define FC_QOS_RSCN_EVENT		0x0c
4235a36c61f9SKrishna Gudipati #define FC_FABRIC_NAME_RSCN_EVENT	0x0d
4236a36c61f9SKrishna Gudipati 
4237a36c61f9SKrishna Gudipati /*
4238a36c61f9SKrishna Gudipati  * forward declarations
4239a36c61f9SKrishna Gudipati  */
4240a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4241a36c61f9SKrishna Gudipati 					  struct bfa_fcxp_s *fcxp_alloced);
4242a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
4243a36c61f9SKrishna Gudipati 					      struct bfa_fcxp_s *fcxp,
4244a36c61f9SKrishna Gudipati 					      void *cbarg,
4245a36c61f9SKrishna Gudipati 					      bfa_status_t req_status,
4246a36c61f9SKrishna Gudipati 					      u32 rsp_len,
4247a36c61f9SKrishna Gudipati 					      u32 resid_len,
4248a36c61f9SKrishna Gudipati 					      struct fchs_s *rsp_fchs);
4249a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4250a36c61f9SKrishna Gudipati 					     struct fchs_s *rx_fchs);
4251a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_timeout(void *arg);
4252a36c61f9SKrishna Gudipati 
4253a36c61f9SKrishna Gudipati /**
4254a36c61f9SKrishna Gudipati  *  fcs_scm_sm FCS SCN state machine
4255a36c61f9SKrishna Gudipati  */
4256a36c61f9SKrishna Gudipati 
4257a36c61f9SKrishna Gudipati /**
4258a36c61f9SKrishna Gudipati  * VPort SCN State Machine events
4259a36c61f9SKrishna Gudipati  */
4260a36c61f9SKrishna Gudipati enum port_scn_event {
4261a36c61f9SKrishna Gudipati 	SCNSM_EVENT_PORT_ONLINE = 1,
4262a36c61f9SKrishna Gudipati 	SCNSM_EVENT_PORT_OFFLINE = 2,
4263a36c61f9SKrishna Gudipati 	SCNSM_EVENT_RSP_OK = 3,
4264a36c61f9SKrishna Gudipati 	SCNSM_EVENT_RSP_ERROR = 4,
4265a36c61f9SKrishna Gudipati 	SCNSM_EVENT_TIMEOUT = 5,
4266a36c61f9SKrishna Gudipati 	SCNSM_EVENT_SCR_SENT = 6,
4267a36c61f9SKrishna Gudipati };
4268a36c61f9SKrishna Gudipati 
4269a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4270a36c61f9SKrishna Gudipati 					    enum port_scn_event event);
4271a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_sm_sending_scr(
4272a36c61f9SKrishna Gudipati 					struct bfa_fcs_lport_scn_s *scn,
4273a36c61f9SKrishna Gudipati 					enum port_scn_event event);
4274a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4275a36c61f9SKrishna Gudipati 					enum port_scn_event event);
4276a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4277a36c61f9SKrishna Gudipati 					      enum port_scn_event event);
4278a36c61f9SKrishna Gudipati static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4279a36c61f9SKrishna Gudipati 					   enum port_scn_event event);
4280a36c61f9SKrishna Gudipati 
4281a36c61f9SKrishna Gudipati /**
4282a36c61f9SKrishna Gudipati  *	Starting state - awaiting link up.
4283a36c61f9SKrishna Gudipati  */
4284a36c61f9SKrishna Gudipati static void
4285a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4286a36c61f9SKrishna Gudipati 			enum port_scn_event event)
4287a36c61f9SKrishna Gudipati {
4288a36c61f9SKrishna Gudipati 	switch (event) {
4289a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_PORT_ONLINE:
4290a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4291a36c61f9SKrishna Gudipati 		bfa_fcs_lport_scn_send_scr(scn, NULL);
4292a36c61f9SKrishna Gudipati 		break;
4293a36c61f9SKrishna Gudipati 
4294a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_PORT_OFFLINE:
4295a36c61f9SKrishna Gudipati 		break;
4296a36c61f9SKrishna Gudipati 
4297a36c61f9SKrishna Gudipati 	default:
4298a36c61f9SKrishna Gudipati 		bfa_sm_fault(scn->port->fcs, event);
4299a36c61f9SKrishna Gudipati 	}
4300a36c61f9SKrishna Gudipati }
4301a36c61f9SKrishna Gudipati 
4302a36c61f9SKrishna Gudipati static void
4303a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4304a36c61f9SKrishna Gudipati 				enum port_scn_event event)
4305a36c61f9SKrishna Gudipati {
4306a36c61f9SKrishna Gudipati 	switch (event) {
4307a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_SCR_SENT:
4308a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4309a36c61f9SKrishna Gudipati 		break;
4310a36c61f9SKrishna Gudipati 
4311a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_PORT_OFFLINE:
4312a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4313a36c61f9SKrishna Gudipati 		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4314a36c61f9SKrishna Gudipati 		break;
4315a36c61f9SKrishna Gudipati 
4316a36c61f9SKrishna Gudipati 	default:
4317a36c61f9SKrishna Gudipati 		bfa_sm_fault(scn->port->fcs, event);
4318a36c61f9SKrishna Gudipati 	}
4319a36c61f9SKrishna Gudipati }
4320a36c61f9SKrishna Gudipati 
4321a36c61f9SKrishna Gudipati static void
4322a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4323a36c61f9SKrishna Gudipati 			enum port_scn_event event)
4324a36c61f9SKrishna Gudipati {
4325a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = scn->port;
4326a36c61f9SKrishna Gudipati 
4327a36c61f9SKrishna Gudipati 	switch (event) {
4328a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_RSP_OK:
4329a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4330a36c61f9SKrishna Gudipati 		break;
4331a36c61f9SKrishna Gudipati 
4332a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_RSP_ERROR:
4333a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4334a36c61f9SKrishna Gudipati 		bfa_timer_start(port->fcs->bfa, &scn->timer,
4335a36c61f9SKrishna Gudipati 				    bfa_fcs_lport_scn_timeout, scn,
4336a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
4337a36c61f9SKrishna Gudipati 		break;
4338a36c61f9SKrishna Gudipati 
4339a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_PORT_OFFLINE:
4340a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4341a36c61f9SKrishna Gudipati 		bfa_fcxp_discard(scn->fcxp);
4342a36c61f9SKrishna Gudipati 		break;
4343a36c61f9SKrishna Gudipati 
4344a36c61f9SKrishna Gudipati 	default:
4345a36c61f9SKrishna Gudipati 		bfa_sm_fault(port->fcs, event);
4346a36c61f9SKrishna Gudipati 	}
4347a36c61f9SKrishna Gudipati }
4348a36c61f9SKrishna Gudipati 
4349a36c61f9SKrishna Gudipati static void
4350a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4351a36c61f9SKrishna Gudipati 				enum port_scn_event event)
4352a36c61f9SKrishna Gudipati {
4353a36c61f9SKrishna Gudipati 	switch (event) {
4354a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_TIMEOUT:
4355a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4356a36c61f9SKrishna Gudipati 		bfa_fcs_lport_scn_send_scr(scn, NULL);
4357a36c61f9SKrishna Gudipati 		break;
4358a36c61f9SKrishna Gudipati 
4359a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_PORT_OFFLINE:
4360a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4361a36c61f9SKrishna Gudipati 		bfa_timer_stop(&scn->timer);
4362a36c61f9SKrishna Gudipati 		break;
4363a36c61f9SKrishna Gudipati 
4364a36c61f9SKrishna Gudipati 	default:
4365a36c61f9SKrishna Gudipati 		bfa_sm_fault(scn->port->fcs, event);
4366a36c61f9SKrishna Gudipati 	}
4367a36c61f9SKrishna Gudipati }
4368a36c61f9SKrishna Gudipati 
4369a36c61f9SKrishna Gudipati static void
4370a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4371a36c61f9SKrishna Gudipati 			enum port_scn_event event)
4372a36c61f9SKrishna Gudipati {
4373a36c61f9SKrishna Gudipati 	switch (event) {
4374a36c61f9SKrishna Gudipati 	case SCNSM_EVENT_PORT_OFFLINE:
4375a36c61f9SKrishna Gudipati 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4376a36c61f9SKrishna Gudipati 		break;
4377a36c61f9SKrishna Gudipati 
4378a36c61f9SKrishna Gudipati 	default:
4379a36c61f9SKrishna Gudipati 		bfa_sm_fault(scn->port->fcs, event);
4380a36c61f9SKrishna Gudipati 	}
4381a36c61f9SKrishna Gudipati }
4382a36c61f9SKrishna Gudipati 
4383a36c61f9SKrishna Gudipati 
4384a36c61f9SKrishna Gudipati 
4385a36c61f9SKrishna Gudipati /**
4386a36c61f9SKrishna Gudipati  *  fcs_scn_private FCS SCN private functions
4387a36c61f9SKrishna Gudipati  */
4388a36c61f9SKrishna Gudipati 
4389a36c61f9SKrishna Gudipati /**
4390a36c61f9SKrishna Gudipati  * This routine will be called to send a SCR command.
4391a36c61f9SKrishna Gudipati  */
4392a36c61f9SKrishna Gudipati static void
4393a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4394a36c61f9SKrishna Gudipati {
4395a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4396a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = scn->port;
4397a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
4398a36c61f9SKrishna Gudipati 	int             len;
4399a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
4400a36c61f9SKrishna Gudipati 
4401a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->pid);
4402a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4403a36c61f9SKrishna Gudipati 
4404a36c61f9SKrishna Gudipati 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4405a36c61f9SKrishna Gudipati 	if (!fcxp) {
4406a36c61f9SKrishna Gudipati 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4407a36c61f9SKrishna Gudipati 					bfa_fcs_lport_scn_send_scr, scn);
4408a36c61f9SKrishna Gudipati 		return;
4409a36c61f9SKrishna Gudipati 	}
4410a36c61f9SKrishna Gudipati 	scn->fcxp = fcxp;
4411a36c61f9SKrishna Gudipati 
4412a36c61f9SKrishna Gudipati 	/* Handle VU registrations for Base port only */
4413a36c61f9SKrishna Gudipati 	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4414a36c61f9SKrishna Gudipati 		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4415a36c61f9SKrishna Gudipati 				bfa_lps_is_brcd_fabric(port->fabric->lps),
4416a36c61f9SKrishna Gudipati 							port->pid, 0);
4417a36c61f9SKrishna Gudipati 	} else {
4418a36c61f9SKrishna Gudipati 	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4419a36c61f9SKrishna Gudipati 				    BFA_FALSE,
4420a36c61f9SKrishna Gudipati 				    port->pid, 0);
4421a36c61f9SKrishna Gudipati 	}
4422a36c61f9SKrishna Gudipati 
4423a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4424a36c61f9SKrishna Gudipati 			  FC_CLASS_3, len, &fchs,
4425a36c61f9SKrishna Gudipati 			  bfa_fcs_lport_scn_scr_response,
4426a36c61f9SKrishna Gudipati 			  (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4427a36c61f9SKrishna Gudipati 
4428a36c61f9SKrishna Gudipati 	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4429a36c61f9SKrishna Gudipati }
4430a36c61f9SKrishna Gudipati 
4431a36c61f9SKrishna Gudipati static void
4432a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4433a36c61f9SKrishna Gudipati 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
4434a36c61f9SKrishna Gudipati 			      u32 resid_len, struct fchs_s *rsp_fchs)
4435a36c61f9SKrishna Gudipati {
4436a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4437a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_s *port = scn->port;
4438a36c61f9SKrishna Gudipati 	struct fc_els_cmd_s *els_cmd;
4439a36c61f9SKrishna Gudipati 	struct fc_ls_rjt_s *ls_rjt;
4440a36c61f9SKrishna Gudipati 
4441a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4442a36c61f9SKrishna Gudipati 
4443a36c61f9SKrishna Gudipati 	/*
4444a36c61f9SKrishna Gudipati 	 * Sanity Checks
4445a36c61f9SKrishna Gudipati 	 */
4446a36c61f9SKrishna Gudipati 	if (req_status != BFA_STATUS_OK) {
4447a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, req_status);
4448a36c61f9SKrishna Gudipati 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4449a36c61f9SKrishna Gudipati 		return;
4450a36c61f9SKrishna Gudipati 	}
4451a36c61f9SKrishna Gudipati 
4452a36c61f9SKrishna Gudipati 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4453a36c61f9SKrishna Gudipati 
4454a36c61f9SKrishna Gudipati 	switch (els_cmd->els_code) {
4455a36c61f9SKrishna Gudipati 
4456a36c61f9SKrishna Gudipati 	case FC_ELS_ACC:
4457a36c61f9SKrishna Gudipati 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4458a36c61f9SKrishna Gudipati 		break;
4459a36c61f9SKrishna Gudipati 
4460a36c61f9SKrishna Gudipati 	case FC_ELS_LS_RJT:
4461a36c61f9SKrishna Gudipati 
4462a36c61f9SKrishna Gudipati 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4463a36c61f9SKrishna Gudipati 
4464a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, ls_rjt->reason_code);
4465a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4466a36c61f9SKrishna Gudipati 
4467a36c61f9SKrishna Gudipati 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4468a36c61f9SKrishna Gudipati 		break;
4469a36c61f9SKrishna Gudipati 
4470a36c61f9SKrishna Gudipati 	default:
4471a36c61f9SKrishna Gudipati 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4472a36c61f9SKrishna Gudipati 	}
4473a36c61f9SKrishna Gudipati }
4474a36c61f9SKrishna Gudipati 
4475a36c61f9SKrishna Gudipati /*
4476a36c61f9SKrishna Gudipati  * Send a LS Accept
4477a36c61f9SKrishna Gudipati  */
4478a36c61f9SKrishna Gudipati static void
4479a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4480a36c61f9SKrishna Gudipati 				struct fchs_s *rx_fchs)
4481a36c61f9SKrishna Gudipati {
4482a36c61f9SKrishna Gudipati 	struct fchs_s fchs;
4483a36c61f9SKrishna Gudipati 	struct bfa_fcxp_s *fcxp;
4484a36c61f9SKrishna Gudipati 	struct bfa_rport_s *bfa_rport = NULL;
4485a36c61f9SKrishna Gudipati 	int             len;
4486a36c61f9SKrishna Gudipati 
4487a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, rx_fchs->s_id);
4488a36c61f9SKrishna Gudipati 
4489a36c61f9SKrishna Gudipati 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4490a36c61f9SKrishna Gudipati 	if (!fcxp)
4491a36c61f9SKrishna Gudipati 		return;
4492a36c61f9SKrishna Gudipati 
4493a36c61f9SKrishna Gudipati 	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4494a36c61f9SKrishna Gudipati 			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4495a36c61f9SKrishna Gudipati 			      rx_fchs->ox_id);
4496a36c61f9SKrishna Gudipati 
4497a36c61f9SKrishna Gudipati 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4498a36c61f9SKrishna Gudipati 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4499a36c61f9SKrishna Gudipati 			  FC_MAX_PDUSZ, 0);
4500a36c61f9SKrishna Gudipati }
4501a36c61f9SKrishna Gudipati 
4502a36c61f9SKrishna Gudipati /**
4503a36c61f9SKrishna Gudipati  *     This routine will be called by bfa_timer on timer timeouts.
4504a36c61f9SKrishna Gudipati  *
4505a36c61f9SKrishna Gudipati  *	param[in]	vport		- pointer to bfa_fcs_lport_t.
4506a36c61f9SKrishna Gudipati  *	param[out]	vport_status	- pointer to return vport status in
4507a36c61f9SKrishna Gudipati  *
4508a36c61f9SKrishna Gudipati  *	return
4509a36c61f9SKrishna Gudipati  *		void
4510a36c61f9SKrishna Gudipati  *
4511a36c61f9SKrishna Gudipati  *	Special Considerations:
4512a36c61f9SKrishna Gudipati  *
4513a36c61f9SKrishna Gudipati  *	note
4514a36c61f9SKrishna Gudipati  */
4515a36c61f9SKrishna Gudipati static void
4516a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_timeout(void *arg)
4517a36c61f9SKrishna Gudipati {
4518a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4519a36c61f9SKrishna Gudipati 
4520a36c61f9SKrishna Gudipati 	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4521a36c61f9SKrishna Gudipati }
4522a36c61f9SKrishna Gudipati 
4523a36c61f9SKrishna Gudipati 
4524a36c61f9SKrishna Gudipati 
4525a36c61f9SKrishna Gudipati /**
4526a36c61f9SKrishna Gudipati  *  fcs_scn_public FCS state change notification public interfaces
4527a36c61f9SKrishna Gudipati  */
4528a36c61f9SKrishna Gudipati 
4529a36c61f9SKrishna Gudipati /*
4530a36c61f9SKrishna Gudipati  * Functions called by port/fab
4531a36c61f9SKrishna Gudipati  */
4532a36c61f9SKrishna Gudipati void
4533a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4534a36c61f9SKrishna Gudipati {
4535a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4536a36c61f9SKrishna Gudipati 
4537a36c61f9SKrishna Gudipati 	scn->port = port;
4538a36c61f9SKrishna Gudipati 	bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4539a36c61f9SKrishna Gudipati }
4540a36c61f9SKrishna Gudipati 
4541a36c61f9SKrishna Gudipati void
4542a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4543a36c61f9SKrishna Gudipati {
4544a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4545a36c61f9SKrishna Gudipati 
4546a36c61f9SKrishna Gudipati 	scn->port = port;
4547a36c61f9SKrishna Gudipati 	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4548a36c61f9SKrishna Gudipati }
4549a36c61f9SKrishna Gudipati 
4550a36c61f9SKrishna Gudipati void
4551a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4552a36c61f9SKrishna Gudipati {
4553a36c61f9SKrishna Gudipati 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4554a36c61f9SKrishna Gudipati 
4555a36c61f9SKrishna Gudipati 	scn->port = port;
4556a36c61f9SKrishna Gudipati 	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4557a36c61f9SKrishna Gudipati }
4558a36c61f9SKrishna Gudipati 
4559a36c61f9SKrishna Gudipati static void
4560a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4561a36c61f9SKrishna Gudipati {
4562a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport;
4563a36c61f9SKrishna Gudipati 
4564a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, rpid);
4565a36c61f9SKrishna Gudipati 
4566a36c61f9SKrishna Gudipati 	/**
4567a36c61f9SKrishna Gudipati 	 * If this is an unknown device, then it just came online.
4568a36c61f9SKrishna Gudipati 	 * Otherwise let rport handle the RSCN event.
4569a36c61f9SKrishna Gudipati 	 */
4570a36c61f9SKrishna Gudipati 	rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4571a36c61f9SKrishna Gudipati 	if (rport == NULL) {
4572a36c61f9SKrishna Gudipati 		/*
4573a36c61f9SKrishna Gudipati 		 * If min cfg mode is enabled, we donot need to
4574a36c61f9SKrishna Gudipati 		 * discover any new rports.
4575a36c61f9SKrishna Gudipati 		 */
4576a36c61f9SKrishna Gudipati 		if (!__fcs_min_cfg(port->fcs))
4577a36c61f9SKrishna Gudipati 			rport = bfa_fcs_rport_create(port, rpid);
4578a36c61f9SKrishna Gudipati 	} else
4579a36c61f9SKrishna Gudipati 		bfa_fcs_rport_scn(rport);
4580a36c61f9SKrishna Gudipati }
4581a36c61f9SKrishna Gudipati 
4582a36c61f9SKrishna Gudipati /**
4583a36c61f9SKrishna Gudipati  * rscn format based PID comparison
4584a36c61f9SKrishna Gudipati  */
4585a36c61f9SKrishna Gudipati #define __fc_pid_match(__c0, __c1, __fmt)		\
4586a36c61f9SKrishna Gudipati 	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
4587a36c61f9SKrishna Gudipati 	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
4588a36c61f9SKrishna Gudipati 	  ((__c0)[0] == (__c1)[0])) ||				\
4589a36c61f9SKrishna Gudipati 	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
4590a36c61f9SKrishna Gudipati 	  ((__c0)[0] == (__c1)[0]) &&				\
4591a36c61f9SKrishna Gudipati 	  ((__c0)[1] == (__c1)[1])))
4592a36c61f9SKrishna Gudipati 
4593a36c61f9SKrishna Gudipati static void
4594a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4595a36c61f9SKrishna Gudipati 				enum fc_rscn_format format,
4596a36c61f9SKrishna Gudipati 				u32 rscn_pid)
4597a36c61f9SKrishna Gudipati {
4598a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport;
4599a36c61f9SKrishna Gudipati 	struct list_head        *qe, *qe_next;
4600a36c61f9SKrishna Gudipati 	u8        *c0, *c1;
4601a36c61f9SKrishna Gudipati 
4602a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, format);
4603a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, rscn_pid);
4604a36c61f9SKrishna Gudipati 
4605a36c61f9SKrishna Gudipati 	c0 = (u8 *) &rscn_pid;
4606a36c61f9SKrishna Gudipati 
4607a36c61f9SKrishna Gudipati 	list_for_each_safe(qe, qe_next, &port->rport_q) {
4608a36c61f9SKrishna Gudipati 		rport = (struct bfa_fcs_rport_s *) qe;
4609a36c61f9SKrishna Gudipati 		c1 = (u8 *) &rport->pid;
4610a36c61f9SKrishna Gudipati 		if (__fc_pid_match(c0, c1, format))
4611a36c61f9SKrishna Gudipati 			bfa_fcs_rport_scn(rport);
4612a36c61f9SKrishna Gudipati 	}
4613a36c61f9SKrishna Gudipati }
4614a36c61f9SKrishna Gudipati 
4615a36c61f9SKrishna Gudipati 
4616a36c61f9SKrishna Gudipati void
4617a36c61f9SKrishna Gudipati bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4618a36c61f9SKrishna Gudipati 			struct fchs_s *fchs, u32 len)
4619a36c61f9SKrishna Gudipati {
4620a36c61f9SKrishna Gudipati 	struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4621a36c61f9SKrishna Gudipati 	int             num_entries;
4622a36c61f9SKrishna Gudipati 	u32        rscn_pid;
4623a36c61f9SKrishna Gudipati 	bfa_boolean_t   nsquery = BFA_FALSE, found;
4624a36c61f9SKrishna Gudipati 	int             i = 0, j;
4625a36c61f9SKrishna Gudipati 
4626a36c61f9SKrishna Gudipati 	num_entries =
4627ba816ea8SJing Huang 		(be16_to_cpu(rscn->payldlen) -
4628a36c61f9SKrishna Gudipati 		 sizeof(u32)) / sizeof(rscn->event[0]);
4629a36c61f9SKrishna Gudipati 
4630a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, num_entries);
4631a36c61f9SKrishna Gudipati 
4632a36c61f9SKrishna Gudipati 	port->stats.num_rscn++;
4633a36c61f9SKrishna Gudipati 
4634a36c61f9SKrishna Gudipati 	bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4635a36c61f9SKrishna Gudipati 
4636a36c61f9SKrishna Gudipati 	for (i = 0; i < num_entries; i++) {
4637a36c61f9SKrishna Gudipati 		rscn_pid = rscn->event[i].portid;
4638a36c61f9SKrishna Gudipati 
4639a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, rscn->event[i].format);
4640a36c61f9SKrishna Gudipati 		bfa_trc(port->fcs, rscn_pid);
4641a36c61f9SKrishna Gudipati 
4642a36c61f9SKrishna Gudipati 		/* check for duplicate entries in the list */
4643a36c61f9SKrishna Gudipati 		found = BFA_FALSE;
4644a36c61f9SKrishna Gudipati 		for (j = 0; j < i; j++) {
4645a36c61f9SKrishna Gudipati 			if (rscn->event[j].portid == rscn_pid) {
4646a36c61f9SKrishna Gudipati 				found = BFA_TRUE;
4647a36c61f9SKrishna Gudipati 				break;
4648a36c61f9SKrishna Gudipati 			}
4649a36c61f9SKrishna Gudipati 		}
4650a36c61f9SKrishna Gudipati 
4651a36c61f9SKrishna Gudipati 		/* if found in down the list, pid has been already processed */
4652a36c61f9SKrishna Gudipati 		if (found) {
4653a36c61f9SKrishna Gudipati 			bfa_trc(port->fcs, rscn_pid);
4654a36c61f9SKrishna Gudipati 			continue;
4655a36c61f9SKrishna Gudipati 		}
4656a36c61f9SKrishna Gudipati 
4657a36c61f9SKrishna Gudipati 		switch (rscn->event[i].format) {
4658a36c61f9SKrishna Gudipati 		case FC_RSCN_FORMAT_PORTID:
4659a36c61f9SKrishna Gudipati 			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4660a36c61f9SKrishna Gudipati 				/*
4661a36c61f9SKrishna Gudipati 				 * Ignore this event.
4662a36c61f9SKrishna Gudipati 				 * f/w would have processed it
4663a36c61f9SKrishna Gudipati 				 */
4664a36c61f9SKrishna Gudipati 				bfa_trc(port->fcs, rscn_pid);
4665a36c61f9SKrishna Gudipati 			} else {
4666a36c61f9SKrishna Gudipati 				port->stats.num_portid_rscn++;
4667a36c61f9SKrishna Gudipati 				bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4668a36c61f9SKrishna Gudipati 			}
4669a36c61f9SKrishna Gudipati 		break;
4670a36c61f9SKrishna Gudipati 
4671a36c61f9SKrishna Gudipati 		case FC_RSCN_FORMAT_FABRIC:
4672a36c61f9SKrishna Gudipati 			if (rscn->event[i].qualifier ==
4673a36c61f9SKrishna Gudipati 					FC_FABRIC_NAME_RSCN_EVENT) {
4674a36c61f9SKrishna Gudipati 				bfa_fcs_lport_ms_fabric_rscn(port);
4675a36c61f9SKrishna Gudipati 				break;
4676a36c61f9SKrishna Gudipati 			}
4677a36c61f9SKrishna Gudipati 			/* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
4678a36c61f9SKrishna Gudipati 
4679a36c61f9SKrishna Gudipati 		case FC_RSCN_FORMAT_AREA:
4680a36c61f9SKrishna Gudipati 		case FC_RSCN_FORMAT_DOMAIN:
4681a36c61f9SKrishna Gudipati 			nsquery = BFA_TRUE;
4682a36c61f9SKrishna Gudipati 			bfa_fcs_lport_scn_multiport_rscn(port,
4683a36c61f9SKrishna Gudipati 							rscn->event[i].format,
4684a36c61f9SKrishna Gudipati 							rscn_pid);
4685a36c61f9SKrishna Gudipati 			break;
4686a36c61f9SKrishna Gudipati 
4687a36c61f9SKrishna Gudipati 
4688a36c61f9SKrishna Gudipati 		default:
4689a36c61f9SKrishna Gudipati 			bfa_assert(0);
4690a36c61f9SKrishna Gudipati 			nsquery = BFA_TRUE;
4691a36c61f9SKrishna Gudipati 		}
4692a36c61f9SKrishna Gudipati 	}
4693a36c61f9SKrishna Gudipati 
4694a36c61f9SKrishna Gudipati 	/**
4695a36c61f9SKrishna Gudipati 	 * If any of area, domain or fabric RSCN is received, do a fresh discovery
4696a36c61f9SKrishna Gudipati 	 * to find new devices.
4697a36c61f9SKrishna Gudipati 	 */
4698a36c61f9SKrishna Gudipati 	if (nsquery)
4699a36c61f9SKrishna Gudipati 		bfa_fcs_lport_ns_query(port);
4700a36c61f9SKrishna Gudipati }
4701a36c61f9SKrishna Gudipati 
4702a36c61f9SKrishna Gudipati /**
4703a36c61f9SKrishna Gudipati  * BFA FCS port
4704a36c61f9SKrishna Gudipati  */
4705a36c61f9SKrishna Gudipati /**
4706a36c61f9SKrishna Gudipati  *  fcs_port_api BFA FCS port API
4707a36c61f9SKrishna Gudipati  */
4708a36c61f9SKrishna Gudipati struct bfa_fcs_lport_s *
4709a36c61f9SKrishna Gudipati bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4710a36c61f9SKrishna Gudipati {
4711a36c61f9SKrishna Gudipati 	return &fcs->fabric.bport;
4712a36c61f9SKrishna Gudipati }
4713a36c61f9SKrishna Gudipati 
4714a36c61f9SKrishna Gudipati wwn_t
4715a36c61f9SKrishna Gudipati bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4716a36c61f9SKrishna Gudipati 		int nrports, bfa_boolean_t bwwn)
4717a36c61f9SKrishna Gudipati {
4718a36c61f9SKrishna Gudipati 	struct list_head	*qh, *qe;
4719a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport = NULL;
4720a36c61f9SKrishna Gudipati 	int	i;
4721a36c61f9SKrishna Gudipati 	struct bfa_fcs_s	*fcs;
4722a36c61f9SKrishna Gudipati 
4723a36c61f9SKrishna Gudipati 	if (port == NULL || nrports == 0)
4724a36c61f9SKrishna Gudipati 		return (wwn_t) 0;
4725a36c61f9SKrishna Gudipati 
4726a36c61f9SKrishna Gudipati 	fcs = port->fcs;
4727a36c61f9SKrishna Gudipati 	bfa_trc(fcs, (u32) nrports);
4728a36c61f9SKrishna Gudipati 
4729a36c61f9SKrishna Gudipati 	i = 0;
4730a36c61f9SKrishna Gudipati 	qh = &port->rport_q;
4731a36c61f9SKrishna Gudipati 	qe = bfa_q_first(qh);
4732a36c61f9SKrishna Gudipati 
4733a36c61f9SKrishna Gudipati 	while ((qe != qh) && (i < nrports)) {
4734a36c61f9SKrishna Gudipati 		rport = (struct bfa_fcs_rport_s *) qe;
4735a36c61f9SKrishna Gudipati 		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
4736a36c61f9SKrishna Gudipati 			qe = bfa_q_next(qe);
4737a36c61f9SKrishna Gudipati 			bfa_trc(fcs, (u32) rport->pwwn);
4738a36c61f9SKrishna Gudipati 			bfa_trc(fcs, rport->pid);
4739a36c61f9SKrishna Gudipati 			bfa_trc(fcs, i);
4740a36c61f9SKrishna Gudipati 			continue;
4741a36c61f9SKrishna Gudipati 		}
4742a36c61f9SKrishna Gudipati 
4743a36c61f9SKrishna Gudipati 		if (bwwn) {
4744a36c61f9SKrishna Gudipati 			if (!memcmp(&wwn, &rport->pwwn, 8))
4745a36c61f9SKrishna Gudipati 				break;
4746a36c61f9SKrishna Gudipati 		} else {
4747a36c61f9SKrishna Gudipati 			if (i == index)
4748a36c61f9SKrishna Gudipati 				break;
4749a36c61f9SKrishna Gudipati 		}
4750a36c61f9SKrishna Gudipati 
4751a36c61f9SKrishna Gudipati 		i++;
4752a36c61f9SKrishna Gudipati 		qe = bfa_q_next(qe);
4753a36c61f9SKrishna Gudipati 	}
4754a36c61f9SKrishna Gudipati 
4755a36c61f9SKrishna Gudipati 	bfa_trc(fcs, i);
4756a36c61f9SKrishna Gudipati 	if (rport)
4757a36c61f9SKrishna Gudipati 		return rport->pwwn;
4758a36c61f9SKrishna Gudipati 	else
4759a36c61f9SKrishna Gudipati 		return (wwn_t) 0;
4760a36c61f9SKrishna Gudipati }
4761a36c61f9SKrishna Gudipati 
4762a36c61f9SKrishna Gudipati void
4763a36c61f9SKrishna Gudipati bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4764a36c61f9SKrishna Gudipati 	 wwn_t rport_wwns[], int *nrports)
4765a36c61f9SKrishna Gudipati {
4766a36c61f9SKrishna Gudipati 	struct list_head	*qh, *qe;
4767a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport = NULL;
4768a36c61f9SKrishna Gudipati 	int	i;
4769a36c61f9SKrishna Gudipati 	struct bfa_fcs_s	*fcs;
4770a36c61f9SKrishna Gudipati 
4771a36c61f9SKrishna Gudipati 	if (port == NULL || rport_wwns == NULL || *nrports == 0)
4772a36c61f9SKrishna Gudipati 		return;
4773a36c61f9SKrishna Gudipati 
4774a36c61f9SKrishna Gudipati 	fcs = port->fcs;
4775a36c61f9SKrishna Gudipati 	bfa_trc(fcs, (u32) *nrports);
4776a36c61f9SKrishna Gudipati 
4777a36c61f9SKrishna Gudipati 	i = 0;
4778a36c61f9SKrishna Gudipati 	qh = &port->rport_q;
4779a36c61f9SKrishna Gudipati 	qe = bfa_q_first(qh);
4780a36c61f9SKrishna Gudipati 
4781a36c61f9SKrishna Gudipati 	while ((qe != qh) && (i < *nrports)) {
4782a36c61f9SKrishna Gudipati 		rport = (struct bfa_fcs_rport_s *) qe;
4783a36c61f9SKrishna Gudipati 		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
4784a36c61f9SKrishna Gudipati 			qe = bfa_q_next(qe);
4785a36c61f9SKrishna Gudipati 			bfa_trc(fcs, (u32) rport->pwwn);
4786a36c61f9SKrishna Gudipati 			bfa_trc(fcs, rport->pid);
4787a36c61f9SKrishna Gudipati 			bfa_trc(fcs, i);
4788a36c61f9SKrishna Gudipati 			continue;
4789a36c61f9SKrishna Gudipati 		}
4790a36c61f9SKrishna Gudipati 
4791a36c61f9SKrishna Gudipati 		rport_wwns[i] = rport->pwwn;
4792a36c61f9SKrishna Gudipati 
4793a36c61f9SKrishna Gudipati 		i++;
4794a36c61f9SKrishna Gudipati 		qe = bfa_q_next(qe);
4795a36c61f9SKrishna Gudipati 	}
4796a36c61f9SKrishna Gudipati 
4797a36c61f9SKrishna Gudipati 	bfa_trc(fcs, i);
4798a36c61f9SKrishna Gudipati 	*nrports = i;
4799a36c61f9SKrishna Gudipati }
4800a36c61f9SKrishna Gudipati 
4801a36c61f9SKrishna Gudipati /*
4802a36c61f9SKrishna Gudipati  * Iterate's through all the rport's in the given port to
4803a36c61f9SKrishna Gudipati  * determine the maximum operating speed.
4804a36c61f9SKrishna Gudipati  *
4805a36c61f9SKrishna Gudipati  * !!!! To be used in TRL Functionality only !!!!
4806a36c61f9SKrishna Gudipati  */
4807a36c61f9SKrishna Gudipati bfa_port_speed_t
4808a36c61f9SKrishna Gudipati bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4809a36c61f9SKrishna Gudipati {
4810a36c61f9SKrishna Gudipati 	struct list_head *qh, *qe;
4811a36c61f9SKrishna Gudipati 	struct bfa_fcs_rport_s *rport = NULL;
4812a36c61f9SKrishna Gudipati 	struct bfa_fcs_s	*fcs;
4813a36c61f9SKrishna Gudipati 	bfa_port_speed_t max_speed = 0;
4814a36c61f9SKrishna Gudipati 	struct bfa_port_attr_s port_attr;
4815a36c61f9SKrishna Gudipati 	bfa_port_speed_t port_speed, rport_speed;
4816a36c61f9SKrishna Gudipati 	bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4817a36c61f9SKrishna Gudipati 
4818a36c61f9SKrishna Gudipati 
4819a36c61f9SKrishna Gudipati 	if (port == NULL)
4820a36c61f9SKrishna Gudipati 		return 0;
4821a36c61f9SKrishna Gudipati 
4822a36c61f9SKrishna Gudipati 	fcs = port->fcs;
4823a36c61f9SKrishna Gudipati 
4824a36c61f9SKrishna Gudipati 	/* Get Physical port's current speed */
4825a36c61f9SKrishna Gudipati 	bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4826a36c61f9SKrishna Gudipati 	port_speed = port_attr.speed;
4827a36c61f9SKrishna Gudipati 	bfa_trc(fcs, port_speed);
4828a36c61f9SKrishna Gudipati 
4829a36c61f9SKrishna Gudipati 	qh = &port->rport_q;
4830a36c61f9SKrishna Gudipati 	qe = bfa_q_first(qh);
4831a36c61f9SKrishna Gudipati 
4832a36c61f9SKrishna Gudipati 	while (qe != qh) {
4833a36c61f9SKrishna Gudipati 		rport = (struct bfa_fcs_rport_s *) qe;
4834a36c61f9SKrishna Gudipati 		if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
4835a36c61f9SKrishna Gudipati 			(bfa_fcs_rport_get_state(rport) ==
4836a36c61f9SKrishna Gudipati 			  BFA_RPORT_OFFLINE)) {
4837a36c61f9SKrishna Gudipati 			qe = bfa_q_next(qe);
4838a36c61f9SKrishna Gudipati 			continue;
4839a36c61f9SKrishna Gudipati 		}
4840a36c61f9SKrishna Gudipati 
4841a36c61f9SKrishna Gudipati 		rport_speed = rport->rpf.rpsc_speed;
4842a36c61f9SKrishna Gudipati 		if ((trl_enabled) && (rport_speed ==
4843a36c61f9SKrishna Gudipati 			BFA_PORT_SPEED_UNKNOWN)) {
4844a36c61f9SKrishna Gudipati 			/* Use default ratelim speed setting */
4845a36c61f9SKrishna Gudipati 			rport_speed =
4846a36c61f9SKrishna Gudipati 				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4847a36c61f9SKrishna Gudipati 		}
4848a36c61f9SKrishna Gudipati 
4849a36c61f9SKrishna Gudipati 		if	((rport_speed  == BFA_PORT_SPEED_8GBPS) ||
4850a36c61f9SKrishna Gudipati 			(rport_speed > port_speed)) {
4851a36c61f9SKrishna Gudipati 			max_speed = rport_speed;
4852a36c61f9SKrishna Gudipati 			break;
4853a36c61f9SKrishna Gudipati 		} else if (rport_speed > max_speed) {
4854a36c61f9SKrishna Gudipati 			max_speed = rport_speed;
4855a36c61f9SKrishna Gudipati 		}
4856a36c61f9SKrishna Gudipati 
4857a36c61f9SKrishna Gudipati 		qe = bfa_q_next(qe);
4858a36c61f9SKrishna Gudipati 	}
4859a36c61f9SKrishna Gudipati 
4860a36c61f9SKrishna Gudipati 	bfa_trc(fcs, max_speed);
4861a36c61f9SKrishna Gudipati 	return max_speed;
4862a36c61f9SKrishna Gudipati }
4863a36c61f9SKrishna Gudipati 
4864a36c61f9SKrishna Gudipati struct bfa_fcs_lport_s *
4865a36c61f9SKrishna Gudipati bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4866a36c61f9SKrishna Gudipati {
4867a36c61f9SKrishna Gudipati 	struct bfa_fcs_vport_s *vport;
4868a36c61f9SKrishna Gudipati 	bfa_fcs_vf_t   *vf;
4869a36c61f9SKrishna Gudipati 
4870a36c61f9SKrishna Gudipati 	bfa_assert(fcs != NULL);
4871a36c61f9SKrishna Gudipati 
4872a36c61f9SKrishna Gudipati 	vf = bfa_fcs_vf_lookup(fcs, vf_id);
4873a36c61f9SKrishna Gudipati 	if (vf == NULL) {
4874a36c61f9SKrishna Gudipati 		bfa_trc(fcs, vf_id);
4875a36c61f9SKrishna Gudipati 		return NULL;
4876a36c61f9SKrishna Gudipati 	}
4877a36c61f9SKrishna Gudipati 
4878a36c61f9SKrishna Gudipati 	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4879a36c61f9SKrishna Gudipati 		return &vf->bport;
4880a36c61f9SKrishna Gudipati 
4881a36c61f9SKrishna Gudipati 	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4882a36c61f9SKrishna Gudipati 	if (vport)
4883a36c61f9SKrishna Gudipati 		return &vport->lport;
4884a36c61f9SKrishna Gudipati 
4885a36c61f9SKrishna Gudipati 	return NULL;
4886a36c61f9SKrishna Gudipati }
4887a36c61f9SKrishna Gudipati 
4888a36c61f9SKrishna Gudipati /*
4889a36c61f9SKrishna Gudipati  *  API corresponding to NPIV_VPORT_GETINFO.
4890a36c61f9SKrishna Gudipati  */
4891a36c61f9SKrishna Gudipati void
4892a36c61f9SKrishna Gudipati bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4893a36c61f9SKrishna Gudipati 	 struct bfa_lport_info_s *port_info)
4894a36c61f9SKrishna Gudipati {
4895a36c61f9SKrishna Gudipati 
4896a36c61f9SKrishna Gudipati 	bfa_trc(port->fcs, port->fabric->fabric_name);
4897a36c61f9SKrishna Gudipati 
4898a36c61f9SKrishna Gudipati 	if (port->vport == NULL) {
4899a36c61f9SKrishna Gudipati 		/*
4900a36c61f9SKrishna Gudipati 		 * This is a Physical port
4901a36c61f9SKrishna Gudipati 		 */
4902a36c61f9SKrishna Gudipati 		port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4903a36c61f9SKrishna Gudipati 
4904a36c61f9SKrishna Gudipati 		/*
4905a36c61f9SKrishna Gudipati 		 * @todo : need to fix the state & reason
4906a36c61f9SKrishna Gudipati 		 */
4907a36c61f9SKrishna Gudipati 		port_info->port_state = 0;
4908a36c61f9SKrishna Gudipati 		port_info->offline_reason = 0;
4909a36c61f9SKrishna Gudipati 
4910a36c61f9SKrishna Gudipati 		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4911a36c61f9SKrishna Gudipati 		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4912a36c61f9SKrishna Gudipati 
4913a36c61f9SKrishna Gudipati 		port_info->max_vports_supp =
4914a36c61f9SKrishna Gudipati 			bfa_lps_get_max_vport(port->fcs->bfa);
4915a36c61f9SKrishna Gudipati 		port_info->num_vports_inuse =
4916a36c61f9SKrishna Gudipati 			bfa_fcs_fabric_vport_count(port->fabric);
4917a36c61f9SKrishna Gudipati 		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
4918a36c61f9SKrishna Gudipati 		port_info->num_rports_inuse = port->num_rports;
4919a36c61f9SKrishna Gudipati 	} else {
4920a36c61f9SKrishna Gudipati 		/*
4921a36c61f9SKrishna Gudipati 		 * This is a virtual port
4922a36c61f9SKrishna Gudipati 		 */
4923a36c61f9SKrishna Gudipati 		port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4924a36c61f9SKrishna Gudipati 
4925a36c61f9SKrishna Gudipati 		/*
4926a36c61f9SKrishna Gudipati 		 * @todo : need to fix the state & reason
4927a36c61f9SKrishna Gudipati 		 */
4928a36c61f9SKrishna Gudipati 		port_info->port_state = 0;
4929a36c61f9SKrishna Gudipati 		port_info->offline_reason = 0;
4930a36c61f9SKrishna Gudipati 
4931a36c61f9SKrishna Gudipati 		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4932a36c61f9SKrishna Gudipati 		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4933a36c61f9SKrishna Gudipati 	}
4934a36c61f9SKrishna Gudipati }
4935a36c61f9SKrishna Gudipati 
4936a36c61f9SKrishna Gudipati void
4937a36c61f9SKrishna Gudipati bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4938a36c61f9SKrishna Gudipati 	 struct bfa_lport_stats_s *port_stats)
4939a36c61f9SKrishna Gudipati {
4940a36c61f9SKrishna Gudipati 	*port_stats = fcs_port->stats;
4941a36c61f9SKrishna Gudipati }
4942a36c61f9SKrishna Gudipati 
4943a36c61f9SKrishna Gudipati void
4944a36c61f9SKrishna Gudipati bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4945a36c61f9SKrishna Gudipati {
49466a18b167SJing Huang 	memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
4947a36c61f9SKrishna Gudipati }
4948a36c61f9SKrishna Gudipati 
4949a36c61f9SKrishna Gudipati /**
4950a36c61f9SKrishna Gudipati  * FCS virtual port state machine
4951a36c61f9SKrishna Gudipati  */
4952a36c61f9SKrishna Gudipati 
4953a36c61f9SKrishna Gudipati #define __vport_fcs(__vp)       ((__vp)->lport.fcs)
4954a36c61f9SKrishna Gudipati #define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
4955a36c61f9SKrishna Gudipati #define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
4956a36c61f9SKrishna Gudipati #define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
4957a36c61f9SKrishna Gudipati #define __vport_fcid(__vp)      ((__vp)->lport.pid)
4958a36c61f9SKrishna Gudipati #define __vport_fabric(__vp)    ((__vp)->lport.fabric)
4959a36c61f9SKrishna Gudipati #define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
4960a36c61f9SKrishna Gudipati 
4961a36c61f9SKrishna Gudipati #define BFA_FCS_VPORT_MAX_RETRIES  5
4962a36c61f9SKrishna Gudipati /*
4963a36c61f9SKrishna Gudipati  * Forward declarations
4964a36c61f9SKrishna Gudipati  */
4965a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4966a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_timeout(void *vport_arg);
4967a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4968a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4969a36c61f9SKrishna Gudipati 
4970a36c61f9SKrishna Gudipati /**
4971a36c61f9SKrishna Gudipati  *  fcs_vport_sm FCS virtual port state machine
4972a36c61f9SKrishna Gudipati  */
4973a36c61f9SKrishna Gudipati 
4974a36c61f9SKrishna Gudipati /**
4975a36c61f9SKrishna Gudipati  * VPort State Machine events
4976a36c61f9SKrishna Gudipati  */
4977a36c61f9SKrishna Gudipati enum bfa_fcs_vport_event {
4978a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
4979a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
4980a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
4981a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
4982a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
4983a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
4984a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
4985a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
4986a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
4987a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
4988a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
4989a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
4990a36c61f9SKrishna Gudipati 	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
4991a36c61f9SKrishna Gudipati };
4992a36c61f9SKrishna Gudipati 
4993a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4994a36c61f9SKrishna Gudipati 					enum bfa_fcs_vport_event event);
4995a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4996a36c61f9SKrishna Gudipati 					 enum bfa_fcs_vport_event event);
4997a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4998a36c61f9SKrishna Gudipati 					 enum bfa_fcs_vport_event event);
4999a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5000a36c61f9SKrishna Gudipati 				       enum bfa_fcs_vport_event event);
5001a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5002a36c61f9SKrishna Gudipati 					     enum bfa_fcs_vport_event event);
5003a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5004a36c61f9SKrishna Gudipati 					enum bfa_fcs_vport_event event);
5005a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5006a36c61f9SKrishna Gudipati 					  enum bfa_fcs_vport_event event);
5007a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5008a36c61f9SKrishna Gudipati 					 enum bfa_fcs_vport_event event);
5009a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5010a36c61f9SKrishna Gudipati 				      enum bfa_fcs_vport_event event);
5011a36c61f9SKrishna Gudipati static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5012a36c61f9SKrishna Gudipati 				      enum bfa_fcs_vport_event event);
5013a36c61f9SKrishna Gudipati 
5014a36c61f9SKrishna Gudipati static struct bfa_sm_table_s  vport_sm_table[] = {
5015a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
5016a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
5017a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
5018a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
5019a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
5020a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
5021a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
5022a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
5023a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
5024a36c61f9SKrishna Gudipati 	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
5025a36c61f9SKrishna Gudipati };
5026a36c61f9SKrishna Gudipati 
5027a36c61f9SKrishna Gudipati /**
5028a36c61f9SKrishna Gudipati  * Beginning state.
5029a36c61f9SKrishna Gudipati  */
5030a36c61f9SKrishna Gudipati static void
5031a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
5032a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5033a36c61f9SKrishna Gudipati {
5034a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5035a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5036a36c61f9SKrishna Gudipati 
5037a36c61f9SKrishna Gudipati 	switch (event) {
5038a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_CREATE:
5039a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5040a36c61f9SKrishna Gudipati 		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
5041a36c61f9SKrishna Gudipati 		break;
5042a36c61f9SKrishna Gudipati 
5043a36c61f9SKrishna Gudipati 	default:
5044a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5045a36c61f9SKrishna Gudipati 	}
5046a36c61f9SKrishna Gudipati }
5047a36c61f9SKrishna Gudipati 
5048a36c61f9SKrishna Gudipati /**
5049a36c61f9SKrishna Gudipati  * Created state - a start event is required to start up the state machine.
5050a36c61f9SKrishna Gudipati  */
5051a36c61f9SKrishna Gudipati static void
5052a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
5053a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5054a36c61f9SKrishna Gudipati {
5055a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5056a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5057a36c61f9SKrishna Gudipati 
5058a36c61f9SKrishna Gudipati 	switch (event) {
5059a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_START:
5060a36c61f9SKrishna Gudipati 		if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
5061a36c61f9SKrishna Gudipati 		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
5062a36c61f9SKrishna Gudipati 			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5063a36c61f9SKrishna Gudipati 			bfa_fcs_vport_do_fdisc(vport);
5064a36c61f9SKrishna Gudipati 		} else {
5065a36c61f9SKrishna Gudipati 			/**
5066a36c61f9SKrishna Gudipati 			 * Fabric is offline or not NPIV capable, stay in
5067a36c61f9SKrishna Gudipati 			 * offline state.
5068a36c61f9SKrishna Gudipati 			 */
5069a36c61f9SKrishna Gudipati 			vport->vport_stats.fab_no_npiv++;
5070a36c61f9SKrishna Gudipati 			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5071a36c61f9SKrishna Gudipati 		}
5072a36c61f9SKrishna Gudipati 		break;
5073a36c61f9SKrishna Gudipati 
5074a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5075a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5076a36c61f9SKrishna Gudipati 		bfa_fcs_lport_delete(&vport->lport);
5077a36c61f9SKrishna Gudipati 		break;
5078a36c61f9SKrishna Gudipati 
5079a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_ONLINE:
5080a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_OFFLINE:
5081a36c61f9SKrishna Gudipati 		/**
5082a36c61f9SKrishna Gudipati 		 * Ignore ONLINE/OFFLINE events from fabric
5083a36c61f9SKrishna Gudipati 		 * till vport is started.
5084a36c61f9SKrishna Gudipati 		 */
5085a36c61f9SKrishna Gudipati 		break;
5086a36c61f9SKrishna Gudipati 
5087a36c61f9SKrishna Gudipati 	default:
5088a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5089a36c61f9SKrishna Gudipati 	}
5090a36c61f9SKrishna Gudipati }
5091a36c61f9SKrishna Gudipati 
5092a36c61f9SKrishna Gudipati /**
5093a36c61f9SKrishna Gudipati  * Offline state - awaiting ONLINE event from fabric SM.
5094a36c61f9SKrishna Gudipati  */
5095a36c61f9SKrishna Gudipati static void
5096a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5097a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5098a36c61f9SKrishna Gudipati {
5099a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5100a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5101a36c61f9SKrishna Gudipati 
5102a36c61f9SKrishna Gudipati 	switch (event) {
5103a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5104a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5105a36c61f9SKrishna Gudipati 		bfa_fcs_lport_delete(&vport->lport);
5106a36c61f9SKrishna Gudipati 		break;
5107a36c61f9SKrishna Gudipati 
5108a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_ONLINE:
5109a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5110a36c61f9SKrishna Gudipati 		vport->fdisc_retries = 0;
5111a36c61f9SKrishna Gudipati 		bfa_fcs_vport_do_fdisc(vport);
5112a36c61f9SKrishna Gudipati 		break;
5113a36c61f9SKrishna Gudipati 
5114a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_OFFLINE:
5115a36c61f9SKrishna Gudipati 		/*
5116a36c61f9SKrishna Gudipati 		 * This can happen if the vport couldn't be initialzied
5117a36c61f9SKrishna Gudipati 		 * due the fact that the npiv was not enabled on the switch.
5118a36c61f9SKrishna Gudipati 		 * In that case we will put the vport in offline state.
5119a36c61f9SKrishna Gudipati 		 * However, the link can go down and cause the this event to
5120a36c61f9SKrishna Gudipati 		 * be sent when we are already offline. Ignore it.
5121a36c61f9SKrishna Gudipati 		 */
5122a36c61f9SKrishna Gudipati 		break;
5123a36c61f9SKrishna Gudipati 
5124a36c61f9SKrishna Gudipati 	default:
5125a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5126a36c61f9SKrishna Gudipati 	}
5127a36c61f9SKrishna Gudipati }
5128a36c61f9SKrishna Gudipati 
5129a36c61f9SKrishna Gudipati 
5130a36c61f9SKrishna Gudipati /**
5131a36c61f9SKrishna Gudipati  * FDISC is sent and awaiting reply from fabric.
5132a36c61f9SKrishna Gudipati  */
5133a36c61f9SKrishna Gudipati static void
5134a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5135a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5136a36c61f9SKrishna Gudipati {
5137a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5138a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5139a36c61f9SKrishna Gudipati 
5140a36c61f9SKrishna Gudipati 	switch (event) {
5141a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5142a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5143a36c61f9SKrishna Gudipati 		bfa_lps_discard(vport->lps);
5144a36c61f9SKrishna Gudipati 		bfa_fcs_lport_delete(&vport->lport);
5145a36c61f9SKrishna Gudipati 		break;
5146a36c61f9SKrishna Gudipati 
5147a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_OFFLINE:
5148a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5149a36c61f9SKrishna Gudipati 		bfa_lps_discard(vport->lps);
5150a36c61f9SKrishna Gudipati 		break;
5151a36c61f9SKrishna Gudipati 
5152a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_RSP_OK:
5153a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5154a36c61f9SKrishna Gudipati 		bfa_fcs_lport_online(&vport->lport);
5155a36c61f9SKrishna Gudipati 		break;
5156a36c61f9SKrishna Gudipati 
5157a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5158a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5159a36c61f9SKrishna Gudipati 		bfa_timer_start(__vport_bfa(vport), &vport->timer,
5160a36c61f9SKrishna Gudipati 				    bfa_fcs_vport_timeout, vport,
5161a36c61f9SKrishna Gudipati 				    BFA_FCS_RETRY_TIMEOUT);
5162a36c61f9SKrishna Gudipati 		break;
5163a36c61f9SKrishna Gudipati 
5164a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_RSP_FAILED:
5165a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5166a36c61f9SKrishna Gudipati 		break;
5167a36c61f9SKrishna Gudipati 
5168a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5169a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5170a36c61f9SKrishna Gudipati 		break;
5171a36c61f9SKrishna Gudipati 
5172a36c61f9SKrishna Gudipati 	default:
5173a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5174a36c61f9SKrishna Gudipati 	}
5175a36c61f9SKrishna Gudipati }
5176a36c61f9SKrishna Gudipati 
5177a36c61f9SKrishna Gudipati /**
5178a36c61f9SKrishna Gudipati  * FDISC attempt failed - a timer is active to retry FDISC.
5179a36c61f9SKrishna Gudipati  */
5180a36c61f9SKrishna Gudipati static void
5181a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5182a36c61f9SKrishna Gudipati 			     enum bfa_fcs_vport_event event)
5183a36c61f9SKrishna Gudipati {
5184a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5185a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5186a36c61f9SKrishna Gudipati 
5187a36c61f9SKrishna Gudipati 	switch (event) {
5188a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5189a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5190a36c61f9SKrishna Gudipati 		bfa_timer_stop(&vport->timer);
5191a36c61f9SKrishna Gudipati 		bfa_fcs_lport_delete(&vport->lport);
5192a36c61f9SKrishna Gudipati 		break;
5193a36c61f9SKrishna Gudipati 
5194a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_OFFLINE:
5195a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5196a36c61f9SKrishna Gudipati 		bfa_timer_stop(&vport->timer);
5197a36c61f9SKrishna Gudipati 		break;
5198a36c61f9SKrishna Gudipati 
5199a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_TIMEOUT:
5200a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5201a36c61f9SKrishna Gudipati 		vport->vport_stats.fdisc_retries++;
5202a36c61f9SKrishna Gudipati 		vport->fdisc_retries++;
5203a36c61f9SKrishna Gudipati 		bfa_fcs_vport_do_fdisc(vport);
5204a36c61f9SKrishna Gudipati 		break;
5205a36c61f9SKrishna Gudipati 
5206a36c61f9SKrishna Gudipati 	default:
5207a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5208a36c61f9SKrishna Gudipati 	}
5209a36c61f9SKrishna Gudipati }
5210a36c61f9SKrishna Gudipati 
5211a36c61f9SKrishna Gudipati /**
5212a36c61f9SKrishna Gudipati  * Vport is online (FDISC is complete).
5213a36c61f9SKrishna Gudipati  */
5214a36c61f9SKrishna Gudipati static void
5215a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5216a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5217a36c61f9SKrishna Gudipati {
5218a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5219a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5220a36c61f9SKrishna Gudipati 
5221a36c61f9SKrishna Gudipati 	switch (event) {
5222a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5223a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5224a36c61f9SKrishna Gudipati 		bfa_fcs_lport_delete(&vport->lport);
5225a36c61f9SKrishna Gudipati 		break;
5226a36c61f9SKrishna Gudipati 
5227a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_OFFLINE:
5228a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5229a36c61f9SKrishna Gudipati 		bfa_lps_discard(vport->lps);
5230a36c61f9SKrishna Gudipati 		bfa_fcs_lport_offline(&vport->lport);
5231a36c61f9SKrishna Gudipati 		break;
5232a36c61f9SKrishna Gudipati 
5233a36c61f9SKrishna Gudipati 	default:
5234a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5235a36c61f9SKrishna Gudipati 	}
5236a36c61f9SKrishna Gudipati }
5237a36c61f9SKrishna Gudipati 
5238a36c61f9SKrishna Gudipati /**
5239a36c61f9SKrishna Gudipati  * Vport is being deleted - awaiting lport delete completion to send
5240a36c61f9SKrishna Gudipati  * LOGO to fabric.
5241a36c61f9SKrishna Gudipati  */
5242a36c61f9SKrishna Gudipati static void
5243a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5244a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5245a36c61f9SKrishna Gudipati {
5246a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5247a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5248a36c61f9SKrishna Gudipati 
5249a36c61f9SKrishna Gudipati 	switch (event) {
5250a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5251a36c61f9SKrishna Gudipati 		break;
5252a36c61f9SKrishna Gudipati 
5253a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELCOMP:
5254a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5255a36c61f9SKrishna Gudipati 		bfa_fcs_vport_do_logo(vport);
5256a36c61f9SKrishna Gudipati 		break;
5257a36c61f9SKrishna Gudipati 
5258a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_OFFLINE:
5259a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5260a36c61f9SKrishna Gudipati 		break;
5261a36c61f9SKrishna Gudipati 
5262a36c61f9SKrishna Gudipati 	default:
5263a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5264a36c61f9SKrishna Gudipati 	}
5265a36c61f9SKrishna Gudipati }
5266a36c61f9SKrishna Gudipati 
5267a36c61f9SKrishna Gudipati /**
5268a36c61f9SKrishna Gudipati  * Error State.
5269a36c61f9SKrishna Gudipati  * This state will be set when the Vport Creation fails due
5270a36c61f9SKrishna Gudipati  * to errors like Dup WWN. In this state only operation allowed
5271a36c61f9SKrishna Gudipati  * is a Vport Delete.
5272a36c61f9SKrishna Gudipati  */
5273a36c61f9SKrishna Gudipati static void
5274a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5275a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5276a36c61f9SKrishna Gudipati {
5277a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5278a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5279a36c61f9SKrishna Gudipati 
5280a36c61f9SKrishna Gudipati 	switch (event) {
5281a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5282a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5283a36c61f9SKrishna Gudipati 		bfa_fcs_lport_delete(&vport->lport);
5284a36c61f9SKrishna Gudipati 		break;
5285a36c61f9SKrishna Gudipati 
5286a36c61f9SKrishna Gudipati 	default:
5287a36c61f9SKrishna Gudipati 		bfa_trc(__vport_fcs(vport), event);
5288a36c61f9SKrishna Gudipati 	}
5289a36c61f9SKrishna Gudipati }
5290a36c61f9SKrishna Gudipati 
5291a36c61f9SKrishna Gudipati /**
5292a36c61f9SKrishna Gudipati  * Lport cleanup is in progress since vport is being deleted. Fabric is
5293a36c61f9SKrishna Gudipati  * offline, so no LOGO is needed to complete vport deletion.
5294a36c61f9SKrishna Gudipati  */
5295a36c61f9SKrishna Gudipati static void
5296a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5297a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5298a36c61f9SKrishna Gudipati {
5299a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5300a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5301a36c61f9SKrishna Gudipati 
5302a36c61f9SKrishna Gudipati 	switch (event) {
5303a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELCOMP:
5304a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5305a36c61f9SKrishna Gudipati 		bfa_fcs_vport_free(vport);
5306a36c61f9SKrishna Gudipati 		break;
5307a36c61f9SKrishna Gudipati 
5308a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5309a36c61f9SKrishna Gudipati 		break;
5310a36c61f9SKrishna Gudipati 
5311a36c61f9SKrishna Gudipati 	default:
5312a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5313a36c61f9SKrishna Gudipati 	}
5314a36c61f9SKrishna Gudipati }
5315a36c61f9SKrishna Gudipati 
5316a36c61f9SKrishna Gudipati /**
5317a36c61f9SKrishna Gudipati  * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5318a36c61f9SKrishna Gudipati  * is done.
5319a36c61f9SKrishna Gudipati  */
5320a36c61f9SKrishna Gudipati static void
5321a36c61f9SKrishna Gudipati bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5322a36c61f9SKrishna Gudipati 			enum bfa_fcs_vport_event event)
5323a36c61f9SKrishna Gudipati {
5324a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5325a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), event);
5326a36c61f9SKrishna Gudipati 
5327a36c61f9SKrishna Gudipati 	switch (event) {
5328a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_OFFLINE:
5329a36c61f9SKrishna Gudipati 		bfa_lps_discard(vport->lps);
5330a36c61f9SKrishna Gudipati 		/*
5331a36c61f9SKrishna Gudipati 		 * !!! fall through !!!
5332a36c61f9SKrishna Gudipati 		 */
5333a36c61f9SKrishna Gudipati 
5334a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_RSP_OK:
5335a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5336a36c61f9SKrishna Gudipati 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5337a36c61f9SKrishna Gudipati 		bfa_fcs_vport_free(vport);
5338a36c61f9SKrishna Gudipati 		break;
5339a36c61f9SKrishna Gudipati 
5340a36c61f9SKrishna Gudipati 	case BFA_FCS_VPORT_SM_DELETE:
5341a36c61f9SKrishna Gudipati 		break;
5342a36c61f9SKrishna Gudipati 
5343a36c61f9SKrishna Gudipati 	default:
5344a36c61f9SKrishna Gudipati 		bfa_sm_fault(__vport_fcs(vport), event);
5345a36c61f9SKrishna Gudipati 	}
5346a36c61f9SKrishna Gudipati }
5347a36c61f9SKrishna Gudipati 
5348a36c61f9SKrishna Gudipati 
5349a36c61f9SKrishna Gudipati 
5350a36c61f9SKrishna Gudipati /**
5351a36c61f9SKrishna Gudipati  *  fcs_vport_private FCS virtual port private functions
5352a36c61f9SKrishna Gudipati  */
5353a36c61f9SKrishna Gudipati /**
5354a36c61f9SKrishna Gudipati  * This routine will be called to send a FDISC command.
5355a36c61f9SKrishna Gudipati  */
5356a36c61f9SKrishna Gudipati static void
5357a36c61f9SKrishna Gudipati bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5358a36c61f9SKrishna Gudipati {
5359a36c61f9SKrishna Gudipati 	bfa_lps_fdisc(vport->lps, vport,
5360a36c61f9SKrishna Gudipati 		bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5361a36c61f9SKrishna Gudipati 		__vport_pwwn(vport), __vport_nwwn(vport));
5362a36c61f9SKrishna Gudipati 	vport->vport_stats.fdisc_sent++;
5363a36c61f9SKrishna Gudipati }
5364a36c61f9SKrishna Gudipati 
5365a36c61f9SKrishna Gudipati static void
5366a36c61f9SKrishna Gudipati bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5367a36c61f9SKrishna Gudipati {
5368a36c61f9SKrishna Gudipati 	u8		lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
5369a36c61f9SKrishna Gudipati 	u8		lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
5370a36c61f9SKrishna Gudipati 
5371a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5372a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), lsrjt_expl);
5373a36c61f9SKrishna Gudipati 
5374a36c61f9SKrishna Gudipati 	/* For certain reason codes, we don't want to retry. */
5375a36c61f9SKrishna Gudipati 	switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
5376a36c61f9SKrishna Gudipati 	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5377a36c61f9SKrishna Gudipati 	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
5378a36c61f9SKrishna Gudipati 		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5379a36c61f9SKrishna Gudipati 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5380a36c61f9SKrishna Gudipati 		else
5381a36c61f9SKrishna Gudipati 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5382a36c61f9SKrishna Gudipati 		break;
5383a36c61f9SKrishna Gudipati 
5384a36c61f9SKrishna Gudipati 	case FC_LS_RJT_EXP_INSUFF_RES:
5385a36c61f9SKrishna Gudipati 		/*
5386a36c61f9SKrishna Gudipati 		 * This means max logins per port/switch setting on the
5387a36c61f9SKrishna Gudipati 		 * switch was exceeded.
5388a36c61f9SKrishna Gudipati 		 */
5389a36c61f9SKrishna Gudipati 		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5390a36c61f9SKrishna Gudipati 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5391a36c61f9SKrishna Gudipati 		else
5392a36c61f9SKrishna Gudipati 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5393a36c61f9SKrishna Gudipati 		break;
5394a36c61f9SKrishna Gudipati 
5395a36c61f9SKrishna Gudipati 	default:
5396a36c61f9SKrishna Gudipati 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5397a36c61f9SKrishna Gudipati 	}
5398a36c61f9SKrishna Gudipati }
5399a36c61f9SKrishna Gudipati 
5400a36c61f9SKrishna Gudipati /**
5401a36c61f9SKrishna Gudipati  *	Called to send a logout to the fabric. Used when a V-Port is
5402a36c61f9SKrishna Gudipati  *	deleted/stopped.
5403a36c61f9SKrishna Gudipati  */
5404a36c61f9SKrishna Gudipati static void
5405a36c61f9SKrishna Gudipati bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5406a36c61f9SKrishna Gudipati {
5407a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5408a36c61f9SKrishna Gudipati 
5409a36c61f9SKrishna Gudipati 	vport->vport_stats.logo_sent++;
5410a36c61f9SKrishna Gudipati 	bfa_lps_fdisclogo(vport->lps);
5411a36c61f9SKrishna Gudipati }
5412a36c61f9SKrishna Gudipati 
5413a36c61f9SKrishna Gudipati 
5414a36c61f9SKrishna Gudipati /**
5415a36c61f9SKrishna Gudipati  *     This routine will be called by bfa_timer on timer timeouts.
5416a36c61f9SKrishna Gudipati  *
5417a36c61f9SKrishna Gudipati  *	param[in]	vport		- pointer to bfa_fcs_vport_t.
5418a36c61f9SKrishna Gudipati  *	param[out]	vport_status	- pointer to return vport status in
5419a36c61f9SKrishna Gudipati  *
5420a36c61f9SKrishna Gudipati  *	return
5421a36c61f9SKrishna Gudipati  *		void
5422a36c61f9SKrishna Gudipati  *
5423a36c61f9SKrishna Gudipati  *	Special Considerations:
5424a36c61f9SKrishna Gudipati  *
5425a36c61f9SKrishna Gudipati  *	note
5426a36c61f9SKrishna Gudipati  */
5427a36c61f9SKrishna Gudipati static void
5428a36c61f9SKrishna Gudipati bfa_fcs_vport_timeout(void *vport_arg)
5429a36c61f9SKrishna Gudipati {
5430a36c61f9SKrishna Gudipati 	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5431a36c61f9SKrishna Gudipati 
5432a36c61f9SKrishna Gudipati 	vport->vport_stats.fdisc_timeouts++;
5433a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5434a36c61f9SKrishna Gudipati }
5435a36c61f9SKrishna Gudipati 
5436a36c61f9SKrishna Gudipati static void
5437a36c61f9SKrishna Gudipati bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5438a36c61f9SKrishna Gudipati {
5439a36c61f9SKrishna Gudipati 	struct bfad_vport_s *vport_drv =
5440a36c61f9SKrishna Gudipati 			(struct bfad_vport_s *)vport->vport_drv;
5441a36c61f9SKrishna Gudipati 
5442a36c61f9SKrishna Gudipati 	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5443a36c61f9SKrishna Gudipati 
5444a36c61f9SKrishna Gudipati 	if (vport_drv->comp_del)
5445a36c61f9SKrishna Gudipati 		complete(vport_drv->comp_del);
5446a36c61f9SKrishna Gudipati 
5447a36c61f9SKrishna Gudipati 	bfa_lps_delete(vport->lps);
5448a36c61f9SKrishna Gudipati }
5449a36c61f9SKrishna Gudipati 
5450a36c61f9SKrishna Gudipati 
5451a36c61f9SKrishna Gudipati 
5452a36c61f9SKrishna Gudipati /**
5453a36c61f9SKrishna Gudipati  *  fcs_vport_public FCS virtual port public interfaces
5454a36c61f9SKrishna Gudipati  */
5455a36c61f9SKrishna Gudipati 
5456a36c61f9SKrishna Gudipati /**
5457a36c61f9SKrishna Gudipati  * Online notification from fabric SM.
5458a36c61f9SKrishna Gudipati  */
5459a36c61f9SKrishna Gudipati void
5460a36c61f9SKrishna Gudipati bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5461a36c61f9SKrishna Gudipati {
5462a36c61f9SKrishna Gudipati 	vport->vport_stats.fab_online++;
5463a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5464a36c61f9SKrishna Gudipati }
5465a36c61f9SKrishna Gudipati 
5466a36c61f9SKrishna Gudipati /**
5467a36c61f9SKrishna Gudipati  * Offline notification from fabric SM.
5468a36c61f9SKrishna Gudipati  */
5469a36c61f9SKrishna Gudipati void
5470a36c61f9SKrishna Gudipati bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5471a36c61f9SKrishna Gudipati {
5472a36c61f9SKrishna Gudipati 	vport->vport_stats.fab_offline++;
5473a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5474a36c61f9SKrishna Gudipati }
5475a36c61f9SKrishna Gudipati 
5476a36c61f9SKrishna Gudipati /**
5477a36c61f9SKrishna Gudipati  * Cleanup notification from fabric SM on link timer expiry.
5478a36c61f9SKrishna Gudipati  */
5479a36c61f9SKrishna Gudipati void
5480a36c61f9SKrishna Gudipati bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5481a36c61f9SKrishna Gudipati {
5482a36c61f9SKrishna Gudipati 	vport->vport_stats.fab_cleanup++;
5483a36c61f9SKrishna Gudipati }
5484a36c61f9SKrishna Gudipati /**
5485a36c61f9SKrishna Gudipati  * delete notification from fabric SM. To be invoked from within FCS.
5486a36c61f9SKrishna Gudipati  */
5487a36c61f9SKrishna Gudipati void
5488a36c61f9SKrishna Gudipati bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5489a36c61f9SKrishna Gudipati {
5490a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5491a36c61f9SKrishna Gudipati }
5492a36c61f9SKrishna Gudipati 
5493a36c61f9SKrishna Gudipati /**
5494a36c61f9SKrishna Gudipati  * Delete completion callback from associated lport
5495a36c61f9SKrishna Gudipati  */
5496a36c61f9SKrishna Gudipati void
5497a36c61f9SKrishna Gudipati bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5498a36c61f9SKrishna Gudipati {
5499a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5500a36c61f9SKrishna Gudipati }
5501a36c61f9SKrishna Gudipati 
5502a36c61f9SKrishna Gudipati 
5503a36c61f9SKrishna Gudipati 
5504a36c61f9SKrishna Gudipati /**
5505a36c61f9SKrishna Gudipati  *  fcs_vport_api Virtual port API
5506a36c61f9SKrishna Gudipati  */
5507a36c61f9SKrishna Gudipati 
5508a36c61f9SKrishna Gudipati /**
5509a36c61f9SKrishna Gudipati  *	Use this function to instantiate a new FCS vport object. This
5510a36c61f9SKrishna Gudipati  *	function will not trigger any HW initialization process (which will be
5511a36c61f9SKrishna Gudipati  *	done in vport_start() call)
5512a36c61f9SKrishna Gudipati  *
5513a36c61f9SKrishna Gudipati  *	param[in] vport	-		pointer to bfa_fcs_vport_t. This space
5514a36c61f9SKrishna Gudipati  *					needs to be allocated by the driver.
5515a36c61f9SKrishna Gudipati  *	param[in] fcs		-	FCS instance
5516a36c61f9SKrishna Gudipati  *	param[in] vport_cfg	-	vport configuration
5517a36c61f9SKrishna Gudipati  *	param[in] vf_id		-	VF_ID if vport is created within a VF.
5518a36c61f9SKrishna Gudipati  *					FC_VF_ID_NULL to specify base fabric.
5519a36c61f9SKrishna Gudipati  *	param[in] vport_drv	-	Opaque handle back to the driver's vport
5520a36c61f9SKrishna Gudipati  *					structure
5521a36c61f9SKrishna Gudipati  *
5522a36c61f9SKrishna Gudipati  *	retval BFA_STATUS_OK - on success.
5523a36c61f9SKrishna Gudipati  *	retval BFA_STATUS_FAILED - on failure.
5524a36c61f9SKrishna Gudipati  */
5525a36c61f9SKrishna Gudipati bfa_status_t
5526a36c61f9SKrishna Gudipati bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5527a36c61f9SKrishna Gudipati 		u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5528a36c61f9SKrishna Gudipati 		struct bfad_vport_s *vport_drv)
5529a36c61f9SKrishna Gudipati {
5530a36c61f9SKrishna Gudipati 	if (vport_cfg->pwwn == 0)
5531a36c61f9SKrishna Gudipati 		return BFA_STATUS_INVALID_WWN;
5532a36c61f9SKrishna Gudipati 
5533a36c61f9SKrishna Gudipati 	if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5534a36c61f9SKrishna Gudipati 		return BFA_STATUS_VPORT_WWN_BP;
5535a36c61f9SKrishna Gudipati 
5536a36c61f9SKrishna Gudipati 	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5537a36c61f9SKrishna Gudipati 		return BFA_STATUS_VPORT_EXISTS;
5538a36c61f9SKrishna Gudipati 
5539a36c61f9SKrishna Gudipati 	if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
5540a36c61f9SKrishna Gudipati 			bfa_lps_get_max_vport(fcs->bfa))
5541a36c61f9SKrishna Gudipati 		return BFA_STATUS_VPORT_MAX;
5542a36c61f9SKrishna Gudipati 
5543a36c61f9SKrishna Gudipati 	vport->lps = bfa_lps_alloc(fcs->bfa);
5544a36c61f9SKrishna Gudipati 	if (!vport->lps)
5545a36c61f9SKrishna Gudipati 		return BFA_STATUS_VPORT_MAX;
5546a36c61f9SKrishna Gudipati 
5547a36c61f9SKrishna Gudipati 	vport->vport_drv = vport_drv;
5548a36c61f9SKrishna Gudipati 	vport_cfg->preboot_vp = BFA_FALSE;
5549a36c61f9SKrishna Gudipati 
5550a36c61f9SKrishna Gudipati 	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5551a36c61f9SKrishna Gudipati 	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5552a36c61f9SKrishna Gudipati 	bfa_fcs_lport_init(&vport->lport, vport_cfg);
5553a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5554a36c61f9SKrishna Gudipati 
5555a36c61f9SKrishna Gudipati 	return BFA_STATUS_OK;
5556a36c61f9SKrishna Gudipati }
5557a36c61f9SKrishna Gudipati 
5558a36c61f9SKrishna Gudipati /**
5559a36c61f9SKrishna Gudipati  *	Use this function to instantiate a new FCS PBC vport object. This
5560a36c61f9SKrishna Gudipati  *	function will not trigger any HW initialization process (which will be
5561a36c61f9SKrishna Gudipati  *	done in vport_start() call)
5562a36c61f9SKrishna Gudipati  *
5563a36c61f9SKrishna Gudipati  *	param[in] vport	-	pointer to bfa_fcs_vport_t. This space
5564a36c61f9SKrishna Gudipati  *				needs to be allocated by the driver.
5565a36c61f9SKrishna Gudipati  *	param[in] fcs	-	FCS instance
5566a36c61f9SKrishna Gudipati  *	param[in] vport_cfg	-	vport configuration
5567a36c61f9SKrishna Gudipati  *	param[in] vf_id		-	VF_ID if vport is created within a VF.
5568a36c61f9SKrishna Gudipati  *					FC_VF_ID_NULL to specify base fabric.
5569a36c61f9SKrishna Gudipati  *	param[in] vport_drv	-	Opaque handle back to the driver's vport
5570a36c61f9SKrishna Gudipati  *					structure
5571a36c61f9SKrishna Gudipati  *
5572a36c61f9SKrishna Gudipati  *	retval BFA_STATUS_OK - on success.
5573a36c61f9SKrishna Gudipati  *	retval BFA_STATUS_FAILED - on failure.
5574a36c61f9SKrishna Gudipati  */
5575a36c61f9SKrishna Gudipati bfa_status_t
5576a36c61f9SKrishna Gudipati bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5577a36c61f9SKrishna Gudipati 			u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5578a36c61f9SKrishna Gudipati 			struct bfad_vport_s *vport_drv)
5579a36c61f9SKrishna Gudipati {
5580a36c61f9SKrishna Gudipati 	bfa_status_t rc;
5581a36c61f9SKrishna Gudipati 
5582a36c61f9SKrishna Gudipati 	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5583a36c61f9SKrishna Gudipati 	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5584a36c61f9SKrishna Gudipati 
5585a36c61f9SKrishna Gudipati 	return rc;
5586a36c61f9SKrishna Gudipati }
5587a36c61f9SKrishna Gudipati 
5588a36c61f9SKrishna Gudipati /**
5589a36c61f9SKrishna Gudipati  *	Use this function to findout if this is a pbc vport or not.
5590a36c61f9SKrishna Gudipati  *
5591a36c61f9SKrishna Gudipati  * @param[in] vport - pointer to bfa_fcs_vport_t.
5592a36c61f9SKrishna Gudipati  *
5593a36c61f9SKrishna Gudipati  * @returns None
5594a36c61f9SKrishna Gudipati  */
5595a36c61f9SKrishna Gudipati bfa_boolean_t
5596a36c61f9SKrishna Gudipati bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5597a36c61f9SKrishna Gudipati {
5598a36c61f9SKrishna Gudipati 
5599a36c61f9SKrishna Gudipati 	if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5600a36c61f9SKrishna Gudipati 		return BFA_TRUE;
5601a36c61f9SKrishna Gudipati 	else
5602a36c61f9SKrishna Gudipati 		return BFA_FALSE;
5603a36c61f9SKrishna Gudipati 
5604a36c61f9SKrishna Gudipati }
5605a36c61f9SKrishna Gudipati 
5606a36c61f9SKrishna Gudipati /**
5607a36c61f9SKrishna Gudipati  * Use this function initialize the vport.
5608a36c61f9SKrishna Gudipati  *
5609a36c61f9SKrishna Gudipati  * @param[in] vport - pointer to bfa_fcs_vport_t.
5610a36c61f9SKrishna Gudipati  *
5611a36c61f9SKrishna Gudipati  * @returns None
5612a36c61f9SKrishna Gudipati  */
5613a36c61f9SKrishna Gudipati bfa_status_t
5614a36c61f9SKrishna Gudipati bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5615a36c61f9SKrishna Gudipati {
5616a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5617a36c61f9SKrishna Gudipati 
5618a36c61f9SKrishna Gudipati 	return BFA_STATUS_OK;
5619a36c61f9SKrishna Gudipati }
5620a36c61f9SKrishna Gudipati 
5621a36c61f9SKrishna Gudipati /**
5622a36c61f9SKrishna Gudipati  *	Use this function quiese the vport object. This function will return
5623a36c61f9SKrishna Gudipati  *	immediately, when the vport is actually stopped, the
5624a36c61f9SKrishna Gudipati  *	bfa_drv_vport_stop_cb() will be called.
5625a36c61f9SKrishna Gudipati  *
5626a36c61f9SKrishna Gudipati  *	param[in] vport - pointer to bfa_fcs_vport_t.
5627a36c61f9SKrishna Gudipati  *
5628a36c61f9SKrishna Gudipati  *	return None
5629a36c61f9SKrishna Gudipati  */
5630a36c61f9SKrishna Gudipati bfa_status_t
5631a36c61f9SKrishna Gudipati bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5632a36c61f9SKrishna Gudipati {
5633a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5634a36c61f9SKrishna Gudipati 
5635a36c61f9SKrishna Gudipati 	return BFA_STATUS_OK;
5636a36c61f9SKrishna Gudipati }
5637a36c61f9SKrishna Gudipati 
5638a36c61f9SKrishna Gudipati /**
5639a36c61f9SKrishna Gudipati  *	Use this function to delete a vport object. Fabric object should
5640a36c61f9SKrishna Gudipati  *	be stopped before this function call.
5641a36c61f9SKrishna Gudipati  *
5642a36c61f9SKrishna Gudipati  *	!!!!!!! Donot invoke this from within FCS  !!!!!!!
5643a36c61f9SKrishna Gudipati  *
5644a36c61f9SKrishna Gudipati  *	param[in] vport - pointer to bfa_fcs_vport_t.
5645a36c61f9SKrishna Gudipati  *
5646a36c61f9SKrishna Gudipati  *	return     None
5647a36c61f9SKrishna Gudipati  */
5648a36c61f9SKrishna Gudipati bfa_status_t
5649a36c61f9SKrishna Gudipati bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5650a36c61f9SKrishna Gudipati {
5651a36c61f9SKrishna Gudipati 
5652a36c61f9SKrishna Gudipati 	if (vport->lport.port_cfg.preboot_vp)
5653a36c61f9SKrishna Gudipati 		return BFA_STATUS_PBC;
5654a36c61f9SKrishna Gudipati 
5655a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5656a36c61f9SKrishna Gudipati 
5657a36c61f9SKrishna Gudipati 	return BFA_STATUS_OK;
5658a36c61f9SKrishna Gudipati }
5659a36c61f9SKrishna Gudipati 
5660a36c61f9SKrishna Gudipati /**
5661a36c61f9SKrishna Gudipati  *	Use this function to get vport's current status info.
5662a36c61f9SKrishna Gudipati  *
5663a36c61f9SKrishna Gudipati  *	param[in] vport		pointer to bfa_fcs_vport_t.
5664a36c61f9SKrishna Gudipati  *	param[out] attr		pointer to return vport attributes
5665a36c61f9SKrishna Gudipati  *
5666a36c61f9SKrishna Gudipati  *	return None
5667a36c61f9SKrishna Gudipati  */
5668a36c61f9SKrishna Gudipati void
5669a36c61f9SKrishna Gudipati bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5670a36c61f9SKrishna Gudipati 			struct bfa_vport_attr_s *attr)
5671a36c61f9SKrishna Gudipati {
5672a36c61f9SKrishna Gudipati 	if (vport == NULL || attr == NULL)
5673a36c61f9SKrishna Gudipati 		return;
5674a36c61f9SKrishna Gudipati 
56756a18b167SJing Huang 	memset(attr, 0, sizeof(struct bfa_vport_attr_s));
5676a36c61f9SKrishna Gudipati 
5677a36c61f9SKrishna Gudipati 	bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5678a36c61f9SKrishna Gudipati 	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5679a36c61f9SKrishna Gudipati }
5680a36c61f9SKrishna Gudipati 
5681a36c61f9SKrishna Gudipati /**
5682a36c61f9SKrishna Gudipati  *	Use this function to get vport's statistics.
5683a36c61f9SKrishna Gudipati  *
5684a36c61f9SKrishna Gudipati  *	param[in]	vport	pointer to bfa_fcs_vport_t.
5685a36c61f9SKrishna Gudipati  *	param[out]	stats	pointer to return vport statistics in
5686a36c61f9SKrishna Gudipati  *
5687a36c61f9SKrishna Gudipati  *	return None
5688a36c61f9SKrishna Gudipati  */
5689a36c61f9SKrishna Gudipati void
5690a36c61f9SKrishna Gudipati bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
5691a36c61f9SKrishna Gudipati 			struct bfa_vport_stats_s *stats)
5692a36c61f9SKrishna Gudipati {
5693a36c61f9SKrishna Gudipati 	*stats = vport->vport_stats;
5694a36c61f9SKrishna Gudipati }
5695a36c61f9SKrishna Gudipati 
5696a36c61f9SKrishna Gudipati /**
5697a36c61f9SKrishna Gudipati  *	Use this function to clear vport's statistics.
5698a36c61f9SKrishna Gudipati  *
5699a36c61f9SKrishna Gudipati  *	param[in]	vport	pointer to bfa_fcs_vport_t.
5700a36c61f9SKrishna Gudipati  *
5701a36c61f9SKrishna Gudipati  *	return None
5702a36c61f9SKrishna Gudipati  */
5703a36c61f9SKrishna Gudipati void
5704a36c61f9SKrishna Gudipati bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
5705a36c61f9SKrishna Gudipati {
57066a18b167SJing Huang 	memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
5707a36c61f9SKrishna Gudipati }
5708a36c61f9SKrishna Gudipati 
5709a36c61f9SKrishna Gudipati /**
5710a36c61f9SKrishna Gudipati  *	Lookup a virtual port. Excludes base port from lookup.
5711a36c61f9SKrishna Gudipati  */
5712a36c61f9SKrishna Gudipati struct bfa_fcs_vport_s *
5713a36c61f9SKrishna Gudipati bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5714a36c61f9SKrishna Gudipati {
5715a36c61f9SKrishna Gudipati 	struct bfa_fcs_vport_s *vport;
5716a36c61f9SKrishna Gudipati 	struct bfa_fcs_fabric_s *fabric;
5717a36c61f9SKrishna Gudipati 
5718a36c61f9SKrishna Gudipati 	bfa_trc(fcs, vf_id);
5719a36c61f9SKrishna Gudipati 	bfa_trc(fcs, vpwwn);
5720a36c61f9SKrishna Gudipati 
5721a36c61f9SKrishna Gudipati 	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5722a36c61f9SKrishna Gudipati 	if (!fabric) {
5723a36c61f9SKrishna Gudipati 		bfa_trc(fcs, vf_id);
5724a36c61f9SKrishna Gudipati 		return NULL;
5725a36c61f9SKrishna Gudipati 	}
5726a36c61f9SKrishna Gudipati 
5727a36c61f9SKrishna Gudipati 	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5728a36c61f9SKrishna Gudipati 	return vport;
5729a36c61f9SKrishna Gudipati }
5730a36c61f9SKrishna Gudipati 
5731a36c61f9SKrishna Gudipati /**
5732a36c61f9SKrishna Gudipati  * FDISC Response
5733a36c61f9SKrishna Gudipati  */
5734a36c61f9SKrishna Gudipati void
5735a36c61f9SKrishna Gudipati bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5736a36c61f9SKrishna Gudipati {
5737a36c61f9SKrishna Gudipati 	struct bfa_fcs_vport_s *vport = uarg;
5738a36c61f9SKrishna Gudipati 
5739a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5740a36c61f9SKrishna Gudipati 	bfa_trc(__vport_fcs(vport), status);
5741a36c61f9SKrishna Gudipati 
5742a36c61f9SKrishna Gudipati 	switch (status) {
5743a36c61f9SKrishna Gudipati 	case BFA_STATUS_OK:
5744a36c61f9SKrishna Gudipati 		/*
5745a36c61f9SKrishna Gudipati 		 * Initialiaze the V-Port fields
5746a36c61f9SKrishna Gudipati 		 */
5747a36c61f9SKrishna Gudipati 		__vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
5748a36c61f9SKrishna Gudipati 		vport->vport_stats.fdisc_accepts++;
5749a36c61f9SKrishna Gudipati 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5750a36c61f9SKrishna Gudipati 		break;
5751a36c61f9SKrishna Gudipati 
5752a36c61f9SKrishna Gudipati 	case BFA_STATUS_INVALID_MAC:
5753a36c61f9SKrishna Gudipati 		/* Only for CNA */
5754a36c61f9SKrishna Gudipati 		vport->vport_stats.fdisc_acc_bad++;
5755a36c61f9SKrishna Gudipati 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5756a36c61f9SKrishna Gudipati 
5757a36c61f9SKrishna Gudipati 		break;
5758a36c61f9SKrishna Gudipati 
5759a36c61f9SKrishna Gudipati 	case BFA_STATUS_EPROTOCOL:
5760a36c61f9SKrishna Gudipati 		switch (bfa_lps_get_extstatus(vport->lps)) {
5761a36c61f9SKrishna Gudipati 		case BFA_EPROTO_BAD_ACCEPT:
5762a36c61f9SKrishna Gudipati 			vport->vport_stats.fdisc_acc_bad++;
5763a36c61f9SKrishna Gudipati 			break;
5764a36c61f9SKrishna Gudipati 
5765a36c61f9SKrishna Gudipati 		case BFA_EPROTO_UNKNOWN_RSP:
5766a36c61f9SKrishna Gudipati 			vport->vport_stats.fdisc_unknown_rsp++;
5767a36c61f9SKrishna Gudipati 			break;
5768a36c61f9SKrishna Gudipati 
5769a36c61f9SKrishna Gudipati 		default:
5770a36c61f9SKrishna Gudipati 			break;
5771a36c61f9SKrishna Gudipati 		}
5772a36c61f9SKrishna Gudipati 
5773a36c61f9SKrishna Gudipati 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5774a36c61f9SKrishna Gudipati 		break;
5775a36c61f9SKrishna Gudipati 
5776a36c61f9SKrishna Gudipati 	case BFA_STATUS_FABRIC_RJT:
5777a36c61f9SKrishna Gudipati 		vport->vport_stats.fdisc_rejects++;
5778a36c61f9SKrishna Gudipati 		bfa_fcs_vport_fdisc_rejected(vport);
5779a36c61f9SKrishna Gudipati 		break;
5780a36c61f9SKrishna Gudipati 
5781a36c61f9SKrishna Gudipati 	default:
5782a36c61f9SKrishna Gudipati 		vport->vport_stats.fdisc_rsp_err++;
5783a36c61f9SKrishna Gudipati 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5784a36c61f9SKrishna Gudipati 	}
5785a36c61f9SKrishna Gudipati }
5786a36c61f9SKrishna Gudipati 
5787a36c61f9SKrishna Gudipati /**
5788a36c61f9SKrishna Gudipati  * LOGO response
5789a36c61f9SKrishna Gudipati  */
5790a36c61f9SKrishna Gudipati void
5791a36c61f9SKrishna Gudipati bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5792a36c61f9SKrishna Gudipati {
5793a36c61f9SKrishna Gudipati 	struct bfa_fcs_vport_s *vport = uarg;
5794a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5795a36c61f9SKrishna Gudipati }
5796a36c61f9SKrishna Gudipati 
5797a36c61f9SKrishna Gudipati /**
5798a36c61f9SKrishna Gudipati  * Received clear virtual link
5799a36c61f9SKrishna Gudipati  */
5800a36c61f9SKrishna Gudipati void
5801a36c61f9SKrishna Gudipati bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5802a36c61f9SKrishna Gudipati {
5803a36c61f9SKrishna Gudipati 	struct bfa_fcs_vport_s *vport = uarg;
5804a36c61f9SKrishna Gudipati 
5805a36c61f9SKrishna Gudipati 	/* Send an Offline followed by an ONLINE */
5806a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5807a36c61f9SKrishna Gudipati 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5808a36c61f9SKrishna Gudipati }
5809