xref: /OK3568_Linux_fs/kernel/drivers/scsi/bfa/bfa_svc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4*4882a593Smuzhiyun  * Copyright (c) 2014- QLogic Corporation.
5*4882a593Smuzhiyun  * All rights reserved
6*4882a593Smuzhiyun  * www.qlogic.com
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "bfad_drv.h"
12*4882a593Smuzhiyun #include "bfad_im.h"
13*4882a593Smuzhiyun #include "bfa_plog.h"
14*4882a593Smuzhiyun #include "bfa_cs.h"
15*4882a593Smuzhiyun #include "bfa_modules.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun BFA_TRC_FILE(HAL, FCXP);
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * LPS related definitions
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun #define BFA_LPS_MIN_LPORTS      (1)
23*4882a593Smuzhiyun #define BFA_LPS_MAX_LPORTS      (256)
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /*
26*4882a593Smuzhiyun  * Maximum Vports supported per physical port or vf.
27*4882a593Smuzhiyun  */
28*4882a593Smuzhiyun #define BFA_LPS_MAX_VPORTS_SUPP_CB  255
29*4882a593Smuzhiyun #define BFA_LPS_MAX_VPORTS_SUPP_CT  190
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun  * FC PORT related definitions
34*4882a593Smuzhiyun  */
35*4882a593Smuzhiyun /*
36*4882a593Smuzhiyun  * The port is considered disabled if corresponding physical port or IOC are
37*4882a593Smuzhiyun  * disabled explicitly
38*4882a593Smuzhiyun  */
39*4882a593Smuzhiyun #define BFA_PORT_IS_DISABLED(bfa) \
40*4882a593Smuzhiyun 	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
41*4882a593Smuzhiyun 	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /*
44*4882a593Smuzhiyun  * BFA port state machine events
45*4882a593Smuzhiyun  */
46*4882a593Smuzhiyun enum bfa_fcport_sm_event {
47*4882a593Smuzhiyun 	BFA_FCPORT_SM_START	= 1,	/*  start port state machine	*/
48*4882a593Smuzhiyun 	BFA_FCPORT_SM_STOP	= 2,	/*  stop port state machine	*/
49*4882a593Smuzhiyun 	BFA_FCPORT_SM_ENABLE	= 3,	/*  enable port		*/
50*4882a593Smuzhiyun 	BFA_FCPORT_SM_DISABLE	= 4,	/*  disable port state machine */
51*4882a593Smuzhiyun 	BFA_FCPORT_SM_FWRSP	= 5,	/*  firmware enable/disable rsp */
52*4882a593Smuzhiyun 	BFA_FCPORT_SM_LINKUP	= 6,	/*  firmware linkup event	*/
53*4882a593Smuzhiyun 	BFA_FCPORT_SM_LINKDOWN	= 7,	/*  firmware linkup down	*/
54*4882a593Smuzhiyun 	BFA_FCPORT_SM_QRESUME	= 8,	/*  CQ space available	*/
55*4882a593Smuzhiyun 	BFA_FCPORT_SM_HWFAIL	= 9,	/*  IOC h/w failure		*/
56*4882a593Smuzhiyun 	BFA_FCPORT_SM_DPORTENABLE = 10, /*  enable dport      */
57*4882a593Smuzhiyun 	BFA_FCPORT_SM_DPORTDISABLE = 11,/*  disable dport     */
58*4882a593Smuzhiyun 	BFA_FCPORT_SM_FAA_MISCONFIG = 12,	/* FAA misconfiguratin */
59*4882a593Smuzhiyun 	BFA_FCPORT_SM_DDPORTENABLE  = 13,	/* enable ddport	*/
60*4882a593Smuzhiyun 	BFA_FCPORT_SM_DDPORTDISABLE = 14,	/* disable ddport	*/
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /*
64*4882a593Smuzhiyun  * BFA port link notification state machine events
65*4882a593Smuzhiyun  */
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun enum bfa_fcport_ln_sm_event {
68*4882a593Smuzhiyun 	BFA_FCPORT_LN_SM_LINKUP		= 1,	/*  linkup event	*/
69*4882a593Smuzhiyun 	BFA_FCPORT_LN_SM_LINKDOWN	= 2,	/*  linkdown event	*/
70*4882a593Smuzhiyun 	BFA_FCPORT_LN_SM_NOTIFICATION	= 3	/*  done notification	*/
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /*
74*4882a593Smuzhiyun  * RPORT related definitions
75*4882a593Smuzhiyun  */
76*4882a593Smuzhiyun #define bfa_rport_offline_cb(__rp) do {					\
77*4882a593Smuzhiyun 	if ((__rp)->bfa->fcs)						\
78*4882a593Smuzhiyun 		bfa_cb_rport_offline((__rp)->rport_drv);      \
79*4882a593Smuzhiyun 	else {								\
80*4882a593Smuzhiyun 		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
81*4882a593Smuzhiyun 				__bfa_cb_rport_offline, (__rp));      \
82*4882a593Smuzhiyun 	}								\
83*4882a593Smuzhiyun } while (0)
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun #define bfa_rport_online_cb(__rp) do {					\
86*4882a593Smuzhiyun 	if ((__rp)->bfa->fcs)						\
87*4882a593Smuzhiyun 		bfa_cb_rport_online((__rp)->rport_drv);      \
88*4882a593Smuzhiyun 	else {								\
89*4882a593Smuzhiyun 		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
90*4882a593Smuzhiyun 				  __bfa_cb_rport_online, (__rp));      \
91*4882a593Smuzhiyun 		}							\
92*4882a593Smuzhiyun } while (0)
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /*
95*4882a593Smuzhiyun  * forward declarations FCXP related functions
96*4882a593Smuzhiyun  */
97*4882a593Smuzhiyun static void	__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
98*4882a593Smuzhiyun static void	hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
99*4882a593Smuzhiyun 				struct bfi_fcxp_send_rsp_s *fcxp_rsp);
100*4882a593Smuzhiyun static void	hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
101*4882a593Smuzhiyun 				struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
102*4882a593Smuzhiyun static void	bfa_fcxp_qresume(void *cbarg);
103*4882a593Smuzhiyun static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
104*4882a593Smuzhiyun 				struct bfi_fcxp_send_req_s *send_req);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun  * forward declarations for LPS functions
108*4882a593Smuzhiyun  */
109*4882a593Smuzhiyun static void bfa_lps_login_rsp(struct bfa_s *bfa,
110*4882a593Smuzhiyun 				struct bfi_lps_login_rsp_s *rsp);
111*4882a593Smuzhiyun static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
112*4882a593Smuzhiyun static void bfa_lps_logout_rsp(struct bfa_s *bfa,
113*4882a593Smuzhiyun 				struct bfi_lps_logout_rsp_s *rsp);
114*4882a593Smuzhiyun static void bfa_lps_reqq_resume(void *lps_arg);
115*4882a593Smuzhiyun static void bfa_lps_free(struct bfa_lps_s *lps);
116*4882a593Smuzhiyun static void bfa_lps_send_login(struct bfa_lps_s *lps);
117*4882a593Smuzhiyun static void bfa_lps_send_logout(struct bfa_lps_s *lps);
118*4882a593Smuzhiyun static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
119*4882a593Smuzhiyun static void bfa_lps_login_comp(struct bfa_lps_s *lps);
120*4882a593Smuzhiyun static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
121*4882a593Smuzhiyun static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun  * forward declaration for LPS state machine
125*4882a593Smuzhiyun  */
126*4882a593Smuzhiyun static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
127*4882a593Smuzhiyun static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
128*4882a593Smuzhiyun static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
129*4882a593Smuzhiyun 					event);
130*4882a593Smuzhiyun static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
131*4882a593Smuzhiyun static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
132*4882a593Smuzhiyun 					enum bfa_lps_event event);
133*4882a593Smuzhiyun static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
134*4882a593Smuzhiyun static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
135*4882a593Smuzhiyun 					event);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun /*
138*4882a593Smuzhiyun  * forward declaration for FC Port functions
139*4882a593Smuzhiyun  */
140*4882a593Smuzhiyun static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
141*4882a593Smuzhiyun static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
142*4882a593Smuzhiyun static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
143*4882a593Smuzhiyun static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
144*4882a593Smuzhiyun static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
145*4882a593Smuzhiyun static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
146*4882a593Smuzhiyun static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
147*4882a593Smuzhiyun 			enum bfa_port_linkstate event, bfa_boolean_t trunk);
148*4882a593Smuzhiyun static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
149*4882a593Smuzhiyun 				enum bfa_port_linkstate event);
150*4882a593Smuzhiyun static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
151*4882a593Smuzhiyun static void bfa_fcport_stats_get_timeout(void *cbarg);
152*4882a593Smuzhiyun static void bfa_fcport_stats_clr_timeout(void *cbarg);
153*4882a593Smuzhiyun static void bfa_trunk_iocdisable(struct bfa_s *bfa);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun  * forward declaration for FC PORT state machine
157*4882a593Smuzhiyun  */
158*4882a593Smuzhiyun static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
159*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
160*4882a593Smuzhiyun static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
161*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
162*4882a593Smuzhiyun static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
163*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
164*4882a593Smuzhiyun static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
165*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
166*4882a593Smuzhiyun static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
167*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
168*4882a593Smuzhiyun static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
169*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
170*4882a593Smuzhiyun static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
171*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
172*4882a593Smuzhiyun static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
173*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
174*4882a593Smuzhiyun static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
175*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
176*4882a593Smuzhiyun static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
177*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
178*4882a593Smuzhiyun static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
179*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
180*4882a593Smuzhiyun static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
181*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
182*4882a593Smuzhiyun static void	bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
183*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
184*4882a593Smuzhiyun static void     bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
185*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
186*4882a593Smuzhiyun static void	bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
187*4882a593Smuzhiyun 					enum bfa_fcport_sm_event event);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
190*4882a593Smuzhiyun 					enum bfa_fcport_ln_sm_event event);
191*4882a593Smuzhiyun static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
192*4882a593Smuzhiyun 					enum bfa_fcport_ln_sm_event event);
193*4882a593Smuzhiyun static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
194*4882a593Smuzhiyun 					enum bfa_fcport_ln_sm_event event);
195*4882a593Smuzhiyun static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
196*4882a593Smuzhiyun 					enum bfa_fcport_ln_sm_event event);
197*4882a593Smuzhiyun static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
198*4882a593Smuzhiyun 					enum bfa_fcport_ln_sm_event event);
199*4882a593Smuzhiyun static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
200*4882a593Smuzhiyun 					enum bfa_fcport_ln_sm_event event);
201*4882a593Smuzhiyun static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
202*4882a593Smuzhiyun 					enum bfa_fcport_ln_sm_event event);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun static struct bfa_sm_table_s hal_port_sm_table[] = {
205*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
206*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
207*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
208*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
209*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
210*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
211*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
212*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
213*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
214*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
215*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
216*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
217*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
218*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},
219*4882a593Smuzhiyun 	{BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
220*4882a593Smuzhiyun };
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /*
224*4882a593Smuzhiyun  * forward declaration for RPORT related functions
225*4882a593Smuzhiyun  */
226*4882a593Smuzhiyun static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
227*4882a593Smuzhiyun static void		bfa_rport_free(struct bfa_rport_s *rport);
228*4882a593Smuzhiyun static bfa_boolean_t	bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
229*4882a593Smuzhiyun static bfa_boolean_t	bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
230*4882a593Smuzhiyun static bfa_boolean_t	bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
231*4882a593Smuzhiyun static void		__bfa_cb_rport_online(void *cbarg,
232*4882a593Smuzhiyun 						bfa_boolean_t complete);
233*4882a593Smuzhiyun static void		__bfa_cb_rport_offline(void *cbarg,
234*4882a593Smuzhiyun 						bfa_boolean_t complete);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun /*
237*4882a593Smuzhiyun  * forward declaration for RPORT state machine
238*4882a593Smuzhiyun  */
239*4882a593Smuzhiyun static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,
240*4882a593Smuzhiyun 					enum bfa_rport_event event);
241*4882a593Smuzhiyun static void     bfa_rport_sm_created(struct bfa_rport_s *rp,
242*4882a593Smuzhiyun 					enum bfa_rport_event event);
243*4882a593Smuzhiyun static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
244*4882a593Smuzhiyun 					enum bfa_rport_event event);
245*4882a593Smuzhiyun static void     bfa_rport_sm_online(struct bfa_rport_s *rp,
246*4882a593Smuzhiyun 					enum bfa_rport_event event);
247*4882a593Smuzhiyun static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
248*4882a593Smuzhiyun 					enum bfa_rport_event event);
249*4882a593Smuzhiyun static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,
250*4882a593Smuzhiyun 					enum bfa_rport_event event);
251*4882a593Smuzhiyun static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,
252*4882a593Smuzhiyun 					enum bfa_rport_event event);
253*4882a593Smuzhiyun static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
254*4882a593Smuzhiyun 					enum bfa_rport_event event);
255*4882a593Smuzhiyun static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
256*4882a593Smuzhiyun 					enum bfa_rport_event event);
257*4882a593Smuzhiyun static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
258*4882a593Smuzhiyun 					enum bfa_rport_event event);
259*4882a593Smuzhiyun static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
260*4882a593Smuzhiyun 					enum bfa_rport_event event);
261*4882a593Smuzhiyun static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
262*4882a593Smuzhiyun 					enum bfa_rport_event event);
263*4882a593Smuzhiyun static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
264*4882a593Smuzhiyun 					enum bfa_rport_event event);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun /*
267*4882a593Smuzhiyun  * PLOG related definitions
268*4882a593Smuzhiyun  */
269*4882a593Smuzhiyun static int
plkd_validate_logrec(struct bfa_plog_rec_s * pl_rec)270*4882a593Smuzhiyun plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
273*4882a593Smuzhiyun 		(pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
274*4882a593Smuzhiyun 		return 1;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
277*4882a593Smuzhiyun 		(pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
278*4882a593Smuzhiyun 		return 1;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun static void
bfa_plog_add(struct bfa_plog_s * plog,struct bfa_plog_rec_s * pl_rec)284*4882a593Smuzhiyun bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	u16 tail;
287*4882a593Smuzhiyun 	struct bfa_plog_rec_s *pl_recp;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	if (plog->plog_enabled == 0)
290*4882a593Smuzhiyun 		return;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	if (plkd_validate_logrec(pl_rec)) {
293*4882a593Smuzhiyun 		WARN_ON(1);
294*4882a593Smuzhiyun 		return;
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	tail = plog->tail;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	pl_recp = &(plog->plog_recs[tail]);
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	pl_recp->tv = ktime_get_real_seconds();
304*4882a593Smuzhiyun 	BFA_PL_LOG_REC_INCR(plog->tail);
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	if (plog->head == plog->tail)
307*4882a593Smuzhiyun 		BFA_PL_LOG_REC_INCR(plog->head);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun void
bfa_plog_init(struct bfa_plog_s * plog)311*4882a593Smuzhiyun bfa_plog_init(struct bfa_plog_s *plog)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	memset((char *)plog, 0, sizeof(struct bfa_plog_s));
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
316*4882a593Smuzhiyun 	plog->head = plog->tail = 0;
317*4882a593Smuzhiyun 	plog->plog_enabled = 1;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun void
bfa_plog_str(struct bfa_plog_s * plog,enum bfa_plog_mid mid,enum bfa_plog_eid event,u16 misc,char * log_str)321*4882a593Smuzhiyun bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
322*4882a593Smuzhiyun 		enum bfa_plog_eid event,
323*4882a593Smuzhiyun 		u16 misc, char *log_str)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun 	struct bfa_plog_rec_s  lp;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	if (plog->plog_enabled) {
328*4882a593Smuzhiyun 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
329*4882a593Smuzhiyun 		lp.mid = mid;
330*4882a593Smuzhiyun 		lp.eid = event;
331*4882a593Smuzhiyun 		lp.log_type = BFA_PL_LOG_TYPE_STRING;
332*4882a593Smuzhiyun 		lp.misc = misc;
333*4882a593Smuzhiyun 		strlcpy(lp.log_entry.string_log, log_str,
334*4882a593Smuzhiyun 			BFA_PL_STRING_LOG_SZ);
335*4882a593Smuzhiyun 		lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
336*4882a593Smuzhiyun 		bfa_plog_add(plog, &lp);
337*4882a593Smuzhiyun 	}
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun void
bfa_plog_intarr(struct bfa_plog_s * plog,enum bfa_plog_mid mid,enum bfa_plog_eid event,u16 misc,u32 * intarr,u32 num_ints)341*4882a593Smuzhiyun bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
342*4882a593Smuzhiyun 		enum bfa_plog_eid event,
343*4882a593Smuzhiyun 		u16 misc, u32 *intarr, u32 num_ints)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	struct bfa_plog_rec_s  lp;
346*4882a593Smuzhiyun 	u32 i;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	if (num_ints > BFA_PL_INT_LOG_SZ)
349*4882a593Smuzhiyun 		num_ints = BFA_PL_INT_LOG_SZ;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if (plog->plog_enabled) {
352*4882a593Smuzhiyun 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
353*4882a593Smuzhiyun 		lp.mid = mid;
354*4882a593Smuzhiyun 		lp.eid = event;
355*4882a593Smuzhiyun 		lp.log_type = BFA_PL_LOG_TYPE_INT;
356*4882a593Smuzhiyun 		lp.misc = misc;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 		for (i = 0; i < num_ints; i++)
359*4882a593Smuzhiyun 			lp.log_entry.int_log[i] = intarr[i];
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 		lp.log_num_ints = (u8) num_ints;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 		bfa_plog_add(plog, &lp);
364*4882a593Smuzhiyun 	}
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun void
bfa_plog_fchdr(struct bfa_plog_s * plog,enum bfa_plog_mid mid,enum bfa_plog_eid event,u16 misc,struct fchs_s * fchdr)368*4882a593Smuzhiyun bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
369*4882a593Smuzhiyun 			enum bfa_plog_eid event,
370*4882a593Smuzhiyun 			u16 misc, struct fchs_s *fchdr)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	struct bfa_plog_rec_s  lp;
373*4882a593Smuzhiyun 	u32	*tmp_int = (u32 *) fchdr;
374*4882a593Smuzhiyun 	u32	ints[BFA_PL_INT_LOG_SZ];
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	if (plog->plog_enabled) {
377*4882a593Smuzhiyun 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 		ints[0] = tmp_int[0];
380*4882a593Smuzhiyun 		ints[1] = tmp_int[1];
381*4882a593Smuzhiyun 		ints[2] = tmp_int[4];
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 		bfa_plog_intarr(plog, mid, event, misc, ints, 3);
384*4882a593Smuzhiyun 	}
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun void
bfa_plog_fchdr_and_pl(struct bfa_plog_s * plog,enum bfa_plog_mid mid,enum bfa_plog_eid event,u16 misc,struct fchs_s * fchdr,u32 pld_w0)388*4882a593Smuzhiyun bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
389*4882a593Smuzhiyun 		      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
390*4882a593Smuzhiyun 		      u32 pld_w0)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	struct bfa_plog_rec_s  lp;
393*4882a593Smuzhiyun 	u32	*tmp_int = (u32 *) fchdr;
394*4882a593Smuzhiyun 	u32	ints[BFA_PL_INT_LOG_SZ];
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	if (plog->plog_enabled) {
397*4882a593Smuzhiyun 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 		ints[0] = tmp_int[0];
400*4882a593Smuzhiyun 		ints[1] = tmp_int[1];
401*4882a593Smuzhiyun 		ints[2] = tmp_int[4];
402*4882a593Smuzhiyun 		ints[3] = pld_w0;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 		bfa_plog_intarr(plog, mid, event, misc, ints, 4);
405*4882a593Smuzhiyun 	}
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun /*
410*4882a593Smuzhiyun  *  fcxp_pvt BFA FCXP private functions
411*4882a593Smuzhiyun  */
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun static void
claim_fcxps_mem(struct bfa_fcxp_mod_s * mod)414*4882a593Smuzhiyun claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	u16	i;
417*4882a593Smuzhiyun 	struct bfa_fcxp_s *fcxp;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
420*4882a593Smuzhiyun 	memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->fcxp_req_free_q);
423*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
424*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->fcxp_active_q);
425*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
426*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	mod->fcxp_list = fcxp;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	for (i = 0; i < mod->num_fcxps; i++) {
431*4882a593Smuzhiyun 		fcxp->fcxp_mod = mod;
432*4882a593Smuzhiyun 		fcxp->fcxp_tag = i;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 		if (i < (mod->num_fcxps / 2)) {
435*4882a593Smuzhiyun 			list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
436*4882a593Smuzhiyun 			fcxp->req_rsp = BFA_TRUE;
437*4882a593Smuzhiyun 		} else {
438*4882a593Smuzhiyun 			list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
439*4882a593Smuzhiyun 			fcxp->req_rsp = BFA_FALSE;
440*4882a593Smuzhiyun 		}
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
443*4882a593Smuzhiyun 		fcxp->reqq_waiting = BFA_FALSE;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 		fcxp = fcxp + 1;
446*4882a593Smuzhiyun 	}
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	bfa_mem_kva_curp(mod) = (void *)fcxp;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun void
bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s * cfg,struct bfa_meminfo_s * minfo,struct bfa_s * bfa)452*4882a593Smuzhiyun bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
453*4882a593Smuzhiyun 		struct bfa_s *bfa)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);
456*4882a593Smuzhiyun 	struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);
457*4882a593Smuzhiyun 	struct bfa_mem_dma_s *seg_ptr;
458*4882a593Smuzhiyun 	u16	nsegs, idx, per_seg_fcxp;
459*4882a593Smuzhiyun 	u16	num_fcxps = cfg->fwcfg.num_fcxp_reqs;
460*4882a593Smuzhiyun 	u32	per_fcxp_sz;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	if (num_fcxps == 0)
463*4882a593Smuzhiyun 		return;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	if (cfg->drvcfg.min_cfg)
466*4882a593Smuzhiyun 		per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;
467*4882a593Smuzhiyun 	else
468*4882a593Smuzhiyun 		per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	/* dma memory */
471*4882a593Smuzhiyun 	nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);
472*4882a593Smuzhiyun 	per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {
475*4882a593Smuzhiyun 		if (num_fcxps >= per_seg_fcxp) {
476*4882a593Smuzhiyun 			num_fcxps -= per_seg_fcxp;
477*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
478*4882a593Smuzhiyun 				per_seg_fcxp * per_fcxp_sz);
479*4882a593Smuzhiyun 		} else
480*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
481*4882a593Smuzhiyun 				num_fcxps * per_fcxp_sz);
482*4882a593Smuzhiyun 	}
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	/* kva memory */
485*4882a593Smuzhiyun 	bfa_mem_kva_setup(minfo, fcxp_kva,
486*4882a593Smuzhiyun 		cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun void
bfa_fcxp_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)490*4882a593Smuzhiyun bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
491*4882a593Smuzhiyun 		struct bfa_pcidev_s *pcidev)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	mod->bfa = bfa;
496*4882a593Smuzhiyun 	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	/*
499*4882a593Smuzhiyun 	 * Initialize FCXP request and response payload sizes.
500*4882a593Smuzhiyun 	 */
501*4882a593Smuzhiyun 	mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
502*4882a593Smuzhiyun 	if (!cfg->drvcfg.min_cfg)
503*4882a593Smuzhiyun 		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->req_wait_q);
506*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->rsp_wait_q);
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	claim_fcxps_mem(mod);
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun void
bfa_fcxp_iocdisable(struct bfa_s * bfa)512*4882a593Smuzhiyun bfa_fcxp_iocdisable(struct bfa_s *bfa)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
515*4882a593Smuzhiyun 	struct bfa_fcxp_s *fcxp;
516*4882a593Smuzhiyun 	struct list_head	      *qe, *qen;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	/* Enqueue unused fcxp resources to free_q */
519*4882a593Smuzhiyun 	list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
520*4882a593Smuzhiyun 	list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
523*4882a593Smuzhiyun 		fcxp = (struct bfa_fcxp_s *) qe;
524*4882a593Smuzhiyun 		if (fcxp->caller == NULL) {
525*4882a593Smuzhiyun 			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
526*4882a593Smuzhiyun 					BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
527*4882a593Smuzhiyun 			bfa_fcxp_free(fcxp);
528*4882a593Smuzhiyun 		} else {
529*4882a593Smuzhiyun 			fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
530*4882a593Smuzhiyun 			bfa_cb_queue(bfa, &fcxp->hcb_qe,
531*4882a593Smuzhiyun 				     __bfa_fcxp_send_cbfn, fcxp);
532*4882a593Smuzhiyun 		}
533*4882a593Smuzhiyun 	}
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun static struct bfa_fcxp_s *
bfa_fcxp_get(struct bfa_fcxp_mod_s * fm,bfa_boolean_t req)537*4882a593Smuzhiyun bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	struct bfa_fcxp_s *fcxp;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	if (req)
542*4882a593Smuzhiyun 		bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
543*4882a593Smuzhiyun 	else
544*4882a593Smuzhiyun 		bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	if (fcxp)
547*4882a593Smuzhiyun 		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	return fcxp;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun static void
bfa_fcxp_init_reqrsp(struct bfa_fcxp_s * fcxp,struct bfa_s * bfa,u8 * use_ibuf,u32 * nr_sgles,bfa_fcxp_get_sgaddr_t * r_sga_cbfn,bfa_fcxp_get_sglen_t * r_sglen_cbfn,struct list_head * r_sgpg_q,int n_sgles,bfa_fcxp_get_sgaddr_t sga_cbfn,bfa_fcxp_get_sglen_t sglen_cbfn)553*4882a593Smuzhiyun bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
554*4882a593Smuzhiyun 	       struct bfa_s *bfa,
555*4882a593Smuzhiyun 	       u8 *use_ibuf,
556*4882a593Smuzhiyun 	       u32 *nr_sgles,
557*4882a593Smuzhiyun 	       bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
558*4882a593Smuzhiyun 	       bfa_fcxp_get_sglen_t *r_sglen_cbfn,
559*4882a593Smuzhiyun 	       struct list_head *r_sgpg_q,
560*4882a593Smuzhiyun 	       int n_sgles,
561*4882a593Smuzhiyun 	       bfa_fcxp_get_sgaddr_t sga_cbfn,
562*4882a593Smuzhiyun 	       bfa_fcxp_get_sglen_t sglen_cbfn)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	WARN_ON(bfa == NULL);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	bfa_trc(bfa, fcxp->fcxp_tag);
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	if (n_sgles == 0) {
570*4882a593Smuzhiyun 		*use_ibuf = 1;
571*4882a593Smuzhiyun 	} else {
572*4882a593Smuzhiyun 		WARN_ON(*sga_cbfn == NULL);
573*4882a593Smuzhiyun 		WARN_ON(*sglen_cbfn == NULL);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 		*use_ibuf = 0;
576*4882a593Smuzhiyun 		*r_sga_cbfn = sga_cbfn;
577*4882a593Smuzhiyun 		*r_sglen_cbfn = sglen_cbfn;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 		*nr_sgles = n_sgles;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 		/*
582*4882a593Smuzhiyun 		 * alloc required sgpgs
583*4882a593Smuzhiyun 		 */
584*4882a593Smuzhiyun 		if (n_sgles > BFI_SGE_INLINE)
585*4882a593Smuzhiyun 			WARN_ON(1);
586*4882a593Smuzhiyun 	}
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun static void
bfa_fcxp_init(struct bfa_fcxp_s * fcxp,void * caller,struct bfa_s * bfa,int nreq_sgles,int nrsp_sgles,bfa_fcxp_get_sgaddr_t req_sga_cbfn,bfa_fcxp_get_sglen_t req_sglen_cbfn,bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,bfa_fcxp_get_sglen_t rsp_sglen_cbfn)591*4882a593Smuzhiyun bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
592*4882a593Smuzhiyun 	       void *caller, struct bfa_s *bfa, int nreq_sgles,
593*4882a593Smuzhiyun 	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
594*4882a593Smuzhiyun 	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
595*4882a593Smuzhiyun 	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
596*4882a593Smuzhiyun 	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	WARN_ON(bfa == NULL);
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	bfa_trc(bfa, fcxp->fcxp_tag);
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	fcxp->caller = caller;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	bfa_fcxp_init_reqrsp(fcxp, bfa,
606*4882a593Smuzhiyun 		&fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
607*4882a593Smuzhiyun 		&fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
608*4882a593Smuzhiyun 		nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	bfa_fcxp_init_reqrsp(fcxp, bfa,
611*4882a593Smuzhiyun 		&fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
612*4882a593Smuzhiyun 		&fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
613*4882a593Smuzhiyun 		nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun static void
bfa_fcxp_put(struct bfa_fcxp_s * fcxp)618*4882a593Smuzhiyun bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
621*4882a593Smuzhiyun 	struct bfa_fcxp_wqe_s *wqe;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	if (fcxp->req_rsp)
624*4882a593Smuzhiyun 		bfa_q_deq(&mod->req_wait_q, &wqe);
625*4882a593Smuzhiyun 	else
626*4882a593Smuzhiyun 		bfa_q_deq(&mod->rsp_wait_q, &wqe);
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	if (wqe) {
629*4882a593Smuzhiyun 		bfa_trc(mod->bfa, fcxp->fcxp_tag);
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 		bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
632*4882a593Smuzhiyun 			wqe->nrsp_sgles, wqe->req_sga_cbfn,
633*4882a593Smuzhiyun 			wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
634*4882a593Smuzhiyun 			wqe->rsp_sglen_cbfn);
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 		wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
637*4882a593Smuzhiyun 		return;
638*4882a593Smuzhiyun 	}
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
641*4882a593Smuzhiyun 	list_del(&fcxp->qe);
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	if (fcxp->req_rsp)
644*4882a593Smuzhiyun 		list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
645*4882a593Smuzhiyun 	else
646*4882a593Smuzhiyun 		list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun static void
bfa_fcxp_null_comp(void * bfad_fcxp,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)650*4882a593Smuzhiyun bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
651*4882a593Smuzhiyun 		   bfa_status_t req_status, u32 rsp_len,
652*4882a593Smuzhiyun 		   u32 resid_len, struct fchs_s *rsp_fchs)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun 	/* discarded fcxp completion */
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun static void
__bfa_fcxp_send_cbfn(void * cbarg,bfa_boolean_t complete)658*4882a593Smuzhiyun __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun 	struct bfa_fcxp_s *fcxp = cbarg;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	if (complete) {
663*4882a593Smuzhiyun 		fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
664*4882a593Smuzhiyun 				fcxp->rsp_status, fcxp->rsp_len,
665*4882a593Smuzhiyun 				fcxp->residue_len, &fcxp->rsp_fchs);
666*4882a593Smuzhiyun 	} else {
667*4882a593Smuzhiyun 		bfa_fcxp_free(fcxp);
668*4882a593Smuzhiyun 	}
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun static void
hal_fcxp_send_comp(struct bfa_s * bfa,struct bfi_fcxp_send_rsp_s * fcxp_rsp)672*4882a593Smuzhiyun hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
675*4882a593Smuzhiyun 	struct bfa_fcxp_s	*fcxp;
676*4882a593Smuzhiyun 	u16		fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	bfa_trc(bfa, fcxp_tag);
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	/*
683*4882a593Smuzhiyun 	 * @todo f/w should not set residue to non-0 when everything
684*4882a593Smuzhiyun 	 *	 is received.
685*4882a593Smuzhiyun 	 */
686*4882a593Smuzhiyun 	if (fcxp_rsp->req_status == BFA_STATUS_OK)
687*4882a593Smuzhiyun 		fcxp_rsp->residue_len = 0;
688*4882a593Smuzhiyun 	else
689*4882a593Smuzhiyun 		fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	WARN_ON(fcxp->send_cbfn == NULL);
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	if (fcxp->send_cbfn != NULL) {
698*4882a593Smuzhiyun 		bfa_trc(mod->bfa, (NULL == fcxp->caller));
699*4882a593Smuzhiyun 		if (fcxp->caller == NULL) {
700*4882a593Smuzhiyun 			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
701*4882a593Smuzhiyun 					fcxp_rsp->req_status, fcxp_rsp->rsp_len,
702*4882a593Smuzhiyun 					fcxp_rsp->residue_len, &fcxp_rsp->fchs);
703*4882a593Smuzhiyun 			/*
704*4882a593Smuzhiyun 			 * fcxp automatically freed on return from the callback
705*4882a593Smuzhiyun 			 */
706*4882a593Smuzhiyun 			bfa_fcxp_free(fcxp);
707*4882a593Smuzhiyun 		} else {
708*4882a593Smuzhiyun 			fcxp->rsp_status = fcxp_rsp->req_status;
709*4882a593Smuzhiyun 			fcxp->rsp_len = fcxp_rsp->rsp_len;
710*4882a593Smuzhiyun 			fcxp->residue_len = fcxp_rsp->residue_len;
711*4882a593Smuzhiyun 			fcxp->rsp_fchs = fcxp_rsp->fchs;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 			bfa_cb_queue(bfa, &fcxp->hcb_qe,
714*4882a593Smuzhiyun 					__bfa_fcxp_send_cbfn, fcxp);
715*4882a593Smuzhiyun 		}
716*4882a593Smuzhiyun 	} else {
717*4882a593Smuzhiyun 		bfa_trc(bfa, (NULL == fcxp->send_cbfn));
718*4882a593Smuzhiyun 	}
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun static void
hal_fcxp_tx_plog(struct bfa_s * bfa,u32 reqlen,struct bfa_fcxp_s * fcxp,struct fchs_s * fchs)722*4882a593Smuzhiyun hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
723*4882a593Smuzhiyun 		 struct fchs_s *fchs)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun 	/*
726*4882a593Smuzhiyun 	 * TODO: TX ox_id
727*4882a593Smuzhiyun 	 */
728*4882a593Smuzhiyun 	if (reqlen > 0) {
729*4882a593Smuzhiyun 		if (fcxp->use_ireqbuf) {
730*4882a593Smuzhiyun 			u32	pld_w0 =
731*4882a593Smuzhiyun 				*((u32 *) BFA_FCXP_REQ_PLD(fcxp));
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
734*4882a593Smuzhiyun 					BFA_PL_EID_TX,
735*4882a593Smuzhiyun 					reqlen + sizeof(struct fchs_s), fchs,
736*4882a593Smuzhiyun 					pld_w0);
737*4882a593Smuzhiyun 		} else {
738*4882a593Smuzhiyun 			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
739*4882a593Smuzhiyun 					BFA_PL_EID_TX,
740*4882a593Smuzhiyun 					reqlen + sizeof(struct fchs_s),
741*4882a593Smuzhiyun 					fchs);
742*4882a593Smuzhiyun 		}
743*4882a593Smuzhiyun 	} else {
744*4882a593Smuzhiyun 		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
745*4882a593Smuzhiyun 			       reqlen + sizeof(struct fchs_s), fchs);
746*4882a593Smuzhiyun 	}
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun static void
hal_fcxp_rx_plog(struct bfa_s * bfa,struct bfa_fcxp_s * fcxp,struct bfi_fcxp_send_rsp_s * fcxp_rsp)750*4882a593Smuzhiyun hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
751*4882a593Smuzhiyun 		 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun 	if (fcxp_rsp->rsp_len > 0) {
754*4882a593Smuzhiyun 		if (fcxp->use_irspbuf) {
755*4882a593Smuzhiyun 			u32	pld_w0 =
756*4882a593Smuzhiyun 				*((u32 *) BFA_FCXP_RSP_PLD(fcxp));
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
759*4882a593Smuzhiyun 					      BFA_PL_EID_RX,
760*4882a593Smuzhiyun 					      (u16) fcxp_rsp->rsp_len,
761*4882a593Smuzhiyun 					      &fcxp_rsp->fchs, pld_w0);
762*4882a593Smuzhiyun 		} else {
763*4882a593Smuzhiyun 			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
764*4882a593Smuzhiyun 				       BFA_PL_EID_RX,
765*4882a593Smuzhiyun 				       (u16) fcxp_rsp->rsp_len,
766*4882a593Smuzhiyun 				       &fcxp_rsp->fchs);
767*4882a593Smuzhiyun 		}
768*4882a593Smuzhiyun 	} else {
769*4882a593Smuzhiyun 		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
770*4882a593Smuzhiyun 			       (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
771*4882a593Smuzhiyun 	}
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun /*
775*4882a593Smuzhiyun  * Handler to resume sending fcxp when space in available in cpe queue.
776*4882a593Smuzhiyun  */
777*4882a593Smuzhiyun static void
bfa_fcxp_qresume(void * cbarg)778*4882a593Smuzhiyun bfa_fcxp_qresume(void *cbarg)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun 	struct bfa_fcxp_s		*fcxp = cbarg;
781*4882a593Smuzhiyun 	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
782*4882a593Smuzhiyun 	struct bfi_fcxp_send_req_s	*send_req;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	fcxp->reqq_waiting = BFA_FALSE;
785*4882a593Smuzhiyun 	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
786*4882a593Smuzhiyun 	bfa_fcxp_queue(fcxp, send_req);
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun /*
790*4882a593Smuzhiyun  * Queue fcxp send request to foimrware.
791*4882a593Smuzhiyun  */
792*4882a593Smuzhiyun static void
bfa_fcxp_queue(struct bfa_fcxp_s * fcxp,struct bfi_fcxp_send_req_s * send_req)793*4882a593Smuzhiyun bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun 	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
796*4882a593Smuzhiyun 	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
797*4882a593Smuzhiyun 	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
798*4882a593Smuzhiyun 	struct bfa_rport_s		*rport = reqi->bfa_rport;
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
801*4882a593Smuzhiyun 		    bfa_fn_lpu(bfa));
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
804*4882a593Smuzhiyun 	if (rport) {
805*4882a593Smuzhiyun 		send_req->rport_fw_hndl = rport->fw_handle;
806*4882a593Smuzhiyun 		send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);
807*4882a593Smuzhiyun 		if (send_req->max_frmsz == 0)
808*4882a593Smuzhiyun 			send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
809*4882a593Smuzhiyun 	} else {
810*4882a593Smuzhiyun 		send_req->rport_fw_hndl = 0;
811*4882a593Smuzhiyun 		send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
812*4882a593Smuzhiyun 	}
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	send_req->vf_id = cpu_to_be16(reqi->vf_id);
815*4882a593Smuzhiyun 	send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
816*4882a593Smuzhiyun 	send_req->class = reqi->class;
817*4882a593Smuzhiyun 	send_req->rsp_timeout = rspi->rsp_timeout;
818*4882a593Smuzhiyun 	send_req->cts = reqi->cts;
819*4882a593Smuzhiyun 	send_req->fchs = reqi->fchs;
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	send_req->req_len = cpu_to_be32(reqi->req_tot_len);
822*4882a593Smuzhiyun 	send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 	/*
825*4882a593Smuzhiyun 	 * setup req sgles
826*4882a593Smuzhiyun 	 */
827*4882a593Smuzhiyun 	if (fcxp->use_ireqbuf == 1) {
828*4882a593Smuzhiyun 		bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
829*4882a593Smuzhiyun 					BFA_FCXP_REQ_PLD_PA(fcxp));
830*4882a593Smuzhiyun 	} else {
831*4882a593Smuzhiyun 		if (fcxp->nreq_sgles > 0) {
832*4882a593Smuzhiyun 			WARN_ON(fcxp->nreq_sgles != 1);
833*4882a593Smuzhiyun 			bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
834*4882a593Smuzhiyun 				fcxp->req_sga_cbfn(fcxp->caller, 0));
835*4882a593Smuzhiyun 		} else {
836*4882a593Smuzhiyun 			WARN_ON(reqi->req_tot_len != 0);
837*4882a593Smuzhiyun 			bfa_alen_set(&send_req->rsp_alen, 0, 0);
838*4882a593Smuzhiyun 		}
839*4882a593Smuzhiyun 	}
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	/*
842*4882a593Smuzhiyun 	 * setup rsp sgles
843*4882a593Smuzhiyun 	 */
844*4882a593Smuzhiyun 	if (fcxp->use_irspbuf == 1) {
845*4882a593Smuzhiyun 		WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 		bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
848*4882a593Smuzhiyun 					BFA_FCXP_RSP_PLD_PA(fcxp));
849*4882a593Smuzhiyun 	} else {
850*4882a593Smuzhiyun 		if (fcxp->nrsp_sgles > 0) {
851*4882a593Smuzhiyun 			WARN_ON(fcxp->nrsp_sgles != 1);
852*4882a593Smuzhiyun 			bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
853*4882a593Smuzhiyun 				fcxp->rsp_sga_cbfn(fcxp->caller, 0));
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 		} else {
856*4882a593Smuzhiyun 			WARN_ON(rspi->rsp_maxlen != 0);
857*4882a593Smuzhiyun 			bfa_alen_set(&send_req->rsp_alen, 0, 0);
858*4882a593Smuzhiyun 		}
859*4882a593Smuzhiyun 	}
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
866*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun /*
870*4882a593Smuzhiyun  * Allocate an FCXP instance to send a response or to send a request
871*4882a593Smuzhiyun  * that has a response. Request/response buffers are allocated by caller.
872*4882a593Smuzhiyun  *
873*4882a593Smuzhiyun  * @param[in]	bfa		BFA bfa instance
874*4882a593Smuzhiyun  * @param[in]	nreq_sgles	Number of SG elements required for request
875*4882a593Smuzhiyun  *				buffer. 0, if fcxp internal buffers are	used.
876*4882a593Smuzhiyun  *				Use bfa_fcxp_get_reqbuf() to get the
877*4882a593Smuzhiyun  *				internal req buffer.
878*4882a593Smuzhiyun  * @param[in]	req_sgles	SG elements describing request buffer. Will be
879*4882a593Smuzhiyun  *				copied in by BFA and hence can be freed on
880*4882a593Smuzhiyun  *				return from this function.
881*4882a593Smuzhiyun  * @param[in]	get_req_sga	function ptr to be called to get a request SG
882*4882a593Smuzhiyun  *				Address (given the sge index).
883*4882a593Smuzhiyun  * @param[in]	get_req_sglen	function ptr to be called to get a request SG
884*4882a593Smuzhiyun  *				len (given the sge index).
885*4882a593Smuzhiyun  * @param[in]	get_rsp_sga	function ptr to be called to get a response SG
886*4882a593Smuzhiyun  *				Address (given the sge index).
887*4882a593Smuzhiyun  * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
888*4882a593Smuzhiyun  *				len (given the sge index).
889*4882a593Smuzhiyun  * @param[in]	req		Allocated FCXP is used to send req or rsp?
890*4882a593Smuzhiyun  *				request - BFA_TRUE, response - BFA_FALSE
891*4882a593Smuzhiyun  *
892*4882a593Smuzhiyun  * @return FCXP instance. NULL on failure.
893*4882a593Smuzhiyun  */
894*4882a593Smuzhiyun struct bfa_fcxp_s *
bfa_fcxp_req_rsp_alloc(void * caller,struct bfa_s * bfa,int nreq_sgles,int nrsp_sgles,bfa_fcxp_get_sgaddr_t req_sga_cbfn,bfa_fcxp_get_sglen_t req_sglen_cbfn,bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,bfa_fcxp_get_sglen_t rsp_sglen_cbfn,bfa_boolean_t req)895*4882a593Smuzhiyun bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
896*4882a593Smuzhiyun 		int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
897*4882a593Smuzhiyun 		bfa_fcxp_get_sglen_t req_sglen_cbfn,
898*4882a593Smuzhiyun 		bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
899*4882a593Smuzhiyun 		bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun 	struct bfa_fcxp_s *fcxp = NULL;
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 	WARN_ON(bfa == NULL);
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
906*4882a593Smuzhiyun 	if (fcxp == NULL)
907*4882a593Smuzhiyun 		return NULL;
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	bfa_trc(bfa, fcxp->fcxp_tag);
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun 	bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
912*4882a593Smuzhiyun 			req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	return fcxp;
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun /*
918*4882a593Smuzhiyun  * Get the internal request buffer pointer
919*4882a593Smuzhiyun  *
920*4882a593Smuzhiyun  * @param[in]	fcxp	BFA fcxp pointer
921*4882a593Smuzhiyun  *
922*4882a593Smuzhiyun  * @return		pointer to the internal request buffer
923*4882a593Smuzhiyun  */
924*4882a593Smuzhiyun void *
bfa_fcxp_get_reqbuf(struct bfa_fcxp_s * fcxp)925*4882a593Smuzhiyun bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
926*4882a593Smuzhiyun {
927*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
928*4882a593Smuzhiyun 	void	*reqbuf;
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	WARN_ON(fcxp->use_ireqbuf != 1);
931*4882a593Smuzhiyun 	reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
932*4882a593Smuzhiyun 				mod->req_pld_sz + mod->rsp_pld_sz);
933*4882a593Smuzhiyun 	return reqbuf;
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun u32
bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s * fcxp)937*4882a593Smuzhiyun bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	return mod->req_pld_sz;
942*4882a593Smuzhiyun }
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun /*
945*4882a593Smuzhiyun  * Get the internal response buffer pointer
946*4882a593Smuzhiyun  *
947*4882a593Smuzhiyun  * @param[in]	fcxp	BFA fcxp pointer
948*4882a593Smuzhiyun  *
949*4882a593Smuzhiyun  * @return		pointer to the internal request buffer
950*4882a593Smuzhiyun  */
951*4882a593Smuzhiyun void *
bfa_fcxp_get_rspbuf(struct bfa_fcxp_s * fcxp)952*4882a593Smuzhiyun bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
955*4882a593Smuzhiyun 	void	*fcxp_buf;
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun 	WARN_ON(fcxp->use_irspbuf != 1);
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 	fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
960*4882a593Smuzhiyun 				mod->req_pld_sz + mod->rsp_pld_sz);
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun 	/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
963*4882a593Smuzhiyun 	return ((u8 *) fcxp_buf) + mod->req_pld_sz;
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun /*
967*4882a593Smuzhiyun  * Free the BFA FCXP
968*4882a593Smuzhiyun  *
969*4882a593Smuzhiyun  * @param[in]	fcxp			BFA fcxp pointer
970*4882a593Smuzhiyun  *
971*4882a593Smuzhiyun  * @return		void
972*4882a593Smuzhiyun  */
973*4882a593Smuzhiyun void
bfa_fcxp_free(struct bfa_fcxp_s * fcxp)974*4882a593Smuzhiyun bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
975*4882a593Smuzhiyun {
976*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	WARN_ON(fcxp == NULL);
979*4882a593Smuzhiyun 	bfa_trc(mod->bfa, fcxp->fcxp_tag);
980*4882a593Smuzhiyun 	bfa_fcxp_put(fcxp);
981*4882a593Smuzhiyun }
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun /*
984*4882a593Smuzhiyun  * Send a FCXP request
985*4882a593Smuzhiyun  *
986*4882a593Smuzhiyun  * @param[in]	fcxp	BFA fcxp pointer
987*4882a593Smuzhiyun  * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
988*4882a593Smuzhiyun  * @param[in]	vf_id	virtual Fabric ID
989*4882a593Smuzhiyun  * @param[in]	lp_tag	lport tag
990*4882a593Smuzhiyun  * @param[in]	cts	use Continuous sequence
991*4882a593Smuzhiyun  * @param[in]	cos	fc Class of Service
992*4882a593Smuzhiyun  * @param[in]	reqlen	request length, does not include FCHS length
993*4882a593Smuzhiyun  * @param[in]	fchs	fc Header Pointer. The header content will be copied
994*4882a593Smuzhiyun  *			in by BFA.
995*4882a593Smuzhiyun  *
996*4882a593Smuzhiyun  * @param[in]	cbfn	call back function to be called on receiving
997*4882a593Smuzhiyun  *								the response
998*4882a593Smuzhiyun  * @param[in]	cbarg	arg for cbfn
999*4882a593Smuzhiyun  * @param[in]	rsp_timeout
1000*4882a593Smuzhiyun  *			response timeout
1001*4882a593Smuzhiyun  *
1002*4882a593Smuzhiyun  * @return		bfa_status_t
1003*4882a593Smuzhiyun  */
1004*4882a593Smuzhiyun void
bfa_fcxp_send(struct bfa_fcxp_s * fcxp,struct bfa_rport_s * rport,u16 vf_id,u8 lp_tag,bfa_boolean_t cts,enum fc_cos cos,u32 reqlen,struct fchs_s * fchs,bfa_cb_fcxp_send_t cbfn,void * cbarg,u32 rsp_maxlen,u8 rsp_timeout)1005*4882a593Smuzhiyun bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
1006*4882a593Smuzhiyun 	      u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
1007*4882a593Smuzhiyun 	      u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
1008*4882a593Smuzhiyun 	      void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
1009*4882a593Smuzhiyun {
1010*4882a593Smuzhiyun 	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;
1011*4882a593Smuzhiyun 	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
1012*4882a593Smuzhiyun 	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
1013*4882a593Smuzhiyun 	struct bfi_fcxp_send_req_s	*send_req;
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun 	bfa_trc(bfa, fcxp->fcxp_tag);
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun 	/*
1018*4882a593Smuzhiyun 	 * setup request/response info
1019*4882a593Smuzhiyun 	 */
1020*4882a593Smuzhiyun 	reqi->bfa_rport = rport;
1021*4882a593Smuzhiyun 	reqi->vf_id = vf_id;
1022*4882a593Smuzhiyun 	reqi->lp_tag = lp_tag;
1023*4882a593Smuzhiyun 	reqi->class = cos;
1024*4882a593Smuzhiyun 	rspi->rsp_timeout = rsp_timeout;
1025*4882a593Smuzhiyun 	reqi->cts = cts;
1026*4882a593Smuzhiyun 	reqi->fchs = *fchs;
1027*4882a593Smuzhiyun 	reqi->req_tot_len = reqlen;
1028*4882a593Smuzhiyun 	rspi->rsp_maxlen = rsp_maxlen;
1029*4882a593Smuzhiyun 	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1030*4882a593Smuzhiyun 	fcxp->send_cbarg = cbarg;
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	/*
1033*4882a593Smuzhiyun 	 * If no room in CPE queue, wait for space in request queue
1034*4882a593Smuzhiyun 	 */
1035*4882a593Smuzhiyun 	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1036*4882a593Smuzhiyun 	if (!send_req) {
1037*4882a593Smuzhiyun 		bfa_trc(bfa, fcxp->fcxp_tag);
1038*4882a593Smuzhiyun 		fcxp->reqq_waiting = BFA_TRUE;
1039*4882a593Smuzhiyun 		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1040*4882a593Smuzhiyun 		return;
1041*4882a593Smuzhiyun 	}
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun 	bfa_fcxp_queue(fcxp, send_req);
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun /*
1047*4882a593Smuzhiyun  * Abort a BFA FCXP
1048*4882a593Smuzhiyun  *
1049*4882a593Smuzhiyun  * @param[in]	fcxp	BFA fcxp pointer
1050*4882a593Smuzhiyun  *
1051*4882a593Smuzhiyun  * @return		void
1052*4882a593Smuzhiyun  */
1053*4882a593Smuzhiyun bfa_status_t
bfa_fcxp_abort(struct bfa_fcxp_s * fcxp)1054*4882a593Smuzhiyun bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1055*4882a593Smuzhiyun {
1056*4882a593Smuzhiyun 	bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
1057*4882a593Smuzhiyun 	WARN_ON(1);
1058*4882a593Smuzhiyun 	return BFA_STATUS_OK;
1059*4882a593Smuzhiyun }
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun void
bfa_fcxp_req_rsp_alloc_wait(struct bfa_s * bfa,struct bfa_fcxp_wqe_s * wqe,bfa_fcxp_alloc_cbfn_t alloc_cbfn,void * alloc_cbarg,void * caller,int nreq_sgles,int nrsp_sgles,bfa_fcxp_get_sgaddr_t req_sga_cbfn,bfa_fcxp_get_sglen_t req_sglen_cbfn,bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,bfa_fcxp_get_sglen_t rsp_sglen_cbfn,bfa_boolean_t req)1062*4882a593Smuzhiyun bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1063*4882a593Smuzhiyun 	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1064*4882a593Smuzhiyun 	       void *caller, int nreq_sgles,
1065*4882a593Smuzhiyun 	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1066*4882a593Smuzhiyun 	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
1067*4882a593Smuzhiyun 	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1068*4882a593Smuzhiyun 	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
1069*4882a593Smuzhiyun {
1070*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 	if (req)
1073*4882a593Smuzhiyun 		WARN_ON(!list_empty(&mod->fcxp_req_free_q));
1074*4882a593Smuzhiyun 	else
1075*4882a593Smuzhiyun 		WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun 	wqe->alloc_cbfn = alloc_cbfn;
1078*4882a593Smuzhiyun 	wqe->alloc_cbarg = alloc_cbarg;
1079*4882a593Smuzhiyun 	wqe->caller = caller;
1080*4882a593Smuzhiyun 	wqe->bfa = bfa;
1081*4882a593Smuzhiyun 	wqe->nreq_sgles = nreq_sgles;
1082*4882a593Smuzhiyun 	wqe->nrsp_sgles = nrsp_sgles;
1083*4882a593Smuzhiyun 	wqe->req_sga_cbfn = req_sga_cbfn;
1084*4882a593Smuzhiyun 	wqe->req_sglen_cbfn = req_sglen_cbfn;
1085*4882a593Smuzhiyun 	wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1086*4882a593Smuzhiyun 	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	if (req)
1089*4882a593Smuzhiyun 		list_add_tail(&wqe->qe, &mod->req_wait_q);
1090*4882a593Smuzhiyun 	else
1091*4882a593Smuzhiyun 		list_add_tail(&wqe->qe, &mod->rsp_wait_q);
1092*4882a593Smuzhiyun }
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun void
bfa_fcxp_walloc_cancel(struct bfa_s * bfa,struct bfa_fcxp_wqe_s * wqe)1095*4882a593Smuzhiyun bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1096*4882a593Smuzhiyun {
1097*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun 	WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
1100*4882a593Smuzhiyun 		!bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
1101*4882a593Smuzhiyun 	list_del(&wqe->qe);
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun void
bfa_fcxp_discard(struct bfa_fcxp_s * fcxp)1105*4882a593Smuzhiyun bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1106*4882a593Smuzhiyun {
1107*4882a593Smuzhiyun 	/*
1108*4882a593Smuzhiyun 	 * If waiting for room in request queue, cancel reqq wait
1109*4882a593Smuzhiyun 	 * and free fcxp.
1110*4882a593Smuzhiyun 	 */
1111*4882a593Smuzhiyun 	if (fcxp->reqq_waiting) {
1112*4882a593Smuzhiyun 		fcxp->reqq_waiting = BFA_FALSE;
1113*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcxp->reqq_wqe);
1114*4882a593Smuzhiyun 		bfa_fcxp_free(fcxp);
1115*4882a593Smuzhiyun 		return;
1116*4882a593Smuzhiyun 	}
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 	fcxp->send_cbfn = bfa_fcxp_null_comp;
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun void
bfa_fcxp_isr(struct bfa_s * bfa,struct bfi_msg_s * msg)1122*4882a593Smuzhiyun bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1123*4882a593Smuzhiyun {
1124*4882a593Smuzhiyun 	switch (msg->mhdr.msg_id) {
1125*4882a593Smuzhiyun 	case BFI_FCXP_I2H_SEND_RSP:
1126*4882a593Smuzhiyun 		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1127*4882a593Smuzhiyun 		break;
1128*4882a593Smuzhiyun 
1129*4882a593Smuzhiyun 	default:
1130*4882a593Smuzhiyun 		bfa_trc(bfa, msg->mhdr.msg_id);
1131*4882a593Smuzhiyun 		WARN_ON(1);
1132*4882a593Smuzhiyun 	}
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun u32
bfa_fcxp_get_maxrsp(struct bfa_s * bfa)1136*4882a593Smuzhiyun bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1137*4882a593Smuzhiyun {
1138*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun 	return mod->rsp_pld_sz;
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun void
bfa_fcxp_res_recfg(struct bfa_s * bfa,u16 num_fcxp_fw)1144*4882a593Smuzhiyun bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1145*4882a593Smuzhiyun {
1146*4882a593Smuzhiyun 	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
1147*4882a593Smuzhiyun 	struct list_head	*qe;
1148*4882a593Smuzhiyun 	int	i;
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun 	for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1151*4882a593Smuzhiyun 		if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
1152*4882a593Smuzhiyun 			bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
1153*4882a593Smuzhiyun 			list_add_tail(qe, &mod->fcxp_req_unused_q);
1154*4882a593Smuzhiyun 		} else {
1155*4882a593Smuzhiyun 			bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
1156*4882a593Smuzhiyun 			list_add_tail(qe, &mod->fcxp_rsp_unused_q);
1157*4882a593Smuzhiyun 		}
1158*4882a593Smuzhiyun 	}
1159*4882a593Smuzhiyun }
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun /*
1162*4882a593Smuzhiyun  *  BFA LPS state machine functions
1163*4882a593Smuzhiyun  */
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun /*
1166*4882a593Smuzhiyun  * Init state -- no login
1167*4882a593Smuzhiyun  */
1168*4882a593Smuzhiyun static void
bfa_lps_sm_init(struct bfa_lps_s * lps,enum bfa_lps_event event)1169*4882a593Smuzhiyun bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1170*4882a593Smuzhiyun {
1171*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1172*4882a593Smuzhiyun 	bfa_trc(lps->bfa, event);
1173*4882a593Smuzhiyun 
1174*4882a593Smuzhiyun 	switch (event) {
1175*4882a593Smuzhiyun 	case BFA_LPS_SM_LOGIN:
1176*4882a593Smuzhiyun 		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1177*4882a593Smuzhiyun 			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1178*4882a593Smuzhiyun 			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1179*4882a593Smuzhiyun 		} else {
1180*4882a593Smuzhiyun 			bfa_sm_set_state(lps, bfa_lps_sm_login);
1181*4882a593Smuzhiyun 			bfa_lps_send_login(lps);
1182*4882a593Smuzhiyun 		}
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 		if (lps->fdisc)
1185*4882a593Smuzhiyun 			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1186*4882a593Smuzhiyun 				BFA_PL_EID_LOGIN, 0, "FDISC Request");
1187*4882a593Smuzhiyun 		else
1188*4882a593Smuzhiyun 			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1189*4882a593Smuzhiyun 				BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1190*4882a593Smuzhiyun 		break;
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun 	case BFA_LPS_SM_LOGOUT:
1193*4882a593Smuzhiyun 		bfa_lps_logout_comp(lps);
1194*4882a593Smuzhiyun 		break;
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun 	case BFA_LPS_SM_DELETE:
1197*4882a593Smuzhiyun 		bfa_lps_free(lps);
1198*4882a593Smuzhiyun 		break;
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 	case BFA_LPS_SM_RX_CVL:
1201*4882a593Smuzhiyun 	case BFA_LPS_SM_OFFLINE:
1202*4882a593Smuzhiyun 		break;
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun 	case BFA_LPS_SM_FWRSP:
1205*4882a593Smuzhiyun 		/*
1206*4882a593Smuzhiyun 		 * Could happen when fabric detects loopback and discards
1207*4882a593Smuzhiyun 		 * the lps request. Fw will eventually sent out the timeout
1208*4882a593Smuzhiyun 		 * Just ignore
1209*4882a593Smuzhiyun 		 */
1210*4882a593Smuzhiyun 		break;
1211*4882a593Smuzhiyun 	case BFA_LPS_SM_SET_N2N_PID:
1212*4882a593Smuzhiyun 		/*
1213*4882a593Smuzhiyun 		 * When topology is set to loop, bfa_lps_set_n2n_pid() sends
1214*4882a593Smuzhiyun 		 * this event. Ignore this event.
1215*4882a593Smuzhiyun 		 */
1216*4882a593Smuzhiyun 		break;
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun 	default:
1219*4882a593Smuzhiyun 		bfa_sm_fault(lps->bfa, event);
1220*4882a593Smuzhiyun 	}
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun /*
1224*4882a593Smuzhiyun  * login is in progress -- awaiting response from firmware
1225*4882a593Smuzhiyun  */
1226*4882a593Smuzhiyun static void
bfa_lps_sm_login(struct bfa_lps_s * lps,enum bfa_lps_event event)1227*4882a593Smuzhiyun bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1228*4882a593Smuzhiyun {
1229*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1230*4882a593Smuzhiyun 	bfa_trc(lps->bfa, event);
1231*4882a593Smuzhiyun 
1232*4882a593Smuzhiyun 	switch (event) {
1233*4882a593Smuzhiyun 	case BFA_LPS_SM_FWRSP:
1234*4882a593Smuzhiyun 		if (lps->status == BFA_STATUS_OK) {
1235*4882a593Smuzhiyun 			bfa_sm_set_state(lps, bfa_lps_sm_online);
1236*4882a593Smuzhiyun 			if (lps->fdisc)
1237*4882a593Smuzhiyun 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1238*4882a593Smuzhiyun 					BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1239*4882a593Smuzhiyun 			else
1240*4882a593Smuzhiyun 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1241*4882a593Smuzhiyun 					BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
1242*4882a593Smuzhiyun 			/* If N2N, send the assigned PID to FW */
1243*4882a593Smuzhiyun 			bfa_trc(lps->bfa, lps->fport);
1244*4882a593Smuzhiyun 			bfa_trc(lps->bfa, lps->lp_pid);
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun 			if (!lps->fport && lps->lp_pid)
1247*4882a593Smuzhiyun 				bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1248*4882a593Smuzhiyun 		} else {
1249*4882a593Smuzhiyun 			bfa_sm_set_state(lps, bfa_lps_sm_init);
1250*4882a593Smuzhiyun 			if (lps->fdisc)
1251*4882a593Smuzhiyun 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1252*4882a593Smuzhiyun 					BFA_PL_EID_LOGIN, 0,
1253*4882a593Smuzhiyun 					"FDISC Fail (RJT or timeout)");
1254*4882a593Smuzhiyun 			else
1255*4882a593Smuzhiyun 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1256*4882a593Smuzhiyun 					BFA_PL_EID_LOGIN, 0,
1257*4882a593Smuzhiyun 					"FLOGI Fail (RJT or timeout)");
1258*4882a593Smuzhiyun 		}
1259*4882a593Smuzhiyun 		bfa_lps_login_comp(lps);
1260*4882a593Smuzhiyun 		break;
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	case BFA_LPS_SM_OFFLINE:
1263*4882a593Smuzhiyun 	case BFA_LPS_SM_DELETE:
1264*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1265*4882a593Smuzhiyun 		break;
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun 	case BFA_LPS_SM_SET_N2N_PID:
1268*4882a593Smuzhiyun 		bfa_trc(lps->bfa, lps->fport);
1269*4882a593Smuzhiyun 		bfa_trc(lps->bfa, lps->lp_pid);
1270*4882a593Smuzhiyun 		break;
1271*4882a593Smuzhiyun 
1272*4882a593Smuzhiyun 	default:
1273*4882a593Smuzhiyun 		bfa_sm_fault(lps->bfa, event);
1274*4882a593Smuzhiyun 	}
1275*4882a593Smuzhiyun }
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun /*
1278*4882a593Smuzhiyun  * login pending - awaiting space in request queue
1279*4882a593Smuzhiyun  */
1280*4882a593Smuzhiyun static void
bfa_lps_sm_loginwait(struct bfa_lps_s * lps,enum bfa_lps_event event)1281*4882a593Smuzhiyun bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1282*4882a593Smuzhiyun {
1283*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1284*4882a593Smuzhiyun 	bfa_trc(lps->bfa, event);
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	switch (event) {
1287*4882a593Smuzhiyun 	case BFA_LPS_SM_RESUME:
1288*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_login);
1289*4882a593Smuzhiyun 		bfa_lps_send_login(lps);
1290*4882a593Smuzhiyun 		break;
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun 	case BFA_LPS_SM_OFFLINE:
1293*4882a593Smuzhiyun 	case BFA_LPS_SM_DELETE:
1294*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1295*4882a593Smuzhiyun 		bfa_reqq_wcancel(&lps->wqe);
1296*4882a593Smuzhiyun 		break;
1297*4882a593Smuzhiyun 
1298*4882a593Smuzhiyun 	case BFA_LPS_SM_RX_CVL:
1299*4882a593Smuzhiyun 		/*
1300*4882a593Smuzhiyun 		 * Login was not even sent out; so when getting out
1301*4882a593Smuzhiyun 		 * of this state, it will appear like a login retry
1302*4882a593Smuzhiyun 		 * after Clear virtual link
1303*4882a593Smuzhiyun 		 */
1304*4882a593Smuzhiyun 		break;
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	default:
1307*4882a593Smuzhiyun 		bfa_sm_fault(lps->bfa, event);
1308*4882a593Smuzhiyun 	}
1309*4882a593Smuzhiyun }
1310*4882a593Smuzhiyun 
1311*4882a593Smuzhiyun /*
1312*4882a593Smuzhiyun  * login complete
1313*4882a593Smuzhiyun  */
1314*4882a593Smuzhiyun static void
bfa_lps_sm_online(struct bfa_lps_s * lps,enum bfa_lps_event event)1315*4882a593Smuzhiyun bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1316*4882a593Smuzhiyun {
1317*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1318*4882a593Smuzhiyun 	bfa_trc(lps->bfa, event);
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun 	switch (event) {
1321*4882a593Smuzhiyun 	case BFA_LPS_SM_LOGOUT:
1322*4882a593Smuzhiyun 		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1323*4882a593Smuzhiyun 			bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1324*4882a593Smuzhiyun 			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1325*4882a593Smuzhiyun 		} else {
1326*4882a593Smuzhiyun 			bfa_sm_set_state(lps, bfa_lps_sm_logout);
1327*4882a593Smuzhiyun 			bfa_lps_send_logout(lps);
1328*4882a593Smuzhiyun 		}
1329*4882a593Smuzhiyun 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1330*4882a593Smuzhiyun 			BFA_PL_EID_LOGO, 0, "Logout");
1331*4882a593Smuzhiyun 		break;
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun 	case BFA_LPS_SM_RX_CVL:
1334*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun 		/* Let the vport module know about this event */
1337*4882a593Smuzhiyun 		bfa_lps_cvl_event(lps);
1338*4882a593Smuzhiyun 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1339*4882a593Smuzhiyun 			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1340*4882a593Smuzhiyun 		break;
1341*4882a593Smuzhiyun 
1342*4882a593Smuzhiyun 	case BFA_LPS_SM_SET_N2N_PID:
1343*4882a593Smuzhiyun 		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1344*4882a593Smuzhiyun 			bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1345*4882a593Smuzhiyun 			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1346*4882a593Smuzhiyun 		} else
1347*4882a593Smuzhiyun 			bfa_lps_send_set_n2n_pid(lps);
1348*4882a593Smuzhiyun 		break;
1349*4882a593Smuzhiyun 
1350*4882a593Smuzhiyun 	case BFA_LPS_SM_OFFLINE:
1351*4882a593Smuzhiyun 	case BFA_LPS_SM_DELETE:
1352*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1353*4882a593Smuzhiyun 		break;
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun 	default:
1356*4882a593Smuzhiyun 		bfa_sm_fault(lps->bfa, event);
1357*4882a593Smuzhiyun 	}
1358*4882a593Smuzhiyun }
1359*4882a593Smuzhiyun 
1360*4882a593Smuzhiyun /*
1361*4882a593Smuzhiyun  * login complete
1362*4882a593Smuzhiyun  */
1363*4882a593Smuzhiyun static void
bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s * lps,enum bfa_lps_event event)1364*4882a593Smuzhiyun bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1365*4882a593Smuzhiyun {
1366*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1367*4882a593Smuzhiyun 	bfa_trc(lps->bfa, event);
1368*4882a593Smuzhiyun 
1369*4882a593Smuzhiyun 	switch (event) {
1370*4882a593Smuzhiyun 	case BFA_LPS_SM_RESUME:
1371*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_online);
1372*4882a593Smuzhiyun 		bfa_lps_send_set_n2n_pid(lps);
1373*4882a593Smuzhiyun 		break;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	case BFA_LPS_SM_LOGOUT:
1376*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1377*4882a593Smuzhiyun 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1378*4882a593Smuzhiyun 			BFA_PL_EID_LOGO, 0, "Logout");
1379*4882a593Smuzhiyun 		break;
1380*4882a593Smuzhiyun 
1381*4882a593Smuzhiyun 	case BFA_LPS_SM_RX_CVL:
1382*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1383*4882a593Smuzhiyun 		bfa_reqq_wcancel(&lps->wqe);
1384*4882a593Smuzhiyun 
1385*4882a593Smuzhiyun 		/* Let the vport module know about this event */
1386*4882a593Smuzhiyun 		bfa_lps_cvl_event(lps);
1387*4882a593Smuzhiyun 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1388*4882a593Smuzhiyun 			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1389*4882a593Smuzhiyun 		break;
1390*4882a593Smuzhiyun 
1391*4882a593Smuzhiyun 	case BFA_LPS_SM_OFFLINE:
1392*4882a593Smuzhiyun 	case BFA_LPS_SM_DELETE:
1393*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1394*4882a593Smuzhiyun 		bfa_reqq_wcancel(&lps->wqe);
1395*4882a593Smuzhiyun 		break;
1396*4882a593Smuzhiyun 
1397*4882a593Smuzhiyun 	default:
1398*4882a593Smuzhiyun 		bfa_sm_fault(lps->bfa, event);
1399*4882a593Smuzhiyun 	}
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun 
1402*4882a593Smuzhiyun /*
1403*4882a593Smuzhiyun  * logout in progress - awaiting firmware response
1404*4882a593Smuzhiyun  */
1405*4882a593Smuzhiyun static void
bfa_lps_sm_logout(struct bfa_lps_s * lps,enum bfa_lps_event event)1406*4882a593Smuzhiyun bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1407*4882a593Smuzhiyun {
1408*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1409*4882a593Smuzhiyun 	bfa_trc(lps->bfa, event);
1410*4882a593Smuzhiyun 
1411*4882a593Smuzhiyun 	switch (event) {
1412*4882a593Smuzhiyun 	case BFA_LPS_SM_FWRSP:
1413*4882a593Smuzhiyun 	case BFA_LPS_SM_OFFLINE:
1414*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1415*4882a593Smuzhiyun 		bfa_lps_logout_comp(lps);
1416*4882a593Smuzhiyun 		break;
1417*4882a593Smuzhiyun 
1418*4882a593Smuzhiyun 	case BFA_LPS_SM_DELETE:
1419*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1420*4882a593Smuzhiyun 		break;
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun 	default:
1423*4882a593Smuzhiyun 		bfa_sm_fault(lps->bfa, event);
1424*4882a593Smuzhiyun 	}
1425*4882a593Smuzhiyun }
1426*4882a593Smuzhiyun 
1427*4882a593Smuzhiyun /*
1428*4882a593Smuzhiyun  * logout pending -- awaiting space in request queue
1429*4882a593Smuzhiyun  */
1430*4882a593Smuzhiyun static void
bfa_lps_sm_logowait(struct bfa_lps_s * lps,enum bfa_lps_event event)1431*4882a593Smuzhiyun bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1432*4882a593Smuzhiyun {
1433*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1434*4882a593Smuzhiyun 	bfa_trc(lps->bfa, event);
1435*4882a593Smuzhiyun 
1436*4882a593Smuzhiyun 	switch (event) {
1437*4882a593Smuzhiyun 	case BFA_LPS_SM_RESUME:
1438*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_logout);
1439*4882a593Smuzhiyun 		bfa_lps_send_logout(lps);
1440*4882a593Smuzhiyun 		break;
1441*4882a593Smuzhiyun 
1442*4882a593Smuzhiyun 	case BFA_LPS_SM_OFFLINE:
1443*4882a593Smuzhiyun 	case BFA_LPS_SM_DELETE:
1444*4882a593Smuzhiyun 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1445*4882a593Smuzhiyun 		bfa_reqq_wcancel(&lps->wqe);
1446*4882a593Smuzhiyun 		break;
1447*4882a593Smuzhiyun 
1448*4882a593Smuzhiyun 	default:
1449*4882a593Smuzhiyun 		bfa_sm_fault(lps->bfa, event);
1450*4882a593Smuzhiyun 	}
1451*4882a593Smuzhiyun }
1452*4882a593Smuzhiyun 
1453*4882a593Smuzhiyun 
1454*4882a593Smuzhiyun 
1455*4882a593Smuzhiyun /*
1456*4882a593Smuzhiyun  *  lps_pvt BFA LPS private functions
1457*4882a593Smuzhiyun  */
1458*4882a593Smuzhiyun 
1459*4882a593Smuzhiyun /*
1460*4882a593Smuzhiyun  * return memory requirement
1461*4882a593Smuzhiyun  */
1462*4882a593Smuzhiyun void
bfa_lps_meminfo(struct bfa_iocfc_cfg_s * cfg,struct bfa_meminfo_s * minfo,struct bfa_s * bfa)1463*4882a593Smuzhiyun bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
1464*4882a593Smuzhiyun 		struct bfa_s *bfa)
1465*4882a593Smuzhiyun {
1466*4882a593Smuzhiyun 	struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
1467*4882a593Smuzhiyun 
1468*4882a593Smuzhiyun 	if (cfg->drvcfg.min_cfg)
1469*4882a593Smuzhiyun 		bfa_mem_kva_setup(minfo, lps_kva,
1470*4882a593Smuzhiyun 			sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
1471*4882a593Smuzhiyun 	else
1472*4882a593Smuzhiyun 		bfa_mem_kva_setup(minfo, lps_kva,
1473*4882a593Smuzhiyun 			sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
1474*4882a593Smuzhiyun }
1475*4882a593Smuzhiyun 
1476*4882a593Smuzhiyun /*
1477*4882a593Smuzhiyun  * bfa module attach at initialization time
1478*4882a593Smuzhiyun  */
1479*4882a593Smuzhiyun void
bfa_lps_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)1480*4882a593Smuzhiyun bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1481*4882a593Smuzhiyun 	struct bfa_pcidev_s *pcidev)
1482*4882a593Smuzhiyun {
1483*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1484*4882a593Smuzhiyun 	struct bfa_lps_s	*lps;
1485*4882a593Smuzhiyun 	int			i;
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun 	mod->num_lps = BFA_LPS_MAX_LPORTS;
1488*4882a593Smuzhiyun 	if (cfg->drvcfg.min_cfg)
1489*4882a593Smuzhiyun 		mod->num_lps = BFA_LPS_MIN_LPORTS;
1490*4882a593Smuzhiyun 	else
1491*4882a593Smuzhiyun 		mod->num_lps = BFA_LPS_MAX_LPORTS;
1492*4882a593Smuzhiyun 	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun 	bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
1495*4882a593Smuzhiyun 
1496*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->lps_free_q);
1497*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->lps_active_q);
1498*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->lps_login_q);
1499*4882a593Smuzhiyun 
1500*4882a593Smuzhiyun 	for (i = 0; i < mod->num_lps; i++, lps++) {
1501*4882a593Smuzhiyun 		lps->bfa	= bfa;
1502*4882a593Smuzhiyun 		lps->bfa_tag	= (u8) i;
1503*4882a593Smuzhiyun 		lps->reqq	= BFA_REQQ_LPS;
1504*4882a593Smuzhiyun 		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1505*4882a593Smuzhiyun 		list_add_tail(&lps->qe, &mod->lps_free_q);
1506*4882a593Smuzhiyun 	}
1507*4882a593Smuzhiyun }
1508*4882a593Smuzhiyun 
1509*4882a593Smuzhiyun /*
1510*4882a593Smuzhiyun  * IOC in disabled state -- consider all lps offline
1511*4882a593Smuzhiyun  */
1512*4882a593Smuzhiyun void
bfa_lps_iocdisable(struct bfa_s * bfa)1513*4882a593Smuzhiyun bfa_lps_iocdisable(struct bfa_s *bfa)
1514*4882a593Smuzhiyun {
1515*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1516*4882a593Smuzhiyun 	struct bfa_lps_s	*lps;
1517*4882a593Smuzhiyun 	struct list_head		*qe, *qen;
1518*4882a593Smuzhiyun 
1519*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &mod->lps_active_q) {
1520*4882a593Smuzhiyun 		lps = (struct bfa_lps_s *) qe;
1521*4882a593Smuzhiyun 		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1522*4882a593Smuzhiyun 	}
1523*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &mod->lps_login_q) {
1524*4882a593Smuzhiyun 		lps = (struct bfa_lps_s *) qe;
1525*4882a593Smuzhiyun 		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1526*4882a593Smuzhiyun 	}
1527*4882a593Smuzhiyun 	list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
1528*4882a593Smuzhiyun }
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun /*
1531*4882a593Smuzhiyun  * Firmware login response
1532*4882a593Smuzhiyun  */
1533*4882a593Smuzhiyun static void
bfa_lps_login_rsp(struct bfa_s * bfa,struct bfi_lps_login_rsp_s * rsp)1534*4882a593Smuzhiyun bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1535*4882a593Smuzhiyun {
1536*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1537*4882a593Smuzhiyun 	struct bfa_lps_s	*lps;
1538*4882a593Smuzhiyun 
1539*4882a593Smuzhiyun 	WARN_ON(rsp->bfa_tag >= mod->num_lps);
1540*4882a593Smuzhiyun 	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1541*4882a593Smuzhiyun 
1542*4882a593Smuzhiyun 	lps->status = rsp->status;
1543*4882a593Smuzhiyun 	switch (rsp->status) {
1544*4882a593Smuzhiyun 	case BFA_STATUS_OK:
1545*4882a593Smuzhiyun 		lps->fw_tag	= rsp->fw_tag;
1546*4882a593Smuzhiyun 		lps->fport	= rsp->f_port;
1547*4882a593Smuzhiyun 		if (lps->fport)
1548*4882a593Smuzhiyun 			lps->lp_pid = rsp->lp_pid;
1549*4882a593Smuzhiyun 		lps->npiv_en	= rsp->npiv_en;
1550*4882a593Smuzhiyun 		lps->pr_bbcred	= be16_to_cpu(rsp->bb_credit);
1551*4882a593Smuzhiyun 		lps->pr_pwwn	= rsp->port_name;
1552*4882a593Smuzhiyun 		lps->pr_nwwn	= rsp->node_name;
1553*4882a593Smuzhiyun 		lps->auth_req	= rsp->auth_req;
1554*4882a593Smuzhiyun 		lps->lp_mac	= rsp->lp_mac;
1555*4882a593Smuzhiyun 		lps->brcd_switch = rsp->brcd_switch;
1556*4882a593Smuzhiyun 		lps->fcf_mac	= rsp->fcf_mac;
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun 		break;
1559*4882a593Smuzhiyun 
1560*4882a593Smuzhiyun 	case BFA_STATUS_FABRIC_RJT:
1561*4882a593Smuzhiyun 		lps->lsrjt_rsn = rsp->lsrjt_rsn;
1562*4882a593Smuzhiyun 		lps->lsrjt_expl = rsp->lsrjt_expl;
1563*4882a593Smuzhiyun 
1564*4882a593Smuzhiyun 		break;
1565*4882a593Smuzhiyun 
1566*4882a593Smuzhiyun 	case BFA_STATUS_EPROTOCOL:
1567*4882a593Smuzhiyun 		lps->ext_status = rsp->ext_status;
1568*4882a593Smuzhiyun 
1569*4882a593Smuzhiyun 		break;
1570*4882a593Smuzhiyun 
1571*4882a593Smuzhiyun 	case BFA_STATUS_VPORT_MAX:
1572*4882a593Smuzhiyun 		if (rsp->ext_status)
1573*4882a593Smuzhiyun 			bfa_lps_no_res(lps, rsp->ext_status);
1574*4882a593Smuzhiyun 		break;
1575*4882a593Smuzhiyun 
1576*4882a593Smuzhiyun 	default:
1577*4882a593Smuzhiyun 		/* Nothing to do with other status */
1578*4882a593Smuzhiyun 		break;
1579*4882a593Smuzhiyun 	}
1580*4882a593Smuzhiyun 
1581*4882a593Smuzhiyun 	list_del(&lps->qe);
1582*4882a593Smuzhiyun 	list_add_tail(&lps->qe, &mod->lps_active_q);
1583*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1584*4882a593Smuzhiyun }
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun static void
bfa_lps_no_res(struct bfa_lps_s * first_lps,u8 count)1587*4882a593Smuzhiyun bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
1588*4882a593Smuzhiyun {
1589*4882a593Smuzhiyun 	struct bfa_s		*bfa = first_lps->bfa;
1590*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1591*4882a593Smuzhiyun 	struct list_head	*qe, *qe_next;
1592*4882a593Smuzhiyun 	struct bfa_lps_s	*lps;
1593*4882a593Smuzhiyun 
1594*4882a593Smuzhiyun 	bfa_trc(bfa, count);
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun 	qe = bfa_q_next(first_lps);
1597*4882a593Smuzhiyun 
1598*4882a593Smuzhiyun 	while (count && qe) {
1599*4882a593Smuzhiyun 		qe_next = bfa_q_next(qe);
1600*4882a593Smuzhiyun 		lps = (struct bfa_lps_s *)qe;
1601*4882a593Smuzhiyun 		bfa_trc(bfa, lps->bfa_tag);
1602*4882a593Smuzhiyun 		lps->status = first_lps->status;
1603*4882a593Smuzhiyun 		list_del(&lps->qe);
1604*4882a593Smuzhiyun 		list_add_tail(&lps->qe, &mod->lps_active_q);
1605*4882a593Smuzhiyun 		bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1606*4882a593Smuzhiyun 		qe = qe_next;
1607*4882a593Smuzhiyun 		count--;
1608*4882a593Smuzhiyun 	}
1609*4882a593Smuzhiyun }
1610*4882a593Smuzhiyun 
1611*4882a593Smuzhiyun /*
1612*4882a593Smuzhiyun  * Firmware logout response
1613*4882a593Smuzhiyun  */
1614*4882a593Smuzhiyun static void
bfa_lps_logout_rsp(struct bfa_s * bfa,struct bfi_lps_logout_rsp_s * rsp)1615*4882a593Smuzhiyun bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1616*4882a593Smuzhiyun {
1617*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1618*4882a593Smuzhiyun 	struct bfa_lps_s	*lps;
1619*4882a593Smuzhiyun 
1620*4882a593Smuzhiyun 	WARN_ON(rsp->bfa_tag >= mod->num_lps);
1621*4882a593Smuzhiyun 	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1622*4882a593Smuzhiyun 
1623*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1624*4882a593Smuzhiyun }
1625*4882a593Smuzhiyun 
1626*4882a593Smuzhiyun /*
1627*4882a593Smuzhiyun  * Firmware received a Clear virtual link request (for FCoE)
1628*4882a593Smuzhiyun  */
1629*4882a593Smuzhiyun static void
bfa_lps_rx_cvl_event(struct bfa_s * bfa,struct bfi_lps_cvl_event_s * cvl)1630*4882a593Smuzhiyun bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1631*4882a593Smuzhiyun {
1632*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1633*4882a593Smuzhiyun 	struct bfa_lps_s	*lps;
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun 	lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
1636*4882a593Smuzhiyun 
1637*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1638*4882a593Smuzhiyun }
1639*4882a593Smuzhiyun 
1640*4882a593Smuzhiyun /*
1641*4882a593Smuzhiyun  * Space is available in request queue, resume queueing request to firmware.
1642*4882a593Smuzhiyun  */
1643*4882a593Smuzhiyun static void
bfa_lps_reqq_resume(void * lps_arg)1644*4882a593Smuzhiyun bfa_lps_reqq_resume(void *lps_arg)
1645*4882a593Smuzhiyun {
1646*4882a593Smuzhiyun 	struct bfa_lps_s	*lps = lps_arg;
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1649*4882a593Smuzhiyun }
1650*4882a593Smuzhiyun 
1651*4882a593Smuzhiyun /*
1652*4882a593Smuzhiyun  * lps is freed -- triggered by vport delete
1653*4882a593Smuzhiyun  */
1654*4882a593Smuzhiyun static void
bfa_lps_free(struct bfa_lps_s * lps)1655*4882a593Smuzhiyun bfa_lps_free(struct bfa_lps_s *lps)
1656*4882a593Smuzhiyun {
1657*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun 	lps->lp_pid = 0;
1660*4882a593Smuzhiyun 	list_del(&lps->qe);
1661*4882a593Smuzhiyun 	list_add_tail(&lps->qe, &mod->lps_free_q);
1662*4882a593Smuzhiyun }
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun /*
1665*4882a593Smuzhiyun  * send login request to firmware
1666*4882a593Smuzhiyun  */
1667*4882a593Smuzhiyun static void
bfa_lps_send_login(struct bfa_lps_s * lps)1668*4882a593Smuzhiyun bfa_lps_send_login(struct bfa_lps_s *lps)
1669*4882a593Smuzhiyun {
1670*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
1671*4882a593Smuzhiyun 	struct bfi_lps_login_req_s	*m;
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 	m = bfa_reqq_next(lps->bfa, lps->reqq);
1674*4882a593Smuzhiyun 	WARN_ON(!m);
1675*4882a593Smuzhiyun 
1676*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
1677*4882a593Smuzhiyun 		bfa_fn_lpu(lps->bfa));
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun 	m->bfa_tag	= lps->bfa_tag;
1680*4882a593Smuzhiyun 	m->alpa		= lps->alpa;
1681*4882a593Smuzhiyun 	m->pdu_size	= cpu_to_be16(lps->pdusz);
1682*4882a593Smuzhiyun 	m->pwwn		= lps->pwwn;
1683*4882a593Smuzhiyun 	m->nwwn		= lps->nwwn;
1684*4882a593Smuzhiyun 	m->fdisc	= lps->fdisc;
1685*4882a593Smuzhiyun 	m->auth_en	= lps->auth_en;
1686*4882a593Smuzhiyun 
1687*4882a593Smuzhiyun 	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1688*4882a593Smuzhiyun 	list_del(&lps->qe);
1689*4882a593Smuzhiyun 	list_add_tail(&lps->qe, &mod->lps_login_q);
1690*4882a593Smuzhiyun }
1691*4882a593Smuzhiyun 
1692*4882a593Smuzhiyun /*
1693*4882a593Smuzhiyun  * send logout request to firmware
1694*4882a593Smuzhiyun  */
1695*4882a593Smuzhiyun static void
bfa_lps_send_logout(struct bfa_lps_s * lps)1696*4882a593Smuzhiyun bfa_lps_send_logout(struct bfa_lps_s *lps)
1697*4882a593Smuzhiyun {
1698*4882a593Smuzhiyun 	struct bfi_lps_logout_req_s *m;
1699*4882a593Smuzhiyun 
1700*4882a593Smuzhiyun 	m = bfa_reqq_next(lps->bfa, lps->reqq);
1701*4882a593Smuzhiyun 	WARN_ON(!m);
1702*4882a593Smuzhiyun 
1703*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
1704*4882a593Smuzhiyun 		bfa_fn_lpu(lps->bfa));
1705*4882a593Smuzhiyun 
1706*4882a593Smuzhiyun 	m->fw_tag = lps->fw_tag;
1707*4882a593Smuzhiyun 	m->port_name = lps->pwwn;
1708*4882a593Smuzhiyun 	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1709*4882a593Smuzhiyun }
1710*4882a593Smuzhiyun 
1711*4882a593Smuzhiyun /*
1712*4882a593Smuzhiyun  * send n2n pid set request to firmware
1713*4882a593Smuzhiyun  */
1714*4882a593Smuzhiyun static void
bfa_lps_send_set_n2n_pid(struct bfa_lps_s * lps)1715*4882a593Smuzhiyun bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1716*4882a593Smuzhiyun {
1717*4882a593Smuzhiyun 	struct bfi_lps_n2n_pid_req_s *m;
1718*4882a593Smuzhiyun 
1719*4882a593Smuzhiyun 	m = bfa_reqq_next(lps->bfa, lps->reqq);
1720*4882a593Smuzhiyun 	WARN_ON(!m);
1721*4882a593Smuzhiyun 
1722*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
1723*4882a593Smuzhiyun 		bfa_fn_lpu(lps->bfa));
1724*4882a593Smuzhiyun 
1725*4882a593Smuzhiyun 	m->fw_tag = lps->fw_tag;
1726*4882a593Smuzhiyun 	m->lp_pid = lps->lp_pid;
1727*4882a593Smuzhiyun 	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1728*4882a593Smuzhiyun }
1729*4882a593Smuzhiyun 
1730*4882a593Smuzhiyun /*
1731*4882a593Smuzhiyun  * Indirect login completion handler for non-fcs
1732*4882a593Smuzhiyun  */
1733*4882a593Smuzhiyun static void
bfa_lps_login_comp_cb(void * arg,bfa_boolean_t complete)1734*4882a593Smuzhiyun bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1735*4882a593Smuzhiyun {
1736*4882a593Smuzhiyun 	struct bfa_lps_s *lps	= arg;
1737*4882a593Smuzhiyun 
1738*4882a593Smuzhiyun 	if (!complete)
1739*4882a593Smuzhiyun 		return;
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun 	if (lps->fdisc)
1742*4882a593Smuzhiyun 		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1743*4882a593Smuzhiyun 	else
1744*4882a593Smuzhiyun 		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1745*4882a593Smuzhiyun }
1746*4882a593Smuzhiyun 
1747*4882a593Smuzhiyun /*
1748*4882a593Smuzhiyun  * Login completion handler -- direct call for fcs, queue for others
1749*4882a593Smuzhiyun  */
1750*4882a593Smuzhiyun static void
bfa_lps_login_comp(struct bfa_lps_s * lps)1751*4882a593Smuzhiyun bfa_lps_login_comp(struct bfa_lps_s *lps)
1752*4882a593Smuzhiyun {
1753*4882a593Smuzhiyun 	if (!lps->bfa->fcs) {
1754*4882a593Smuzhiyun 		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1755*4882a593Smuzhiyun 			lps);
1756*4882a593Smuzhiyun 		return;
1757*4882a593Smuzhiyun 	}
1758*4882a593Smuzhiyun 
1759*4882a593Smuzhiyun 	if (lps->fdisc)
1760*4882a593Smuzhiyun 		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1761*4882a593Smuzhiyun 	else
1762*4882a593Smuzhiyun 		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1763*4882a593Smuzhiyun }
1764*4882a593Smuzhiyun 
1765*4882a593Smuzhiyun /*
1766*4882a593Smuzhiyun  * Indirect logout completion handler for non-fcs
1767*4882a593Smuzhiyun  */
1768*4882a593Smuzhiyun static void
bfa_lps_logout_comp_cb(void * arg,bfa_boolean_t complete)1769*4882a593Smuzhiyun bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1770*4882a593Smuzhiyun {
1771*4882a593Smuzhiyun 	struct bfa_lps_s *lps	= arg;
1772*4882a593Smuzhiyun 
1773*4882a593Smuzhiyun 	if (!complete)
1774*4882a593Smuzhiyun 		return;
1775*4882a593Smuzhiyun 
1776*4882a593Smuzhiyun 	if (lps->fdisc)
1777*4882a593Smuzhiyun 		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1778*4882a593Smuzhiyun 	else
1779*4882a593Smuzhiyun 		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
1780*4882a593Smuzhiyun }
1781*4882a593Smuzhiyun 
1782*4882a593Smuzhiyun /*
1783*4882a593Smuzhiyun  * Logout completion handler -- direct call for fcs, queue for others
1784*4882a593Smuzhiyun  */
1785*4882a593Smuzhiyun static void
bfa_lps_logout_comp(struct bfa_lps_s * lps)1786*4882a593Smuzhiyun bfa_lps_logout_comp(struct bfa_lps_s *lps)
1787*4882a593Smuzhiyun {
1788*4882a593Smuzhiyun 	if (!lps->bfa->fcs) {
1789*4882a593Smuzhiyun 		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1790*4882a593Smuzhiyun 			lps);
1791*4882a593Smuzhiyun 		return;
1792*4882a593Smuzhiyun 	}
1793*4882a593Smuzhiyun 	if (lps->fdisc)
1794*4882a593Smuzhiyun 		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1795*4882a593Smuzhiyun }
1796*4882a593Smuzhiyun 
1797*4882a593Smuzhiyun /*
1798*4882a593Smuzhiyun  * Clear virtual link completion handler for non-fcs
1799*4882a593Smuzhiyun  */
1800*4882a593Smuzhiyun static void
bfa_lps_cvl_event_cb(void * arg,bfa_boolean_t complete)1801*4882a593Smuzhiyun bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1802*4882a593Smuzhiyun {
1803*4882a593Smuzhiyun 	struct bfa_lps_s *lps	= arg;
1804*4882a593Smuzhiyun 
1805*4882a593Smuzhiyun 	if (!complete)
1806*4882a593Smuzhiyun 		return;
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun 	/* Clear virtual link to base port will result in link down */
1809*4882a593Smuzhiyun 	if (lps->fdisc)
1810*4882a593Smuzhiyun 		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1811*4882a593Smuzhiyun }
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun /*
1814*4882a593Smuzhiyun  * Received Clear virtual link event --direct call for fcs,
1815*4882a593Smuzhiyun  * queue for others
1816*4882a593Smuzhiyun  */
1817*4882a593Smuzhiyun static void
bfa_lps_cvl_event(struct bfa_lps_s * lps)1818*4882a593Smuzhiyun bfa_lps_cvl_event(struct bfa_lps_s *lps)
1819*4882a593Smuzhiyun {
1820*4882a593Smuzhiyun 	if (!lps->bfa->fcs) {
1821*4882a593Smuzhiyun 		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1822*4882a593Smuzhiyun 			lps);
1823*4882a593Smuzhiyun 		return;
1824*4882a593Smuzhiyun 	}
1825*4882a593Smuzhiyun 
1826*4882a593Smuzhiyun 	/* Clear virtual link to base port will result in link down */
1827*4882a593Smuzhiyun 	if (lps->fdisc)
1828*4882a593Smuzhiyun 		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1829*4882a593Smuzhiyun }
1830*4882a593Smuzhiyun 
1831*4882a593Smuzhiyun 
1832*4882a593Smuzhiyun 
1833*4882a593Smuzhiyun /*
1834*4882a593Smuzhiyun  *  lps_public BFA LPS public functions
1835*4882a593Smuzhiyun  */
1836*4882a593Smuzhiyun 
1837*4882a593Smuzhiyun u32
bfa_lps_get_max_vport(struct bfa_s * bfa)1838*4882a593Smuzhiyun bfa_lps_get_max_vport(struct bfa_s *bfa)
1839*4882a593Smuzhiyun {
1840*4882a593Smuzhiyun 	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1841*4882a593Smuzhiyun 		return BFA_LPS_MAX_VPORTS_SUPP_CT;
1842*4882a593Smuzhiyun 	else
1843*4882a593Smuzhiyun 		return BFA_LPS_MAX_VPORTS_SUPP_CB;
1844*4882a593Smuzhiyun }
1845*4882a593Smuzhiyun 
1846*4882a593Smuzhiyun /*
1847*4882a593Smuzhiyun  * Allocate a lport srvice tag.
1848*4882a593Smuzhiyun  */
1849*4882a593Smuzhiyun struct bfa_lps_s  *
bfa_lps_alloc(struct bfa_s * bfa)1850*4882a593Smuzhiyun bfa_lps_alloc(struct bfa_s *bfa)
1851*4882a593Smuzhiyun {
1852*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1853*4882a593Smuzhiyun 	struct bfa_lps_s	*lps = NULL;
1854*4882a593Smuzhiyun 
1855*4882a593Smuzhiyun 	bfa_q_deq(&mod->lps_free_q, &lps);
1856*4882a593Smuzhiyun 
1857*4882a593Smuzhiyun 	if (lps == NULL)
1858*4882a593Smuzhiyun 		return NULL;
1859*4882a593Smuzhiyun 
1860*4882a593Smuzhiyun 	list_add_tail(&lps->qe, &mod->lps_active_q);
1861*4882a593Smuzhiyun 
1862*4882a593Smuzhiyun 	bfa_sm_set_state(lps, bfa_lps_sm_init);
1863*4882a593Smuzhiyun 	return lps;
1864*4882a593Smuzhiyun }
1865*4882a593Smuzhiyun 
1866*4882a593Smuzhiyun /*
1867*4882a593Smuzhiyun  * Free lport service tag. This can be called anytime after an alloc.
1868*4882a593Smuzhiyun  * No need to wait for any pending login/logout completions.
1869*4882a593Smuzhiyun  */
1870*4882a593Smuzhiyun void
bfa_lps_delete(struct bfa_lps_s * lps)1871*4882a593Smuzhiyun bfa_lps_delete(struct bfa_lps_s *lps)
1872*4882a593Smuzhiyun {
1873*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1874*4882a593Smuzhiyun }
1875*4882a593Smuzhiyun 
1876*4882a593Smuzhiyun /*
1877*4882a593Smuzhiyun  * Initiate a lport login.
1878*4882a593Smuzhiyun  */
1879*4882a593Smuzhiyun void
bfa_lps_flogi(struct bfa_lps_s * lps,void * uarg,u8 alpa,u16 pdusz,wwn_t pwwn,wwn_t nwwn,bfa_boolean_t auth_en)1880*4882a593Smuzhiyun bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1881*4882a593Smuzhiyun 	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
1882*4882a593Smuzhiyun {
1883*4882a593Smuzhiyun 	lps->uarg	= uarg;
1884*4882a593Smuzhiyun 	lps->alpa	= alpa;
1885*4882a593Smuzhiyun 	lps->pdusz	= pdusz;
1886*4882a593Smuzhiyun 	lps->pwwn	= pwwn;
1887*4882a593Smuzhiyun 	lps->nwwn	= nwwn;
1888*4882a593Smuzhiyun 	lps->fdisc	= BFA_FALSE;
1889*4882a593Smuzhiyun 	lps->auth_en	= auth_en;
1890*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1891*4882a593Smuzhiyun }
1892*4882a593Smuzhiyun 
1893*4882a593Smuzhiyun /*
1894*4882a593Smuzhiyun  * Initiate a lport fdisc login.
1895*4882a593Smuzhiyun  */
1896*4882a593Smuzhiyun void
bfa_lps_fdisc(struct bfa_lps_s * lps,void * uarg,u16 pdusz,wwn_t pwwn,wwn_t nwwn)1897*4882a593Smuzhiyun bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1898*4882a593Smuzhiyun 	wwn_t nwwn)
1899*4882a593Smuzhiyun {
1900*4882a593Smuzhiyun 	lps->uarg	= uarg;
1901*4882a593Smuzhiyun 	lps->alpa	= 0;
1902*4882a593Smuzhiyun 	lps->pdusz	= pdusz;
1903*4882a593Smuzhiyun 	lps->pwwn	= pwwn;
1904*4882a593Smuzhiyun 	lps->nwwn	= nwwn;
1905*4882a593Smuzhiyun 	lps->fdisc	= BFA_TRUE;
1906*4882a593Smuzhiyun 	lps->auth_en	= BFA_FALSE;
1907*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1908*4882a593Smuzhiyun }
1909*4882a593Smuzhiyun 
1910*4882a593Smuzhiyun 
1911*4882a593Smuzhiyun /*
1912*4882a593Smuzhiyun  * Initiate a lport FDSIC logout.
1913*4882a593Smuzhiyun  */
1914*4882a593Smuzhiyun void
bfa_lps_fdisclogo(struct bfa_lps_s * lps)1915*4882a593Smuzhiyun bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1916*4882a593Smuzhiyun {
1917*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1918*4882a593Smuzhiyun }
1919*4882a593Smuzhiyun 
1920*4882a593Smuzhiyun u8
bfa_lps_get_fwtag(struct bfa_s * bfa,u8 lp_tag)1921*4882a593Smuzhiyun bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
1922*4882a593Smuzhiyun {
1923*4882a593Smuzhiyun 	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1924*4882a593Smuzhiyun 
1925*4882a593Smuzhiyun 	return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
1926*4882a593Smuzhiyun }
1927*4882a593Smuzhiyun 
1928*4882a593Smuzhiyun /*
1929*4882a593Smuzhiyun  * Return lport services tag given the pid
1930*4882a593Smuzhiyun  */
1931*4882a593Smuzhiyun u8
bfa_lps_get_tag_from_pid(struct bfa_s * bfa,u32 pid)1932*4882a593Smuzhiyun bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1933*4882a593Smuzhiyun {
1934*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1935*4882a593Smuzhiyun 	struct bfa_lps_s	*lps;
1936*4882a593Smuzhiyun 	int			i;
1937*4882a593Smuzhiyun 
1938*4882a593Smuzhiyun 	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1939*4882a593Smuzhiyun 		if (lps->lp_pid == pid)
1940*4882a593Smuzhiyun 			return lps->bfa_tag;
1941*4882a593Smuzhiyun 	}
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun 	/* Return base port tag anyway */
1944*4882a593Smuzhiyun 	return 0;
1945*4882a593Smuzhiyun }
1946*4882a593Smuzhiyun 
1947*4882a593Smuzhiyun 
1948*4882a593Smuzhiyun /*
1949*4882a593Smuzhiyun  * return port id assigned to the base lport
1950*4882a593Smuzhiyun  */
1951*4882a593Smuzhiyun u32
bfa_lps_get_base_pid(struct bfa_s * bfa)1952*4882a593Smuzhiyun bfa_lps_get_base_pid(struct bfa_s *bfa)
1953*4882a593Smuzhiyun {
1954*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1955*4882a593Smuzhiyun 
1956*4882a593Smuzhiyun 	return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1957*4882a593Smuzhiyun }
1958*4882a593Smuzhiyun 
1959*4882a593Smuzhiyun /*
1960*4882a593Smuzhiyun  * Set PID in case of n2n (which is assigned during PLOGI)
1961*4882a593Smuzhiyun  */
1962*4882a593Smuzhiyun void
bfa_lps_set_n2n_pid(struct bfa_lps_s * lps,uint32_t n2n_pid)1963*4882a593Smuzhiyun bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1964*4882a593Smuzhiyun {
1965*4882a593Smuzhiyun 	bfa_trc(lps->bfa, lps->bfa_tag);
1966*4882a593Smuzhiyun 	bfa_trc(lps->bfa, n2n_pid);
1967*4882a593Smuzhiyun 
1968*4882a593Smuzhiyun 	lps->lp_pid = n2n_pid;
1969*4882a593Smuzhiyun 	bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1970*4882a593Smuzhiyun }
1971*4882a593Smuzhiyun 
1972*4882a593Smuzhiyun /*
1973*4882a593Smuzhiyun  * LPS firmware message class handler.
1974*4882a593Smuzhiyun  */
1975*4882a593Smuzhiyun void
bfa_lps_isr(struct bfa_s * bfa,struct bfi_msg_s * m)1976*4882a593Smuzhiyun bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1977*4882a593Smuzhiyun {
1978*4882a593Smuzhiyun 	union bfi_lps_i2h_msg_u	msg;
1979*4882a593Smuzhiyun 
1980*4882a593Smuzhiyun 	bfa_trc(bfa, m->mhdr.msg_id);
1981*4882a593Smuzhiyun 	msg.msg = m;
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun 	switch (m->mhdr.msg_id) {
1984*4882a593Smuzhiyun 	case BFI_LPS_I2H_LOGIN_RSP:
1985*4882a593Smuzhiyun 		bfa_lps_login_rsp(bfa, msg.login_rsp);
1986*4882a593Smuzhiyun 		break;
1987*4882a593Smuzhiyun 
1988*4882a593Smuzhiyun 	case BFI_LPS_I2H_LOGOUT_RSP:
1989*4882a593Smuzhiyun 		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
1990*4882a593Smuzhiyun 		break;
1991*4882a593Smuzhiyun 
1992*4882a593Smuzhiyun 	case BFI_LPS_I2H_CVL_EVENT:
1993*4882a593Smuzhiyun 		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
1994*4882a593Smuzhiyun 		break;
1995*4882a593Smuzhiyun 
1996*4882a593Smuzhiyun 	default:
1997*4882a593Smuzhiyun 		bfa_trc(bfa, m->mhdr.msg_id);
1998*4882a593Smuzhiyun 		WARN_ON(1);
1999*4882a593Smuzhiyun 	}
2000*4882a593Smuzhiyun }
2001*4882a593Smuzhiyun 
2002*4882a593Smuzhiyun static void
bfa_fcport_aen_post(struct bfa_fcport_s * fcport,enum bfa_port_aen_event event)2003*4882a593Smuzhiyun bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
2004*4882a593Smuzhiyun {
2005*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2006*4882a593Smuzhiyun 	struct bfa_aen_entry_s  *aen_entry;
2007*4882a593Smuzhiyun 
2008*4882a593Smuzhiyun 	bfad_get_aen_entry(bfad, aen_entry);
2009*4882a593Smuzhiyun 	if (!aen_entry)
2010*4882a593Smuzhiyun 		return;
2011*4882a593Smuzhiyun 
2012*4882a593Smuzhiyun 	aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
2013*4882a593Smuzhiyun 	aen_entry->aen_data.port.pwwn = fcport->pwwn;
2014*4882a593Smuzhiyun 
2015*4882a593Smuzhiyun 	/* Send the AEN notification */
2016*4882a593Smuzhiyun 	bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,
2017*4882a593Smuzhiyun 				  BFA_AEN_CAT_PORT, event);
2018*4882a593Smuzhiyun }
2019*4882a593Smuzhiyun 
2020*4882a593Smuzhiyun /*
2021*4882a593Smuzhiyun  * FC PORT state machine functions
2022*4882a593Smuzhiyun  */
2023*4882a593Smuzhiyun static void
bfa_fcport_sm_uninit(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2024*4882a593Smuzhiyun bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
2025*4882a593Smuzhiyun 			enum bfa_fcport_sm_event event)
2026*4882a593Smuzhiyun {
2027*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2028*4882a593Smuzhiyun 
2029*4882a593Smuzhiyun 	switch (event) {
2030*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2031*4882a593Smuzhiyun 		/*
2032*4882a593Smuzhiyun 		 * Start event after IOC is configured and BFA is started.
2033*4882a593Smuzhiyun 		 */
2034*4882a593Smuzhiyun 		fcport->use_flash_cfg = BFA_TRUE;
2035*4882a593Smuzhiyun 
2036*4882a593Smuzhiyun 		if (bfa_fcport_send_enable(fcport)) {
2037*4882a593Smuzhiyun 			bfa_trc(fcport->bfa, BFA_TRUE);
2038*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2039*4882a593Smuzhiyun 		} else {
2040*4882a593Smuzhiyun 			bfa_trc(fcport->bfa, BFA_FALSE);
2041*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2042*4882a593Smuzhiyun 					bfa_fcport_sm_enabling_qwait);
2043*4882a593Smuzhiyun 		}
2044*4882a593Smuzhiyun 		break;
2045*4882a593Smuzhiyun 
2046*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2047*4882a593Smuzhiyun 		/*
2048*4882a593Smuzhiyun 		 * Port is persistently configured to be in enabled state. Do
2049*4882a593Smuzhiyun 		 * not change state. Port enabling is done when START event is
2050*4882a593Smuzhiyun 		 * received.
2051*4882a593Smuzhiyun 		 */
2052*4882a593Smuzhiyun 		break;
2053*4882a593Smuzhiyun 
2054*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2055*4882a593Smuzhiyun 		/*
2056*4882a593Smuzhiyun 		 * If a port is persistently configured to be disabled, the
2057*4882a593Smuzhiyun 		 * first event will a port disable request.
2058*4882a593Smuzhiyun 		 */
2059*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2060*4882a593Smuzhiyun 		break;
2061*4882a593Smuzhiyun 
2062*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2063*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2064*4882a593Smuzhiyun 		break;
2065*4882a593Smuzhiyun 
2066*4882a593Smuzhiyun 	default:
2067*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2068*4882a593Smuzhiyun 	}
2069*4882a593Smuzhiyun }
2070*4882a593Smuzhiyun 
2071*4882a593Smuzhiyun static void
bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2072*4882a593Smuzhiyun bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2073*4882a593Smuzhiyun 				enum bfa_fcport_sm_event event)
2074*4882a593Smuzhiyun {
2075*4882a593Smuzhiyun 	char pwwn_buf[BFA_STRING_32];
2076*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2077*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2078*4882a593Smuzhiyun 
2079*4882a593Smuzhiyun 	switch (event) {
2080*4882a593Smuzhiyun 	case BFA_FCPORT_SM_QRESUME:
2081*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2082*4882a593Smuzhiyun 		bfa_fcport_send_enable(fcport);
2083*4882a593Smuzhiyun 		break;
2084*4882a593Smuzhiyun 
2085*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2086*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->reqq_wait);
2087*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2088*4882a593Smuzhiyun 		break;
2089*4882a593Smuzhiyun 
2090*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2091*4882a593Smuzhiyun 		/*
2092*4882a593Smuzhiyun 		 * Already enable is in progress.
2093*4882a593Smuzhiyun 		 */
2094*4882a593Smuzhiyun 		break;
2095*4882a593Smuzhiyun 
2096*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2097*4882a593Smuzhiyun 		/*
2098*4882a593Smuzhiyun 		 * Just send disable request to firmware when room becomes
2099*4882a593Smuzhiyun 		 * available in request queue.
2100*4882a593Smuzhiyun 		 */
2101*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2102*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->reqq_wait);
2103*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2104*4882a593Smuzhiyun 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2105*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2106*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2107*4882a593Smuzhiyun 			"Base port disabled: WWN = %s\n", pwwn_buf);
2108*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2109*4882a593Smuzhiyun 		break;
2110*4882a593Smuzhiyun 
2111*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKUP:
2112*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKDOWN:
2113*4882a593Smuzhiyun 		/*
2114*4882a593Smuzhiyun 		 * Possible to get link events when doing back-to-back
2115*4882a593Smuzhiyun 		 * enable/disables.
2116*4882a593Smuzhiyun 		 */
2117*4882a593Smuzhiyun 		break;
2118*4882a593Smuzhiyun 
2119*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2120*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->reqq_wait);
2121*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2122*4882a593Smuzhiyun 		break;
2123*4882a593Smuzhiyun 
2124*4882a593Smuzhiyun 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2125*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2126*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2127*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2128*4882a593Smuzhiyun 		break;
2129*4882a593Smuzhiyun 
2130*4882a593Smuzhiyun 	default:
2131*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2132*4882a593Smuzhiyun 	}
2133*4882a593Smuzhiyun }
2134*4882a593Smuzhiyun 
2135*4882a593Smuzhiyun static void
bfa_fcport_sm_enabling(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2136*4882a593Smuzhiyun bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2137*4882a593Smuzhiyun 						enum bfa_fcport_sm_event event)
2138*4882a593Smuzhiyun {
2139*4882a593Smuzhiyun 	char pwwn_buf[BFA_STRING_32];
2140*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2141*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2142*4882a593Smuzhiyun 
2143*4882a593Smuzhiyun 	switch (event) {
2144*4882a593Smuzhiyun 	case BFA_FCPORT_SM_FWRSP:
2145*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKDOWN:
2146*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2147*4882a593Smuzhiyun 		break;
2148*4882a593Smuzhiyun 
2149*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKUP:
2150*4882a593Smuzhiyun 		bfa_fcport_update_linkinfo(fcport);
2151*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2152*4882a593Smuzhiyun 
2153*4882a593Smuzhiyun 		WARN_ON(!fcport->event_cbfn);
2154*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2155*4882a593Smuzhiyun 		break;
2156*4882a593Smuzhiyun 
2157*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2158*4882a593Smuzhiyun 		/*
2159*4882a593Smuzhiyun 		 * Already being enabled.
2160*4882a593Smuzhiyun 		 */
2161*4882a593Smuzhiyun 		break;
2162*4882a593Smuzhiyun 
2163*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2164*4882a593Smuzhiyun 		if (bfa_fcport_send_disable(fcport))
2165*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2166*4882a593Smuzhiyun 		else
2167*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2168*4882a593Smuzhiyun 					 bfa_fcport_sm_disabling_qwait);
2169*4882a593Smuzhiyun 
2170*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2171*4882a593Smuzhiyun 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2172*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2173*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2174*4882a593Smuzhiyun 			"Base port disabled: WWN = %s\n", pwwn_buf);
2175*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2176*4882a593Smuzhiyun 		break;
2177*4882a593Smuzhiyun 
2178*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2179*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2180*4882a593Smuzhiyun 		break;
2181*4882a593Smuzhiyun 
2182*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2183*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2184*4882a593Smuzhiyun 		break;
2185*4882a593Smuzhiyun 
2186*4882a593Smuzhiyun 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2187*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2188*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2189*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2190*4882a593Smuzhiyun 		break;
2191*4882a593Smuzhiyun 
2192*4882a593Smuzhiyun 	default:
2193*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2194*4882a593Smuzhiyun 	}
2195*4882a593Smuzhiyun }
2196*4882a593Smuzhiyun 
2197*4882a593Smuzhiyun static void
bfa_fcport_sm_linkdown(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2198*4882a593Smuzhiyun bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2199*4882a593Smuzhiyun 						enum bfa_fcport_sm_event event)
2200*4882a593Smuzhiyun {
2201*4882a593Smuzhiyun 	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2202*4882a593Smuzhiyun 	char pwwn_buf[BFA_STRING_32];
2203*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2204*4882a593Smuzhiyun 
2205*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2206*4882a593Smuzhiyun 
2207*4882a593Smuzhiyun 	switch (event) {
2208*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKUP:
2209*4882a593Smuzhiyun 		bfa_fcport_update_linkinfo(fcport);
2210*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2211*4882a593Smuzhiyun 		WARN_ON(!fcport->event_cbfn);
2212*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2213*4882a593Smuzhiyun 				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2214*4882a593Smuzhiyun 		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2215*4882a593Smuzhiyun 
2216*4882a593Smuzhiyun 			bfa_trc(fcport->bfa,
2217*4882a593Smuzhiyun 				pevent->link_state.attr.vc_fcf.fcf.fipenabled);
2218*4882a593Smuzhiyun 			bfa_trc(fcport->bfa,
2219*4882a593Smuzhiyun 				pevent->link_state.attr.vc_fcf.fcf.fipfailed);
2220*4882a593Smuzhiyun 
2221*4882a593Smuzhiyun 			if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
2222*4882a593Smuzhiyun 				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2223*4882a593Smuzhiyun 					BFA_PL_EID_FIP_FCF_DISC, 0,
2224*4882a593Smuzhiyun 					"FIP FCF Discovery Failed");
2225*4882a593Smuzhiyun 			else
2226*4882a593Smuzhiyun 				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2227*4882a593Smuzhiyun 					BFA_PL_EID_FIP_FCF_DISC, 0,
2228*4882a593Smuzhiyun 					"FIP FCF Discovered");
2229*4882a593Smuzhiyun 		}
2230*4882a593Smuzhiyun 
2231*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2232*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2233*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2234*4882a593Smuzhiyun 			"Base port online: WWN = %s\n", pwwn_buf);
2235*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
2236*4882a593Smuzhiyun 
2237*4882a593Smuzhiyun 		/* If QoS is enabled and it is not online, send AEN */
2238*4882a593Smuzhiyun 		if (fcport->cfg.qos_enabled &&
2239*4882a593Smuzhiyun 		    fcport->qos_attr.state != BFA_QOS_ONLINE)
2240*4882a593Smuzhiyun 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
2241*4882a593Smuzhiyun 		break;
2242*4882a593Smuzhiyun 
2243*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKDOWN:
2244*4882a593Smuzhiyun 		/*
2245*4882a593Smuzhiyun 		 * Possible to get link down event.
2246*4882a593Smuzhiyun 		 */
2247*4882a593Smuzhiyun 		break;
2248*4882a593Smuzhiyun 
2249*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2250*4882a593Smuzhiyun 		/*
2251*4882a593Smuzhiyun 		 * Already enabled.
2252*4882a593Smuzhiyun 		 */
2253*4882a593Smuzhiyun 		break;
2254*4882a593Smuzhiyun 
2255*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2256*4882a593Smuzhiyun 		if (bfa_fcport_send_disable(fcport))
2257*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2258*4882a593Smuzhiyun 		else
2259*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2260*4882a593Smuzhiyun 					 bfa_fcport_sm_disabling_qwait);
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2263*4882a593Smuzhiyun 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2264*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2265*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2266*4882a593Smuzhiyun 			"Base port disabled: WWN = %s\n", pwwn_buf);
2267*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2268*4882a593Smuzhiyun 		break;
2269*4882a593Smuzhiyun 
2270*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2271*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2272*4882a593Smuzhiyun 		break;
2273*4882a593Smuzhiyun 
2274*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2275*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2276*4882a593Smuzhiyun 		break;
2277*4882a593Smuzhiyun 
2278*4882a593Smuzhiyun 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2279*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2280*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2281*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2282*4882a593Smuzhiyun 		break;
2283*4882a593Smuzhiyun 
2284*4882a593Smuzhiyun 	default:
2285*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2286*4882a593Smuzhiyun 	}
2287*4882a593Smuzhiyun }
2288*4882a593Smuzhiyun 
2289*4882a593Smuzhiyun static void
bfa_fcport_sm_linkup(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2290*4882a593Smuzhiyun bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2291*4882a593Smuzhiyun 	enum bfa_fcport_sm_event event)
2292*4882a593Smuzhiyun {
2293*4882a593Smuzhiyun 	char pwwn_buf[BFA_STRING_32];
2294*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2295*4882a593Smuzhiyun 
2296*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2297*4882a593Smuzhiyun 
2298*4882a593Smuzhiyun 	switch (event) {
2299*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2300*4882a593Smuzhiyun 		/*
2301*4882a593Smuzhiyun 		 * Already enabled.
2302*4882a593Smuzhiyun 		 */
2303*4882a593Smuzhiyun 		break;
2304*4882a593Smuzhiyun 
2305*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2306*4882a593Smuzhiyun 		if (bfa_fcport_send_disable(fcport))
2307*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2308*4882a593Smuzhiyun 		else
2309*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2310*4882a593Smuzhiyun 					 bfa_fcport_sm_disabling_qwait);
2311*4882a593Smuzhiyun 
2312*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2313*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2314*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2315*4882a593Smuzhiyun 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2316*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2317*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2318*4882a593Smuzhiyun 			"Base port offline: WWN = %s\n", pwwn_buf);
2319*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2320*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2321*4882a593Smuzhiyun 			"Base port disabled: WWN = %s\n", pwwn_buf);
2322*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2323*4882a593Smuzhiyun 		break;
2324*4882a593Smuzhiyun 
2325*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKDOWN:
2326*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2327*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2328*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2329*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2330*4882a593Smuzhiyun 				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2331*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2332*4882a593Smuzhiyun 		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2333*4882a593Smuzhiyun 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2334*4882a593Smuzhiyun 				"Base port offline: WWN = %s\n", pwwn_buf);
2335*4882a593Smuzhiyun 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2336*4882a593Smuzhiyun 		} else {
2337*4882a593Smuzhiyun 			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2338*4882a593Smuzhiyun 				"Base port (WWN = %s) "
2339*4882a593Smuzhiyun 				"lost fabric connectivity\n", pwwn_buf);
2340*4882a593Smuzhiyun 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2341*4882a593Smuzhiyun 		}
2342*4882a593Smuzhiyun 		break;
2343*4882a593Smuzhiyun 
2344*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2345*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2346*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2347*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2348*4882a593Smuzhiyun 		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2349*4882a593Smuzhiyun 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2350*4882a593Smuzhiyun 				"Base port offline: WWN = %s\n", pwwn_buf);
2351*4882a593Smuzhiyun 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2352*4882a593Smuzhiyun 		} else {
2353*4882a593Smuzhiyun 			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2354*4882a593Smuzhiyun 				"Base port (WWN = %s) "
2355*4882a593Smuzhiyun 				"lost fabric connectivity\n", pwwn_buf);
2356*4882a593Smuzhiyun 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2357*4882a593Smuzhiyun 		}
2358*4882a593Smuzhiyun 		break;
2359*4882a593Smuzhiyun 
2360*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2361*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2362*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2363*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2364*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2365*4882a593Smuzhiyun 		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2366*4882a593Smuzhiyun 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2367*4882a593Smuzhiyun 				"Base port offline: WWN = %s\n", pwwn_buf);
2368*4882a593Smuzhiyun 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2369*4882a593Smuzhiyun 		} else {
2370*4882a593Smuzhiyun 			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2371*4882a593Smuzhiyun 				"Base port (WWN = %s) "
2372*4882a593Smuzhiyun 				"lost fabric connectivity\n", pwwn_buf);
2373*4882a593Smuzhiyun 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2374*4882a593Smuzhiyun 		}
2375*4882a593Smuzhiyun 		break;
2376*4882a593Smuzhiyun 
2377*4882a593Smuzhiyun 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2378*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2379*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2380*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2381*4882a593Smuzhiyun 		break;
2382*4882a593Smuzhiyun 
2383*4882a593Smuzhiyun 	default:
2384*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2385*4882a593Smuzhiyun 	}
2386*4882a593Smuzhiyun }
2387*4882a593Smuzhiyun 
2388*4882a593Smuzhiyun static void
bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2389*4882a593Smuzhiyun bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2390*4882a593Smuzhiyun 				 enum bfa_fcport_sm_event event)
2391*4882a593Smuzhiyun {
2392*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2393*4882a593Smuzhiyun 
2394*4882a593Smuzhiyun 	switch (event) {
2395*4882a593Smuzhiyun 	case BFA_FCPORT_SM_QRESUME:
2396*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2397*4882a593Smuzhiyun 		bfa_fcport_send_disable(fcport);
2398*4882a593Smuzhiyun 		break;
2399*4882a593Smuzhiyun 
2400*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2401*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2402*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->reqq_wait);
2403*4882a593Smuzhiyun 		break;
2404*4882a593Smuzhiyun 
2405*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2406*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2407*4882a593Smuzhiyun 		break;
2408*4882a593Smuzhiyun 
2409*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2410*4882a593Smuzhiyun 		/*
2411*4882a593Smuzhiyun 		 * Already being disabled.
2412*4882a593Smuzhiyun 		 */
2413*4882a593Smuzhiyun 		break;
2414*4882a593Smuzhiyun 
2415*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKUP:
2416*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKDOWN:
2417*4882a593Smuzhiyun 		/*
2418*4882a593Smuzhiyun 		 * Possible to get link events when doing back-to-back
2419*4882a593Smuzhiyun 		 * enable/disables.
2420*4882a593Smuzhiyun 		 */
2421*4882a593Smuzhiyun 		break;
2422*4882a593Smuzhiyun 
2423*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2424*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2425*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->reqq_wait);
2426*4882a593Smuzhiyun 		break;
2427*4882a593Smuzhiyun 
2428*4882a593Smuzhiyun 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2429*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2430*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2431*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2432*4882a593Smuzhiyun 		break;
2433*4882a593Smuzhiyun 
2434*4882a593Smuzhiyun 	default:
2435*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2436*4882a593Smuzhiyun 	}
2437*4882a593Smuzhiyun }
2438*4882a593Smuzhiyun 
2439*4882a593Smuzhiyun static void
bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2440*4882a593Smuzhiyun bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2441*4882a593Smuzhiyun 				 enum bfa_fcport_sm_event event)
2442*4882a593Smuzhiyun {
2443*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2444*4882a593Smuzhiyun 
2445*4882a593Smuzhiyun 	switch (event) {
2446*4882a593Smuzhiyun 	case BFA_FCPORT_SM_QRESUME:
2447*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2448*4882a593Smuzhiyun 		bfa_fcport_send_disable(fcport);
2449*4882a593Smuzhiyun 		if (bfa_fcport_send_enable(fcport))
2450*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2451*4882a593Smuzhiyun 		else
2452*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2453*4882a593Smuzhiyun 					 bfa_fcport_sm_enabling_qwait);
2454*4882a593Smuzhiyun 		break;
2455*4882a593Smuzhiyun 
2456*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2457*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2458*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->reqq_wait);
2459*4882a593Smuzhiyun 		break;
2460*4882a593Smuzhiyun 
2461*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2462*4882a593Smuzhiyun 		break;
2463*4882a593Smuzhiyun 
2464*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2465*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2466*4882a593Smuzhiyun 		break;
2467*4882a593Smuzhiyun 
2468*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKUP:
2469*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKDOWN:
2470*4882a593Smuzhiyun 		/*
2471*4882a593Smuzhiyun 		 * Possible to get link events when doing back-to-back
2472*4882a593Smuzhiyun 		 * enable/disables.
2473*4882a593Smuzhiyun 		 */
2474*4882a593Smuzhiyun 		break;
2475*4882a593Smuzhiyun 
2476*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2477*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2478*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->reqq_wait);
2479*4882a593Smuzhiyun 		break;
2480*4882a593Smuzhiyun 
2481*4882a593Smuzhiyun 	default:
2482*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2483*4882a593Smuzhiyun 	}
2484*4882a593Smuzhiyun }
2485*4882a593Smuzhiyun 
2486*4882a593Smuzhiyun static void
bfa_fcport_sm_disabling(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2487*4882a593Smuzhiyun bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2488*4882a593Smuzhiyun 						enum bfa_fcport_sm_event event)
2489*4882a593Smuzhiyun {
2490*4882a593Smuzhiyun 	char pwwn_buf[BFA_STRING_32];
2491*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2492*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2493*4882a593Smuzhiyun 
2494*4882a593Smuzhiyun 	switch (event) {
2495*4882a593Smuzhiyun 	case BFA_FCPORT_SM_FWRSP:
2496*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2497*4882a593Smuzhiyun 		break;
2498*4882a593Smuzhiyun 
2499*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2500*4882a593Smuzhiyun 		/*
2501*4882a593Smuzhiyun 		 * Already being disabled.
2502*4882a593Smuzhiyun 		 */
2503*4882a593Smuzhiyun 		break;
2504*4882a593Smuzhiyun 
2505*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2506*4882a593Smuzhiyun 		if (bfa_fcport_send_enable(fcport))
2507*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2508*4882a593Smuzhiyun 		else
2509*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2510*4882a593Smuzhiyun 					 bfa_fcport_sm_enabling_qwait);
2511*4882a593Smuzhiyun 
2512*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2513*4882a593Smuzhiyun 				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2514*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2515*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2516*4882a593Smuzhiyun 			"Base port enabled: WWN = %s\n", pwwn_buf);
2517*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2518*4882a593Smuzhiyun 		break;
2519*4882a593Smuzhiyun 
2520*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2521*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2522*4882a593Smuzhiyun 		break;
2523*4882a593Smuzhiyun 
2524*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKUP:
2525*4882a593Smuzhiyun 	case BFA_FCPORT_SM_LINKDOWN:
2526*4882a593Smuzhiyun 		/*
2527*4882a593Smuzhiyun 		 * Possible to get link events when doing back-to-back
2528*4882a593Smuzhiyun 		 * enable/disables.
2529*4882a593Smuzhiyun 		 */
2530*4882a593Smuzhiyun 		break;
2531*4882a593Smuzhiyun 
2532*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2533*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2534*4882a593Smuzhiyun 		break;
2535*4882a593Smuzhiyun 
2536*4882a593Smuzhiyun 	default:
2537*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2538*4882a593Smuzhiyun 	}
2539*4882a593Smuzhiyun }
2540*4882a593Smuzhiyun 
2541*4882a593Smuzhiyun static void
bfa_fcport_sm_disabled(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2542*4882a593Smuzhiyun bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2543*4882a593Smuzhiyun 						enum bfa_fcport_sm_event event)
2544*4882a593Smuzhiyun {
2545*4882a593Smuzhiyun 	char pwwn_buf[BFA_STRING_32];
2546*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2547*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2548*4882a593Smuzhiyun 
2549*4882a593Smuzhiyun 	switch (event) {
2550*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2551*4882a593Smuzhiyun 		/*
2552*4882a593Smuzhiyun 		 * Ignore start event for a port that is disabled.
2553*4882a593Smuzhiyun 		 */
2554*4882a593Smuzhiyun 		break;
2555*4882a593Smuzhiyun 
2556*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2557*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2558*4882a593Smuzhiyun 		break;
2559*4882a593Smuzhiyun 
2560*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2561*4882a593Smuzhiyun 		if (bfa_fcport_send_enable(fcport))
2562*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2563*4882a593Smuzhiyun 		else
2564*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2565*4882a593Smuzhiyun 					 bfa_fcport_sm_enabling_qwait);
2566*4882a593Smuzhiyun 
2567*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2568*4882a593Smuzhiyun 				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2569*4882a593Smuzhiyun 		wwn2str(pwwn_buf, fcport->pwwn);
2570*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2571*4882a593Smuzhiyun 			"Base port enabled: WWN = %s\n", pwwn_buf);
2572*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2573*4882a593Smuzhiyun 		break;
2574*4882a593Smuzhiyun 
2575*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2576*4882a593Smuzhiyun 		/*
2577*4882a593Smuzhiyun 		 * Already disabled.
2578*4882a593Smuzhiyun 		 */
2579*4882a593Smuzhiyun 		break;
2580*4882a593Smuzhiyun 
2581*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2582*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2583*4882a593Smuzhiyun 		break;
2584*4882a593Smuzhiyun 
2585*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DPORTENABLE:
2586*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
2587*4882a593Smuzhiyun 		break;
2588*4882a593Smuzhiyun 
2589*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DDPORTENABLE:
2590*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
2591*4882a593Smuzhiyun 		break;
2592*4882a593Smuzhiyun 
2593*4882a593Smuzhiyun 	default:
2594*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2595*4882a593Smuzhiyun 	}
2596*4882a593Smuzhiyun }
2597*4882a593Smuzhiyun 
2598*4882a593Smuzhiyun static void
bfa_fcport_sm_stopped(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2599*4882a593Smuzhiyun bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2600*4882a593Smuzhiyun 			 enum bfa_fcport_sm_event event)
2601*4882a593Smuzhiyun {
2602*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2603*4882a593Smuzhiyun 
2604*4882a593Smuzhiyun 	switch (event) {
2605*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2606*4882a593Smuzhiyun 		if (bfa_fcport_send_enable(fcport))
2607*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2608*4882a593Smuzhiyun 		else
2609*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2610*4882a593Smuzhiyun 					 bfa_fcport_sm_enabling_qwait);
2611*4882a593Smuzhiyun 		break;
2612*4882a593Smuzhiyun 
2613*4882a593Smuzhiyun 	default:
2614*4882a593Smuzhiyun 		/*
2615*4882a593Smuzhiyun 		 * Ignore all other events.
2616*4882a593Smuzhiyun 		 */
2617*4882a593Smuzhiyun 		;
2618*4882a593Smuzhiyun 	}
2619*4882a593Smuzhiyun }
2620*4882a593Smuzhiyun 
2621*4882a593Smuzhiyun /*
2622*4882a593Smuzhiyun  * Port is enabled. IOC is down/failed.
2623*4882a593Smuzhiyun  */
2624*4882a593Smuzhiyun static void
bfa_fcport_sm_iocdown(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2625*4882a593Smuzhiyun bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2626*4882a593Smuzhiyun 			 enum bfa_fcport_sm_event event)
2627*4882a593Smuzhiyun {
2628*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2629*4882a593Smuzhiyun 
2630*4882a593Smuzhiyun 	switch (event) {
2631*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2632*4882a593Smuzhiyun 		if (bfa_fcport_send_enable(fcport))
2633*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2634*4882a593Smuzhiyun 		else
2635*4882a593Smuzhiyun 			bfa_sm_set_state(fcport,
2636*4882a593Smuzhiyun 					 bfa_fcport_sm_enabling_qwait);
2637*4882a593Smuzhiyun 		break;
2638*4882a593Smuzhiyun 
2639*4882a593Smuzhiyun 	default:
2640*4882a593Smuzhiyun 		/*
2641*4882a593Smuzhiyun 		 * Ignore all events.
2642*4882a593Smuzhiyun 		 */
2643*4882a593Smuzhiyun 		;
2644*4882a593Smuzhiyun 	}
2645*4882a593Smuzhiyun }
2646*4882a593Smuzhiyun 
2647*4882a593Smuzhiyun /*
2648*4882a593Smuzhiyun  * Port is disabled. IOC is down/failed.
2649*4882a593Smuzhiyun  */
2650*4882a593Smuzhiyun static void
bfa_fcport_sm_iocfail(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2651*4882a593Smuzhiyun bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2652*4882a593Smuzhiyun 			 enum bfa_fcport_sm_event event)
2653*4882a593Smuzhiyun {
2654*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2655*4882a593Smuzhiyun 
2656*4882a593Smuzhiyun 	switch (event) {
2657*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2658*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2659*4882a593Smuzhiyun 		break;
2660*4882a593Smuzhiyun 
2661*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2662*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2663*4882a593Smuzhiyun 		break;
2664*4882a593Smuzhiyun 
2665*4882a593Smuzhiyun 	default:
2666*4882a593Smuzhiyun 		/*
2667*4882a593Smuzhiyun 		 * Ignore all events.
2668*4882a593Smuzhiyun 		 */
2669*4882a593Smuzhiyun 		;
2670*4882a593Smuzhiyun 	}
2671*4882a593Smuzhiyun }
2672*4882a593Smuzhiyun 
2673*4882a593Smuzhiyun static void
bfa_fcport_sm_dport(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2674*4882a593Smuzhiyun bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
2675*4882a593Smuzhiyun {
2676*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2677*4882a593Smuzhiyun 
2678*4882a593Smuzhiyun 	switch (event) {
2679*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DPORTENABLE:
2680*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2681*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2682*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2683*4882a593Smuzhiyun 		/*
2684*4882a593Smuzhiyun 		 * Ignore event for a port that is dport
2685*4882a593Smuzhiyun 		 */
2686*4882a593Smuzhiyun 		break;
2687*4882a593Smuzhiyun 
2688*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2689*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2690*4882a593Smuzhiyun 		break;
2691*4882a593Smuzhiyun 
2692*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2693*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2694*4882a593Smuzhiyun 		break;
2695*4882a593Smuzhiyun 
2696*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DPORTDISABLE:
2697*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2698*4882a593Smuzhiyun 		break;
2699*4882a593Smuzhiyun 
2700*4882a593Smuzhiyun 	default:
2701*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2702*4882a593Smuzhiyun 	}
2703*4882a593Smuzhiyun }
2704*4882a593Smuzhiyun 
2705*4882a593Smuzhiyun static void
bfa_fcport_sm_ddport(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2706*4882a593Smuzhiyun bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
2707*4882a593Smuzhiyun 			enum bfa_fcport_sm_event event)
2708*4882a593Smuzhiyun {
2709*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2710*4882a593Smuzhiyun 
2711*4882a593Smuzhiyun 	switch (event) {
2712*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2713*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DDPORTDISABLE:
2714*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2715*4882a593Smuzhiyun 		break;
2716*4882a593Smuzhiyun 
2717*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DPORTENABLE:
2718*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DPORTDISABLE:
2719*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2720*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2721*4882a593Smuzhiyun 		/*
2722*4882a593Smuzhiyun 		 * Ignore event for a port that is ddport
2723*4882a593Smuzhiyun 		 */
2724*4882a593Smuzhiyun 		break;
2725*4882a593Smuzhiyun 
2726*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2727*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2728*4882a593Smuzhiyun 		break;
2729*4882a593Smuzhiyun 
2730*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2731*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2732*4882a593Smuzhiyun 		break;
2733*4882a593Smuzhiyun 
2734*4882a593Smuzhiyun 	default:
2735*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2736*4882a593Smuzhiyun 	}
2737*4882a593Smuzhiyun }
2738*4882a593Smuzhiyun 
2739*4882a593Smuzhiyun static void
bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s * fcport,enum bfa_fcport_sm_event event)2740*4882a593Smuzhiyun bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
2741*4882a593Smuzhiyun 			    enum bfa_fcport_sm_event event)
2742*4882a593Smuzhiyun {
2743*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, event);
2744*4882a593Smuzhiyun 
2745*4882a593Smuzhiyun 	switch (event) {
2746*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DPORTENABLE:
2747*4882a593Smuzhiyun 	case BFA_FCPORT_SM_ENABLE:
2748*4882a593Smuzhiyun 	case BFA_FCPORT_SM_START:
2749*4882a593Smuzhiyun 		/*
2750*4882a593Smuzhiyun 		 * Ignore event for a port as there is FAA misconfig
2751*4882a593Smuzhiyun 		 */
2752*4882a593Smuzhiyun 		break;
2753*4882a593Smuzhiyun 
2754*4882a593Smuzhiyun 	case BFA_FCPORT_SM_DISABLE:
2755*4882a593Smuzhiyun 		if (bfa_fcport_send_disable(fcport))
2756*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2757*4882a593Smuzhiyun 		else
2758*4882a593Smuzhiyun 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2759*4882a593Smuzhiyun 
2760*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2761*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2762*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2763*4882a593Smuzhiyun 			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2764*4882a593Smuzhiyun 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2765*4882a593Smuzhiyun 		break;
2766*4882a593Smuzhiyun 
2767*4882a593Smuzhiyun 	case BFA_FCPORT_SM_STOP:
2768*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2769*4882a593Smuzhiyun 		break;
2770*4882a593Smuzhiyun 
2771*4882a593Smuzhiyun 	case BFA_FCPORT_SM_HWFAIL:
2772*4882a593Smuzhiyun 		bfa_fcport_reset_linkinfo(fcport);
2773*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2774*4882a593Smuzhiyun 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2775*4882a593Smuzhiyun 		break;
2776*4882a593Smuzhiyun 
2777*4882a593Smuzhiyun 	default:
2778*4882a593Smuzhiyun 		bfa_sm_fault(fcport->bfa, event);
2779*4882a593Smuzhiyun 	}
2780*4882a593Smuzhiyun }
2781*4882a593Smuzhiyun 
2782*4882a593Smuzhiyun /*
2783*4882a593Smuzhiyun  * Link state is down
2784*4882a593Smuzhiyun  */
2785*4882a593Smuzhiyun static void
bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s * ln,enum bfa_fcport_ln_sm_event event)2786*4882a593Smuzhiyun bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2787*4882a593Smuzhiyun 		enum bfa_fcport_ln_sm_event event)
2788*4882a593Smuzhiyun {
2789*4882a593Smuzhiyun 	bfa_trc(ln->fcport->bfa, event);
2790*4882a593Smuzhiyun 
2791*4882a593Smuzhiyun 	switch (event) {
2792*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_LINKUP:
2793*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2794*4882a593Smuzhiyun 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2795*4882a593Smuzhiyun 		break;
2796*4882a593Smuzhiyun 
2797*4882a593Smuzhiyun 	default:
2798*4882a593Smuzhiyun 		bfa_sm_fault(ln->fcport->bfa, event);
2799*4882a593Smuzhiyun 	}
2800*4882a593Smuzhiyun }
2801*4882a593Smuzhiyun 
2802*4882a593Smuzhiyun /*
2803*4882a593Smuzhiyun  * Link state is waiting for down notification
2804*4882a593Smuzhiyun  */
2805*4882a593Smuzhiyun static void
bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s * ln,enum bfa_fcport_ln_sm_event event)2806*4882a593Smuzhiyun bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2807*4882a593Smuzhiyun 		enum bfa_fcport_ln_sm_event event)
2808*4882a593Smuzhiyun {
2809*4882a593Smuzhiyun 	bfa_trc(ln->fcport->bfa, event);
2810*4882a593Smuzhiyun 
2811*4882a593Smuzhiyun 	switch (event) {
2812*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_LINKUP:
2813*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2814*4882a593Smuzhiyun 		break;
2815*4882a593Smuzhiyun 
2816*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2817*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2818*4882a593Smuzhiyun 		break;
2819*4882a593Smuzhiyun 
2820*4882a593Smuzhiyun 	default:
2821*4882a593Smuzhiyun 		bfa_sm_fault(ln->fcport->bfa, event);
2822*4882a593Smuzhiyun 	}
2823*4882a593Smuzhiyun }
2824*4882a593Smuzhiyun 
2825*4882a593Smuzhiyun /*
2826*4882a593Smuzhiyun  * Link state is waiting for down notification and there is a pending up
2827*4882a593Smuzhiyun  */
2828*4882a593Smuzhiyun static void
bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s * ln,enum bfa_fcport_ln_sm_event event)2829*4882a593Smuzhiyun bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
2830*4882a593Smuzhiyun 		enum bfa_fcport_ln_sm_event event)
2831*4882a593Smuzhiyun {
2832*4882a593Smuzhiyun 	bfa_trc(ln->fcport->bfa, event);
2833*4882a593Smuzhiyun 
2834*4882a593Smuzhiyun 	switch (event) {
2835*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_LINKDOWN:
2836*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2837*4882a593Smuzhiyun 		break;
2838*4882a593Smuzhiyun 
2839*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2840*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2841*4882a593Smuzhiyun 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2842*4882a593Smuzhiyun 		break;
2843*4882a593Smuzhiyun 
2844*4882a593Smuzhiyun 	default:
2845*4882a593Smuzhiyun 		bfa_sm_fault(ln->fcport->bfa, event);
2846*4882a593Smuzhiyun 	}
2847*4882a593Smuzhiyun }
2848*4882a593Smuzhiyun 
2849*4882a593Smuzhiyun /*
2850*4882a593Smuzhiyun  * Link state is up
2851*4882a593Smuzhiyun  */
2852*4882a593Smuzhiyun static void
bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s * ln,enum bfa_fcport_ln_sm_event event)2853*4882a593Smuzhiyun bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2854*4882a593Smuzhiyun 		enum bfa_fcport_ln_sm_event event)
2855*4882a593Smuzhiyun {
2856*4882a593Smuzhiyun 	bfa_trc(ln->fcport->bfa, event);
2857*4882a593Smuzhiyun 
2858*4882a593Smuzhiyun 	switch (event) {
2859*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_LINKDOWN:
2860*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2861*4882a593Smuzhiyun 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2862*4882a593Smuzhiyun 		break;
2863*4882a593Smuzhiyun 
2864*4882a593Smuzhiyun 	default:
2865*4882a593Smuzhiyun 		bfa_sm_fault(ln->fcport->bfa, event);
2866*4882a593Smuzhiyun 	}
2867*4882a593Smuzhiyun }
2868*4882a593Smuzhiyun 
2869*4882a593Smuzhiyun /*
2870*4882a593Smuzhiyun  * Link state is waiting for up notification
2871*4882a593Smuzhiyun  */
2872*4882a593Smuzhiyun static void
bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s * ln,enum bfa_fcport_ln_sm_event event)2873*4882a593Smuzhiyun bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2874*4882a593Smuzhiyun 		enum bfa_fcport_ln_sm_event event)
2875*4882a593Smuzhiyun {
2876*4882a593Smuzhiyun 	bfa_trc(ln->fcport->bfa, event);
2877*4882a593Smuzhiyun 
2878*4882a593Smuzhiyun 	switch (event) {
2879*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_LINKDOWN:
2880*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2881*4882a593Smuzhiyun 		break;
2882*4882a593Smuzhiyun 
2883*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2884*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2885*4882a593Smuzhiyun 		break;
2886*4882a593Smuzhiyun 
2887*4882a593Smuzhiyun 	default:
2888*4882a593Smuzhiyun 		bfa_sm_fault(ln->fcport->bfa, event);
2889*4882a593Smuzhiyun 	}
2890*4882a593Smuzhiyun }
2891*4882a593Smuzhiyun 
2892*4882a593Smuzhiyun /*
2893*4882a593Smuzhiyun  * Link state is waiting for up notification and there is a pending down
2894*4882a593Smuzhiyun  */
2895*4882a593Smuzhiyun static void
bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s * ln,enum bfa_fcport_ln_sm_event event)2896*4882a593Smuzhiyun bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
2897*4882a593Smuzhiyun 		enum bfa_fcport_ln_sm_event event)
2898*4882a593Smuzhiyun {
2899*4882a593Smuzhiyun 	bfa_trc(ln->fcport->bfa, event);
2900*4882a593Smuzhiyun 
2901*4882a593Smuzhiyun 	switch (event) {
2902*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_LINKUP:
2903*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2904*4882a593Smuzhiyun 		break;
2905*4882a593Smuzhiyun 
2906*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2907*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2908*4882a593Smuzhiyun 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2909*4882a593Smuzhiyun 		break;
2910*4882a593Smuzhiyun 
2911*4882a593Smuzhiyun 	default:
2912*4882a593Smuzhiyun 		bfa_sm_fault(ln->fcport->bfa, event);
2913*4882a593Smuzhiyun 	}
2914*4882a593Smuzhiyun }
2915*4882a593Smuzhiyun 
2916*4882a593Smuzhiyun /*
2917*4882a593Smuzhiyun  * Link state is waiting for up notification and there are pending down and up
2918*4882a593Smuzhiyun  */
2919*4882a593Smuzhiyun static void
bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s * ln,enum bfa_fcport_ln_sm_event event)2920*4882a593Smuzhiyun bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2921*4882a593Smuzhiyun 			enum bfa_fcport_ln_sm_event event)
2922*4882a593Smuzhiyun {
2923*4882a593Smuzhiyun 	bfa_trc(ln->fcport->bfa, event);
2924*4882a593Smuzhiyun 
2925*4882a593Smuzhiyun 	switch (event) {
2926*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_LINKDOWN:
2927*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2928*4882a593Smuzhiyun 		break;
2929*4882a593Smuzhiyun 
2930*4882a593Smuzhiyun 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2931*4882a593Smuzhiyun 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2932*4882a593Smuzhiyun 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2933*4882a593Smuzhiyun 		break;
2934*4882a593Smuzhiyun 
2935*4882a593Smuzhiyun 	default:
2936*4882a593Smuzhiyun 		bfa_sm_fault(ln->fcport->bfa, event);
2937*4882a593Smuzhiyun 	}
2938*4882a593Smuzhiyun }
2939*4882a593Smuzhiyun 
2940*4882a593Smuzhiyun static void
__bfa_cb_fcport_event(void * cbarg,bfa_boolean_t complete)2941*4882a593Smuzhiyun __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2942*4882a593Smuzhiyun {
2943*4882a593Smuzhiyun 	struct bfa_fcport_ln_s *ln = cbarg;
2944*4882a593Smuzhiyun 
2945*4882a593Smuzhiyun 	if (complete)
2946*4882a593Smuzhiyun 		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2947*4882a593Smuzhiyun 	else
2948*4882a593Smuzhiyun 		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2949*4882a593Smuzhiyun }
2950*4882a593Smuzhiyun 
2951*4882a593Smuzhiyun /*
2952*4882a593Smuzhiyun  * Send SCN notification to upper layers.
2953*4882a593Smuzhiyun  * trunk - false if caller is fcport to ignore fcport event in trunked mode
2954*4882a593Smuzhiyun  */
2955*4882a593Smuzhiyun static void
bfa_fcport_scn(struct bfa_fcport_s * fcport,enum bfa_port_linkstate event,bfa_boolean_t trunk)2956*4882a593Smuzhiyun bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2957*4882a593Smuzhiyun 	bfa_boolean_t trunk)
2958*4882a593Smuzhiyun {
2959*4882a593Smuzhiyun 	if (fcport->cfg.trunked && !trunk)
2960*4882a593Smuzhiyun 		return;
2961*4882a593Smuzhiyun 
2962*4882a593Smuzhiyun 	switch (event) {
2963*4882a593Smuzhiyun 	case BFA_PORT_LINKUP:
2964*4882a593Smuzhiyun 		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2965*4882a593Smuzhiyun 		break;
2966*4882a593Smuzhiyun 	case BFA_PORT_LINKDOWN:
2967*4882a593Smuzhiyun 		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2968*4882a593Smuzhiyun 		break;
2969*4882a593Smuzhiyun 	default:
2970*4882a593Smuzhiyun 		WARN_ON(1);
2971*4882a593Smuzhiyun 	}
2972*4882a593Smuzhiyun }
2973*4882a593Smuzhiyun 
2974*4882a593Smuzhiyun static void
bfa_fcport_queue_cb(struct bfa_fcport_ln_s * ln,enum bfa_port_linkstate event)2975*4882a593Smuzhiyun bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2976*4882a593Smuzhiyun {
2977*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = ln->fcport;
2978*4882a593Smuzhiyun 
2979*4882a593Smuzhiyun 	if (fcport->bfa->fcs) {
2980*4882a593Smuzhiyun 		fcport->event_cbfn(fcport->event_cbarg, event);
2981*4882a593Smuzhiyun 		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2982*4882a593Smuzhiyun 	} else {
2983*4882a593Smuzhiyun 		ln->ln_event = event;
2984*4882a593Smuzhiyun 		bfa_cb_queue(fcport->bfa, &ln->ln_qe,
2985*4882a593Smuzhiyun 			__bfa_cb_fcport_event, ln);
2986*4882a593Smuzhiyun 	}
2987*4882a593Smuzhiyun }
2988*4882a593Smuzhiyun 
2989*4882a593Smuzhiyun #define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
2990*4882a593Smuzhiyun 							BFA_CACHELINE_SZ))
2991*4882a593Smuzhiyun 
2992*4882a593Smuzhiyun void
bfa_fcport_meminfo(struct bfa_iocfc_cfg_s * cfg,struct bfa_meminfo_s * minfo,struct bfa_s * bfa)2993*4882a593Smuzhiyun bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
2994*4882a593Smuzhiyun 		   struct bfa_s *bfa)
2995*4882a593Smuzhiyun {
2996*4882a593Smuzhiyun 	struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
2997*4882a593Smuzhiyun 
2998*4882a593Smuzhiyun 	bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
2999*4882a593Smuzhiyun }
3000*4882a593Smuzhiyun 
3001*4882a593Smuzhiyun static void
bfa_fcport_qresume(void * cbarg)3002*4882a593Smuzhiyun bfa_fcport_qresume(void *cbarg)
3003*4882a593Smuzhiyun {
3004*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = cbarg;
3005*4882a593Smuzhiyun 
3006*4882a593Smuzhiyun 	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
3007*4882a593Smuzhiyun }
3008*4882a593Smuzhiyun 
3009*4882a593Smuzhiyun static void
bfa_fcport_mem_claim(struct bfa_fcport_s * fcport)3010*4882a593Smuzhiyun bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
3011*4882a593Smuzhiyun {
3012*4882a593Smuzhiyun 	struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
3013*4882a593Smuzhiyun 
3014*4882a593Smuzhiyun 	fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
3015*4882a593Smuzhiyun 	fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);
3016*4882a593Smuzhiyun 	fcport->stats = (union bfa_fcport_stats_u *)
3017*4882a593Smuzhiyun 				bfa_mem_dma_virt(fcport_dma);
3018*4882a593Smuzhiyun }
3019*4882a593Smuzhiyun 
3020*4882a593Smuzhiyun /*
3021*4882a593Smuzhiyun  * Memory initialization.
3022*4882a593Smuzhiyun  */
3023*4882a593Smuzhiyun void
bfa_fcport_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)3024*4882a593Smuzhiyun bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
3025*4882a593Smuzhiyun 		struct bfa_pcidev_s *pcidev)
3026*4882a593Smuzhiyun {
3027*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3028*4882a593Smuzhiyun 	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
3029*4882a593Smuzhiyun 	struct bfa_fcport_ln_s *ln = &fcport->ln;
3030*4882a593Smuzhiyun 
3031*4882a593Smuzhiyun 	fcport->bfa = bfa;
3032*4882a593Smuzhiyun 	ln->fcport = fcport;
3033*4882a593Smuzhiyun 
3034*4882a593Smuzhiyun 	bfa_fcport_mem_claim(fcport);
3035*4882a593Smuzhiyun 
3036*4882a593Smuzhiyun 	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
3037*4882a593Smuzhiyun 	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
3038*4882a593Smuzhiyun 
3039*4882a593Smuzhiyun 	/*
3040*4882a593Smuzhiyun 	 * initialize time stamp for stats reset
3041*4882a593Smuzhiyun 	 */
3042*4882a593Smuzhiyun 	fcport->stats_reset_time = ktime_get_seconds();
3043*4882a593Smuzhiyun 	fcport->stats_dma_ready = BFA_FALSE;
3044*4882a593Smuzhiyun 
3045*4882a593Smuzhiyun 	/*
3046*4882a593Smuzhiyun 	 * initialize and set default configuration
3047*4882a593Smuzhiyun 	 */
3048*4882a593Smuzhiyun 	port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
3049*4882a593Smuzhiyun 	port_cfg->speed = BFA_PORT_SPEED_AUTO;
3050*4882a593Smuzhiyun 	port_cfg->trunked = BFA_FALSE;
3051*4882a593Smuzhiyun 	port_cfg->maxfrsize = 0;
3052*4882a593Smuzhiyun 
3053*4882a593Smuzhiyun 	port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
3054*4882a593Smuzhiyun 	port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
3055*4882a593Smuzhiyun 	port_cfg->qos_bw.med = BFA_QOS_BW_MED;
3056*4882a593Smuzhiyun 	port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
3057*4882a593Smuzhiyun 
3058*4882a593Smuzhiyun 	fcport->fec_state = BFA_FEC_OFFLINE;
3059*4882a593Smuzhiyun 
3060*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcport->stats_pending_q);
3061*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3062*4882a593Smuzhiyun 
3063*4882a593Smuzhiyun 	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
3064*4882a593Smuzhiyun }
3065*4882a593Smuzhiyun 
3066*4882a593Smuzhiyun void
bfa_fcport_start(struct bfa_s * bfa)3067*4882a593Smuzhiyun bfa_fcport_start(struct bfa_s *bfa)
3068*4882a593Smuzhiyun {
3069*4882a593Smuzhiyun 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
3070*4882a593Smuzhiyun }
3071*4882a593Smuzhiyun 
3072*4882a593Smuzhiyun /*
3073*4882a593Smuzhiyun  * Called when IOC failure is detected.
3074*4882a593Smuzhiyun  */
3075*4882a593Smuzhiyun void
bfa_fcport_iocdisable(struct bfa_s * bfa)3076*4882a593Smuzhiyun bfa_fcport_iocdisable(struct bfa_s *bfa)
3077*4882a593Smuzhiyun {
3078*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3079*4882a593Smuzhiyun 
3080*4882a593Smuzhiyun 	bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
3081*4882a593Smuzhiyun 	bfa_trunk_iocdisable(bfa);
3082*4882a593Smuzhiyun }
3083*4882a593Smuzhiyun 
3084*4882a593Smuzhiyun /*
3085*4882a593Smuzhiyun  * Update loop info in fcport for SCN online
3086*4882a593Smuzhiyun  */
3087*4882a593Smuzhiyun static void
bfa_fcport_update_loop_info(struct bfa_fcport_s * fcport,struct bfa_fcport_loop_info_s * loop_info)3088*4882a593Smuzhiyun bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
3089*4882a593Smuzhiyun 			struct bfa_fcport_loop_info_s *loop_info)
3090*4882a593Smuzhiyun {
3091*4882a593Smuzhiyun 	fcport->myalpa = loop_info->myalpa;
3092*4882a593Smuzhiyun 	fcport->alpabm_valid =
3093*4882a593Smuzhiyun 			loop_info->alpabm_val;
3094*4882a593Smuzhiyun 	memcpy(fcport->alpabm.alpa_bm,
3095*4882a593Smuzhiyun 			loop_info->alpabm.alpa_bm,
3096*4882a593Smuzhiyun 			sizeof(struct fc_alpabm_s));
3097*4882a593Smuzhiyun }
3098*4882a593Smuzhiyun 
3099*4882a593Smuzhiyun static void
bfa_fcport_update_linkinfo(struct bfa_fcport_s * fcport)3100*4882a593Smuzhiyun bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
3101*4882a593Smuzhiyun {
3102*4882a593Smuzhiyun 	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
3103*4882a593Smuzhiyun 	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3104*4882a593Smuzhiyun 
3105*4882a593Smuzhiyun 	fcport->speed = pevent->link_state.speed;
3106*4882a593Smuzhiyun 	fcport->topology = pevent->link_state.topology;
3107*4882a593Smuzhiyun 
3108*4882a593Smuzhiyun 	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
3109*4882a593Smuzhiyun 		bfa_fcport_update_loop_info(fcport,
3110*4882a593Smuzhiyun 				&pevent->link_state.attr.loop_info);
3111*4882a593Smuzhiyun 		return;
3112*4882a593Smuzhiyun 	}
3113*4882a593Smuzhiyun 
3114*4882a593Smuzhiyun 	/* QoS Details */
3115*4882a593Smuzhiyun 	fcport->qos_attr = pevent->link_state.qos_attr;
3116*4882a593Smuzhiyun 	fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
3117*4882a593Smuzhiyun 
3118*4882a593Smuzhiyun 	if (fcport->cfg.bb_cr_enabled)
3119*4882a593Smuzhiyun 		fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
3120*4882a593Smuzhiyun 
3121*4882a593Smuzhiyun 	fcport->fec_state = pevent->link_state.fec_state;
3122*4882a593Smuzhiyun 
3123*4882a593Smuzhiyun 	/*
3124*4882a593Smuzhiyun 	 * update trunk state if applicable
3125*4882a593Smuzhiyun 	 */
3126*4882a593Smuzhiyun 	if (!fcport->cfg.trunked)
3127*4882a593Smuzhiyun 		trunk->attr.state = BFA_TRUNK_DISABLED;
3128*4882a593Smuzhiyun 
3129*4882a593Smuzhiyun 	/* update FCoE specific */
3130*4882a593Smuzhiyun 	fcport->fcoe_vlan =
3131*4882a593Smuzhiyun 		be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
3132*4882a593Smuzhiyun 
3133*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, fcport->speed);
3134*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, fcport->topology);
3135*4882a593Smuzhiyun }
3136*4882a593Smuzhiyun 
3137*4882a593Smuzhiyun static void
bfa_fcport_reset_linkinfo(struct bfa_fcport_s * fcport)3138*4882a593Smuzhiyun bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
3139*4882a593Smuzhiyun {
3140*4882a593Smuzhiyun 	fcport->speed = BFA_PORT_SPEED_UNKNOWN;
3141*4882a593Smuzhiyun 	fcport->topology = BFA_PORT_TOPOLOGY_NONE;
3142*4882a593Smuzhiyun 	fcport->fec_state = BFA_FEC_OFFLINE;
3143*4882a593Smuzhiyun }
3144*4882a593Smuzhiyun 
3145*4882a593Smuzhiyun /*
3146*4882a593Smuzhiyun  * Send port enable message to firmware.
3147*4882a593Smuzhiyun  */
3148*4882a593Smuzhiyun static bfa_boolean_t
bfa_fcport_send_enable(struct bfa_fcport_s * fcport)3149*4882a593Smuzhiyun bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
3150*4882a593Smuzhiyun {
3151*4882a593Smuzhiyun 	struct bfi_fcport_enable_req_s *m;
3152*4882a593Smuzhiyun 
3153*4882a593Smuzhiyun 	/*
3154*4882a593Smuzhiyun 	 * Increment message tag before queue check, so that responses to old
3155*4882a593Smuzhiyun 	 * requests are discarded.
3156*4882a593Smuzhiyun 	 */
3157*4882a593Smuzhiyun 	fcport->msgtag++;
3158*4882a593Smuzhiyun 
3159*4882a593Smuzhiyun 	/*
3160*4882a593Smuzhiyun 	 * check for room in queue to send request now
3161*4882a593Smuzhiyun 	 */
3162*4882a593Smuzhiyun 	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3163*4882a593Smuzhiyun 	if (!m) {
3164*4882a593Smuzhiyun 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3165*4882a593Smuzhiyun 							&fcport->reqq_wait);
3166*4882a593Smuzhiyun 		return BFA_FALSE;
3167*4882a593Smuzhiyun 	}
3168*4882a593Smuzhiyun 
3169*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
3170*4882a593Smuzhiyun 			bfa_fn_lpu(fcport->bfa));
3171*4882a593Smuzhiyun 	m->nwwn = fcport->nwwn;
3172*4882a593Smuzhiyun 	m->pwwn = fcport->pwwn;
3173*4882a593Smuzhiyun 	m->port_cfg = fcport->cfg;
3174*4882a593Smuzhiyun 	m->msgtag = fcport->msgtag;
3175*4882a593Smuzhiyun 	m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
3176*4882a593Smuzhiyun 	 m->use_flash_cfg = fcport->use_flash_cfg;
3177*4882a593Smuzhiyun 	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
3178*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
3179*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
3180*4882a593Smuzhiyun 
3181*4882a593Smuzhiyun 	/*
3182*4882a593Smuzhiyun 	 * queue I/O message to firmware
3183*4882a593Smuzhiyun 	 */
3184*4882a593Smuzhiyun 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3185*4882a593Smuzhiyun 	return BFA_TRUE;
3186*4882a593Smuzhiyun }
3187*4882a593Smuzhiyun 
3188*4882a593Smuzhiyun /*
3189*4882a593Smuzhiyun  * Send port disable message to firmware.
3190*4882a593Smuzhiyun  */
3191*4882a593Smuzhiyun static	bfa_boolean_t
bfa_fcport_send_disable(struct bfa_fcport_s * fcport)3192*4882a593Smuzhiyun bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
3193*4882a593Smuzhiyun {
3194*4882a593Smuzhiyun 	struct bfi_fcport_req_s *m;
3195*4882a593Smuzhiyun 
3196*4882a593Smuzhiyun 	/*
3197*4882a593Smuzhiyun 	 * Increment message tag before queue check, so that responses to old
3198*4882a593Smuzhiyun 	 * requests are discarded.
3199*4882a593Smuzhiyun 	 */
3200*4882a593Smuzhiyun 	fcport->msgtag++;
3201*4882a593Smuzhiyun 
3202*4882a593Smuzhiyun 	/*
3203*4882a593Smuzhiyun 	 * check for room in queue to send request now
3204*4882a593Smuzhiyun 	 */
3205*4882a593Smuzhiyun 	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3206*4882a593Smuzhiyun 	if (!m) {
3207*4882a593Smuzhiyun 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3208*4882a593Smuzhiyun 							&fcport->reqq_wait);
3209*4882a593Smuzhiyun 		return BFA_FALSE;
3210*4882a593Smuzhiyun 	}
3211*4882a593Smuzhiyun 
3212*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
3213*4882a593Smuzhiyun 			bfa_fn_lpu(fcport->bfa));
3214*4882a593Smuzhiyun 	m->msgtag = fcport->msgtag;
3215*4882a593Smuzhiyun 
3216*4882a593Smuzhiyun 	/*
3217*4882a593Smuzhiyun 	 * queue I/O message to firmware
3218*4882a593Smuzhiyun 	 */
3219*4882a593Smuzhiyun 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3220*4882a593Smuzhiyun 
3221*4882a593Smuzhiyun 	return BFA_TRUE;
3222*4882a593Smuzhiyun }
3223*4882a593Smuzhiyun 
3224*4882a593Smuzhiyun static void
bfa_fcport_set_wwns(struct bfa_fcport_s * fcport)3225*4882a593Smuzhiyun bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3226*4882a593Smuzhiyun {
3227*4882a593Smuzhiyun 	fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3228*4882a593Smuzhiyun 	fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
3229*4882a593Smuzhiyun 
3230*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, fcport->pwwn);
3231*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, fcport->nwwn);
3232*4882a593Smuzhiyun }
3233*4882a593Smuzhiyun 
3234*4882a593Smuzhiyun static void
bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s * d,struct bfa_qos_stats_s * s)3235*4882a593Smuzhiyun bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3236*4882a593Smuzhiyun 	struct bfa_qos_stats_s *s)
3237*4882a593Smuzhiyun {
3238*4882a593Smuzhiyun 	u32	*dip = (u32 *) d;
3239*4882a593Smuzhiyun 	__be32	*sip = (__be32 *) s;
3240*4882a593Smuzhiyun 	int		i;
3241*4882a593Smuzhiyun 
3242*4882a593Smuzhiyun 	/* Now swap the 32 bit fields */
3243*4882a593Smuzhiyun 	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
3244*4882a593Smuzhiyun 		dip[i] = be32_to_cpu(sip[i]);
3245*4882a593Smuzhiyun }
3246*4882a593Smuzhiyun 
3247*4882a593Smuzhiyun static void
bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s * d,struct bfa_fcoe_stats_s * s)3248*4882a593Smuzhiyun bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3249*4882a593Smuzhiyun 	struct bfa_fcoe_stats_s *s)
3250*4882a593Smuzhiyun {
3251*4882a593Smuzhiyun 	u32	*dip = (u32 *) d;
3252*4882a593Smuzhiyun 	__be32	*sip = (__be32 *) s;
3253*4882a593Smuzhiyun 	int		i;
3254*4882a593Smuzhiyun 
3255*4882a593Smuzhiyun 	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3256*4882a593Smuzhiyun 	     i = i + 2) {
3257*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
3258*4882a593Smuzhiyun 		dip[i] = be32_to_cpu(sip[i]);
3259*4882a593Smuzhiyun 		dip[i + 1] = be32_to_cpu(sip[i + 1]);
3260*4882a593Smuzhiyun #else
3261*4882a593Smuzhiyun 		dip[i] = be32_to_cpu(sip[i + 1]);
3262*4882a593Smuzhiyun 		dip[i + 1] = be32_to_cpu(sip[i]);
3263*4882a593Smuzhiyun #endif
3264*4882a593Smuzhiyun 	}
3265*4882a593Smuzhiyun }
3266*4882a593Smuzhiyun 
3267*4882a593Smuzhiyun static void
__bfa_cb_fcport_stats_get(void * cbarg,bfa_boolean_t complete)3268*4882a593Smuzhiyun __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3269*4882a593Smuzhiyun {
3270*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
3271*4882a593Smuzhiyun 	struct bfa_cb_pending_q_s *cb;
3272*4882a593Smuzhiyun 	struct list_head *qe, *qen;
3273*4882a593Smuzhiyun 	union bfa_fcport_stats_u *ret;
3274*4882a593Smuzhiyun 
3275*4882a593Smuzhiyun 	if (complete) {
3276*4882a593Smuzhiyun 		time64_t time = ktime_get_seconds();
3277*4882a593Smuzhiyun 
3278*4882a593Smuzhiyun 		list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
3279*4882a593Smuzhiyun 			bfa_q_deq(&fcport->stats_pending_q, &qe);
3280*4882a593Smuzhiyun 			cb = (struct bfa_cb_pending_q_s *)qe;
3281*4882a593Smuzhiyun 			if (fcport->stats_status == BFA_STATUS_OK) {
3282*4882a593Smuzhiyun 				ret = (union bfa_fcport_stats_u *)cb->data;
3283*4882a593Smuzhiyun 				/* Swap FC QoS or FCoE stats */
3284*4882a593Smuzhiyun 				if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
3285*4882a593Smuzhiyun 					bfa_fcport_qos_stats_swap(&ret->fcqos,
3286*4882a593Smuzhiyun 							&fcport->stats->fcqos);
3287*4882a593Smuzhiyun 				else {
3288*4882a593Smuzhiyun 					bfa_fcport_fcoe_stats_swap(&ret->fcoe,
3289*4882a593Smuzhiyun 							&fcport->stats->fcoe);
3290*4882a593Smuzhiyun 					ret->fcoe.secs_reset =
3291*4882a593Smuzhiyun 						time - fcport->stats_reset_time;
3292*4882a593Smuzhiyun 				}
3293*4882a593Smuzhiyun 			}
3294*4882a593Smuzhiyun 			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3295*4882a593Smuzhiyun 					fcport->stats_status);
3296*4882a593Smuzhiyun 		}
3297*4882a593Smuzhiyun 		fcport->stats_status = BFA_STATUS_OK;
3298*4882a593Smuzhiyun 	} else {
3299*4882a593Smuzhiyun 		INIT_LIST_HEAD(&fcport->stats_pending_q);
3300*4882a593Smuzhiyun 		fcport->stats_status = BFA_STATUS_OK;
3301*4882a593Smuzhiyun 	}
3302*4882a593Smuzhiyun }
3303*4882a593Smuzhiyun 
3304*4882a593Smuzhiyun static void
bfa_fcport_stats_get_timeout(void * cbarg)3305*4882a593Smuzhiyun bfa_fcport_stats_get_timeout(void *cbarg)
3306*4882a593Smuzhiyun {
3307*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3308*4882a593Smuzhiyun 
3309*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, fcport->stats_qfull);
3310*4882a593Smuzhiyun 
3311*4882a593Smuzhiyun 	if (fcport->stats_qfull) {
3312*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3313*4882a593Smuzhiyun 		fcport->stats_qfull = BFA_FALSE;
3314*4882a593Smuzhiyun 	}
3315*4882a593Smuzhiyun 
3316*4882a593Smuzhiyun 	fcport->stats_status = BFA_STATUS_ETIMER;
3317*4882a593Smuzhiyun 	__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3318*4882a593Smuzhiyun }
3319*4882a593Smuzhiyun 
3320*4882a593Smuzhiyun static void
bfa_fcport_send_stats_get(void * cbarg)3321*4882a593Smuzhiyun bfa_fcport_send_stats_get(void *cbarg)
3322*4882a593Smuzhiyun {
3323*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3324*4882a593Smuzhiyun 	struct bfi_fcport_req_s *msg;
3325*4882a593Smuzhiyun 
3326*4882a593Smuzhiyun 	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3327*4882a593Smuzhiyun 
3328*4882a593Smuzhiyun 	if (!msg) {
3329*4882a593Smuzhiyun 		fcport->stats_qfull = BFA_TRUE;
3330*4882a593Smuzhiyun 		bfa_reqq_winit(&fcport->stats_reqq_wait,
3331*4882a593Smuzhiyun 				bfa_fcport_send_stats_get, fcport);
3332*4882a593Smuzhiyun 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3333*4882a593Smuzhiyun 				&fcport->stats_reqq_wait);
3334*4882a593Smuzhiyun 		return;
3335*4882a593Smuzhiyun 	}
3336*4882a593Smuzhiyun 	fcport->stats_qfull = BFA_FALSE;
3337*4882a593Smuzhiyun 
3338*4882a593Smuzhiyun 	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3339*4882a593Smuzhiyun 	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
3340*4882a593Smuzhiyun 			bfa_fn_lpu(fcport->bfa));
3341*4882a593Smuzhiyun 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3342*4882a593Smuzhiyun }
3343*4882a593Smuzhiyun 
3344*4882a593Smuzhiyun static void
__bfa_cb_fcport_stats_clr(void * cbarg,bfa_boolean_t complete)3345*4882a593Smuzhiyun __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3346*4882a593Smuzhiyun {
3347*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3348*4882a593Smuzhiyun 	struct bfa_cb_pending_q_s *cb;
3349*4882a593Smuzhiyun 	struct list_head *qe, *qen;
3350*4882a593Smuzhiyun 
3351*4882a593Smuzhiyun 	if (complete) {
3352*4882a593Smuzhiyun 		/*
3353*4882a593Smuzhiyun 		 * re-initialize time stamp for stats reset
3354*4882a593Smuzhiyun 		 */
3355*4882a593Smuzhiyun 		fcport->stats_reset_time = ktime_get_seconds();
3356*4882a593Smuzhiyun 		list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
3357*4882a593Smuzhiyun 			bfa_q_deq(&fcport->statsclr_pending_q, &qe);
3358*4882a593Smuzhiyun 			cb = (struct bfa_cb_pending_q_s *)qe;
3359*4882a593Smuzhiyun 			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3360*4882a593Smuzhiyun 						fcport->stats_status);
3361*4882a593Smuzhiyun 		}
3362*4882a593Smuzhiyun 		fcport->stats_status = BFA_STATUS_OK;
3363*4882a593Smuzhiyun 	} else {
3364*4882a593Smuzhiyun 		INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3365*4882a593Smuzhiyun 		fcport->stats_status = BFA_STATUS_OK;
3366*4882a593Smuzhiyun 	}
3367*4882a593Smuzhiyun }
3368*4882a593Smuzhiyun 
3369*4882a593Smuzhiyun static void
bfa_fcport_stats_clr_timeout(void * cbarg)3370*4882a593Smuzhiyun bfa_fcport_stats_clr_timeout(void *cbarg)
3371*4882a593Smuzhiyun {
3372*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3373*4882a593Smuzhiyun 
3374*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, fcport->stats_qfull);
3375*4882a593Smuzhiyun 
3376*4882a593Smuzhiyun 	if (fcport->stats_qfull) {
3377*4882a593Smuzhiyun 		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3378*4882a593Smuzhiyun 		fcport->stats_qfull = BFA_FALSE;
3379*4882a593Smuzhiyun 	}
3380*4882a593Smuzhiyun 
3381*4882a593Smuzhiyun 	fcport->stats_status = BFA_STATUS_ETIMER;
3382*4882a593Smuzhiyun 	__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3383*4882a593Smuzhiyun }
3384*4882a593Smuzhiyun 
3385*4882a593Smuzhiyun static void
bfa_fcport_send_stats_clear(void * cbarg)3386*4882a593Smuzhiyun bfa_fcport_send_stats_clear(void *cbarg)
3387*4882a593Smuzhiyun {
3388*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3389*4882a593Smuzhiyun 	struct bfi_fcport_req_s *msg;
3390*4882a593Smuzhiyun 
3391*4882a593Smuzhiyun 	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3392*4882a593Smuzhiyun 
3393*4882a593Smuzhiyun 	if (!msg) {
3394*4882a593Smuzhiyun 		fcport->stats_qfull = BFA_TRUE;
3395*4882a593Smuzhiyun 		bfa_reqq_winit(&fcport->stats_reqq_wait,
3396*4882a593Smuzhiyun 				bfa_fcport_send_stats_clear, fcport);
3397*4882a593Smuzhiyun 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3398*4882a593Smuzhiyun 						&fcport->stats_reqq_wait);
3399*4882a593Smuzhiyun 		return;
3400*4882a593Smuzhiyun 	}
3401*4882a593Smuzhiyun 	fcport->stats_qfull = BFA_FALSE;
3402*4882a593Smuzhiyun 
3403*4882a593Smuzhiyun 	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3404*4882a593Smuzhiyun 	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
3405*4882a593Smuzhiyun 			bfa_fn_lpu(fcport->bfa));
3406*4882a593Smuzhiyun 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3407*4882a593Smuzhiyun }
3408*4882a593Smuzhiyun 
3409*4882a593Smuzhiyun /*
3410*4882a593Smuzhiyun  * Handle trunk SCN event from firmware.
3411*4882a593Smuzhiyun  */
3412*4882a593Smuzhiyun static void
bfa_trunk_scn(struct bfa_fcport_s * fcport,struct bfi_fcport_trunk_scn_s * scn)3413*4882a593Smuzhiyun bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3414*4882a593Smuzhiyun {
3415*4882a593Smuzhiyun 	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3416*4882a593Smuzhiyun 	struct bfi_fcport_trunk_link_s *tlink;
3417*4882a593Smuzhiyun 	struct bfa_trunk_link_attr_s *lattr;
3418*4882a593Smuzhiyun 	enum bfa_trunk_state state_prev;
3419*4882a593Smuzhiyun 	int i;
3420*4882a593Smuzhiyun 	int link_bm = 0;
3421*4882a593Smuzhiyun 
3422*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, fcport->cfg.trunked);
3423*4882a593Smuzhiyun 	WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3424*4882a593Smuzhiyun 		   scn->trunk_state != BFA_TRUNK_OFFLINE);
3425*4882a593Smuzhiyun 
3426*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, trunk->attr.state);
3427*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, scn->trunk_state);
3428*4882a593Smuzhiyun 	bfa_trc(fcport->bfa, scn->trunk_speed);
3429*4882a593Smuzhiyun 
3430*4882a593Smuzhiyun 	/*
3431*4882a593Smuzhiyun 	 * Save off new state for trunk attribute query
3432*4882a593Smuzhiyun 	 */
3433*4882a593Smuzhiyun 	state_prev = trunk->attr.state;
3434*4882a593Smuzhiyun 	if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3435*4882a593Smuzhiyun 		trunk->attr.state = scn->trunk_state;
3436*4882a593Smuzhiyun 	trunk->attr.speed = scn->trunk_speed;
3437*4882a593Smuzhiyun 	for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3438*4882a593Smuzhiyun 		lattr = &trunk->attr.link_attr[i];
3439*4882a593Smuzhiyun 		tlink = &scn->tlink[i];
3440*4882a593Smuzhiyun 
3441*4882a593Smuzhiyun 		lattr->link_state = tlink->state;
3442*4882a593Smuzhiyun 		lattr->trunk_wwn  = tlink->trunk_wwn;
3443*4882a593Smuzhiyun 		lattr->fctl	  = tlink->fctl;
3444*4882a593Smuzhiyun 		lattr->speed	  = tlink->speed;
3445*4882a593Smuzhiyun 		lattr->deskew	  = be32_to_cpu(tlink->deskew);
3446*4882a593Smuzhiyun 
3447*4882a593Smuzhiyun 		if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3448*4882a593Smuzhiyun 			fcport->speed	 = tlink->speed;
3449*4882a593Smuzhiyun 			fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3450*4882a593Smuzhiyun 			link_bm |= 1 << i;
3451*4882a593Smuzhiyun 		}
3452*4882a593Smuzhiyun 
3453*4882a593Smuzhiyun 		bfa_trc(fcport->bfa, lattr->link_state);
3454*4882a593Smuzhiyun 		bfa_trc(fcport->bfa, lattr->trunk_wwn);
3455*4882a593Smuzhiyun 		bfa_trc(fcport->bfa, lattr->fctl);
3456*4882a593Smuzhiyun 		bfa_trc(fcport->bfa, lattr->speed);
3457*4882a593Smuzhiyun 		bfa_trc(fcport->bfa, lattr->deskew);
3458*4882a593Smuzhiyun 	}
3459*4882a593Smuzhiyun 
3460*4882a593Smuzhiyun 	switch (link_bm) {
3461*4882a593Smuzhiyun 	case 3:
3462*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3463*4882a593Smuzhiyun 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3464*4882a593Smuzhiyun 		break;
3465*4882a593Smuzhiyun 	case 2:
3466*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3467*4882a593Smuzhiyun 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3468*4882a593Smuzhiyun 		break;
3469*4882a593Smuzhiyun 	case 1:
3470*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3471*4882a593Smuzhiyun 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3472*4882a593Smuzhiyun 		break;
3473*4882a593Smuzhiyun 	default:
3474*4882a593Smuzhiyun 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3475*4882a593Smuzhiyun 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3476*4882a593Smuzhiyun 	}
3477*4882a593Smuzhiyun 
3478*4882a593Smuzhiyun 	/*
3479*4882a593Smuzhiyun 	 * Notify upper layers if trunk state changed.
3480*4882a593Smuzhiyun 	 */
3481*4882a593Smuzhiyun 	if ((state_prev != trunk->attr.state) ||
3482*4882a593Smuzhiyun 		(scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3483*4882a593Smuzhiyun 		bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3484*4882a593Smuzhiyun 			BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3485*4882a593Smuzhiyun 	}
3486*4882a593Smuzhiyun }
3487*4882a593Smuzhiyun 
3488*4882a593Smuzhiyun static void
bfa_trunk_iocdisable(struct bfa_s * bfa)3489*4882a593Smuzhiyun bfa_trunk_iocdisable(struct bfa_s *bfa)
3490*4882a593Smuzhiyun {
3491*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3492*4882a593Smuzhiyun 	int i = 0;
3493*4882a593Smuzhiyun 
3494*4882a593Smuzhiyun 	/*
3495*4882a593Smuzhiyun 	 * In trunked mode, notify upper layers that link is down
3496*4882a593Smuzhiyun 	 */
3497*4882a593Smuzhiyun 	if (fcport->cfg.trunked) {
3498*4882a593Smuzhiyun 		if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3499*4882a593Smuzhiyun 			bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3500*4882a593Smuzhiyun 
3501*4882a593Smuzhiyun 		fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3502*4882a593Smuzhiyun 		fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3503*4882a593Smuzhiyun 		for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3504*4882a593Smuzhiyun 			fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3505*4882a593Smuzhiyun 			fcport->trunk.attr.link_attr[i].fctl =
3506*4882a593Smuzhiyun 						BFA_TRUNK_LINK_FCTL_NORMAL;
3507*4882a593Smuzhiyun 			fcport->trunk.attr.link_attr[i].link_state =
3508*4882a593Smuzhiyun 						BFA_TRUNK_LINK_STATE_DN_LINKDN;
3509*4882a593Smuzhiyun 			fcport->trunk.attr.link_attr[i].speed =
3510*4882a593Smuzhiyun 						BFA_PORT_SPEED_UNKNOWN;
3511*4882a593Smuzhiyun 			fcport->trunk.attr.link_attr[i].deskew = 0;
3512*4882a593Smuzhiyun 		}
3513*4882a593Smuzhiyun 	}
3514*4882a593Smuzhiyun }
3515*4882a593Smuzhiyun 
3516*4882a593Smuzhiyun /*
3517*4882a593Smuzhiyun  * Called to initialize port attributes
3518*4882a593Smuzhiyun  */
3519*4882a593Smuzhiyun void
bfa_fcport_init(struct bfa_s * bfa)3520*4882a593Smuzhiyun bfa_fcport_init(struct bfa_s *bfa)
3521*4882a593Smuzhiyun {
3522*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3523*4882a593Smuzhiyun 
3524*4882a593Smuzhiyun 	/*
3525*4882a593Smuzhiyun 	 * Initialize port attributes from IOC hardware data.
3526*4882a593Smuzhiyun 	 */
3527*4882a593Smuzhiyun 	bfa_fcport_set_wwns(fcport);
3528*4882a593Smuzhiyun 	if (fcport->cfg.maxfrsize == 0)
3529*4882a593Smuzhiyun 		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3530*4882a593Smuzhiyun 	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3531*4882a593Smuzhiyun 	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3532*4882a593Smuzhiyun 
3533*4882a593Smuzhiyun 	if (bfa_fcport_is_pbcdisabled(bfa))
3534*4882a593Smuzhiyun 		bfa->modules.port.pbc_disabled = BFA_TRUE;
3535*4882a593Smuzhiyun 
3536*4882a593Smuzhiyun 	WARN_ON(!fcport->cfg.maxfrsize);
3537*4882a593Smuzhiyun 	WARN_ON(!fcport->cfg.rx_bbcredit);
3538*4882a593Smuzhiyun 	WARN_ON(!fcport->speed_sup);
3539*4882a593Smuzhiyun }
3540*4882a593Smuzhiyun 
3541*4882a593Smuzhiyun /*
3542*4882a593Smuzhiyun  * Firmware message handler.
3543*4882a593Smuzhiyun  */
3544*4882a593Smuzhiyun void
bfa_fcport_isr(struct bfa_s * bfa,struct bfi_msg_s * msg)3545*4882a593Smuzhiyun bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3546*4882a593Smuzhiyun {
3547*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3548*4882a593Smuzhiyun 	union bfi_fcport_i2h_msg_u i2hmsg;
3549*4882a593Smuzhiyun 
3550*4882a593Smuzhiyun 	i2hmsg.msg = msg;
3551*4882a593Smuzhiyun 	fcport->event_arg.i2hmsg = i2hmsg;
3552*4882a593Smuzhiyun 
3553*4882a593Smuzhiyun 	bfa_trc(bfa, msg->mhdr.msg_id);
3554*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
3555*4882a593Smuzhiyun 
3556*4882a593Smuzhiyun 	switch (msg->mhdr.msg_id) {
3557*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_ENABLE_RSP:
3558*4882a593Smuzhiyun 		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3559*4882a593Smuzhiyun 
3560*4882a593Smuzhiyun 			fcport->stats_dma_ready = BFA_TRUE;
3561*4882a593Smuzhiyun 			if (fcport->use_flash_cfg) {
3562*4882a593Smuzhiyun 				fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3563*4882a593Smuzhiyun 				fcport->cfg.maxfrsize =
3564*4882a593Smuzhiyun 					cpu_to_be16(fcport->cfg.maxfrsize);
3565*4882a593Smuzhiyun 				fcport->cfg.path_tov =
3566*4882a593Smuzhiyun 					cpu_to_be16(fcport->cfg.path_tov);
3567*4882a593Smuzhiyun 				fcport->cfg.q_depth =
3568*4882a593Smuzhiyun 					cpu_to_be16(fcport->cfg.q_depth);
3569*4882a593Smuzhiyun 
3570*4882a593Smuzhiyun 				if (fcport->cfg.trunked)
3571*4882a593Smuzhiyun 					fcport->trunk.attr.state =
3572*4882a593Smuzhiyun 						BFA_TRUNK_OFFLINE;
3573*4882a593Smuzhiyun 				else
3574*4882a593Smuzhiyun 					fcport->trunk.attr.state =
3575*4882a593Smuzhiyun 						BFA_TRUNK_DISABLED;
3576*4882a593Smuzhiyun 				fcport->qos_attr.qos_bw =
3577*4882a593Smuzhiyun 					i2hmsg.penable_rsp->port_cfg.qos_bw;
3578*4882a593Smuzhiyun 				fcport->use_flash_cfg = BFA_FALSE;
3579*4882a593Smuzhiyun 			}
3580*4882a593Smuzhiyun 
3581*4882a593Smuzhiyun 			if (fcport->cfg.qos_enabled)
3582*4882a593Smuzhiyun 				fcport->qos_attr.state = BFA_QOS_OFFLINE;
3583*4882a593Smuzhiyun 			else
3584*4882a593Smuzhiyun 				fcport->qos_attr.state = BFA_QOS_DISABLED;
3585*4882a593Smuzhiyun 
3586*4882a593Smuzhiyun 			fcport->qos_attr.qos_bw_op =
3587*4882a593Smuzhiyun 					i2hmsg.penable_rsp->port_cfg.qos_bw;
3588*4882a593Smuzhiyun 
3589*4882a593Smuzhiyun 			if (fcport->cfg.bb_cr_enabled)
3590*4882a593Smuzhiyun 				fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3591*4882a593Smuzhiyun 			else
3592*4882a593Smuzhiyun 				fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3593*4882a593Smuzhiyun 
3594*4882a593Smuzhiyun 			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3595*4882a593Smuzhiyun 		}
3596*4882a593Smuzhiyun 		break;
3597*4882a593Smuzhiyun 
3598*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_DISABLE_RSP:
3599*4882a593Smuzhiyun 		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3600*4882a593Smuzhiyun 			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3601*4882a593Smuzhiyun 		break;
3602*4882a593Smuzhiyun 
3603*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_EVENT:
3604*4882a593Smuzhiyun 		if (fcport->cfg.bb_cr_enabled)
3605*4882a593Smuzhiyun 			fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3606*4882a593Smuzhiyun 		else
3607*4882a593Smuzhiyun 			fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3608*4882a593Smuzhiyun 
3609*4882a593Smuzhiyun 		if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3610*4882a593Smuzhiyun 			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3611*4882a593Smuzhiyun 		else {
3612*4882a593Smuzhiyun 			if (i2hmsg.event->link_state.linkstate_rsn ==
3613*4882a593Smuzhiyun 			    BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
3614*4882a593Smuzhiyun 				bfa_sm_send_event(fcport,
3615*4882a593Smuzhiyun 						  BFA_FCPORT_SM_FAA_MISCONFIG);
3616*4882a593Smuzhiyun 			else
3617*4882a593Smuzhiyun 				bfa_sm_send_event(fcport,
3618*4882a593Smuzhiyun 						  BFA_FCPORT_SM_LINKDOWN);
3619*4882a593Smuzhiyun 		}
3620*4882a593Smuzhiyun 		fcport->qos_attr.qos_bw_op =
3621*4882a593Smuzhiyun 				i2hmsg.event->link_state.qos_attr.qos_bw_op;
3622*4882a593Smuzhiyun 		break;
3623*4882a593Smuzhiyun 
3624*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_TRUNK_SCN:
3625*4882a593Smuzhiyun 		bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3626*4882a593Smuzhiyun 		break;
3627*4882a593Smuzhiyun 
3628*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_STATS_GET_RSP:
3629*4882a593Smuzhiyun 		/*
3630*4882a593Smuzhiyun 		 * check for timer pop before processing the rsp
3631*4882a593Smuzhiyun 		 */
3632*4882a593Smuzhiyun 		if (list_empty(&fcport->stats_pending_q) ||
3633*4882a593Smuzhiyun 		    (fcport->stats_status == BFA_STATUS_ETIMER))
3634*4882a593Smuzhiyun 			break;
3635*4882a593Smuzhiyun 
3636*4882a593Smuzhiyun 		bfa_timer_stop(&fcport->timer);
3637*4882a593Smuzhiyun 		fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3638*4882a593Smuzhiyun 		__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3639*4882a593Smuzhiyun 		break;
3640*4882a593Smuzhiyun 
3641*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3642*4882a593Smuzhiyun 		/*
3643*4882a593Smuzhiyun 		 * check for timer pop before processing the rsp
3644*4882a593Smuzhiyun 		 */
3645*4882a593Smuzhiyun 		if (list_empty(&fcport->statsclr_pending_q) ||
3646*4882a593Smuzhiyun 		    (fcport->stats_status == BFA_STATUS_ETIMER))
3647*4882a593Smuzhiyun 			break;
3648*4882a593Smuzhiyun 
3649*4882a593Smuzhiyun 		bfa_timer_stop(&fcport->timer);
3650*4882a593Smuzhiyun 		fcport->stats_status = BFA_STATUS_OK;
3651*4882a593Smuzhiyun 		__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3652*4882a593Smuzhiyun 		break;
3653*4882a593Smuzhiyun 
3654*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_ENABLE_AEN:
3655*4882a593Smuzhiyun 		bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3656*4882a593Smuzhiyun 		break;
3657*4882a593Smuzhiyun 
3658*4882a593Smuzhiyun 	case BFI_FCPORT_I2H_DISABLE_AEN:
3659*4882a593Smuzhiyun 		bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3660*4882a593Smuzhiyun 		break;
3661*4882a593Smuzhiyun 
3662*4882a593Smuzhiyun 	default:
3663*4882a593Smuzhiyun 		WARN_ON(1);
3664*4882a593Smuzhiyun 	break;
3665*4882a593Smuzhiyun 	}
3666*4882a593Smuzhiyun }
3667*4882a593Smuzhiyun 
3668*4882a593Smuzhiyun /*
3669*4882a593Smuzhiyun  * Registered callback for port events.
3670*4882a593Smuzhiyun  */
3671*4882a593Smuzhiyun void
bfa_fcport_event_register(struct bfa_s * bfa,void (* cbfn)(void * cbarg,enum bfa_port_linkstate event),void * cbarg)3672*4882a593Smuzhiyun bfa_fcport_event_register(struct bfa_s *bfa,
3673*4882a593Smuzhiyun 				void (*cbfn) (void *cbarg,
3674*4882a593Smuzhiyun 				enum bfa_port_linkstate event),
3675*4882a593Smuzhiyun 				void *cbarg)
3676*4882a593Smuzhiyun {
3677*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3678*4882a593Smuzhiyun 
3679*4882a593Smuzhiyun 	fcport->event_cbfn = cbfn;
3680*4882a593Smuzhiyun 	fcport->event_cbarg = cbarg;
3681*4882a593Smuzhiyun }
3682*4882a593Smuzhiyun 
3683*4882a593Smuzhiyun bfa_status_t
bfa_fcport_enable(struct bfa_s * bfa)3684*4882a593Smuzhiyun bfa_fcport_enable(struct bfa_s *bfa)
3685*4882a593Smuzhiyun {
3686*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3687*4882a593Smuzhiyun 
3688*4882a593Smuzhiyun 	if (bfa_fcport_is_pbcdisabled(bfa))
3689*4882a593Smuzhiyun 		return BFA_STATUS_PBC;
3690*4882a593Smuzhiyun 
3691*4882a593Smuzhiyun 	if (bfa_ioc_is_disabled(&bfa->ioc))
3692*4882a593Smuzhiyun 		return BFA_STATUS_IOC_DISABLED;
3693*4882a593Smuzhiyun 
3694*4882a593Smuzhiyun 	if (fcport->diag_busy)
3695*4882a593Smuzhiyun 		return BFA_STATUS_DIAG_BUSY;
3696*4882a593Smuzhiyun 
3697*4882a593Smuzhiyun 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3698*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3699*4882a593Smuzhiyun }
3700*4882a593Smuzhiyun 
3701*4882a593Smuzhiyun bfa_status_t
bfa_fcport_disable(struct bfa_s * bfa)3702*4882a593Smuzhiyun bfa_fcport_disable(struct bfa_s *bfa)
3703*4882a593Smuzhiyun {
3704*4882a593Smuzhiyun 	if (bfa_fcport_is_pbcdisabled(bfa))
3705*4882a593Smuzhiyun 		return BFA_STATUS_PBC;
3706*4882a593Smuzhiyun 
3707*4882a593Smuzhiyun 	if (bfa_ioc_is_disabled(&bfa->ioc))
3708*4882a593Smuzhiyun 		return BFA_STATUS_IOC_DISABLED;
3709*4882a593Smuzhiyun 
3710*4882a593Smuzhiyun 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3711*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3712*4882a593Smuzhiyun }
3713*4882a593Smuzhiyun 
3714*4882a593Smuzhiyun /* If PBC is disabled on port, return error */
3715*4882a593Smuzhiyun bfa_status_t
bfa_fcport_is_pbcdisabled(struct bfa_s * bfa)3716*4882a593Smuzhiyun bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
3717*4882a593Smuzhiyun {
3718*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3719*4882a593Smuzhiyun 	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
3720*4882a593Smuzhiyun 	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
3721*4882a593Smuzhiyun 
3722*4882a593Smuzhiyun 	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
3723*4882a593Smuzhiyun 		bfa_trc(bfa, fcport->pwwn);
3724*4882a593Smuzhiyun 		return BFA_STATUS_PBC;
3725*4882a593Smuzhiyun 	}
3726*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3727*4882a593Smuzhiyun }
3728*4882a593Smuzhiyun 
3729*4882a593Smuzhiyun /*
3730*4882a593Smuzhiyun  * Configure port speed.
3731*4882a593Smuzhiyun  */
3732*4882a593Smuzhiyun bfa_status_t
bfa_fcport_cfg_speed(struct bfa_s * bfa,enum bfa_port_speed speed)3733*4882a593Smuzhiyun bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3734*4882a593Smuzhiyun {
3735*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3736*4882a593Smuzhiyun 
3737*4882a593Smuzhiyun 	bfa_trc(bfa, speed);
3738*4882a593Smuzhiyun 
3739*4882a593Smuzhiyun 	if (fcport->cfg.trunked == BFA_TRUE)
3740*4882a593Smuzhiyun 		return BFA_STATUS_TRUNK_ENABLED;
3741*4882a593Smuzhiyun 	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
3742*4882a593Smuzhiyun 			(speed == BFA_PORT_SPEED_16GBPS))
3743*4882a593Smuzhiyun 		return BFA_STATUS_UNSUPP_SPEED;
3744*4882a593Smuzhiyun 	if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3745*4882a593Smuzhiyun 		bfa_trc(bfa, fcport->speed_sup);
3746*4882a593Smuzhiyun 		return BFA_STATUS_UNSUPP_SPEED;
3747*4882a593Smuzhiyun 	}
3748*4882a593Smuzhiyun 
3749*4882a593Smuzhiyun 	/* Port speed entered needs to be checked */
3750*4882a593Smuzhiyun 	if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
3751*4882a593Smuzhiyun 		/* For CT2, 1G is not supported */
3752*4882a593Smuzhiyun 		if ((speed == BFA_PORT_SPEED_1GBPS) &&
3753*4882a593Smuzhiyun 		    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
3754*4882a593Smuzhiyun 			return BFA_STATUS_UNSUPP_SPEED;
3755*4882a593Smuzhiyun 
3756*4882a593Smuzhiyun 		/* Already checked for Auto Speed and Max Speed supp */
3757*4882a593Smuzhiyun 		if (!(speed == BFA_PORT_SPEED_1GBPS ||
3758*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_2GBPS ||
3759*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_4GBPS ||
3760*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_8GBPS ||
3761*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_16GBPS ||
3762*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_AUTO))
3763*4882a593Smuzhiyun 			return BFA_STATUS_UNSUPP_SPEED;
3764*4882a593Smuzhiyun 	} else {
3765*4882a593Smuzhiyun 		if (speed != BFA_PORT_SPEED_10GBPS)
3766*4882a593Smuzhiyun 			return BFA_STATUS_UNSUPP_SPEED;
3767*4882a593Smuzhiyun 	}
3768*4882a593Smuzhiyun 
3769*4882a593Smuzhiyun 	fcport->cfg.speed = speed;
3770*4882a593Smuzhiyun 
3771*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3772*4882a593Smuzhiyun }
3773*4882a593Smuzhiyun 
3774*4882a593Smuzhiyun /*
3775*4882a593Smuzhiyun  * Get current speed.
3776*4882a593Smuzhiyun  */
3777*4882a593Smuzhiyun enum bfa_port_speed
bfa_fcport_get_speed(struct bfa_s * bfa)3778*4882a593Smuzhiyun bfa_fcport_get_speed(struct bfa_s *bfa)
3779*4882a593Smuzhiyun {
3780*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3781*4882a593Smuzhiyun 
3782*4882a593Smuzhiyun 	return fcport->speed;
3783*4882a593Smuzhiyun }
3784*4882a593Smuzhiyun 
3785*4882a593Smuzhiyun /*
3786*4882a593Smuzhiyun  * Configure port topology.
3787*4882a593Smuzhiyun  */
3788*4882a593Smuzhiyun bfa_status_t
bfa_fcport_cfg_topology(struct bfa_s * bfa,enum bfa_port_topology topology)3789*4882a593Smuzhiyun bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3790*4882a593Smuzhiyun {
3791*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3792*4882a593Smuzhiyun 
3793*4882a593Smuzhiyun 	bfa_trc(bfa, topology);
3794*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->cfg.topology);
3795*4882a593Smuzhiyun 
3796*4882a593Smuzhiyun 	switch (topology) {
3797*4882a593Smuzhiyun 	case BFA_PORT_TOPOLOGY_P2P:
3798*4882a593Smuzhiyun 		break;
3799*4882a593Smuzhiyun 
3800*4882a593Smuzhiyun 	case BFA_PORT_TOPOLOGY_LOOP:
3801*4882a593Smuzhiyun 		if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
3802*4882a593Smuzhiyun 			(fcport->qos_attr.state != BFA_QOS_DISABLED))
3803*4882a593Smuzhiyun 			return BFA_STATUS_ERROR_QOS_ENABLED;
3804*4882a593Smuzhiyun 		if (fcport->cfg.ratelimit != BFA_FALSE)
3805*4882a593Smuzhiyun 			return BFA_STATUS_ERROR_TRL_ENABLED;
3806*4882a593Smuzhiyun 		if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
3807*4882a593Smuzhiyun 			(fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
3808*4882a593Smuzhiyun 			return BFA_STATUS_ERROR_TRUNK_ENABLED;
3809*4882a593Smuzhiyun 		if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
3810*4882a593Smuzhiyun 			(fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
3811*4882a593Smuzhiyun 			return BFA_STATUS_UNSUPP_SPEED;
3812*4882a593Smuzhiyun 		if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
3813*4882a593Smuzhiyun 			return BFA_STATUS_LOOP_UNSUPP_MEZZ;
3814*4882a593Smuzhiyun 		if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
3815*4882a593Smuzhiyun 			return BFA_STATUS_DPORT_ERR;
3816*4882a593Smuzhiyun 		if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
3817*4882a593Smuzhiyun 			return BFA_STATUS_DPORT_ERR;
3818*4882a593Smuzhiyun 		break;
3819*4882a593Smuzhiyun 
3820*4882a593Smuzhiyun 	case BFA_PORT_TOPOLOGY_AUTO:
3821*4882a593Smuzhiyun 		break;
3822*4882a593Smuzhiyun 
3823*4882a593Smuzhiyun 	default:
3824*4882a593Smuzhiyun 		return BFA_STATUS_EINVAL;
3825*4882a593Smuzhiyun 	}
3826*4882a593Smuzhiyun 
3827*4882a593Smuzhiyun 	fcport->cfg.topology = topology;
3828*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3829*4882a593Smuzhiyun }
3830*4882a593Smuzhiyun 
3831*4882a593Smuzhiyun /*
3832*4882a593Smuzhiyun  * Get current topology.
3833*4882a593Smuzhiyun  */
3834*4882a593Smuzhiyun enum bfa_port_topology
bfa_fcport_get_topology(struct bfa_s * bfa)3835*4882a593Smuzhiyun bfa_fcport_get_topology(struct bfa_s *bfa)
3836*4882a593Smuzhiyun {
3837*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3838*4882a593Smuzhiyun 
3839*4882a593Smuzhiyun 	return fcport->topology;
3840*4882a593Smuzhiyun }
3841*4882a593Smuzhiyun 
3842*4882a593Smuzhiyun /*
3843*4882a593Smuzhiyun  * Get config topology.
3844*4882a593Smuzhiyun  */
3845*4882a593Smuzhiyun enum bfa_port_topology
bfa_fcport_get_cfg_topology(struct bfa_s * bfa)3846*4882a593Smuzhiyun bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
3847*4882a593Smuzhiyun {
3848*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3849*4882a593Smuzhiyun 
3850*4882a593Smuzhiyun 	return fcport->cfg.topology;
3851*4882a593Smuzhiyun }
3852*4882a593Smuzhiyun 
3853*4882a593Smuzhiyun bfa_status_t
bfa_fcport_cfg_hardalpa(struct bfa_s * bfa,u8 alpa)3854*4882a593Smuzhiyun bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3855*4882a593Smuzhiyun {
3856*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3857*4882a593Smuzhiyun 
3858*4882a593Smuzhiyun 	bfa_trc(bfa, alpa);
3859*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3860*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->cfg.hardalpa);
3861*4882a593Smuzhiyun 
3862*4882a593Smuzhiyun 	fcport->cfg.cfg_hardalpa = BFA_TRUE;
3863*4882a593Smuzhiyun 	fcport->cfg.hardalpa = alpa;
3864*4882a593Smuzhiyun 
3865*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3866*4882a593Smuzhiyun }
3867*4882a593Smuzhiyun 
3868*4882a593Smuzhiyun bfa_status_t
bfa_fcport_clr_hardalpa(struct bfa_s * bfa)3869*4882a593Smuzhiyun bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3870*4882a593Smuzhiyun {
3871*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3872*4882a593Smuzhiyun 
3873*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3874*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->cfg.hardalpa);
3875*4882a593Smuzhiyun 
3876*4882a593Smuzhiyun 	fcport->cfg.cfg_hardalpa = BFA_FALSE;
3877*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3878*4882a593Smuzhiyun }
3879*4882a593Smuzhiyun 
3880*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_get_hardalpa(struct bfa_s * bfa,u8 * alpa)3881*4882a593Smuzhiyun bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
3882*4882a593Smuzhiyun {
3883*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3884*4882a593Smuzhiyun 
3885*4882a593Smuzhiyun 	*alpa = fcport->cfg.hardalpa;
3886*4882a593Smuzhiyun 	return fcport->cfg.cfg_hardalpa;
3887*4882a593Smuzhiyun }
3888*4882a593Smuzhiyun 
3889*4882a593Smuzhiyun u8
bfa_fcport_get_myalpa(struct bfa_s * bfa)3890*4882a593Smuzhiyun bfa_fcport_get_myalpa(struct bfa_s *bfa)
3891*4882a593Smuzhiyun {
3892*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3893*4882a593Smuzhiyun 
3894*4882a593Smuzhiyun 	return fcport->myalpa;
3895*4882a593Smuzhiyun }
3896*4882a593Smuzhiyun 
3897*4882a593Smuzhiyun bfa_status_t
bfa_fcport_cfg_maxfrsize(struct bfa_s * bfa,u16 maxfrsize)3898*4882a593Smuzhiyun bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3899*4882a593Smuzhiyun {
3900*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3901*4882a593Smuzhiyun 
3902*4882a593Smuzhiyun 	bfa_trc(bfa, maxfrsize);
3903*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->cfg.maxfrsize);
3904*4882a593Smuzhiyun 
3905*4882a593Smuzhiyun 	/* with in range */
3906*4882a593Smuzhiyun 	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3907*4882a593Smuzhiyun 		return BFA_STATUS_INVLD_DFSZ;
3908*4882a593Smuzhiyun 
3909*4882a593Smuzhiyun 	/* power of 2, if not the max frame size of 2112 */
3910*4882a593Smuzhiyun 	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3911*4882a593Smuzhiyun 		return BFA_STATUS_INVLD_DFSZ;
3912*4882a593Smuzhiyun 
3913*4882a593Smuzhiyun 	fcport->cfg.maxfrsize = maxfrsize;
3914*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3915*4882a593Smuzhiyun }
3916*4882a593Smuzhiyun 
3917*4882a593Smuzhiyun u16
bfa_fcport_get_maxfrsize(struct bfa_s * bfa)3918*4882a593Smuzhiyun bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3919*4882a593Smuzhiyun {
3920*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3921*4882a593Smuzhiyun 
3922*4882a593Smuzhiyun 	return fcport->cfg.maxfrsize;
3923*4882a593Smuzhiyun }
3924*4882a593Smuzhiyun 
3925*4882a593Smuzhiyun u8
bfa_fcport_get_rx_bbcredit(struct bfa_s * bfa)3926*4882a593Smuzhiyun bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3927*4882a593Smuzhiyun {
3928*4882a593Smuzhiyun 	if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
3929*4882a593Smuzhiyun 		return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
3930*4882a593Smuzhiyun 
3931*4882a593Smuzhiyun 	else
3932*4882a593Smuzhiyun 		return 0;
3933*4882a593Smuzhiyun }
3934*4882a593Smuzhiyun 
3935*4882a593Smuzhiyun void
bfa_fcport_set_tx_bbcredit(struct bfa_s * bfa,u16 tx_bbcredit)3936*4882a593Smuzhiyun bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
3937*4882a593Smuzhiyun {
3938*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3939*4882a593Smuzhiyun 
3940*4882a593Smuzhiyun 	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3941*4882a593Smuzhiyun }
3942*4882a593Smuzhiyun 
3943*4882a593Smuzhiyun /*
3944*4882a593Smuzhiyun  * Get port attributes.
3945*4882a593Smuzhiyun  */
3946*4882a593Smuzhiyun 
3947*4882a593Smuzhiyun wwn_t
bfa_fcport_get_wwn(struct bfa_s * bfa,bfa_boolean_t node)3948*4882a593Smuzhiyun bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
3949*4882a593Smuzhiyun {
3950*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3951*4882a593Smuzhiyun 	if (node)
3952*4882a593Smuzhiyun 		return fcport->nwwn;
3953*4882a593Smuzhiyun 	else
3954*4882a593Smuzhiyun 		return fcport->pwwn;
3955*4882a593Smuzhiyun }
3956*4882a593Smuzhiyun 
3957*4882a593Smuzhiyun void
bfa_fcport_get_attr(struct bfa_s * bfa,struct bfa_port_attr_s * attr)3958*4882a593Smuzhiyun bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3959*4882a593Smuzhiyun {
3960*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3961*4882a593Smuzhiyun 
3962*4882a593Smuzhiyun 	memset(attr, 0, sizeof(struct bfa_port_attr_s));
3963*4882a593Smuzhiyun 
3964*4882a593Smuzhiyun 	attr->nwwn = fcport->nwwn;
3965*4882a593Smuzhiyun 	attr->pwwn = fcport->pwwn;
3966*4882a593Smuzhiyun 
3967*4882a593Smuzhiyun 	attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
3968*4882a593Smuzhiyun 	attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
3969*4882a593Smuzhiyun 
3970*4882a593Smuzhiyun 	memcpy(&attr->pport_cfg, &fcport->cfg,
3971*4882a593Smuzhiyun 		sizeof(struct bfa_port_cfg_s));
3972*4882a593Smuzhiyun 	/* speed attributes */
3973*4882a593Smuzhiyun 	attr->pport_cfg.speed = fcport->cfg.speed;
3974*4882a593Smuzhiyun 	attr->speed_supported = fcport->speed_sup;
3975*4882a593Smuzhiyun 	attr->speed = fcport->speed;
3976*4882a593Smuzhiyun 	attr->cos_supported = FC_CLASS_3;
3977*4882a593Smuzhiyun 
3978*4882a593Smuzhiyun 	/* topology attributes */
3979*4882a593Smuzhiyun 	attr->pport_cfg.topology = fcport->cfg.topology;
3980*4882a593Smuzhiyun 	attr->topology = fcport->topology;
3981*4882a593Smuzhiyun 	attr->pport_cfg.trunked = fcport->cfg.trunked;
3982*4882a593Smuzhiyun 
3983*4882a593Smuzhiyun 	/* beacon attributes */
3984*4882a593Smuzhiyun 	attr->beacon = fcport->beacon;
3985*4882a593Smuzhiyun 	attr->link_e2e_beacon = fcport->link_e2e_beacon;
3986*4882a593Smuzhiyun 
3987*4882a593Smuzhiyun 	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
3988*4882a593Smuzhiyun 	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
3989*4882a593Smuzhiyun 	attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
3990*4882a593Smuzhiyun 
3991*4882a593Smuzhiyun 	attr->fec_state = fcport->fec_state;
3992*4882a593Smuzhiyun 
3993*4882a593Smuzhiyun 	/* PBC Disabled State */
3994*4882a593Smuzhiyun 	if (bfa_fcport_is_pbcdisabled(bfa))
3995*4882a593Smuzhiyun 		attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
3996*4882a593Smuzhiyun 	else {
3997*4882a593Smuzhiyun 		if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
3998*4882a593Smuzhiyun 			attr->port_state = BFA_PORT_ST_IOCDIS;
3999*4882a593Smuzhiyun 		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
4000*4882a593Smuzhiyun 			attr->port_state = BFA_PORT_ST_FWMISMATCH;
4001*4882a593Smuzhiyun 	}
4002*4882a593Smuzhiyun 
4003*4882a593Smuzhiyun 	/* FCoE vlan */
4004*4882a593Smuzhiyun 	attr->fcoe_vlan = fcport->fcoe_vlan;
4005*4882a593Smuzhiyun }
4006*4882a593Smuzhiyun 
4007*4882a593Smuzhiyun #define BFA_FCPORT_STATS_TOV	1000
4008*4882a593Smuzhiyun 
4009*4882a593Smuzhiyun /*
4010*4882a593Smuzhiyun  * Fetch port statistics (FCQoS or FCoE).
4011*4882a593Smuzhiyun  */
4012*4882a593Smuzhiyun bfa_status_t
bfa_fcport_get_stats(struct bfa_s * bfa,struct bfa_cb_pending_q_s * cb)4013*4882a593Smuzhiyun bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4014*4882a593Smuzhiyun {
4015*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4016*4882a593Smuzhiyun 
4017*4882a593Smuzhiyun 	if (!bfa_iocfc_is_operational(bfa) ||
4018*4882a593Smuzhiyun 	    !fcport->stats_dma_ready)
4019*4882a593Smuzhiyun 		return BFA_STATUS_IOC_NON_OP;
4020*4882a593Smuzhiyun 
4021*4882a593Smuzhiyun 	if (!list_empty(&fcport->statsclr_pending_q))
4022*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
4023*4882a593Smuzhiyun 
4024*4882a593Smuzhiyun 	if (list_empty(&fcport->stats_pending_q)) {
4025*4882a593Smuzhiyun 		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4026*4882a593Smuzhiyun 		bfa_fcport_send_stats_get(fcport);
4027*4882a593Smuzhiyun 		bfa_timer_start(bfa, &fcport->timer,
4028*4882a593Smuzhiyun 				bfa_fcport_stats_get_timeout,
4029*4882a593Smuzhiyun 				fcport, BFA_FCPORT_STATS_TOV);
4030*4882a593Smuzhiyun 	} else
4031*4882a593Smuzhiyun 		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4032*4882a593Smuzhiyun 
4033*4882a593Smuzhiyun 	return BFA_STATUS_OK;
4034*4882a593Smuzhiyun }
4035*4882a593Smuzhiyun 
4036*4882a593Smuzhiyun /*
4037*4882a593Smuzhiyun  * Reset port statistics (FCQoS or FCoE).
4038*4882a593Smuzhiyun  */
4039*4882a593Smuzhiyun bfa_status_t
bfa_fcport_clear_stats(struct bfa_s * bfa,struct bfa_cb_pending_q_s * cb)4040*4882a593Smuzhiyun bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4041*4882a593Smuzhiyun {
4042*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4043*4882a593Smuzhiyun 
4044*4882a593Smuzhiyun 	if (!bfa_iocfc_is_operational(bfa) ||
4045*4882a593Smuzhiyun 	    !fcport->stats_dma_ready)
4046*4882a593Smuzhiyun 		return BFA_STATUS_IOC_NON_OP;
4047*4882a593Smuzhiyun 
4048*4882a593Smuzhiyun 	if (!list_empty(&fcport->stats_pending_q))
4049*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
4050*4882a593Smuzhiyun 
4051*4882a593Smuzhiyun 	if (list_empty(&fcport->statsclr_pending_q)) {
4052*4882a593Smuzhiyun 		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4053*4882a593Smuzhiyun 		bfa_fcport_send_stats_clear(fcport);
4054*4882a593Smuzhiyun 		bfa_timer_start(bfa, &fcport->timer,
4055*4882a593Smuzhiyun 				bfa_fcport_stats_clr_timeout,
4056*4882a593Smuzhiyun 				fcport, BFA_FCPORT_STATS_TOV);
4057*4882a593Smuzhiyun 	} else
4058*4882a593Smuzhiyun 		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4059*4882a593Smuzhiyun 
4060*4882a593Smuzhiyun 	return BFA_STATUS_OK;
4061*4882a593Smuzhiyun }
4062*4882a593Smuzhiyun 
4063*4882a593Smuzhiyun /*
4064*4882a593Smuzhiyun  * Fetch port attributes.
4065*4882a593Smuzhiyun  */
4066*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_is_disabled(struct bfa_s * bfa)4067*4882a593Smuzhiyun bfa_fcport_is_disabled(struct bfa_s *bfa)
4068*4882a593Smuzhiyun {
4069*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4070*4882a593Smuzhiyun 
4071*4882a593Smuzhiyun 	return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4072*4882a593Smuzhiyun 		BFA_PORT_ST_DISABLED;
4073*4882a593Smuzhiyun 
4074*4882a593Smuzhiyun }
4075*4882a593Smuzhiyun 
4076*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_is_dport(struct bfa_s * bfa)4077*4882a593Smuzhiyun bfa_fcport_is_dport(struct bfa_s *bfa)
4078*4882a593Smuzhiyun {
4079*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4080*4882a593Smuzhiyun 
4081*4882a593Smuzhiyun 	return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4082*4882a593Smuzhiyun 		BFA_PORT_ST_DPORT);
4083*4882a593Smuzhiyun }
4084*4882a593Smuzhiyun 
4085*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_is_ddport(struct bfa_s * bfa)4086*4882a593Smuzhiyun bfa_fcport_is_ddport(struct bfa_s *bfa)
4087*4882a593Smuzhiyun {
4088*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4089*4882a593Smuzhiyun 
4090*4882a593Smuzhiyun 	return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4091*4882a593Smuzhiyun 		BFA_PORT_ST_DDPORT);
4092*4882a593Smuzhiyun }
4093*4882a593Smuzhiyun 
4094*4882a593Smuzhiyun bfa_status_t
bfa_fcport_set_qos_bw(struct bfa_s * bfa,struct bfa_qos_bw_s * qos_bw)4095*4882a593Smuzhiyun bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
4096*4882a593Smuzhiyun {
4097*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4098*4882a593Smuzhiyun 	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
4099*4882a593Smuzhiyun 
4100*4882a593Smuzhiyun 	bfa_trc(bfa, ioc_type);
4101*4882a593Smuzhiyun 
4102*4882a593Smuzhiyun 	if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
4103*4882a593Smuzhiyun 		return BFA_STATUS_QOS_BW_INVALID;
4104*4882a593Smuzhiyun 
4105*4882a593Smuzhiyun 	if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
4106*4882a593Smuzhiyun 		return BFA_STATUS_QOS_BW_INVALID;
4107*4882a593Smuzhiyun 
4108*4882a593Smuzhiyun 	if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
4109*4882a593Smuzhiyun 	    (qos_bw->low > qos_bw->high))
4110*4882a593Smuzhiyun 		return BFA_STATUS_QOS_BW_INVALID;
4111*4882a593Smuzhiyun 
4112*4882a593Smuzhiyun 	if ((ioc_type == BFA_IOC_TYPE_FC) &&
4113*4882a593Smuzhiyun 	    (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
4114*4882a593Smuzhiyun 		fcport->cfg.qos_bw = *qos_bw;
4115*4882a593Smuzhiyun 
4116*4882a593Smuzhiyun 	return BFA_STATUS_OK;
4117*4882a593Smuzhiyun }
4118*4882a593Smuzhiyun 
4119*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_is_ratelim(struct bfa_s * bfa)4120*4882a593Smuzhiyun bfa_fcport_is_ratelim(struct bfa_s *bfa)
4121*4882a593Smuzhiyun {
4122*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4123*4882a593Smuzhiyun 
4124*4882a593Smuzhiyun 	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
4125*4882a593Smuzhiyun 
4126*4882a593Smuzhiyun }
4127*4882a593Smuzhiyun 
4128*4882a593Smuzhiyun /*
4129*4882a593Smuzhiyun  *	Enable/Disable FAA feature in port config
4130*4882a593Smuzhiyun  */
4131*4882a593Smuzhiyun void
bfa_fcport_cfg_faa(struct bfa_s * bfa,u8 state)4132*4882a593Smuzhiyun bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
4133*4882a593Smuzhiyun {
4134*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4135*4882a593Smuzhiyun 
4136*4882a593Smuzhiyun 	bfa_trc(bfa, state);
4137*4882a593Smuzhiyun 	fcport->cfg.faa_state = state;
4138*4882a593Smuzhiyun }
4139*4882a593Smuzhiyun 
4140*4882a593Smuzhiyun /*
4141*4882a593Smuzhiyun  * Get default minimum ratelim speed
4142*4882a593Smuzhiyun  */
4143*4882a593Smuzhiyun enum bfa_port_speed
bfa_fcport_get_ratelim_speed(struct bfa_s * bfa)4144*4882a593Smuzhiyun bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
4145*4882a593Smuzhiyun {
4146*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4147*4882a593Smuzhiyun 
4148*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->cfg.trl_def_speed);
4149*4882a593Smuzhiyun 	return fcport->cfg.trl_def_speed;
4150*4882a593Smuzhiyun 
4151*4882a593Smuzhiyun }
4152*4882a593Smuzhiyun 
4153*4882a593Smuzhiyun void
bfa_fcport_beacon(void * dev,bfa_boolean_t beacon,bfa_boolean_t link_e2e_beacon)4154*4882a593Smuzhiyun bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
4155*4882a593Smuzhiyun 		  bfa_boolean_t link_e2e_beacon)
4156*4882a593Smuzhiyun {
4157*4882a593Smuzhiyun 	struct bfa_s *bfa = dev;
4158*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4159*4882a593Smuzhiyun 
4160*4882a593Smuzhiyun 	bfa_trc(bfa, beacon);
4161*4882a593Smuzhiyun 	bfa_trc(bfa, link_e2e_beacon);
4162*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->beacon);
4163*4882a593Smuzhiyun 	bfa_trc(bfa, fcport->link_e2e_beacon);
4164*4882a593Smuzhiyun 
4165*4882a593Smuzhiyun 	fcport->beacon = beacon;
4166*4882a593Smuzhiyun 	fcport->link_e2e_beacon = link_e2e_beacon;
4167*4882a593Smuzhiyun }
4168*4882a593Smuzhiyun 
4169*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_is_linkup(struct bfa_s * bfa)4170*4882a593Smuzhiyun bfa_fcport_is_linkup(struct bfa_s *bfa)
4171*4882a593Smuzhiyun {
4172*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4173*4882a593Smuzhiyun 
4174*4882a593Smuzhiyun 	return	(!fcport->cfg.trunked &&
4175*4882a593Smuzhiyun 		 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
4176*4882a593Smuzhiyun 		(fcport->cfg.trunked &&
4177*4882a593Smuzhiyun 		 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
4178*4882a593Smuzhiyun }
4179*4882a593Smuzhiyun 
4180*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_is_qos_enabled(struct bfa_s * bfa)4181*4882a593Smuzhiyun bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
4182*4882a593Smuzhiyun {
4183*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4184*4882a593Smuzhiyun 
4185*4882a593Smuzhiyun 	return fcport->cfg.qos_enabled;
4186*4882a593Smuzhiyun }
4187*4882a593Smuzhiyun 
4188*4882a593Smuzhiyun bfa_boolean_t
bfa_fcport_is_trunk_enabled(struct bfa_s * bfa)4189*4882a593Smuzhiyun bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
4190*4882a593Smuzhiyun {
4191*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4192*4882a593Smuzhiyun 
4193*4882a593Smuzhiyun 	return fcport->cfg.trunked;
4194*4882a593Smuzhiyun }
4195*4882a593Smuzhiyun 
4196*4882a593Smuzhiyun bfa_status_t
bfa_fcport_cfg_bbcr(struct bfa_s * bfa,bfa_boolean_t on_off,u8 bb_scn)4197*4882a593Smuzhiyun bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
4198*4882a593Smuzhiyun {
4199*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4200*4882a593Smuzhiyun 
4201*4882a593Smuzhiyun 	bfa_trc(bfa, on_off);
4202*4882a593Smuzhiyun 
4203*4882a593Smuzhiyun 	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4204*4882a593Smuzhiyun 		return BFA_STATUS_BBCR_FC_ONLY;
4205*4882a593Smuzhiyun 
4206*4882a593Smuzhiyun 	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
4207*4882a593Smuzhiyun 		(bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
4208*4882a593Smuzhiyun 		return BFA_STATUS_CMD_NOTSUPP_MEZZ;
4209*4882a593Smuzhiyun 
4210*4882a593Smuzhiyun 	if (on_off) {
4211*4882a593Smuzhiyun 		if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4212*4882a593Smuzhiyun 			return BFA_STATUS_TOPOLOGY_LOOP;
4213*4882a593Smuzhiyun 
4214*4882a593Smuzhiyun 		if (fcport->cfg.qos_enabled)
4215*4882a593Smuzhiyun 			return BFA_STATUS_ERROR_QOS_ENABLED;
4216*4882a593Smuzhiyun 
4217*4882a593Smuzhiyun 		if (fcport->cfg.trunked)
4218*4882a593Smuzhiyun 			return BFA_STATUS_TRUNK_ENABLED;
4219*4882a593Smuzhiyun 
4220*4882a593Smuzhiyun 		if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
4221*4882a593Smuzhiyun 			(fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
4222*4882a593Smuzhiyun 			return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
4223*4882a593Smuzhiyun 
4224*4882a593Smuzhiyun 		if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
4225*4882a593Smuzhiyun 			return BFA_STATUS_FEATURE_NOT_SUPPORTED;
4226*4882a593Smuzhiyun 
4227*4882a593Smuzhiyun 		if (fcport->cfg.bb_cr_enabled) {
4228*4882a593Smuzhiyun 			if (bb_scn != fcport->cfg.bb_scn)
4229*4882a593Smuzhiyun 				return BFA_STATUS_BBCR_CFG_NO_CHANGE;
4230*4882a593Smuzhiyun 			else
4231*4882a593Smuzhiyun 				return BFA_STATUS_NO_CHANGE;
4232*4882a593Smuzhiyun 		}
4233*4882a593Smuzhiyun 
4234*4882a593Smuzhiyun 		if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
4235*4882a593Smuzhiyun 			bb_scn = BFA_BB_SCN_DEF;
4236*4882a593Smuzhiyun 
4237*4882a593Smuzhiyun 		fcport->cfg.bb_cr_enabled = on_off;
4238*4882a593Smuzhiyun 		fcport->cfg.bb_scn = bb_scn;
4239*4882a593Smuzhiyun 	} else {
4240*4882a593Smuzhiyun 		if (!fcport->cfg.bb_cr_enabled)
4241*4882a593Smuzhiyun 			return BFA_STATUS_NO_CHANGE;
4242*4882a593Smuzhiyun 
4243*4882a593Smuzhiyun 		fcport->cfg.bb_cr_enabled = on_off;
4244*4882a593Smuzhiyun 		fcport->cfg.bb_scn = 0;
4245*4882a593Smuzhiyun 	}
4246*4882a593Smuzhiyun 
4247*4882a593Smuzhiyun 	return BFA_STATUS_OK;
4248*4882a593Smuzhiyun }
4249*4882a593Smuzhiyun 
4250*4882a593Smuzhiyun bfa_status_t
bfa_fcport_get_bbcr_attr(struct bfa_s * bfa,struct bfa_bbcr_attr_s * bbcr_attr)4251*4882a593Smuzhiyun bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
4252*4882a593Smuzhiyun 		struct bfa_bbcr_attr_s *bbcr_attr)
4253*4882a593Smuzhiyun {
4254*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4255*4882a593Smuzhiyun 
4256*4882a593Smuzhiyun 	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4257*4882a593Smuzhiyun 		return BFA_STATUS_BBCR_FC_ONLY;
4258*4882a593Smuzhiyun 
4259*4882a593Smuzhiyun 	if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4260*4882a593Smuzhiyun 		return BFA_STATUS_TOPOLOGY_LOOP;
4261*4882a593Smuzhiyun 
4262*4882a593Smuzhiyun 	*bbcr_attr = fcport->bbcr_attr;
4263*4882a593Smuzhiyun 
4264*4882a593Smuzhiyun 	return BFA_STATUS_OK;
4265*4882a593Smuzhiyun }
4266*4882a593Smuzhiyun 
4267*4882a593Smuzhiyun void
bfa_fcport_dportenable(struct bfa_s * bfa)4268*4882a593Smuzhiyun bfa_fcport_dportenable(struct bfa_s *bfa)
4269*4882a593Smuzhiyun {
4270*4882a593Smuzhiyun 	/*
4271*4882a593Smuzhiyun 	 * Assume caller check for port is in disable state
4272*4882a593Smuzhiyun 	 */
4273*4882a593Smuzhiyun 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
4274*4882a593Smuzhiyun 	bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
4275*4882a593Smuzhiyun }
4276*4882a593Smuzhiyun 
4277*4882a593Smuzhiyun void
bfa_fcport_dportdisable(struct bfa_s * bfa)4278*4882a593Smuzhiyun bfa_fcport_dportdisable(struct bfa_s *bfa)
4279*4882a593Smuzhiyun {
4280*4882a593Smuzhiyun 	/*
4281*4882a593Smuzhiyun 	 * Assume caller check for port is in disable state
4282*4882a593Smuzhiyun 	 */
4283*4882a593Smuzhiyun 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
4284*4882a593Smuzhiyun 	bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
4285*4882a593Smuzhiyun }
4286*4882a593Smuzhiyun 
4287*4882a593Smuzhiyun static void
bfa_fcport_ddportenable(struct bfa_s * bfa)4288*4882a593Smuzhiyun bfa_fcport_ddportenable(struct bfa_s *bfa)
4289*4882a593Smuzhiyun {
4290*4882a593Smuzhiyun 	/*
4291*4882a593Smuzhiyun 	 * Assume caller check for port is in disable state
4292*4882a593Smuzhiyun 	 */
4293*4882a593Smuzhiyun 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
4294*4882a593Smuzhiyun }
4295*4882a593Smuzhiyun 
4296*4882a593Smuzhiyun static void
bfa_fcport_ddportdisable(struct bfa_s * bfa)4297*4882a593Smuzhiyun bfa_fcport_ddportdisable(struct bfa_s *bfa)
4298*4882a593Smuzhiyun {
4299*4882a593Smuzhiyun 	/*
4300*4882a593Smuzhiyun 	 * Assume caller check for port is in disable state
4301*4882a593Smuzhiyun 	 */
4302*4882a593Smuzhiyun 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
4303*4882a593Smuzhiyun }
4304*4882a593Smuzhiyun 
4305*4882a593Smuzhiyun /*
4306*4882a593Smuzhiyun  * Rport State machine functions
4307*4882a593Smuzhiyun  */
4308*4882a593Smuzhiyun /*
4309*4882a593Smuzhiyun  * Beginning state, only online event expected.
4310*4882a593Smuzhiyun  */
4311*4882a593Smuzhiyun static void
bfa_rport_sm_uninit(struct bfa_rport_s * rp,enum bfa_rport_event event)4312*4882a593Smuzhiyun bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
4313*4882a593Smuzhiyun {
4314*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4315*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4316*4882a593Smuzhiyun 
4317*4882a593Smuzhiyun 	switch (event) {
4318*4882a593Smuzhiyun 	case BFA_RPORT_SM_CREATE:
4319*4882a593Smuzhiyun 		bfa_stats(rp, sm_un_cr);
4320*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_created);
4321*4882a593Smuzhiyun 		break;
4322*4882a593Smuzhiyun 
4323*4882a593Smuzhiyun 	default:
4324*4882a593Smuzhiyun 		bfa_stats(rp, sm_un_unexp);
4325*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4326*4882a593Smuzhiyun 	}
4327*4882a593Smuzhiyun }
4328*4882a593Smuzhiyun 
4329*4882a593Smuzhiyun static void
bfa_rport_sm_created(struct bfa_rport_s * rp,enum bfa_rport_event event)4330*4882a593Smuzhiyun bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
4331*4882a593Smuzhiyun {
4332*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4333*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4334*4882a593Smuzhiyun 
4335*4882a593Smuzhiyun 	switch (event) {
4336*4882a593Smuzhiyun 	case BFA_RPORT_SM_ONLINE:
4337*4882a593Smuzhiyun 		bfa_stats(rp, sm_cr_on);
4338*4882a593Smuzhiyun 		if (bfa_rport_send_fwcreate(rp))
4339*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4340*4882a593Smuzhiyun 		else
4341*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4342*4882a593Smuzhiyun 		break;
4343*4882a593Smuzhiyun 
4344*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4345*4882a593Smuzhiyun 		bfa_stats(rp, sm_cr_del);
4346*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4347*4882a593Smuzhiyun 		bfa_rport_free(rp);
4348*4882a593Smuzhiyun 		break;
4349*4882a593Smuzhiyun 
4350*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4351*4882a593Smuzhiyun 		bfa_stats(rp, sm_cr_hwf);
4352*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4353*4882a593Smuzhiyun 		break;
4354*4882a593Smuzhiyun 
4355*4882a593Smuzhiyun 	default:
4356*4882a593Smuzhiyun 		bfa_stats(rp, sm_cr_unexp);
4357*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4358*4882a593Smuzhiyun 	}
4359*4882a593Smuzhiyun }
4360*4882a593Smuzhiyun 
4361*4882a593Smuzhiyun /*
4362*4882a593Smuzhiyun  * Waiting for rport create response from firmware.
4363*4882a593Smuzhiyun  */
4364*4882a593Smuzhiyun static void
bfa_rport_sm_fwcreate(struct bfa_rport_s * rp,enum bfa_rport_event event)4365*4882a593Smuzhiyun bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
4366*4882a593Smuzhiyun {
4367*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4368*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4369*4882a593Smuzhiyun 
4370*4882a593Smuzhiyun 	switch (event) {
4371*4882a593Smuzhiyun 	case BFA_RPORT_SM_FWRSP:
4372*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_rsp);
4373*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_online);
4374*4882a593Smuzhiyun 		bfa_rport_online_cb(rp);
4375*4882a593Smuzhiyun 		break;
4376*4882a593Smuzhiyun 
4377*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4378*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_del);
4379*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4380*4882a593Smuzhiyun 		break;
4381*4882a593Smuzhiyun 
4382*4882a593Smuzhiyun 	case BFA_RPORT_SM_OFFLINE:
4383*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_off);
4384*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
4385*4882a593Smuzhiyun 		break;
4386*4882a593Smuzhiyun 
4387*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4388*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_hwf);
4389*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4390*4882a593Smuzhiyun 		break;
4391*4882a593Smuzhiyun 
4392*4882a593Smuzhiyun 	default:
4393*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_unexp);
4394*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4395*4882a593Smuzhiyun 	}
4396*4882a593Smuzhiyun }
4397*4882a593Smuzhiyun 
4398*4882a593Smuzhiyun /*
4399*4882a593Smuzhiyun  * Request queue is full, awaiting queue resume to send create request.
4400*4882a593Smuzhiyun  */
4401*4882a593Smuzhiyun static void
bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s * rp,enum bfa_rport_event event)4402*4882a593Smuzhiyun bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4403*4882a593Smuzhiyun {
4404*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4405*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4406*4882a593Smuzhiyun 
4407*4882a593Smuzhiyun 	switch (event) {
4408*4882a593Smuzhiyun 	case BFA_RPORT_SM_QRESUME:
4409*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4410*4882a593Smuzhiyun 		bfa_rport_send_fwcreate(rp);
4411*4882a593Smuzhiyun 		break;
4412*4882a593Smuzhiyun 
4413*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4414*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_del);
4415*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4416*4882a593Smuzhiyun 		bfa_reqq_wcancel(&rp->reqq_wait);
4417*4882a593Smuzhiyun 		bfa_rport_free(rp);
4418*4882a593Smuzhiyun 		break;
4419*4882a593Smuzhiyun 
4420*4882a593Smuzhiyun 	case BFA_RPORT_SM_OFFLINE:
4421*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_off);
4422*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_offline);
4423*4882a593Smuzhiyun 		bfa_reqq_wcancel(&rp->reqq_wait);
4424*4882a593Smuzhiyun 		bfa_rport_offline_cb(rp);
4425*4882a593Smuzhiyun 		break;
4426*4882a593Smuzhiyun 
4427*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4428*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_hwf);
4429*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4430*4882a593Smuzhiyun 		bfa_reqq_wcancel(&rp->reqq_wait);
4431*4882a593Smuzhiyun 		break;
4432*4882a593Smuzhiyun 
4433*4882a593Smuzhiyun 	default:
4434*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwc_unexp);
4435*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4436*4882a593Smuzhiyun 	}
4437*4882a593Smuzhiyun }
4438*4882a593Smuzhiyun 
4439*4882a593Smuzhiyun /*
4440*4882a593Smuzhiyun  * Online state - normal parking state.
4441*4882a593Smuzhiyun  */
4442*4882a593Smuzhiyun static void
bfa_rport_sm_online(struct bfa_rport_s * rp,enum bfa_rport_event event)4443*4882a593Smuzhiyun bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
4444*4882a593Smuzhiyun {
4445*4882a593Smuzhiyun 	struct bfi_rport_qos_scn_s *qos_scn;
4446*4882a593Smuzhiyun 
4447*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4448*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4449*4882a593Smuzhiyun 
4450*4882a593Smuzhiyun 	switch (event) {
4451*4882a593Smuzhiyun 	case BFA_RPORT_SM_OFFLINE:
4452*4882a593Smuzhiyun 		bfa_stats(rp, sm_on_off);
4453*4882a593Smuzhiyun 		if (bfa_rport_send_fwdelete(rp))
4454*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4455*4882a593Smuzhiyun 		else
4456*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4457*4882a593Smuzhiyun 		break;
4458*4882a593Smuzhiyun 
4459*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4460*4882a593Smuzhiyun 		bfa_stats(rp, sm_on_del);
4461*4882a593Smuzhiyun 		if (bfa_rport_send_fwdelete(rp))
4462*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4463*4882a593Smuzhiyun 		else
4464*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4465*4882a593Smuzhiyun 		break;
4466*4882a593Smuzhiyun 
4467*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4468*4882a593Smuzhiyun 		bfa_stats(rp, sm_on_hwf);
4469*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4470*4882a593Smuzhiyun 		break;
4471*4882a593Smuzhiyun 
4472*4882a593Smuzhiyun 	case BFA_RPORT_SM_SET_SPEED:
4473*4882a593Smuzhiyun 		bfa_rport_send_fwspeed(rp);
4474*4882a593Smuzhiyun 		break;
4475*4882a593Smuzhiyun 
4476*4882a593Smuzhiyun 	case BFA_RPORT_SM_QOS_SCN:
4477*4882a593Smuzhiyun 		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
4478*4882a593Smuzhiyun 		rp->qos_attr = qos_scn->new_qos_attr;
4479*4882a593Smuzhiyun 		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
4480*4882a593Smuzhiyun 		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
4481*4882a593Smuzhiyun 		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
4482*4882a593Smuzhiyun 		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
4483*4882a593Smuzhiyun 
4484*4882a593Smuzhiyun 		qos_scn->old_qos_attr.qos_flow_id  =
4485*4882a593Smuzhiyun 			be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);
4486*4882a593Smuzhiyun 		qos_scn->new_qos_attr.qos_flow_id  =
4487*4882a593Smuzhiyun 			be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);
4488*4882a593Smuzhiyun 
4489*4882a593Smuzhiyun 		if (qos_scn->old_qos_attr.qos_flow_id !=
4490*4882a593Smuzhiyun 			qos_scn->new_qos_attr.qos_flow_id)
4491*4882a593Smuzhiyun 			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
4492*4882a593Smuzhiyun 						    qos_scn->old_qos_attr,
4493*4882a593Smuzhiyun 						    qos_scn->new_qos_attr);
4494*4882a593Smuzhiyun 		if (qos_scn->old_qos_attr.qos_priority !=
4495*4882a593Smuzhiyun 			qos_scn->new_qos_attr.qos_priority)
4496*4882a593Smuzhiyun 			bfa_cb_rport_qos_scn_prio(rp->rport_drv,
4497*4882a593Smuzhiyun 						  qos_scn->old_qos_attr,
4498*4882a593Smuzhiyun 						  qos_scn->new_qos_attr);
4499*4882a593Smuzhiyun 		break;
4500*4882a593Smuzhiyun 
4501*4882a593Smuzhiyun 	default:
4502*4882a593Smuzhiyun 		bfa_stats(rp, sm_on_unexp);
4503*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4504*4882a593Smuzhiyun 	}
4505*4882a593Smuzhiyun }
4506*4882a593Smuzhiyun 
4507*4882a593Smuzhiyun /*
4508*4882a593Smuzhiyun  * Firmware rport is being deleted - awaiting f/w response.
4509*4882a593Smuzhiyun  */
4510*4882a593Smuzhiyun static void
bfa_rport_sm_fwdelete(struct bfa_rport_s * rp,enum bfa_rport_event event)4511*4882a593Smuzhiyun bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
4512*4882a593Smuzhiyun {
4513*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4514*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4515*4882a593Smuzhiyun 
4516*4882a593Smuzhiyun 	switch (event) {
4517*4882a593Smuzhiyun 	case BFA_RPORT_SM_FWRSP:
4518*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwd_rsp);
4519*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_offline);
4520*4882a593Smuzhiyun 		bfa_rport_offline_cb(rp);
4521*4882a593Smuzhiyun 		break;
4522*4882a593Smuzhiyun 
4523*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4524*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwd_del);
4525*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4526*4882a593Smuzhiyun 		break;
4527*4882a593Smuzhiyun 
4528*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4529*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwd_hwf);
4530*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4531*4882a593Smuzhiyun 		bfa_rport_offline_cb(rp);
4532*4882a593Smuzhiyun 		break;
4533*4882a593Smuzhiyun 
4534*4882a593Smuzhiyun 	default:
4535*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwd_unexp);
4536*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4537*4882a593Smuzhiyun 	}
4538*4882a593Smuzhiyun }
4539*4882a593Smuzhiyun 
4540*4882a593Smuzhiyun static void
bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s * rp,enum bfa_rport_event event)4541*4882a593Smuzhiyun bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4542*4882a593Smuzhiyun {
4543*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4544*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4545*4882a593Smuzhiyun 
4546*4882a593Smuzhiyun 	switch (event) {
4547*4882a593Smuzhiyun 	case BFA_RPORT_SM_QRESUME:
4548*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4549*4882a593Smuzhiyun 		bfa_rport_send_fwdelete(rp);
4550*4882a593Smuzhiyun 		break;
4551*4882a593Smuzhiyun 
4552*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4553*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwd_del);
4554*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4555*4882a593Smuzhiyun 		break;
4556*4882a593Smuzhiyun 
4557*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4558*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwd_hwf);
4559*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4560*4882a593Smuzhiyun 		bfa_reqq_wcancel(&rp->reqq_wait);
4561*4882a593Smuzhiyun 		bfa_rport_offline_cb(rp);
4562*4882a593Smuzhiyun 		break;
4563*4882a593Smuzhiyun 
4564*4882a593Smuzhiyun 	default:
4565*4882a593Smuzhiyun 		bfa_stats(rp, sm_fwd_unexp);
4566*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4567*4882a593Smuzhiyun 	}
4568*4882a593Smuzhiyun }
4569*4882a593Smuzhiyun 
4570*4882a593Smuzhiyun /*
4571*4882a593Smuzhiyun  * Offline state.
4572*4882a593Smuzhiyun  */
4573*4882a593Smuzhiyun static void
bfa_rport_sm_offline(struct bfa_rport_s * rp,enum bfa_rport_event event)4574*4882a593Smuzhiyun bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4575*4882a593Smuzhiyun {
4576*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4577*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4578*4882a593Smuzhiyun 
4579*4882a593Smuzhiyun 	switch (event) {
4580*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4581*4882a593Smuzhiyun 		bfa_stats(rp, sm_off_del);
4582*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4583*4882a593Smuzhiyun 		bfa_rport_free(rp);
4584*4882a593Smuzhiyun 		break;
4585*4882a593Smuzhiyun 
4586*4882a593Smuzhiyun 	case BFA_RPORT_SM_ONLINE:
4587*4882a593Smuzhiyun 		bfa_stats(rp, sm_off_on);
4588*4882a593Smuzhiyun 		if (bfa_rport_send_fwcreate(rp))
4589*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4590*4882a593Smuzhiyun 		else
4591*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4592*4882a593Smuzhiyun 		break;
4593*4882a593Smuzhiyun 
4594*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4595*4882a593Smuzhiyun 		bfa_stats(rp, sm_off_hwf);
4596*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4597*4882a593Smuzhiyun 		break;
4598*4882a593Smuzhiyun 
4599*4882a593Smuzhiyun 	case BFA_RPORT_SM_OFFLINE:
4600*4882a593Smuzhiyun 		bfa_rport_offline_cb(rp);
4601*4882a593Smuzhiyun 		break;
4602*4882a593Smuzhiyun 
4603*4882a593Smuzhiyun 	default:
4604*4882a593Smuzhiyun 		bfa_stats(rp, sm_off_unexp);
4605*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4606*4882a593Smuzhiyun 	}
4607*4882a593Smuzhiyun }
4608*4882a593Smuzhiyun 
4609*4882a593Smuzhiyun /*
4610*4882a593Smuzhiyun  * Rport is deleted, waiting for firmware response to delete.
4611*4882a593Smuzhiyun  */
4612*4882a593Smuzhiyun static void
bfa_rport_sm_deleting(struct bfa_rport_s * rp,enum bfa_rport_event event)4613*4882a593Smuzhiyun bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
4614*4882a593Smuzhiyun {
4615*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4616*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4617*4882a593Smuzhiyun 
4618*4882a593Smuzhiyun 	switch (event) {
4619*4882a593Smuzhiyun 	case BFA_RPORT_SM_FWRSP:
4620*4882a593Smuzhiyun 		bfa_stats(rp, sm_del_fwrsp);
4621*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4622*4882a593Smuzhiyun 		bfa_rport_free(rp);
4623*4882a593Smuzhiyun 		break;
4624*4882a593Smuzhiyun 
4625*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4626*4882a593Smuzhiyun 		bfa_stats(rp, sm_del_hwf);
4627*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4628*4882a593Smuzhiyun 		bfa_rport_free(rp);
4629*4882a593Smuzhiyun 		break;
4630*4882a593Smuzhiyun 
4631*4882a593Smuzhiyun 	default:
4632*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4633*4882a593Smuzhiyun 	}
4634*4882a593Smuzhiyun }
4635*4882a593Smuzhiyun 
4636*4882a593Smuzhiyun static void
bfa_rport_sm_deleting_qfull(struct bfa_rport_s * rp,enum bfa_rport_event event)4637*4882a593Smuzhiyun bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4638*4882a593Smuzhiyun {
4639*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4640*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4641*4882a593Smuzhiyun 
4642*4882a593Smuzhiyun 	switch (event) {
4643*4882a593Smuzhiyun 	case BFA_RPORT_SM_QRESUME:
4644*4882a593Smuzhiyun 		bfa_stats(rp, sm_del_fwrsp);
4645*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4646*4882a593Smuzhiyun 		bfa_rport_send_fwdelete(rp);
4647*4882a593Smuzhiyun 		break;
4648*4882a593Smuzhiyun 
4649*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4650*4882a593Smuzhiyun 		bfa_stats(rp, sm_del_hwf);
4651*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4652*4882a593Smuzhiyun 		bfa_reqq_wcancel(&rp->reqq_wait);
4653*4882a593Smuzhiyun 		bfa_rport_free(rp);
4654*4882a593Smuzhiyun 		break;
4655*4882a593Smuzhiyun 
4656*4882a593Smuzhiyun 	default:
4657*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4658*4882a593Smuzhiyun 	}
4659*4882a593Smuzhiyun }
4660*4882a593Smuzhiyun 
4661*4882a593Smuzhiyun /*
4662*4882a593Smuzhiyun  * Waiting for rport create response from firmware. A delete is pending.
4663*4882a593Smuzhiyun  */
4664*4882a593Smuzhiyun static void
bfa_rport_sm_delete_pending(struct bfa_rport_s * rp,enum bfa_rport_event event)4665*4882a593Smuzhiyun bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
4666*4882a593Smuzhiyun 				enum bfa_rport_event event)
4667*4882a593Smuzhiyun {
4668*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4669*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4670*4882a593Smuzhiyun 
4671*4882a593Smuzhiyun 	switch (event) {
4672*4882a593Smuzhiyun 	case BFA_RPORT_SM_FWRSP:
4673*4882a593Smuzhiyun 		bfa_stats(rp, sm_delp_fwrsp);
4674*4882a593Smuzhiyun 		if (bfa_rport_send_fwdelete(rp))
4675*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4676*4882a593Smuzhiyun 		else
4677*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4678*4882a593Smuzhiyun 		break;
4679*4882a593Smuzhiyun 
4680*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4681*4882a593Smuzhiyun 		bfa_stats(rp, sm_delp_hwf);
4682*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4683*4882a593Smuzhiyun 		bfa_rport_free(rp);
4684*4882a593Smuzhiyun 		break;
4685*4882a593Smuzhiyun 
4686*4882a593Smuzhiyun 	default:
4687*4882a593Smuzhiyun 		bfa_stats(rp, sm_delp_unexp);
4688*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4689*4882a593Smuzhiyun 	}
4690*4882a593Smuzhiyun }
4691*4882a593Smuzhiyun 
4692*4882a593Smuzhiyun /*
4693*4882a593Smuzhiyun  * Waiting for rport create response from firmware. Rport offline is pending.
4694*4882a593Smuzhiyun  */
4695*4882a593Smuzhiyun static void
bfa_rport_sm_offline_pending(struct bfa_rport_s * rp,enum bfa_rport_event event)4696*4882a593Smuzhiyun bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4697*4882a593Smuzhiyun 				 enum bfa_rport_event event)
4698*4882a593Smuzhiyun {
4699*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4700*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4701*4882a593Smuzhiyun 
4702*4882a593Smuzhiyun 	switch (event) {
4703*4882a593Smuzhiyun 	case BFA_RPORT_SM_FWRSP:
4704*4882a593Smuzhiyun 		bfa_stats(rp, sm_offp_fwrsp);
4705*4882a593Smuzhiyun 		if (bfa_rport_send_fwdelete(rp))
4706*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4707*4882a593Smuzhiyun 		else
4708*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4709*4882a593Smuzhiyun 		break;
4710*4882a593Smuzhiyun 
4711*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4712*4882a593Smuzhiyun 		bfa_stats(rp, sm_offp_del);
4713*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4714*4882a593Smuzhiyun 		break;
4715*4882a593Smuzhiyun 
4716*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4717*4882a593Smuzhiyun 		bfa_stats(rp, sm_offp_hwf);
4718*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4719*4882a593Smuzhiyun 		bfa_rport_offline_cb(rp);
4720*4882a593Smuzhiyun 		break;
4721*4882a593Smuzhiyun 
4722*4882a593Smuzhiyun 	default:
4723*4882a593Smuzhiyun 		bfa_stats(rp, sm_offp_unexp);
4724*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4725*4882a593Smuzhiyun 	}
4726*4882a593Smuzhiyun }
4727*4882a593Smuzhiyun 
4728*4882a593Smuzhiyun /*
4729*4882a593Smuzhiyun  * IOC h/w failed.
4730*4882a593Smuzhiyun  */
4731*4882a593Smuzhiyun static void
bfa_rport_sm_iocdisable(struct bfa_rport_s * rp,enum bfa_rport_event event)4732*4882a593Smuzhiyun bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
4733*4882a593Smuzhiyun {
4734*4882a593Smuzhiyun 	bfa_trc(rp->bfa, rp->rport_tag);
4735*4882a593Smuzhiyun 	bfa_trc(rp->bfa, event);
4736*4882a593Smuzhiyun 
4737*4882a593Smuzhiyun 	switch (event) {
4738*4882a593Smuzhiyun 	case BFA_RPORT_SM_OFFLINE:
4739*4882a593Smuzhiyun 		bfa_stats(rp, sm_iocd_off);
4740*4882a593Smuzhiyun 		bfa_rport_offline_cb(rp);
4741*4882a593Smuzhiyun 		break;
4742*4882a593Smuzhiyun 
4743*4882a593Smuzhiyun 	case BFA_RPORT_SM_DELETE:
4744*4882a593Smuzhiyun 		bfa_stats(rp, sm_iocd_del);
4745*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4746*4882a593Smuzhiyun 		bfa_rport_free(rp);
4747*4882a593Smuzhiyun 		break;
4748*4882a593Smuzhiyun 
4749*4882a593Smuzhiyun 	case BFA_RPORT_SM_ONLINE:
4750*4882a593Smuzhiyun 		bfa_stats(rp, sm_iocd_on);
4751*4882a593Smuzhiyun 		if (bfa_rport_send_fwcreate(rp))
4752*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4753*4882a593Smuzhiyun 		else
4754*4882a593Smuzhiyun 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4755*4882a593Smuzhiyun 		break;
4756*4882a593Smuzhiyun 
4757*4882a593Smuzhiyun 	case BFA_RPORT_SM_HWFAIL:
4758*4882a593Smuzhiyun 		break;
4759*4882a593Smuzhiyun 
4760*4882a593Smuzhiyun 	default:
4761*4882a593Smuzhiyun 		bfa_stats(rp, sm_iocd_unexp);
4762*4882a593Smuzhiyun 		bfa_sm_fault(rp->bfa, event);
4763*4882a593Smuzhiyun 	}
4764*4882a593Smuzhiyun }
4765*4882a593Smuzhiyun 
4766*4882a593Smuzhiyun 
4767*4882a593Smuzhiyun 
4768*4882a593Smuzhiyun /*
4769*4882a593Smuzhiyun  *  bfa_rport_private BFA rport private functions
4770*4882a593Smuzhiyun  */
4771*4882a593Smuzhiyun 
4772*4882a593Smuzhiyun static void
__bfa_cb_rport_online(void * cbarg,bfa_boolean_t complete)4773*4882a593Smuzhiyun __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
4774*4882a593Smuzhiyun {
4775*4882a593Smuzhiyun 	struct bfa_rport_s *rp = cbarg;
4776*4882a593Smuzhiyun 
4777*4882a593Smuzhiyun 	if (complete)
4778*4882a593Smuzhiyun 		bfa_cb_rport_online(rp->rport_drv);
4779*4882a593Smuzhiyun }
4780*4882a593Smuzhiyun 
4781*4882a593Smuzhiyun static void
__bfa_cb_rport_offline(void * cbarg,bfa_boolean_t complete)4782*4882a593Smuzhiyun __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
4783*4882a593Smuzhiyun {
4784*4882a593Smuzhiyun 	struct bfa_rport_s *rp = cbarg;
4785*4882a593Smuzhiyun 
4786*4882a593Smuzhiyun 	if (complete)
4787*4882a593Smuzhiyun 		bfa_cb_rport_offline(rp->rport_drv);
4788*4882a593Smuzhiyun }
4789*4882a593Smuzhiyun 
4790*4882a593Smuzhiyun static void
bfa_rport_qresume(void * cbarg)4791*4882a593Smuzhiyun bfa_rport_qresume(void *cbarg)
4792*4882a593Smuzhiyun {
4793*4882a593Smuzhiyun 	struct bfa_rport_s	*rp = cbarg;
4794*4882a593Smuzhiyun 
4795*4882a593Smuzhiyun 	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
4796*4882a593Smuzhiyun }
4797*4882a593Smuzhiyun 
4798*4882a593Smuzhiyun void
bfa_rport_meminfo(struct bfa_iocfc_cfg_s * cfg,struct bfa_meminfo_s * minfo,struct bfa_s * bfa)4799*4882a593Smuzhiyun bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
4800*4882a593Smuzhiyun 		struct bfa_s *bfa)
4801*4882a593Smuzhiyun {
4802*4882a593Smuzhiyun 	struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);
4803*4882a593Smuzhiyun 
4804*4882a593Smuzhiyun 	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
4805*4882a593Smuzhiyun 		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
4806*4882a593Smuzhiyun 
4807*4882a593Smuzhiyun 	/* kva memory */
4808*4882a593Smuzhiyun 	bfa_mem_kva_setup(minfo, rport_kva,
4809*4882a593Smuzhiyun 		cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
4810*4882a593Smuzhiyun }
4811*4882a593Smuzhiyun 
4812*4882a593Smuzhiyun void
bfa_rport_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)4813*4882a593Smuzhiyun bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4814*4882a593Smuzhiyun 		struct bfa_pcidev_s *pcidev)
4815*4882a593Smuzhiyun {
4816*4882a593Smuzhiyun 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4817*4882a593Smuzhiyun 	struct bfa_rport_s *rp;
4818*4882a593Smuzhiyun 	u16 i;
4819*4882a593Smuzhiyun 
4820*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->rp_free_q);
4821*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->rp_active_q);
4822*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->rp_unused_q);
4823*4882a593Smuzhiyun 
4824*4882a593Smuzhiyun 	rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);
4825*4882a593Smuzhiyun 	mod->rps_list = rp;
4826*4882a593Smuzhiyun 	mod->num_rports = cfg->fwcfg.num_rports;
4827*4882a593Smuzhiyun 
4828*4882a593Smuzhiyun 	WARN_ON(!mod->num_rports ||
4829*4882a593Smuzhiyun 		   (mod->num_rports & (mod->num_rports - 1)));
4830*4882a593Smuzhiyun 
4831*4882a593Smuzhiyun 	for (i = 0; i < mod->num_rports; i++, rp++) {
4832*4882a593Smuzhiyun 		memset(rp, 0, sizeof(struct bfa_rport_s));
4833*4882a593Smuzhiyun 		rp->bfa = bfa;
4834*4882a593Smuzhiyun 		rp->rport_tag = i;
4835*4882a593Smuzhiyun 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4836*4882a593Smuzhiyun 
4837*4882a593Smuzhiyun 		/*
4838*4882a593Smuzhiyun 		 *  - is unused
4839*4882a593Smuzhiyun 		 */
4840*4882a593Smuzhiyun 		if (i)
4841*4882a593Smuzhiyun 			list_add_tail(&rp->qe, &mod->rp_free_q);
4842*4882a593Smuzhiyun 
4843*4882a593Smuzhiyun 		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
4844*4882a593Smuzhiyun 	}
4845*4882a593Smuzhiyun 
4846*4882a593Smuzhiyun 	/*
4847*4882a593Smuzhiyun 	 * consume memory
4848*4882a593Smuzhiyun 	 */
4849*4882a593Smuzhiyun 	bfa_mem_kva_curp(mod) = (u8 *) rp;
4850*4882a593Smuzhiyun }
4851*4882a593Smuzhiyun 
4852*4882a593Smuzhiyun void
bfa_rport_iocdisable(struct bfa_s * bfa)4853*4882a593Smuzhiyun bfa_rport_iocdisable(struct bfa_s *bfa)
4854*4882a593Smuzhiyun {
4855*4882a593Smuzhiyun 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4856*4882a593Smuzhiyun 	struct bfa_rport_s *rport;
4857*4882a593Smuzhiyun 	struct list_head *qe, *qen;
4858*4882a593Smuzhiyun 
4859*4882a593Smuzhiyun 	/* Enqueue unused rport resources to free_q */
4860*4882a593Smuzhiyun 	list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
4861*4882a593Smuzhiyun 
4862*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &mod->rp_active_q) {
4863*4882a593Smuzhiyun 		rport = (struct bfa_rport_s *) qe;
4864*4882a593Smuzhiyun 		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
4865*4882a593Smuzhiyun 	}
4866*4882a593Smuzhiyun }
4867*4882a593Smuzhiyun 
4868*4882a593Smuzhiyun static struct bfa_rport_s *
bfa_rport_alloc(struct bfa_rport_mod_s * mod)4869*4882a593Smuzhiyun bfa_rport_alloc(struct bfa_rport_mod_s *mod)
4870*4882a593Smuzhiyun {
4871*4882a593Smuzhiyun 	struct bfa_rport_s *rport;
4872*4882a593Smuzhiyun 
4873*4882a593Smuzhiyun 	bfa_q_deq(&mod->rp_free_q, &rport);
4874*4882a593Smuzhiyun 	if (rport)
4875*4882a593Smuzhiyun 		list_add_tail(&rport->qe, &mod->rp_active_q);
4876*4882a593Smuzhiyun 
4877*4882a593Smuzhiyun 	return rport;
4878*4882a593Smuzhiyun }
4879*4882a593Smuzhiyun 
4880*4882a593Smuzhiyun static void
bfa_rport_free(struct bfa_rport_s * rport)4881*4882a593Smuzhiyun bfa_rport_free(struct bfa_rport_s *rport)
4882*4882a593Smuzhiyun {
4883*4882a593Smuzhiyun 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
4884*4882a593Smuzhiyun 
4885*4882a593Smuzhiyun 	WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
4886*4882a593Smuzhiyun 	list_del(&rport->qe);
4887*4882a593Smuzhiyun 	list_add_tail(&rport->qe, &mod->rp_free_q);
4888*4882a593Smuzhiyun }
4889*4882a593Smuzhiyun 
4890*4882a593Smuzhiyun static bfa_boolean_t
bfa_rport_send_fwcreate(struct bfa_rport_s * rp)4891*4882a593Smuzhiyun bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
4892*4882a593Smuzhiyun {
4893*4882a593Smuzhiyun 	struct bfi_rport_create_req_s *m;
4894*4882a593Smuzhiyun 
4895*4882a593Smuzhiyun 	/*
4896*4882a593Smuzhiyun 	 * check for room in queue to send request now
4897*4882a593Smuzhiyun 	 */
4898*4882a593Smuzhiyun 	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4899*4882a593Smuzhiyun 	if (!m) {
4900*4882a593Smuzhiyun 		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4901*4882a593Smuzhiyun 		return BFA_FALSE;
4902*4882a593Smuzhiyun 	}
4903*4882a593Smuzhiyun 
4904*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
4905*4882a593Smuzhiyun 			bfa_fn_lpu(rp->bfa));
4906*4882a593Smuzhiyun 	m->bfa_handle = rp->rport_tag;
4907*4882a593Smuzhiyun 	m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
4908*4882a593Smuzhiyun 	m->pid = rp->rport_info.pid;
4909*4882a593Smuzhiyun 	m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
4910*4882a593Smuzhiyun 	m->local_pid = rp->rport_info.local_pid;
4911*4882a593Smuzhiyun 	m->fc_class = rp->rport_info.fc_class;
4912*4882a593Smuzhiyun 	m->vf_en = rp->rport_info.vf_en;
4913*4882a593Smuzhiyun 	m->vf_id = rp->rport_info.vf_id;
4914*4882a593Smuzhiyun 	m->cisc = rp->rport_info.cisc;
4915*4882a593Smuzhiyun 
4916*4882a593Smuzhiyun 	/*
4917*4882a593Smuzhiyun 	 * queue I/O message to firmware
4918*4882a593Smuzhiyun 	 */
4919*4882a593Smuzhiyun 	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4920*4882a593Smuzhiyun 	return BFA_TRUE;
4921*4882a593Smuzhiyun }
4922*4882a593Smuzhiyun 
4923*4882a593Smuzhiyun static bfa_boolean_t
bfa_rport_send_fwdelete(struct bfa_rport_s * rp)4924*4882a593Smuzhiyun bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
4925*4882a593Smuzhiyun {
4926*4882a593Smuzhiyun 	struct bfi_rport_delete_req_s *m;
4927*4882a593Smuzhiyun 
4928*4882a593Smuzhiyun 	/*
4929*4882a593Smuzhiyun 	 * check for room in queue to send request now
4930*4882a593Smuzhiyun 	 */
4931*4882a593Smuzhiyun 	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4932*4882a593Smuzhiyun 	if (!m) {
4933*4882a593Smuzhiyun 		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4934*4882a593Smuzhiyun 		return BFA_FALSE;
4935*4882a593Smuzhiyun 	}
4936*4882a593Smuzhiyun 
4937*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
4938*4882a593Smuzhiyun 			bfa_fn_lpu(rp->bfa));
4939*4882a593Smuzhiyun 	m->fw_handle = rp->fw_handle;
4940*4882a593Smuzhiyun 
4941*4882a593Smuzhiyun 	/*
4942*4882a593Smuzhiyun 	 * queue I/O message to firmware
4943*4882a593Smuzhiyun 	 */
4944*4882a593Smuzhiyun 	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4945*4882a593Smuzhiyun 	return BFA_TRUE;
4946*4882a593Smuzhiyun }
4947*4882a593Smuzhiyun 
4948*4882a593Smuzhiyun static bfa_boolean_t
bfa_rport_send_fwspeed(struct bfa_rport_s * rp)4949*4882a593Smuzhiyun bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
4950*4882a593Smuzhiyun {
4951*4882a593Smuzhiyun 	struct bfa_rport_speed_req_s *m;
4952*4882a593Smuzhiyun 
4953*4882a593Smuzhiyun 	/*
4954*4882a593Smuzhiyun 	 * check for room in queue to send request now
4955*4882a593Smuzhiyun 	 */
4956*4882a593Smuzhiyun 	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4957*4882a593Smuzhiyun 	if (!m) {
4958*4882a593Smuzhiyun 		bfa_trc(rp->bfa, rp->rport_info.speed);
4959*4882a593Smuzhiyun 		return BFA_FALSE;
4960*4882a593Smuzhiyun 	}
4961*4882a593Smuzhiyun 
4962*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
4963*4882a593Smuzhiyun 			bfa_fn_lpu(rp->bfa));
4964*4882a593Smuzhiyun 	m->fw_handle = rp->fw_handle;
4965*4882a593Smuzhiyun 	m->speed = (u8)rp->rport_info.speed;
4966*4882a593Smuzhiyun 
4967*4882a593Smuzhiyun 	/*
4968*4882a593Smuzhiyun 	 * queue I/O message to firmware
4969*4882a593Smuzhiyun 	 */
4970*4882a593Smuzhiyun 	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4971*4882a593Smuzhiyun 	return BFA_TRUE;
4972*4882a593Smuzhiyun }
4973*4882a593Smuzhiyun 
4974*4882a593Smuzhiyun 
4975*4882a593Smuzhiyun 
4976*4882a593Smuzhiyun /*
4977*4882a593Smuzhiyun  *  bfa_rport_public
4978*4882a593Smuzhiyun  */
4979*4882a593Smuzhiyun 
4980*4882a593Smuzhiyun /*
4981*4882a593Smuzhiyun  * Rport interrupt processing.
4982*4882a593Smuzhiyun  */
4983*4882a593Smuzhiyun void
bfa_rport_isr(struct bfa_s * bfa,struct bfi_msg_s * m)4984*4882a593Smuzhiyun bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
4985*4882a593Smuzhiyun {
4986*4882a593Smuzhiyun 	union bfi_rport_i2h_msg_u msg;
4987*4882a593Smuzhiyun 	struct bfa_rport_s *rp;
4988*4882a593Smuzhiyun 
4989*4882a593Smuzhiyun 	bfa_trc(bfa, m->mhdr.msg_id);
4990*4882a593Smuzhiyun 
4991*4882a593Smuzhiyun 	msg.msg = m;
4992*4882a593Smuzhiyun 
4993*4882a593Smuzhiyun 	switch (m->mhdr.msg_id) {
4994*4882a593Smuzhiyun 	case BFI_RPORT_I2H_CREATE_RSP:
4995*4882a593Smuzhiyun 		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
4996*4882a593Smuzhiyun 		rp->fw_handle = msg.create_rsp->fw_handle;
4997*4882a593Smuzhiyun 		rp->qos_attr = msg.create_rsp->qos_attr;
4998*4882a593Smuzhiyun 		bfa_rport_set_lunmask(bfa, rp);
4999*4882a593Smuzhiyun 		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
5000*4882a593Smuzhiyun 		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5001*4882a593Smuzhiyun 		break;
5002*4882a593Smuzhiyun 
5003*4882a593Smuzhiyun 	case BFI_RPORT_I2H_DELETE_RSP:
5004*4882a593Smuzhiyun 		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
5005*4882a593Smuzhiyun 		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
5006*4882a593Smuzhiyun 		bfa_rport_unset_lunmask(bfa, rp);
5007*4882a593Smuzhiyun 		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5008*4882a593Smuzhiyun 		break;
5009*4882a593Smuzhiyun 
5010*4882a593Smuzhiyun 	case BFI_RPORT_I2H_QOS_SCN:
5011*4882a593Smuzhiyun 		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
5012*4882a593Smuzhiyun 		rp->event_arg.fw_msg = msg.qos_scn_evt;
5013*4882a593Smuzhiyun 		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
5014*4882a593Smuzhiyun 		break;
5015*4882a593Smuzhiyun 
5016*4882a593Smuzhiyun 	case BFI_RPORT_I2H_LIP_SCN_ONLINE:
5017*4882a593Smuzhiyun 		bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
5018*4882a593Smuzhiyun 				&msg.lip_scn->loop_info);
5019*4882a593Smuzhiyun 		bfa_cb_rport_scn_online(bfa);
5020*4882a593Smuzhiyun 		break;
5021*4882a593Smuzhiyun 
5022*4882a593Smuzhiyun 	case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
5023*4882a593Smuzhiyun 		bfa_cb_rport_scn_offline(bfa);
5024*4882a593Smuzhiyun 		break;
5025*4882a593Smuzhiyun 
5026*4882a593Smuzhiyun 	case BFI_RPORT_I2H_NO_DEV:
5027*4882a593Smuzhiyun 		rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
5028*4882a593Smuzhiyun 		bfa_cb_rport_scn_no_dev(rp->rport_drv);
5029*4882a593Smuzhiyun 		break;
5030*4882a593Smuzhiyun 
5031*4882a593Smuzhiyun 	default:
5032*4882a593Smuzhiyun 		bfa_trc(bfa, m->mhdr.msg_id);
5033*4882a593Smuzhiyun 		WARN_ON(1);
5034*4882a593Smuzhiyun 	}
5035*4882a593Smuzhiyun }
5036*4882a593Smuzhiyun 
5037*4882a593Smuzhiyun void
bfa_rport_res_recfg(struct bfa_s * bfa,u16 num_rport_fw)5038*4882a593Smuzhiyun bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
5039*4882a593Smuzhiyun {
5040*4882a593Smuzhiyun 	struct bfa_rport_mod_s	*mod = BFA_RPORT_MOD(bfa);
5041*4882a593Smuzhiyun 	struct list_head	*qe;
5042*4882a593Smuzhiyun 	int	i;
5043*4882a593Smuzhiyun 
5044*4882a593Smuzhiyun 	for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
5045*4882a593Smuzhiyun 		bfa_q_deq_tail(&mod->rp_free_q, &qe);
5046*4882a593Smuzhiyun 		list_add_tail(qe, &mod->rp_unused_q);
5047*4882a593Smuzhiyun 	}
5048*4882a593Smuzhiyun }
5049*4882a593Smuzhiyun 
5050*4882a593Smuzhiyun /*
5051*4882a593Smuzhiyun  *  bfa_rport_api
5052*4882a593Smuzhiyun  */
5053*4882a593Smuzhiyun 
5054*4882a593Smuzhiyun struct bfa_rport_s *
bfa_rport_create(struct bfa_s * bfa,void * rport_drv)5055*4882a593Smuzhiyun bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
5056*4882a593Smuzhiyun {
5057*4882a593Smuzhiyun 	struct bfa_rport_s *rp;
5058*4882a593Smuzhiyun 
5059*4882a593Smuzhiyun 	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
5060*4882a593Smuzhiyun 
5061*4882a593Smuzhiyun 	if (rp == NULL)
5062*4882a593Smuzhiyun 		return NULL;
5063*4882a593Smuzhiyun 
5064*4882a593Smuzhiyun 	rp->bfa = bfa;
5065*4882a593Smuzhiyun 	rp->rport_drv = rport_drv;
5066*4882a593Smuzhiyun 	memset(&rp->stats, 0, sizeof(rp->stats));
5067*4882a593Smuzhiyun 
5068*4882a593Smuzhiyun 	WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
5069*4882a593Smuzhiyun 	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
5070*4882a593Smuzhiyun 
5071*4882a593Smuzhiyun 	return rp;
5072*4882a593Smuzhiyun }
5073*4882a593Smuzhiyun 
5074*4882a593Smuzhiyun void
bfa_rport_online(struct bfa_rport_s * rport,struct bfa_rport_info_s * rport_info)5075*4882a593Smuzhiyun bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
5076*4882a593Smuzhiyun {
5077*4882a593Smuzhiyun 	WARN_ON(rport_info->max_frmsz == 0);
5078*4882a593Smuzhiyun 
5079*4882a593Smuzhiyun 	/*
5080*4882a593Smuzhiyun 	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
5081*4882a593Smuzhiyun 	 * responses. Default to minimum size.
5082*4882a593Smuzhiyun 	 */
5083*4882a593Smuzhiyun 	if (rport_info->max_frmsz == 0) {
5084*4882a593Smuzhiyun 		bfa_trc(rport->bfa, rport->rport_tag);
5085*4882a593Smuzhiyun 		rport_info->max_frmsz = FC_MIN_PDUSZ;
5086*4882a593Smuzhiyun 	}
5087*4882a593Smuzhiyun 
5088*4882a593Smuzhiyun 	rport->rport_info = *rport_info;
5089*4882a593Smuzhiyun 	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
5090*4882a593Smuzhiyun }
5091*4882a593Smuzhiyun 
5092*4882a593Smuzhiyun void
bfa_rport_speed(struct bfa_rport_s * rport,enum bfa_port_speed speed)5093*4882a593Smuzhiyun bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
5094*4882a593Smuzhiyun {
5095*4882a593Smuzhiyun 	WARN_ON(speed == 0);
5096*4882a593Smuzhiyun 	WARN_ON(speed == BFA_PORT_SPEED_AUTO);
5097*4882a593Smuzhiyun 
5098*4882a593Smuzhiyun 	if (rport) {
5099*4882a593Smuzhiyun 		rport->rport_info.speed = speed;
5100*4882a593Smuzhiyun 		bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
5101*4882a593Smuzhiyun 	}
5102*4882a593Smuzhiyun }
5103*4882a593Smuzhiyun 
5104*4882a593Smuzhiyun /* Set Rport LUN Mask */
5105*4882a593Smuzhiyun void
bfa_rport_set_lunmask(struct bfa_s * bfa,struct bfa_rport_s * rp)5106*4882a593Smuzhiyun bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5107*4882a593Smuzhiyun {
5108*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);
5109*4882a593Smuzhiyun 	wwn_t	lp_wwn, rp_wwn;
5110*4882a593Smuzhiyun 	u8 lp_tag = (u8)rp->rport_info.lp_tag;
5111*4882a593Smuzhiyun 
5112*4882a593Smuzhiyun 	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5113*4882a593Smuzhiyun 	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5114*4882a593Smuzhiyun 
5115*4882a593Smuzhiyun 	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5116*4882a593Smuzhiyun 					rp->lun_mask = BFA_TRUE;
5117*4882a593Smuzhiyun 	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);
5118*4882a593Smuzhiyun }
5119*4882a593Smuzhiyun 
5120*4882a593Smuzhiyun /* Unset Rport LUN mask */
5121*4882a593Smuzhiyun void
bfa_rport_unset_lunmask(struct bfa_s * bfa,struct bfa_rport_s * rp)5122*4882a593Smuzhiyun bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5123*4882a593Smuzhiyun {
5124*4882a593Smuzhiyun 	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);
5125*4882a593Smuzhiyun 	wwn_t	lp_wwn, rp_wwn;
5126*4882a593Smuzhiyun 
5127*4882a593Smuzhiyun 	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5128*4882a593Smuzhiyun 	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5129*4882a593Smuzhiyun 
5130*4882a593Smuzhiyun 	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5131*4882a593Smuzhiyun 				rp->lun_mask = BFA_FALSE;
5132*4882a593Smuzhiyun 	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn,
5133*4882a593Smuzhiyun 			BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID);
5134*4882a593Smuzhiyun }
5135*4882a593Smuzhiyun 
5136*4882a593Smuzhiyun /*
5137*4882a593Smuzhiyun  * SGPG related functions
5138*4882a593Smuzhiyun  */
5139*4882a593Smuzhiyun 
5140*4882a593Smuzhiyun /*
5141*4882a593Smuzhiyun  * Compute and return memory needed by FCP(im) module.
5142*4882a593Smuzhiyun  */
5143*4882a593Smuzhiyun void
bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s * cfg,struct bfa_meminfo_s * minfo,struct bfa_s * bfa)5144*4882a593Smuzhiyun bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5145*4882a593Smuzhiyun 		struct bfa_s *bfa)
5146*4882a593Smuzhiyun {
5147*4882a593Smuzhiyun 	struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);
5148*4882a593Smuzhiyun 	struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);
5149*4882a593Smuzhiyun 	struct bfa_mem_dma_s *seg_ptr;
5150*4882a593Smuzhiyun 	u16	nsegs, idx, per_seg_sgpg, num_sgpg;
5151*4882a593Smuzhiyun 	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
5152*4882a593Smuzhiyun 
5153*4882a593Smuzhiyun 	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
5154*4882a593Smuzhiyun 		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
5155*4882a593Smuzhiyun 	else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)
5156*4882a593Smuzhiyun 		cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;
5157*4882a593Smuzhiyun 
5158*4882a593Smuzhiyun 	num_sgpg = cfg->drvcfg.num_sgpgs;
5159*4882a593Smuzhiyun 
5160*4882a593Smuzhiyun 	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5161*4882a593Smuzhiyun 	per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);
5162*4882a593Smuzhiyun 
5163*4882a593Smuzhiyun 	bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {
5164*4882a593Smuzhiyun 		if (num_sgpg >= per_seg_sgpg) {
5165*4882a593Smuzhiyun 			num_sgpg -= per_seg_sgpg;
5166*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
5167*4882a593Smuzhiyun 					per_seg_sgpg * sgpg_sz);
5168*4882a593Smuzhiyun 		} else
5169*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
5170*4882a593Smuzhiyun 					num_sgpg * sgpg_sz);
5171*4882a593Smuzhiyun 	}
5172*4882a593Smuzhiyun 
5173*4882a593Smuzhiyun 	/* kva memory */
5174*4882a593Smuzhiyun 	bfa_mem_kva_setup(minfo, sgpg_kva,
5175*4882a593Smuzhiyun 		cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
5176*4882a593Smuzhiyun }
5177*4882a593Smuzhiyun 
5178*4882a593Smuzhiyun void
bfa_sgpg_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)5179*4882a593Smuzhiyun bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5180*4882a593Smuzhiyun 		struct bfa_pcidev_s *pcidev)
5181*4882a593Smuzhiyun {
5182*4882a593Smuzhiyun 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5183*4882a593Smuzhiyun 	struct bfa_sgpg_s *hsgpg;
5184*4882a593Smuzhiyun 	struct bfi_sgpg_s *sgpg;
5185*4882a593Smuzhiyun 	u64 align_len;
5186*4882a593Smuzhiyun 	struct bfa_mem_dma_s *seg_ptr;
5187*4882a593Smuzhiyun 	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
5188*4882a593Smuzhiyun 	u16	i, idx, nsegs, per_seg_sgpg, num_sgpg;
5189*4882a593Smuzhiyun 
5190*4882a593Smuzhiyun 	union {
5191*4882a593Smuzhiyun 		u64 pa;
5192*4882a593Smuzhiyun 		union bfi_addr_u addr;
5193*4882a593Smuzhiyun 	} sgpg_pa, sgpg_pa_tmp;
5194*4882a593Smuzhiyun 
5195*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->sgpg_q);
5196*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mod->sgpg_wait_q);
5197*4882a593Smuzhiyun 
5198*4882a593Smuzhiyun 	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
5199*4882a593Smuzhiyun 
5200*4882a593Smuzhiyun 	mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
5201*4882a593Smuzhiyun 
5202*4882a593Smuzhiyun 	num_sgpg = cfg->drvcfg.num_sgpgs;
5203*4882a593Smuzhiyun 	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5204*4882a593Smuzhiyun 
5205*4882a593Smuzhiyun 	/* dma/kva mem claim */
5206*4882a593Smuzhiyun 	hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);
5207*4882a593Smuzhiyun 
5208*4882a593Smuzhiyun 	bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {
5209*4882a593Smuzhiyun 
5210*4882a593Smuzhiyun 		if (!bfa_mem_dma_virt(seg_ptr))
5211*4882a593Smuzhiyun 			break;
5212*4882a593Smuzhiyun 
5213*4882a593Smuzhiyun 		align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -
5214*4882a593Smuzhiyun 					     bfa_mem_dma_phys(seg_ptr);
5215*4882a593Smuzhiyun 
5216*4882a593Smuzhiyun 		sgpg = (struct bfi_sgpg_s *)
5217*4882a593Smuzhiyun 			(((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);
5218*4882a593Smuzhiyun 		sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;
5219*4882a593Smuzhiyun 		WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));
5220*4882a593Smuzhiyun 
5221*4882a593Smuzhiyun 		per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;
5222*4882a593Smuzhiyun 
5223*4882a593Smuzhiyun 		for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {
5224*4882a593Smuzhiyun 			memset(hsgpg, 0, sizeof(*hsgpg));
5225*4882a593Smuzhiyun 			memset(sgpg, 0, sizeof(*sgpg));
5226*4882a593Smuzhiyun 
5227*4882a593Smuzhiyun 			hsgpg->sgpg = sgpg;
5228*4882a593Smuzhiyun 			sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
5229*4882a593Smuzhiyun 			hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
5230*4882a593Smuzhiyun 			list_add_tail(&hsgpg->qe, &mod->sgpg_q);
5231*4882a593Smuzhiyun 
5232*4882a593Smuzhiyun 			sgpg++;
5233*4882a593Smuzhiyun 			hsgpg++;
5234*4882a593Smuzhiyun 			sgpg_pa.pa += sgpg_sz;
5235*4882a593Smuzhiyun 		}
5236*4882a593Smuzhiyun 	}
5237*4882a593Smuzhiyun 
5238*4882a593Smuzhiyun 	bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
5239*4882a593Smuzhiyun }
5240*4882a593Smuzhiyun 
5241*4882a593Smuzhiyun bfa_status_t
bfa_sgpg_malloc(struct bfa_s * bfa,struct list_head * sgpg_q,int nsgpgs)5242*4882a593Smuzhiyun bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
5243*4882a593Smuzhiyun {
5244*4882a593Smuzhiyun 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5245*4882a593Smuzhiyun 	struct bfa_sgpg_s *hsgpg;
5246*4882a593Smuzhiyun 	int i;
5247*4882a593Smuzhiyun 
5248*4882a593Smuzhiyun 	if (mod->free_sgpgs < nsgpgs)
5249*4882a593Smuzhiyun 		return BFA_STATUS_ENOMEM;
5250*4882a593Smuzhiyun 
5251*4882a593Smuzhiyun 	for (i = 0; i < nsgpgs; i++) {
5252*4882a593Smuzhiyun 		bfa_q_deq(&mod->sgpg_q, &hsgpg);
5253*4882a593Smuzhiyun 		WARN_ON(!hsgpg);
5254*4882a593Smuzhiyun 		list_add_tail(&hsgpg->qe, sgpg_q);
5255*4882a593Smuzhiyun 	}
5256*4882a593Smuzhiyun 
5257*4882a593Smuzhiyun 	mod->free_sgpgs -= nsgpgs;
5258*4882a593Smuzhiyun 	return BFA_STATUS_OK;
5259*4882a593Smuzhiyun }
5260*4882a593Smuzhiyun 
5261*4882a593Smuzhiyun void
bfa_sgpg_mfree(struct bfa_s * bfa,struct list_head * sgpg_q,int nsgpg)5262*4882a593Smuzhiyun bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
5263*4882a593Smuzhiyun {
5264*4882a593Smuzhiyun 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5265*4882a593Smuzhiyun 	struct bfa_sgpg_wqe_s *wqe;
5266*4882a593Smuzhiyun 
5267*4882a593Smuzhiyun 	mod->free_sgpgs += nsgpg;
5268*4882a593Smuzhiyun 	WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
5269*4882a593Smuzhiyun 
5270*4882a593Smuzhiyun 	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
5271*4882a593Smuzhiyun 
5272*4882a593Smuzhiyun 	if (list_empty(&mod->sgpg_wait_q))
5273*4882a593Smuzhiyun 		return;
5274*4882a593Smuzhiyun 
5275*4882a593Smuzhiyun 	/*
5276*4882a593Smuzhiyun 	 * satisfy as many waiting requests as possible
5277*4882a593Smuzhiyun 	 */
5278*4882a593Smuzhiyun 	do {
5279*4882a593Smuzhiyun 		wqe = bfa_q_first(&mod->sgpg_wait_q);
5280*4882a593Smuzhiyun 		if (mod->free_sgpgs < wqe->nsgpg)
5281*4882a593Smuzhiyun 			nsgpg = mod->free_sgpgs;
5282*4882a593Smuzhiyun 		else
5283*4882a593Smuzhiyun 			nsgpg = wqe->nsgpg;
5284*4882a593Smuzhiyun 		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
5285*4882a593Smuzhiyun 		wqe->nsgpg -= nsgpg;
5286*4882a593Smuzhiyun 		if (wqe->nsgpg == 0) {
5287*4882a593Smuzhiyun 			list_del(&wqe->qe);
5288*4882a593Smuzhiyun 			wqe->cbfn(wqe->cbarg);
5289*4882a593Smuzhiyun 		}
5290*4882a593Smuzhiyun 	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
5291*4882a593Smuzhiyun }
5292*4882a593Smuzhiyun 
5293*4882a593Smuzhiyun void
bfa_sgpg_wait(struct bfa_s * bfa,struct bfa_sgpg_wqe_s * wqe,int nsgpg)5294*4882a593Smuzhiyun bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
5295*4882a593Smuzhiyun {
5296*4882a593Smuzhiyun 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5297*4882a593Smuzhiyun 
5298*4882a593Smuzhiyun 	WARN_ON(nsgpg <= 0);
5299*4882a593Smuzhiyun 	WARN_ON(nsgpg <= mod->free_sgpgs);
5300*4882a593Smuzhiyun 
5301*4882a593Smuzhiyun 	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
5302*4882a593Smuzhiyun 
5303*4882a593Smuzhiyun 	/*
5304*4882a593Smuzhiyun 	 * allocate any left to this one first
5305*4882a593Smuzhiyun 	 */
5306*4882a593Smuzhiyun 	if (mod->free_sgpgs) {
5307*4882a593Smuzhiyun 		/*
5308*4882a593Smuzhiyun 		 * no one else is waiting for SGPG
5309*4882a593Smuzhiyun 		 */
5310*4882a593Smuzhiyun 		WARN_ON(!list_empty(&mod->sgpg_wait_q));
5311*4882a593Smuzhiyun 		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
5312*4882a593Smuzhiyun 		wqe->nsgpg -= mod->free_sgpgs;
5313*4882a593Smuzhiyun 		mod->free_sgpgs = 0;
5314*4882a593Smuzhiyun 	}
5315*4882a593Smuzhiyun 
5316*4882a593Smuzhiyun 	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
5317*4882a593Smuzhiyun }
5318*4882a593Smuzhiyun 
5319*4882a593Smuzhiyun void
bfa_sgpg_wcancel(struct bfa_s * bfa,struct bfa_sgpg_wqe_s * wqe)5320*4882a593Smuzhiyun bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
5321*4882a593Smuzhiyun {
5322*4882a593Smuzhiyun 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5323*4882a593Smuzhiyun 
5324*4882a593Smuzhiyun 	WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
5325*4882a593Smuzhiyun 	list_del(&wqe->qe);
5326*4882a593Smuzhiyun 
5327*4882a593Smuzhiyun 	if (wqe->nsgpg_total != wqe->nsgpg)
5328*4882a593Smuzhiyun 		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
5329*4882a593Smuzhiyun 				   wqe->nsgpg_total - wqe->nsgpg);
5330*4882a593Smuzhiyun }
5331*4882a593Smuzhiyun 
5332*4882a593Smuzhiyun void
bfa_sgpg_winit(struct bfa_sgpg_wqe_s * wqe,void (* cbfn)(void * cbarg),void * cbarg)5333*4882a593Smuzhiyun bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
5334*4882a593Smuzhiyun 		   void *cbarg)
5335*4882a593Smuzhiyun {
5336*4882a593Smuzhiyun 	INIT_LIST_HEAD(&wqe->sgpg_q);
5337*4882a593Smuzhiyun 	wqe->cbfn = cbfn;
5338*4882a593Smuzhiyun 	wqe->cbarg = cbarg;
5339*4882a593Smuzhiyun }
5340*4882a593Smuzhiyun 
5341*4882a593Smuzhiyun /*
5342*4882a593Smuzhiyun  *  UF related functions
5343*4882a593Smuzhiyun  */
5344*4882a593Smuzhiyun /*
5345*4882a593Smuzhiyun  *****************************************************************************
5346*4882a593Smuzhiyun  * Internal functions
5347*4882a593Smuzhiyun  *****************************************************************************
5348*4882a593Smuzhiyun  */
5349*4882a593Smuzhiyun static void
__bfa_cb_uf_recv(void * cbarg,bfa_boolean_t complete)5350*4882a593Smuzhiyun __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
5351*4882a593Smuzhiyun {
5352*4882a593Smuzhiyun 	struct bfa_uf_s   *uf = cbarg;
5353*4882a593Smuzhiyun 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
5354*4882a593Smuzhiyun 
5355*4882a593Smuzhiyun 	if (complete)
5356*4882a593Smuzhiyun 		ufm->ufrecv(ufm->cbarg, uf);
5357*4882a593Smuzhiyun }
5358*4882a593Smuzhiyun 
5359*4882a593Smuzhiyun static void
claim_uf_post_msgs(struct bfa_uf_mod_s * ufm)5360*4882a593Smuzhiyun claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)
5361*4882a593Smuzhiyun {
5362*4882a593Smuzhiyun 	struct bfi_uf_buf_post_s *uf_bp_msg;
5363*4882a593Smuzhiyun 	u16 i;
5364*4882a593Smuzhiyun 	u16 buf_len;
5365*4882a593Smuzhiyun 
5366*4882a593Smuzhiyun 	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);
5367*4882a593Smuzhiyun 	uf_bp_msg = ufm->uf_buf_posts;
5368*4882a593Smuzhiyun 
5369*4882a593Smuzhiyun 	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
5370*4882a593Smuzhiyun 	     i++, uf_bp_msg++) {
5371*4882a593Smuzhiyun 		memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
5372*4882a593Smuzhiyun 
5373*4882a593Smuzhiyun 		uf_bp_msg->buf_tag = i;
5374*4882a593Smuzhiyun 		buf_len = sizeof(struct bfa_uf_buf_s);
5375*4882a593Smuzhiyun 		uf_bp_msg->buf_len = cpu_to_be16(buf_len);
5376*4882a593Smuzhiyun 		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
5377*4882a593Smuzhiyun 			    bfa_fn_lpu(ufm->bfa));
5378*4882a593Smuzhiyun 		bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
5379*4882a593Smuzhiyun 	}
5380*4882a593Smuzhiyun 
5381*4882a593Smuzhiyun 	/*
5382*4882a593Smuzhiyun 	 * advance pointer beyond consumed memory
5383*4882a593Smuzhiyun 	 */
5384*4882a593Smuzhiyun 	bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;
5385*4882a593Smuzhiyun }
5386*4882a593Smuzhiyun 
5387*4882a593Smuzhiyun static void
claim_ufs(struct bfa_uf_mod_s * ufm)5388*4882a593Smuzhiyun claim_ufs(struct bfa_uf_mod_s *ufm)
5389*4882a593Smuzhiyun {
5390*4882a593Smuzhiyun 	u16 i;
5391*4882a593Smuzhiyun 	struct bfa_uf_s   *uf;
5392*4882a593Smuzhiyun 
5393*4882a593Smuzhiyun 	/*
5394*4882a593Smuzhiyun 	 * Claim block of memory for UF list
5395*4882a593Smuzhiyun 	 */
5396*4882a593Smuzhiyun 	ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);
5397*4882a593Smuzhiyun 
5398*4882a593Smuzhiyun 	/*
5399*4882a593Smuzhiyun 	 * Initialize UFs and queue it in UF free queue
5400*4882a593Smuzhiyun 	 */
5401*4882a593Smuzhiyun 	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
5402*4882a593Smuzhiyun 		memset(uf, 0, sizeof(struct bfa_uf_s));
5403*4882a593Smuzhiyun 		uf->bfa = ufm->bfa;
5404*4882a593Smuzhiyun 		uf->uf_tag = i;
5405*4882a593Smuzhiyun 		uf->pb_len = BFA_PER_UF_DMA_SZ;
5406*4882a593Smuzhiyun 		uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);
5407*4882a593Smuzhiyun 		uf->buf_pa = ufm_pbs_pa(ufm, i);
5408*4882a593Smuzhiyun 		list_add_tail(&uf->qe, &ufm->uf_free_q);
5409*4882a593Smuzhiyun 	}
5410*4882a593Smuzhiyun 
5411*4882a593Smuzhiyun 	/*
5412*4882a593Smuzhiyun 	 * advance memory pointer
5413*4882a593Smuzhiyun 	 */
5414*4882a593Smuzhiyun 	bfa_mem_kva_curp(ufm) = (u8 *) uf;
5415*4882a593Smuzhiyun }
5416*4882a593Smuzhiyun 
5417*4882a593Smuzhiyun static void
uf_mem_claim(struct bfa_uf_mod_s * ufm)5418*4882a593Smuzhiyun uf_mem_claim(struct bfa_uf_mod_s *ufm)
5419*4882a593Smuzhiyun {
5420*4882a593Smuzhiyun 	claim_ufs(ufm);
5421*4882a593Smuzhiyun 	claim_uf_post_msgs(ufm);
5422*4882a593Smuzhiyun }
5423*4882a593Smuzhiyun 
5424*4882a593Smuzhiyun void
bfa_uf_meminfo(struct bfa_iocfc_cfg_s * cfg,struct bfa_meminfo_s * minfo,struct bfa_s * bfa)5425*4882a593Smuzhiyun bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5426*4882a593Smuzhiyun 		struct bfa_s *bfa)
5427*4882a593Smuzhiyun {
5428*4882a593Smuzhiyun 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5429*4882a593Smuzhiyun 	struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);
5430*4882a593Smuzhiyun 	u32	num_ufs = cfg->fwcfg.num_uf_bufs;
5431*4882a593Smuzhiyun 	struct bfa_mem_dma_s *seg_ptr;
5432*4882a593Smuzhiyun 	u16	nsegs, idx, per_seg_uf = 0;
5433*4882a593Smuzhiyun 
5434*4882a593Smuzhiyun 	nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);
5435*4882a593Smuzhiyun 	per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);
5436*4882a593Smuzhiyun 
5437*4882a593Smuzhiyun 	bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {
5438*4882a593Smuzhiyun 		if (num_ufs >= per_seg_uf) {
5439*4882a593Smuzhiyun 			num_ufs -= per_seg_uf;
5440*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
5441*4882a593Smuzhiyun 				per_seg_uf * BFA_PER_UF_DMA_SZ);
5442*4882a593Smuzhiyun 		} else
5443*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
5444*4882a593Smuzhiyun 				num_ufs * BFA_PER_UF_DMA_SZ);
5445*4882a593Smuzhiyun 	}
5446*4882a593Smuzhiyun 
5447*4882a593Smuzhiyun 	/* kva memory */
5448*4882a593Smuzhiyun 	bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *
5449*4882a593Smuzhiyun 		(sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
5450*4882a593Smuzhiyun }
5451*4882a593Smuzhiyun 
5452*4882a593Smuzhiyun void
bfa_uf_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)5453*4882a593Smuzhiyun bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5454*4882a593Smuzhiyun 		struct bfa_pcidev_s *pcidev)
5455*4882a593Smuzhiyun {
5456*4882a593Smuzhiyun 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5457*4882a593Smuzhiyun 
5458*4882a593Smuzhiyun 	ufm->bfa = bfa;
5459*4882a593Smuzhiyun 	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
5460*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ufm->uf_free_q);
5461*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ufm->uf_posted_q);
5462*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ufm->uf_unused_q);
5463*4882a593Smuzhiyun 
5464*4882a593Smuzhiyun 	uf_mem_claim(ufm);
5465*4882a593Smuzhiyun }
5466*4882a593Smuzhiyun 
5467*4882a593Smuzhiyun static struct bfa_uf_s *
bfa_uf_get(struct bfa_uf_mod_s * uf_mod)5468*4882a593Smuzhiyun bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
5469*4882a593Smuzhiyun {
5470*4882a593Smuzhiyun 	struct bfa_uf_s   *uf;
5471*4882a593Smuzhiyun 
5472*4882a593Smuzhiyun 	bfa_q_deq(&uf_mod->uf_free_q, &uf);
5473*4882a593Smuzhiyun 	return uf;
5474*4882a593Smuzhiyun }
5475*4882a593Smuzhiyun 
5476*4882a593Smuzhiyun static void
bfa_uf_put(struct bfa_uf_mod_s * uf_mod,struct bfa_uf_s * uf)5477*4882a593Smuzhiyun bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
5478*4882a593Smuzhiyun {
5479*4882a593Smuzhiyun 	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
5480*4882a593Smuzhiyun }
5481*4882a593Smuzhiyun 
5482*4882a593Smuzhiyun static bfa_status_t
bfa_uf_post(struct bfa_uf_mod_s * ufm,struct bfa_uf_s * uf)5483*4882a593Smuzhiyun bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
5484*4882a593Smuzhiyun {
5485*4882a593Smuzhiyun 	struct bfi_uf_buf_post_s *uf_post_msg;
5486*4882a593Smuzhiyun 
5487*4882a593Smuzhiyun 	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
5488*4882a593Smuzhiyun 	if (!uf_post_msg)
5489*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
5490*4882a593Smuzhiyun 
5491*4882a593Smuzhiyun 	memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
5492*4882a593Smuzhiyun 		      sizeof(struct bfi_uf_buf_post_s));
5493*4882a593Smuzhiyun 	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
5494*4882a593Smuzhiyun 
5495*4882a593Smuzhiyun 	bfa_trc(ufm->bfa, uf->uf_tag);
5496*4882a593Smuzhiyun 
5497*4882a593Smuzhiyun 	list_add_tail(&uf->qe, &ufm->uf_posted_q);
5498*4882a593Smuzhiyun 	return BFA_STATUS_OK;
5499*4882a593Smuzhiyun }
5500*4882a593Smuzhiyun 
5501*4882a593Smuzhiyun static void
bfa_uf_post_all(struct bfa_uf_mod_s * uf_mod)5502*4882a593Smuzhiyun bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
5503*4882a593Smuzhiyun {
5504*4882a593Smuzhiyun 	struct bfa_uf_s   *uf;
5505*4882a593Smuzhiyun 
5506*4882a593Smuzhiyun 	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
5507*4882a593Smuzhiyun 		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
5508*4882a593Smuzhiyun 			break;
5509*4882a593Smuzhiyun 	}
5510*4882a593Smuzhiyun }
5511*4882a593Smuzhiyun 
5512*4882a593Smuzhiyun static void
uf_recv(struct bfa_s * bfa,struct bfi_uf_frm_rcvd_s * m)5513*4882a593Smuzhiyun uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
5514*4882a593Smuzhiyun {
5515*4882a593Smuzhiyun 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5516*4882a593Smuzhiyun 	u16 uf_tag = m->buf_tag;
5517*4882a593Smuzhiyun 	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
5518*4882a593Smuzhiyun 	struct bfa_uf_buf_s *uf_buf;
5519*4882a593Smuzhiyun 	uint8_t *buf;
5520*4882a593Smuzhiyun 
5521*4882a593Smuzhiyun 	uf_buf = (struct bfa_uf_buf_s *)
5522*4882a593Smuzhiyun 			bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
5523*4882a593Smuzhiyun 	buf = &uf_buf->d[0];
5524*4882a593Smuzhiyun 
5525*4882a593Smuzhiyun 	m->frm_len = be16_to_cpu(m->frm_len);
5526*4882a593Smuzhiyun 	m->xfr_len = be16_to_cpu(m->xfr_len);
5527*4882a593Smuzhiyun 
5528*4882a593Smuzhiyun 	list_del(&uf->qe);	/* dequeue from posted queue */
5529*4882a593Smuzhiyun 
5530*4882a593Smuzhiyun 	uf->data_ptr = buf;
5531*4882a593Smuzhiyun 	uf->data_len = m->xfr_len;
5532*4882a593Smuzhiyun 
5533*4882a593Smuzhiyun 	WARN_ON(uf->data_len < sizeof(struct fchs_s));
5534*4882a593Smuzhiyun 
5535*4882a593Smuzhiyun 	if (uf->data_len == sizeof(struct fchs_s)) {
5536*4882a593Smuzhiyun 		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
5537*4882a593Smuzhiyun 			       uf->data_len, (struct fchs_s *)buf);
5538*4882a593Smuzhiyun 	} else {
5539*4882a593Smuzhiyun 		u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
5540*4882a593Smuzhiyun 		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
5541*4882a593Smuzhiyun 				      BFA_PL_EID_RX, uf->data_len,
5542*4882a593Smuzhiyun 				      (struct fchs_s *)buf, pld_w0);
5543*4882a593Smuzhiyun 	}
5544*4882a593Smuzhiyun 
5545*4882a593Smuzhiyun 	if (bfa->fcs)
5546*4882a593Smuzhiyun 		__bfa_cb_uf_recv(uf, BFA_TRUE);
5547*4882a593Smuzhiyun 	else
5548*4882a593Smuzhiyun 		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
5549*4882a593Smuzhiyun }
5550*4882a593Smuzhiyun 
5551*4882a593Smuzhiyun void
bfa_uf_iocdisable(struct bfa_s * bfa)5552*4882a593Smuzhiyun bfa_uf_iocdisable(struct bfa_s *bfa)
5553*4882a593Smuzhiyun {
5554*4882a593Smuzhiyun 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5555*4882a593Smuzhiyun 	struct bfa_uf_s *uf;
5556*4882a593Smuzhiyun 	struct list_head *qe, *qen;
5557*4882a593Smuzhiyun 
5558*4882a593Smuzhiyun 	/* Enqueue unused uf resources to free_q */
5559*4882a593Smuzhiyun 	list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);
5560*4882a593Smuzhiyun 
5561*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
5562*4882a593Smuzhiyun 		uf = (struct bfa_uf_s *) qe;
5563*4882a593Smuzhiyun 		list_del(&uf->qe);
5564*4882a593Smuzhiyun 		bfa_uf_put(ufm, uf);
5565*4882a593Smuzhiyun 	}
5566*4882a593Smuzhiyun }
5567*4882a593Smuzhiyun 
5568*4882a593Smuzhiyun void
bfa_uf_start(struct bfa_s * bfa)5569*4882a593Smuzhiyun bfa_uf_start(struct bfa_s *bfa)
5570*4882a593Smuzhiyun {
5571*4882a593Smuzhiyun 	bfa_uf_post_all(BFA_UF_MOD(bfa));
5572*4882a593Smuzhiyun }
5573*4882a593Smuzhiyun 
5574*4882a593Smuzhiyun /*
5575*4882a593Smuzhiyun  * Register handler for all unsolicted receive frames.
5576*4882a593Smuzhiyun  *
5577*4882a593Smuzhiyun  * @param[in]	bfa		BFA instance
5578*4882a593Smuzhiyun  * @param[in]	ufrecv	receive handler function
5579*4882a593Smuzhiyun  * @param[in]	cbarg	receive handler arg
5580*4882a593Smuzhiyun  */
5581*4882a593Smuzhiyun void
bfa_uf_recv_register(struct bfa_s * bfa,bfa_cb_uf_recv_t ufrecv,void * cbarg)5582*4882a593Smuzhiyun bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
5583*4882a593Smuzhiyun {
5584*4882a593Smuzhiyun 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5585*4882a593Smuzhiyun 
5586*4882a593Smuzhiyun 	ufm->ufrecv = ufrecv;
5587*4882a593Smuzhiyun 	ufm->cbarg = cbarg;
5588*4882a593Smuzhiyun }
5589*4882a593Smuzhiyun 
5590*4882a593Smuzhiyun /*
5591*4882a593Smuzhiyun  *	Free an unsolicited frame back to BFA.
5592*4882a593Smuzhiyun  *
5593*4882a593Smuzhiyun  * @param[in]		uf		unsolicited frame to be freed
5594*4882a593Smuzhiyun  *
5595*4882a593Smuzhiyun  * @return None
5596*4882a593Smuzhiyun  */
5597*4882a593Smuzhiyun void
bfa_uf_free(struct bfa_uf_s * uf)5598*4882a593Smuzhiyun bfa_uf_free(struct bfa_uf_s *uf)
5599*4882a593Smuzhiyun {
5600*4882a593Smuzhiyun 	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
5601*4882a593Smuzhiyun 	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
5602*4882a593Smuzhiyun }
5603*4882a593Smuzhiyun 
5604*4882a593Smuzhiyun 
5605*4882a593Smuzhiyun 
5606*4882a593Smuzhiyun /*
5607*4882a593Smuzhiyun  *  uf_pub BFA uf module public functions
5608*4882a593Smuzhiyun  */
5609*4882a593Smuzhiyun void
bfa_uf_isr(struct bfa_s * bfa,struct bfi_msg_s * msg)5610*4882a593Smuzhiyun bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5611*4882a593Smuzhiyun {
5612*4882a593Smuzhiyun 	bfa_trc(bfa, msg->mhdr.msg_id);
5613*4882a593Smuzhiyun 
5614*4882a593Smuzhiyun 	switch (msg->mhdr.msg_id) {
5615*4882a593Smuzhiyun 	case BFI_UF_I2H_FRM_RCVD:
5616*4882a593Smuzhiyun 		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
5617*4882a593Smuzhiyun 		break;
5618*4882a593Smuzhiyun 
5619*4882a593Smuzhiyun 	default:
5620*4882a593Smuzhiyun 		bfa_trc(bfa, msg->mhdr.msg_id);
5621*4882a593Smuzhiyun 		WARN_ON(1);
5622*4882a593Smuzhiyun 	}
5623*4882a593Smuzhiyun }
5624*4882a593Smuzhiyun 
5625*4882a593Smuzhiyun void
bfa_uf_res_recfg(struct bfa_s * bfa,u16 num_uf_fw)5626*4882a593Smuzhiyun bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
5627*4882a593Smuzhiyun {
5628*4882a593Smuzhiyun 	struct bfa_uf_mod_s	*mod = BFA_UF_MOD(bfa);
5629*4882a593Smuzhiyun 	struct list_head	*qe;
5630*4882a593Smuzhiyun 	int	i;
5631*4882a593Smuzhiyun 
5632*4882a593Smuzhiyun 	for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
5633*4882a593Smuzhiyun 		bfa_q_deq_tail(&mod->uf_free_q, &qe);
5634*4882a593Smuzhiyun 		list_add_tail(qe, &mod->uf_unused_q);
5635*4882a593Smuzhiyun 	}
5636*4882a593Smuzhiyun }
5637*4882a593Smuzhiyun 
5638*4882a593Smuzhiyun /*
5639*4882a593Smuzhiyun  *	Dport forward declaration
5640*4882a593Smuzhiyun  */
5641*4882a593Smuzhiyun 
5642*4882a593Smuzhiyun enum bfa_dport_test_state_e {
5643*4882a593Smuzhiyun 	BFA_DPORT_ST_DISABLED	= 0,	/*!< dport is disabled */
5644*4882a593Smuzhiyun 	BFA_DPORT_ST_INP	= 1,	/*!< test in progress */
5645*4882a593Smuzhiyun 	BFA_DPORT_ST_COMP	= 2,	/*!< test complete successfully */
5646*4882a593Smuzhiyun 	BFA_DPORT_ST_NO_SFP	= 3,	/*!< sfp is not present */
5647*4882a593Smuzhiyun 	BFA_DPORT_ST_NOTSTART	= 4,	/*!< test not start dport is enabled */
5648*4882a593Smuzhiyun };
5649*4882a593Smuzhiyun 
5650*4882a593Smuzhiyun /*
5651*4882a593Smuzhiyun  * BFA DPORT state machine events
5652*4882a593Smuzhiyun  */
5653*4882a593Smuzhiyun enum bfa_dport_sm_event {
5654*4882a593Smuzhiyun 	BFA_DPORT_SM_ENABLE	= 1,	/* dport enable event         */
5655*4882a593Smuzhiyun 	BFA_DPORT_SM_DISABLE    = 2,    /* dport disable event        */
5656*4882a593Smuzhiyun 	BFA_DPORT_SM_FWRSP      = 3,    /* fw enable/disable rsp      */
5657*4882a593Smuzhiyun 	BFA_DPORT_SM_QRESUME    = 4,    /* CQ space available         */
5658*4882a593Smuzhiyun 	BFA_DPORT_SM_HWFAIL     = 5,    /* IOC h/w failure            */
5659*4882a593Smuzhiyun 	BFA_DPORT_SM_START	= 6,	/* re-start dport test        */
5660*4882a593Smuzhiyun 	BFA_DPORT_SM_REQFAIL	= 7,	/* request failure            */
5661*4882a593Smuzhiyun 	BFA_DPORT_SM_SCN	= 8,	/* state change notify frm fw */
5662*4882a593Smuzhiyun };
5663*4882a593Smuzhiyun 
5664*4882a593Smuzhiyun static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
5665*4882a593Smuzhiyun 				  enum bfa_dport_sm_event event);
5666*4882a593Smuzhiyun static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
5667*4882a593Smuzhiyun 				  enum bfa_dport_sm_event event);
5668*4882a593Smuzhiyun static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
5669*4882a593Smuzhiyun 				  enum bfa_dport_sm_event event);
5670*4882a593Smuzhiyun static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
5671*4882a593Smuzhiyun 				 enum bfa_dport_sm_event event);
5672*4882a593Smuzhiyun static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
5673*4882a593Smuzhiyun 				 enum bfa_dport_sm_event event);
5674*4882a593Smuzhiyun static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
5675*4882a593Smuzhiyun 				   enum bfa_dport_sm_event event);
5676*4882a593Smuzhiyun static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
5677*4882a593Smuzhiyun 					enum bfa_dport_sm_event event);
5678*4882a593Smuzhiyun static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
5679*4882a593Smuzhiyun 				  enum bfa_dport_sm_event event);
5680*4882a593Smuzhiyun static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
5681*4882a593Smuzhiyun 				   enum bfa_dport_sm_event event);
5682*4882a593Smuzhiyun static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
5683*4882a593Smuzhiyun 				   enum bfa_dport_sm_event event);
5684*4882a593Smuzhiyun static void bfa_dport_qresume(void *cbarg);
5685*4882a593Smuzhiyun static void bfa_dport_req_comp(struct bfa_dport_s *dport,
5686*4882a593Smuzhiyun 				struct bfi_diag_dport_rsp_s *msg);
5687*4882a593Smuzhiyun static void bfa_dport_scn(struct bfa_dport_s *dport,
5688*4882a593Smuzhiyun 				struct bfi_diag_dport_scn_s *msg);
5689*4882a593Smuzhiyun 
5690*4882a593Smuzhiyun /*
5691*4882a593Smuzhiyun  *	BFA fcdiag module
5692*4882a593Smuzhiyun  */
5693*4882a593Smuzhiyun #define BFA_DIAG_QTEST_TOV	1000    /* msec */
5694*4882a593Smuzhiyun 
5695*4882a593Smuzhiyun /*
5696*4882a593Smuzhiyun  *	Set port status to busy
5697*4882a593Smuzhiyun  */
5698*4882a593Smuzhiyun static void
bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s * fcdiag)5699*4882a593Smuzhiyun bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
5700*4882a593Smuzhiyun {
5701*4882a593Smuzhiyun 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
5702*4882a593Smuzhiyun 
5703*4882a593Smuzhiyun 	if (fcdiag->lb.lock)
5704*4882a593Smuzhiyun 		fcport->diag_busy = BFA_TRUE;
5705*4882a593Smuzhiyun 	else
5706*4882a593Smuzhiyun 		fcport->diag_busy = BFA_FALSE;
5707*4882a593Smuzhiyun }
5708*4882a593Smuzhiyun 
5709*4882a593Smuzhiyun void
bfa_fcdiag_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)5710*4882a593Smuzhiyun bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5711*4882a593Smuzhiyun 		struct bfa_pcidev_s *pcidev)
5712*4882a593Smuzhiyun {
5713*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5714*4882a593Smuzhiyun 	struct bfa_dport_s  *dport = &fcdiag->dport;
5715*4882a593Smuzhiyun 
5716*4882a593Smuzhiyun 	fcdiag->bfa             = bfa;
5717*4882a593Smuzhiyun 	fcdiag->trcmod  = bfa->trcmod;
5718*4882a593Smuzhiyun 	/* The common DIAG attach bfa_diag_attach() will do all memory claim */
5719*4882a593Smuzhiyun 	dport->bfa = bfa;
5720*4882a593Smuzhiyun 	bfa_sm_set_state(dport, bfa_dport_sm_disabled);
5721*4882a593Smuzhiyun 	bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
5722*4882a593Smuzhiyun 	dport->cbfn = NULL;
5723*4882a593Smuzhiyun 	dport->cbarg = NULL;
5724*4882a593Smuzhiyun 	dport->test_state = BFA_DPORT_ST_DISABLED;
5725*4882a593Smuzhiyun 	memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
5726*4882a593Smuzhiyun }
5727*4882a593Smuzhiyun 
5728*4882a593Smuzhiyun void
bfa_fcdiag_iocdisable(struct bfa_s * bfa)5729*4882a593Smuzhiyun bfa_fcdiag_iocdisable(struct bfa_s *bfa)
5730*4882a593Smuzhiyun {
5731*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5732*4882a593Smuzhiyun 	struct bfa_dport_s *dport = &fcdiag->dport;
5733*4882a593Smuzhiyun 
5734*4882a593Smuzhiyun 	bfa_trc(fcdiag, fcdiag->lb.lock);
5735*4882a593Smuzhiyun 	if (fcdiag->lb.lock) {
5736*4882a593Smuzhiyun 		fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
5737*4882a593Smuzhiyun 		fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5738*4882a593Smuzhiyun 		fcdiag->lb.lock = 0;
5739*4882a593Smuzhiyun 		bfa_fcdiag_set_busy_status(fcdiag);
5740*4882a593Smuzhiyun 	}
5741*4882a593Smuzhiyun 
5742*4882a593Smuzhiyun 	bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
5743*4882a593Smuzhiyun }
5744*4882a593Smuzhiyun 
5745*4882a593Smuzhiyun static void
bfa_fcdiag_queuetest_timeout(void * cbarg)5746*4882a593Smuzhiyun bfa_fcdiag_queuetest_timeout(void *cbarg)
5747*4882a593Smuzhiyun {
5748*4882a593Smuzhiyun 	struct bfa_fcdiag_s       *fcdiag = cbarg;
5749*4882a593Smuzhiyun 	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5750*4882a593Smuzhiyun 
5751*4882a593Smuzhiyun 	bfa_trc(fcdiag, fcdiag->qtest.all);
5752*4882a593Smuzhiyun 	bfa_trc(fcdiag, fcdiag->qtest.count);
5753*4882a593Smuzhiyun 
5754*4882a593Smuzhiyun 	fcdiag->qtest.timer_active = 0;
5755*4882a593Smuzhiyun 
5756*4882a593Smuzhiyun 	res->status = BFA_STATUS_ETIMER;
5757*4882a593Smuzhiyun 	res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5758*4882a593Smuzhiyun 	if (fcdiag->qtest.all)
5759*4882a593Smuzhiyun 		res->queue  = fcdiag->qtest.all;
5760*4882a593Smuzhiyun 
5761*4882a593Smuzhiyun 	bfa_trc(fcdiag, BFA_STATUS_ETIMER);
5762*4882a593Smuzhiyun 	fcdiag->qtest.status = BFA_STATUS_ETIMER;
5763*4882a593Smuzhiyun 	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5764*4882a593Smuzhiyun 	fcdiag->qtest.lock = 0;
5765*4882a593Smuzhiyun }
5766*4882a593Smuzhiyun 
5767*4882a593Smuzhiyun static bfa_status_t
bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s * fcdiag)5768*4882a593Smuzhiyun bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
5769*4882a593Smuzhiyun {
5770*4882a593Smuzhiyun 	u32	i;
5771*4882a593Smuzhiyun 	struct bfi_diag_qtest_req_s *req;
5772*4882a593Smuzhiyun 
5773*4882a593Smuzhiyun 	req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
5774*4882a593Smuzhiyun 	if (!req)
5775*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
5776*4882a593Smuzhiyun 
5777*4882a593Smuzhiyun 	/* build host command */
5778*4882a593Smuzhiyun 	bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
5779*4882a593Smuzhiyun 		bfa_fn_lpu(fcdiag->bfa));
5780*4882a593Smuzhiyun 
5781*4882a593Smuzhiyun 	for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
5782*4882a593Smuzhiyun 		req->data[i] = QTEST_PAT_DEFAULT;
5783*4882a593Smuzhiyun 
5784*4882a593Smuzhiyun 	bfa_trc(fcdiag, fcdiag->qtest.queue);
5785*4882a593Smuzhiyun 	/* ring door bell */
5786*4882a593Smuzhiyun 	bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
5787*4882a593Smuzhiyun 	return BFA_STATUS_OK;
5788*4882a593Smuzhiyun }
5789*4882a593Smuzhiyun 
5790*4882a593Smuzhiyun static void
bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s * fcdiag,bfi_diag_qtest_rsp_t * rsp)5791*4882a593Smuzhiyun bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
5792*4882a593Smuzhiyun 			bfi_diag_qtest_rsp_t *rsp)
5793*4882a593Smuzhiyun {
5794*4882a593Smuzhiyun 	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5795*4882a593Smuzhiyun 	bfa_status_t status = BFA_STATUS_OK;
5796*4882a593Smuzhiyun 	int i;
5797*4882a593Smuzhiyun 
5798*4882a593Smuzhiyun 	/* Check timer, should still be active   */
5799*4882a593Smuzhiyun 	if (!fcdiag->qtest.timer_active) {
5800*4882a593Smuzhiyun 		bfa_trc(fcdiag, fcdiag->qtest.timer_active);
5801*4882a593Smuzhiyun 		return;
5802*4882a593Smuzhiyun 	}
5803*4882a593Smuzhiyun 
5804*4882a593Smuzhiyun 	/* update count */
5805*4882a593Smuzhiyun 	fcdiag->qtest.count--;
5806*4882a593Smuzhiyun 
5807*4882a593Smuzhiyun 	/* Check result */
5808*4882a593Smuzhiyun 	for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
5809*4882a593Smuzhiyun 		if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
5810*4882a593Smuzhiyun 			res->status = BFA_STATUS_DATACORRUPTED;
5811*4882a593Smuzhiyun 			break;
5812*4882a593Smuzhiyun 		}
5813*4882a593Smuzhiyun 	}
5814*4882a593Smuzhiyun 
5815*4882a593Smuzhiyun 	if (res->status == BFA_STATUS_OK) {
5816*4882a593Smuzhiyun 		if (fcdiag->qtest.count > 0) {
5817*4882a593Smuzhiyun 			status = bfa_fcdiag_queuetest_send(fcdiag);
5818*4882a593Smuzhiyun 			if (status == BFA_STATUS_OK)
5819*4882a593Smuzhiyun 				return;
5820*4882a593Smuzhiyun 			else
5821*4882a593Smuzhiyun 				res->status = status;
5822*4882a593Smuzhiyun 		} else if (fcdiag->qtest.all > 0 &&
5823*4882a593Smuzhiyun 			fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
5824*4882a593Smuzhiyun 			fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5825*4882a593Smuzhiyun 			fcdiag->qtest.queue++;
5826*4882a593Smuzhiyun 			status = bfa_fcdiag_queuetest_send(fcdiag);
5827*4882a593Smuzhiyun 			if (status == BFA_STATUS_OK)
5828*4882a593Smuzhiyun 				return;
5829*4882a593Smuzhiyun 			else
5830*4882a593Smuzhiyun 				res->status = status;
5831*4882a593Smuzhiyun 		}
5832*4882a593Smuzhiyun 	}
5833*4882a593Smuzhiyun 
5834*4882a593Smuzhiyun 	/* Stop timer when we comp all queue */
5835*4882a593Smuzhiyun 	if (fcdiag->qtest.timer_active) {
5836*4882a593Smuzhiyun 		bfa_timer_stop(&fcdiag->qtest.timer);
5837*4882a593Smuzhiyun 		fcdiag->qtest.timer_active = 0;
5838*4882a593Smuzhiyun 	}
5839*4882a593Smuzhiyun 	res->queue = fcdiag->qtest.queue;
5840*4882a593Smuzhiyun 	res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5841*4882a593Smuzhiyun 	bfa_trc(fcdiag, res->count);
5842*4882a593Smuzhiyun 	bfa_trc(fcdiag, res->status);
5843*4882a593Smuzhiyun 	fcdiag->qtest.status = res->status;
5844*4882a593Smuzhiyun 	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5845*4882a593Smuzhiyun 	fcdiag->qtest.lock = 0;
5846*4882a593Smuzhiyun }
5847*4882a593Smuzhiyun 
5848*4882a593Smuzhiyun static void
bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s * fcdiag,struct bfi_diag_lb_rsp_s * rsp)5849*4882a593Smuzhiyun bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
5850*4882a593Smuzhiyun 			struct bfi_diag_lb_rsp_s *rsp)
5851*4882a593Smuzhiyun {
5852*4882a593Smuzhiyun 	struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
5853*4882a593Smuzhiyun 
5854*4882a593Smuzhiyun 	res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm);
5855*4882a593Smuzhiyun 	res->numosffrm  = be32_to_cpu(rsp->res.numosffrm);
5856*4882a593Smuzhiyun 	res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm);
5857*4882a593Smuzhiyun 	res->badfrminf  = be32_to_cpu(rsp->res.badfrminf);
5858*4882a593Smuzhiyun 	res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum);
5859*4882a593Smuzhiyun 	res->status     = rsp->res.status;
5860*4882a593Smuzhiyun 	fcdiag->lb.status = rsp->res.status;
5861*4882a593Smuzhiyun 	bfa_trc(fcdiag, fcdiag->lb.status);
5862*4882a593Smuzhiyun 	fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5863*4882a593Smuzhiyun 	fcdiag->lb.lock = 0;
5864*4882a593Smuzhiyun 	bfa_fcdiag_set_busy_status(fcdiag);
5865*4882a593Smuzhiyun }
5866*4882a593Smuzhiyun 
5867*4882a593Smuzhiyun static bfa_status_t
bfa_fcdiag_loopback_send(struct bfa_fcdiag_s * fcdiag,struct bfa_diag_loopback_s * loopback)5868*4882a593Smuzhiyun bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
5869*4882a593Smuzhiyun 			struct bfa_diag_loopback_s *loopback)
5870*4882a593Smuzhiyun {
5871*4882a593Smuzhiyun 	struct bfi_diag_lb_req_s *lb_req;
5872*4882a593Smuzhiyun 
5873*4882a593Smuzhiyun 	lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
5874*4882a593Smuzhiyun 	if (!lb_req)
5875*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
5876*4882a593Smuzhiyun 
5877*4882a593Smuzhiyun 	/* build host command */
5878*4882a593Smuzhiyun 	bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
5879*4882a593Smuzhiyun 		bfa_fn_lpu(fcdiag->bfa));
5880*4882a593Smuzhiyun 
5881*4882a593Smuzhiyun 	lb_req->lb_mode = loopback->lb_mode;
5882*4882a593Smuzhiyun 	lb_req->speed = loopback->speed;
5883*4882a593Smuzhiyun 	lb_req->loopcnt = loopback->loopcnt;
5884*4882a593Smuzhiyun 	lb_req->pattern = loopback->pattern;
5885*4882a593Smuzhiyun 
5886*4882a593Smuzhiyun 	/* ring door bell */
5887*4882a593Smuzhiyun 	bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
5888*4882a593Smuzhiyun 
5889*4882a593Smuzhiyun 	bfa_trc(fcdiag, loopback->lb_mode);
5890*4882a593Smuzhiyun 	bfa_trc(fcdiag, loopback->speed);
5891*4882a593Smuzhiyun 	bfa_trc(fcdiag, loopback->loopcnt);
5892*4882a593Smuzhiyun 	bfa_trc(fcdiag, loopback->pattern);
5893*4882a593Smuzhiyun 	return BFA_STATUS_OK;
5894*4882a593Smuzhiyun }
5895*4882a593Smuzhiyun 
5896*4882a593Smuzhiyun /*
5897*4882a593Smuzhiyun  *	cpe/rme intr handler
5898*4882a593Smuzhiyun  */
5899*4882a593Smuzhiyun void
bfa_fcdiag_intr(struct bfa_s * bfa,struct bfi_msg_s * msg)5900*4882a593Smuzhiyun bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5901*4882a593Smuzhiyun {
5902*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5903*4882a593Smuzhiyun 
5904*4882a593Smuzhiyun 	switch (msg->mhdr.msg_id) {
5905*4882a593Smuzhiyun 	case BFI_DIAG_I2H_LOOPBACK:
5906*4882a593Smuzhiyun 		bfa_fcdiag_loopback_comp(fcdiag,
5907*4882a593Smuzhiyun 				(struct bfi_diag_lb_rsp_s *) msg);
5908*4882a593Smuzhiyun 		break;
5909*4882a593Smuzhiyun 	case BFI_DIAG_I2H_QTEST:
5910*4882a593Smuzhiyun 		bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
5911*4882a593Smuzhiyun 		break;
5912*4882a593Smuzhiyun 	case BFI_DIAG_I2H_DPORT:
5913*4882a593Smuzhiyun 		bfa_dport_req_comp(&fcdiag->dport,
5914*4882a593Smuzhiyun 				(struct bfi_diag_dport_rsp_s *)msg);
5915*4882a593Smuzhiyun 		break;
5916*4882a593Smuzhiyun 	case BFI_DIAG_I2H_DPORT_SCN:
5917*4882a593Smuzhiyun 		bfa_dport_scn(&fcdiag->dport,
5918*4882a593Smuzhiyun 				(struct bfi_diag_dport_scn_s *)msg);
5919*4882a593Smuzhiyun 		break;
5920*4882a593Smuzhiyun 	default:
5921*4882a593Smuzhiyun 		bfa_trc(fcdiag, msg->mhdr.msg_id);
5922*4882a593Smuzhiyun 		WARN_ON(1);
5923*4882a593Smuzhiyun 	}
5924*4882a593Smuzhiyun }
5925*4882a593Smuzhiyun 
5926*4882a593Smuzhiyun /*
5927*4882a593Smuzhiyun  *	Loopback test
5928*4882a593Smuzhiyun  *
5929*4882a593Smuzhiyun  *   @param[in] *bfa            - bfa data struct
5930*4882a593Smuzhiyun  *   @param[in] opmode          - port operation mode
5931*4882a593Smuzhiyun  *   @param[in] speed           - port speed
5932*4882a593Smuzhiyun  *   @param[in] lpcnt           - loop count
5933*4882a593Smuzhiyun  *   @param[in] pat                     - pattern to build packet
5934*4882a593Smuzhiyun  *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct
5935*4882a593Smuzhiyun  *   @param[in] cbfn            - callback function
5936*4882a593Smuzhiyun  *   @param[in] cbarg           - callback functioin arg
5937*4882a593Smuzhiyun  *
5938*4882a593Smuzhiyun  *   @param[out]
5939*4882a593Smuzhiyun  */
5940*4882a593Smuzhiyun bfa_status_t
bfa_fcdiag_loopback(struct bfa_s * bfa,enum bfa_port_opmode opmode,enum bfa_port_speed speed,u32 lpcnt,u32 pat,struct bfa_diag_loopback_result_s * result,bfa_cb_diag_t cbfn,void * cbarg)5941*4882a593Smuzhiyun bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
5942*4882a593Smuzhiyun 		enum bfa_port_speed speed, u32 lpcnt, u32 pat,
5943*4882a593Smuzhiyun 		struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
5944*4882a593Smuzhiyun 		void *cbarg)
5945*4882a593Smuzhiyun {
5946*4882a593Smuzhiyun 	struct  bfa_diag_loopback_s loopback;
5947*4882a593Smuzhiyun 	struct bfa_port_attr_s attr;
5948*4882a593Smuzhiyun 	bfa_status_t status;
5949*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5950*4882a593Smuzhiyun 
5951*4882a593Smuzhiyun 	if (!bfa_iocfc_is_operational(bfa))
5952*4882a593Smuzhiyun 		return BFA_STATUS_IOC_NON_OP;
5953*4882a593Smuzhiyun 
5954*4882a593Smuzhiyun 	/* if port is PBC disabled, return error */
5955*4882a593Smuzhiyun 	if (bfa_fcport_is_pbcdisabled(bfa)) {
5956*4882a593Smuzhiyun 		bfa_trc(fcdiag, BFA_STATUS_PBC);
5957*4882a593Smuzhiyun 		return BFA_STATUS_PBC;
5958*4882a593Smuzhiyun 	}
5959*4882a593Smuzhiyun 
5960*4882a593Smuzhiyun 	if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
5961*4882a593Smuzhiyun 		bfa_trc(fcdiag, opmode);
5962*4882a593Smuzhiyun 		return BFA_STATUS_PORT_NOT_DISABLED;
5963*4882a593Smuzhiyun 	}
5964*4882a593Smuzhiyun 
5965*4882a593Smuzhiyun 	/*
5966*4882a593Smuzhiyun 	 * Check if input speed is supported by the port mode
5967*4882a593Smuzhiyun 	 */
5968*4882a593Smuzhiyun 	if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
5969*4882a593Smuzhiyun 		if (!(speed == BFA_PORT_SPEED_1GBPS ||
5970*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_2GBPS ||
5971*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_4GBPS ||
5972*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_8GBPS ||
5973*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_16GBPS ||
5974*4882a593Smuzhiyun 		      speed == BFA_PORT_SPEED_AUTO)) {
5975*4882a593Smuzhiyun 			bfa_trc(fcdiag, speed);
5976*4882a593Smuzhiyun 			return BFA_STATUS_UNSUPP_SPEED;
5977*4882a593Smuzhiyun 		}
5978*4882a593Smuzhiyun 		bfa_fcport_get_attr(bfa, &attr);
5979*4882a593Smuzhiyun 		bfa_trc(fcdiag, attr.speed_supported);
5980*4882a593Smuzhiyun 		if (speed > attr.speed_supported)
5981*4882a593Smuzhiyun 			return BFA_STATUS_UNSUPP_SPEED;
5982*4882a593Smuzhiyun 	} else {
5983*4882a593Smuzhiyun 		if (speed != BFA_PORT_SPEED_10GBPS) {
5984*4882a593Smuzhiyun 			bfa_trc(fcdiag, speed);
5985*4882a593Smuzhiyun 			return BFA_STATUS_UNSUPP_SPEED;
5986*4882a593Smuzhiyun 		}
5987*4882a593Smuzhiyun 	}
5988*4882a593Smuzhiyun 
5989*4882a593Smuzhiyun 	/*
5990*4882a593Smuzhiyun 	 * For CT2, 1G is not supported
5991*4882a593Smuzhiyun 	 */
5992*4882a593Smuzhiyun 	if ((speed == BFA_PORT_SPEED_1GBPS) &&
5993*4882a593Smuzhiyun 	    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
5994*4882a593Smuzhiyun 		bfa_trc(fcdiag, speed);
5995*4882a593Smuzhiyun 		return BFA_STATUS_UNSUPP_SPEED;
5996*4882a593Smuzhiyun 	}
5997*4882a593Smuzhiyun 
5998*4882a593Smuzhiyun 	/* For Mezz card, port speed entered needs to be checked */
5999*4882a593Smuzhiyun 	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
6000*4882a593Smuzhiyun 		if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
6001*4882a593Smuzhiyun 			if (!(speed == BFA_PORT_SPEED_1GBPS ||
6002*4882a593Smuzhiyun 			      speed == BFA_PORT_SPEED_2GBPS ||
6003*4882a593Smuzhiyun 			      speed == BFA_PORT_SPEED_4GBPS ||
6004*4882a593Smuzhiyun 			      speed == BFA_PORT_SPEED_8GBPS ||
6005*4882a593Smuzhiyun 			      speed == BFA_PORT_SPEED_16GBPS ||
6006*4882a593Smuzhiyun 			      speed == BFA_PORT_SPEED_AUTO))
6007*4882a593Smuzhiyun 				return BFA_STATUS_UNSUPP_SPEED;
6008*4882a593Smuzhiyun 		} else {
6009*4882a593Smuzhiyun 			if (speed != BFA_PORT_SPEED_10GBPS)
6010*4882a593Smuzhiyun 				return BFA_STATUS_UNSUPP_SPEED;
6011*4882a593Smuzhiyun 		}
6012*4882a593Smuzhiyun 	}
6013*4882a593Smuzhiyun 	/* check to see if fcport is dport */
6014*4882a593Smuzhiyun 	if (bfa_fcport_is_dport(bfa)) {
6015*4882a593Smuzhiyun 		bfa_trc(fcdiag, fcdiag->lb.lock);
6016*4882a593Smuzhiyun 		return BFA_STATUS_DPORT_ENABLED;
6017*4882a593Smuzhiyun 	}
6018*4882a593Smuzhiyun 	/* check to see if there is another destructive diag cmd running */
6019*4882a593Smuzhiyun 	if (fcdiag->lb.lock) {
6020*4882a593Smuzhiyun 		bfa_trc(fcdiag, fcdiag->lb.lock);
6021*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
6022*4882a593Smuzhiyun 	}
6023*4882a593Smuzhiyun 
6024*4882a593Smuzhiyun 	fcdiag->lb.lock = 1;
6025*4882a593Smuzhiyun 	loopback.lb_mode = opmode;
6026*4882a593Smuzhiyun 	loopback.speed = speed;
6027*4882a593Smuzhiyun 	loopback.loopcnt = lpcnt;
6028*4882a593Smuzhiyun 	loopback.pattern = pat;
6029*4882a593Smuzhiyun 	fcdiag->lb.result = result;
6030*4882a593Smuzhiyun 	fcdiag->lb.cbfn = cbfn;
6031*4882a593Smuzhiyun 	fcdiag->lb.cbarg = cbarg;
6032*4882a593Smuzhiyun 	memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
6033*4882a593Smuzhiyun 	bfa_fcdiag_set_busy_status(fcdiag);
6034*4882a593Smuzhiyun 
6035*4882a593Smuzhiyun 	/* Send msg to fw */
6036*4882a593Smuzhiyun 	status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
6037*4882a593Smuzhiyun 	return status;
6038*4882a593Smuzhiyun }
6039*4882a593Smuzhiyun 
6040*4882a593Smuzhiyun /*
6041*4882a593Smuzhiyun  *	DIAG queue test command
6042*4882a593Smuzhiyun  *
6043*4882a593Smuzhiyun  *   @param[in] *bfa            - bfa data struct
6044*4882a593Smuzhiyun  *   @param[in] force           - 1: don't do ioc op checking
6045*4882a593Smuzhiyun  *   @param[in] queue           - queue no. to test
6046*4882a593Smuzhiyun  *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct
6047*4882a593Smuzhiyun  *   @param[in] cbfn            - callback function
6048*4882a593Smuzhiyun  *   @param[in] *cbarg          - callback functioin arg
6049*4882a593Smuzhiyun  *
6050*4882a593Smuzhiyun  *   @param[out]
6051*4882a593Smuzhiyun  */
6052*4882a593Smuzhiyun bfa_status_t
bfa_fcdiag_queuetest(struct bfa_s * bfa,u32 force,u32 queue,struct bfa_diag_qtest_result_s * result,bfa_cb_diag_t cbfn,void * cbarg)6053*4882a593Smuzhiyun bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
6054*4882a593Smuzhiyun 		struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
6055*4882a593Smuzhiyun 		void *cbarg)
6056*4882a593Smuzhiyun {
6057*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6058*4882a593Smuzhiyun 	bfa_status_t status;
6059*4882a593Smuzhiyun 	bfa_trc(fcdiag, force);
6060*4882a593Smuzhiyun 	bfa_trc(fcdiag, queue);
6061*4882a593Smuzhiyun 
6062*4882a593Smuzhiyun 	if (!force && !bfa_iocfc_is_operational(bfa))
6063*4882a593Smuzhiyun 		return BFA_STATUS_IOC_NON_OP;
6064*4882a593Smuzhiyun 
6065*4882a593Smuzhiyun 	/* check to see if there is another destructive diag cmd running */
6066*4882a593Smuzhiyun 	if (fcdiag->qtest.lock) {
6067*4882a593Smuzhiyun 		bfa_trc(fcdiag, fcdiag->qtest.lock);
6068*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
6069*4882a593Smuzhiyun 	}
6070*4882a593Smuzhiyun 
6071*4882a593Smuzhiyun 	/* Initialization */
6072*4882a593Smuzhiyun 	fcdiag->qtest.lock = 1;
6073*4882a593Smuzhiyun 	fcdiag->qtest.cbfn = cbfn;
6074*4882a593Smuzhiyun 	fcdiag->qtest.cbarg = cbarg;
6075*4882a593Smuzhiyun 	fcdiag->qtest.result = result;
6076*4882a593Smuzhiyun 	fcdiag->qtest.count = QTEST_CNT_DEFAULT;
6077*4882a593Smuzhiyun 
6078*4882a593Smuzhiyun 	/* Init test results */
6079*4882a593Smuzhiyun 	fcdiag->qtest.result->status = BFA_STATUS_OK;
6080*4882a593Smuzhiyun 	fcdiag->qtest.result->count  = 0;
6081*4882a593Smuzhiyun 
6082*4882a593Smuzhiyun 	/* send */
6083*4882a593Smuzhiyun 	if (queue < BFI_IOC_MAX_CQS) {
6084*4882a593Smuzhiyun 		fcdiag->qtest.result->queue  = (u8)queue;
6085*4882a593Smuzhiyun 		fcdiag->qtest.queue = (u8)queue;
6086*4882a593Smuzhiyun 		fcdiag->qtest.all   = 0;
6087*4882a593Smuzhiyun 	} else {
6088*4882a593Smuzhiyun 		fcdiag->qtest.result->queue  = 0;
6089*4882a593Smuzhiyun 		fcdiag->qtest.queue = 0;
6090*4882a593Smuzhiyun 		fcdiag->qtest.all   = 1;
6091*4882a593Smuzhiyun 	}
6092*4882a593Smuzhiyun 	status = bfa_fcdiag_queuetest_send(fcdiag);
6093*4882a593Smuzhiyun 
6094*4882a593Smuzhiyun 	/* Start a timer */
6095*4882a593Smuzhiyun 	if (status == BFA_STATUS_OK) {
6096*4882a593Smuzhiyun 		bfa_timer_start(bfa, &fcdiag->qtest.timer,
6097*4882a593Smuzhiyun 				bfa_fcdiag_queuetest_timeout, fcdiag,
6098*4882a593Smuzhiyun 				BFA_DIAG_QTEST_TOV);
6099*4882a593Smuzhiyun 		fcdiag->qtest.timer_active = 1;
6100*4882a593Smuzhiyun 	}
6101*4882a593Smuzhiyun 	return status;
6102*4882a593Smuzhiyun }
6103*4882a593Smuzhiyun 
6104*4882a593Smuzhiyun /*
6105*4882a593Smuzhiyun  * DIAG PLB is running
6106*4882a593Smuzhiyun  *
6107*4882a593Smuzhiyun  *   @param[in] *bfa    - bfa data struct
6108*4882a593Smuzhiyun  *
6109*4882a593Smuzhiyun  *   @param[out]
6110*4882a593Smuzhiyun  */
6111*4882a593Smuzhiyun bfa_status_t
bfa_fcdiag_lb_is_running(struct bfa_s * bfa)6112*4882a593Smuzhiyun bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
6113*4882a593Smuzhiyun {
6114*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6115*4882a593Smuzhiyun 	return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
6116*4882a593Smuzhiyun }
6117*4882a593Smuzhiyun 
6118*4882a593Smuzhiyun /*
6119*4882a593Smuzhiyun  *	D-port
6120*4882a593Smuzhiyun  */
6121*4882a593Smuzhiyun #define bfa_dport_result_start(__dport, __mode) do {				\
6122*4882a593Smuzhiyun 		(__dport)->result.start_time = ktime_get_real_seconds();	\
6123*4882a593Smuzhiyun 		(__dport)->result.status = DPORT_TEST_ST_INPRG;			\
6124*4882a593Smuzhiyun 		(__dport)->result.mode = (__mode);				\
6125*4882a593Smuzhiyun 		(__dport)->result.rp_pwwn = (__dport)->rp_pwwn;			\
6126*4882a593Smuzhiyun 		(__dport)->result.rp_nwwn = (__dport)->rp_nwwn;			\
6127*4882a593Smuzhiyun 		(__dport)->result.lpcnt = (__dport)->lpcnt;			\
6128*4882a593Smuzhiyun } while (0)
6129*4882a593Smuzhiyun 
6130*4882a593Smuzhiyun static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
6131*4882a593Smuzhiyun 					enum bfi_dport_req req);
6132*4882a593Smuzhiyun static void
bfa_cb_fcdiag_dport(struct bfa_dport_s * dport,bfa_status_t bfa_status)6133*4882a593Smuzhiyun bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
6134*4882a593Smuzhiyun {
6135*4882a593Smuzhiyun 	if (dport->cbfn != NULL) {
6136*4882a593Smuzhiyun 		dport->cbfn(dport->cbarg, bfa_status);
6137*4882a593Smuzhiyun 		dport->cbfn = NULL;
6138*4882a593Smuzhiyun 		dport->cbarg = NULL;
6139*4882a593Smuzhiyun 	}
6140*4882a593Smuzhiyun }
6141*4882a593Smuzhiyun 
6142*4882a593Smuzhiyun static void
bfa_dport_sm_disabled(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6143*4882a593Smuzhiyun bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6144*4882a593Smuzhiyun {
6145*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6146*4882a593Smuzhiyun 
6147*4882a593Smuzhiyun 	switch (event) {
6148*4882a593Smuzhiyun 	case BFA_DPORT_SM_ENABLE:
6149*4882a593Smuzhiyun 		bfa_fcport_dportenable(dport->bfa);
6150*4882a593Smuzhiyun 		if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
6151*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6152*4882a593Smuzhiyun 		else
6153*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
6154*4882a593Smuzhiyun 		break;
6155*4882a593Smuzhiyun 
6156*4882a593Smuzhiyun 	case BFA_DPORT_SM_DISABLE:
6157*4882a593Smuzhiyun 		/* Already disabled */
6158*4882a593Smuzhiyun 		break;
6159*4882a593Smuzhiyun 
6160*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6161*4882a593Smuzhiyun 		/* ignore */
6162*4882a593Smuzhiyun 		break;
6163*4882a593Smuzhiyun 
6164*4882a593Smuzhiyun 	case BFA_DPORT_SM_SCN:
6165*4882a593Smuzhiyun 		if (dport->i2hmsg.scn.state ==  BFI_DPORT_SCN_DDPORT_ENABLE) {
6166*4882a593Smuzhiyun 			bfa_fcport_ddportenable(dport->bfa);
6167*4882a593Smuzhiyun 			dport->dynamic = BFA_TRUE;
6168*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_NOTSTART;
6169*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6170*4882a593Smuzhiyun 		} else {
6171*4882a593Smuzhiyun 			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6172*4882a593Smuzhiyun 			WARN_ON(1);
6173*4882a593Smuzhiyun 		}
6174*4882a593Smuzhiyun 		break;
6175*4882a593Smuzhiyun 
6176*4882a593Smuzhiyun 	default:
6177*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6178*4882a593Smuzhiyun 	}
6179*4882a593Smuzhiyun }
6180*4882a593Smuzhiyun 
6181*4882a593Smuzhiyun static void
bfa_dport_sm_enabling_qwait(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6182*4882a593Smuzhiyun bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
6183*4882a593Smuzhiyun 			    enum bfa_dport_sm_event event)
6184*4882a593Smuzhiyun {
6185*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6186*4882a593Smuzhiyun 
6187*4882a593Smuzhiyun 	switch (event) {
6188*4882a593Smuzhiyun 	case BFA_DPORT_SM_QRESUME:
6189*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6190*4882a593Smuzhiyun 		bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
6191*4882a593Smuzhiyun 		break;
6192*4882a593Smuzhiyun 
6193*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6194*4882a593Smuzhiyun 		bfa_reqq_wcancel(&dport->reqq_wait);
6195*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6196*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6197*4882a593Smuzhiyun 		break;
6198*4882a593Smuzhiyun 
6199*4882a593Smuzhiyun 	default:
6200*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6201*4882a593Smuzhiyun 	}
6202*4882a593Smuzhiyun }
6203*4882a593Smuzhiyun 
6204*4882a593Smuzhiyun static void
bfa_dport_sm_enabling(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6205*4882a593Smuzhiyun bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6206*4882a593Smuzhiyun {
6207*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6208*4882a593Smuzhiyun 
6209*4882a593Smuzhiyun 	switch (event) {
6210*4882a593Smuzhiyun 	case BFA_DPORT_SM_FWRSP:
6211*4882a593Smuzhiyun 		memset(&dport->result, 0,
6212*4882a593Smuzhiyun 				sizeof(struct bfa_diag_dport_result_s));
6213*4882a593Smuzhiyun 		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6214*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_NO_SFP;
6215*4882a593Smuzhiyun 		} else {
6216*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_INP;
6217*4882a593Smuzhiyun 			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
6218*4882a593Smuzhiyun 		}
6219*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6220*4882a593Smuzhiyun 		break;
6221*4882a593Smuzhiyun 
6222*4882a593Smuzhiyun 	case BFA_DPORT_SM_REQFAIL:
6223*4882a593Smuzhiyun 		dport->test_state = BFA_DPORT_ST_DISABLED;
6224*4882a593Smuzhiyun 		bfa_fcport_dportdisable(dport->bfa);
6225*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6226*4882a593Smuzhiyun 		break;
6227*4882a593Smuzhiyun 
6228*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6229*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6230*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6231*4882a593Smuzhiyun 		break;
6232*4882a593Smuzhiyun 
6233*4882a593Smuzhiyun 	default:
6234*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6235*4882a593Smuzhiyun 	}
6236*4882a593Smuzhiyun }
6237*4882a593Smuzhiyun 
6238*4882a593Smuzhiyun static void
bfa_dport_sm_enabled(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6239*4882a593Smuzhiyun bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6240*4882a593Smuzhiyun {
6241*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6242*4882a593Smuzhiyun 
6243*4882a593Smuzhiyun 	switch (event) {
6244*4882a593Smuzhiyun 	case BFA_DPORT_SM_START:
6245*4882a593Smuzhiyun 		if (bfa_dport_send_req(dport, BFI_DPORT_START))
6246*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_starting);
6247*4882a593Smuzhiyun 		else
6248*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
6249*4882a593Smuzhiyun 		break;
6250*4882a593Smuzhiyun 
6251*4882a593Smuzhiyun 	case BFA_DPORT_SM_DISABLE:
6252*4882a593Smuzhiyun 		bfa_fcport_dportdisable(dport->bfa);
6253*4882a593Smuzhiyun 		if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
6254*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6255*4882a593Smuzhiyun 		else
6256*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
6257*4882a593Smuzhiyun 		break;
6258*4882a593Smuzhiyun 
6259*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6260*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6261*4882a593Smuzhiyun 		break;
6262*4882a593Smuzhiyun 
6263*4882a593Smuzhiyun 	case BFA_DPORT_SM_SCN:
6264*4882a593Smuzhiyun 		switch (dport->i2hmsg.scn.state) {
6265*4882a593Smuzhiyun 		case BFI_DPORT_SCN_TESTCOMP:
6266*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_COMP;
6267*4882a593Smuzhiyun 			break;
6268*4882a593Smuzhiyun 
6269*4882a593Smuzhiyun 		case BFI_DPORT_SCN_TESTSTART:
6270*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_INP;
6271*4882a593Smuzhiyun 			break;
6272*4882a593Smuzhiyun 
6273*4882a593Smuzhiyun 		case BFI_DPORT_SCN_TESTSKIP:
6274*4882a593Smuzhiyun 		case BFI_DPORT_SCN_SUBTESTSTART:
6275*4882a593Smuzhiyun 			/* no state change */
6276*4882a593Smuzhiyun 			break;
6277*4882a593Smuzhiyun 
6278*4882a593Smuzhiyun 		case BFI_DPORT_SCN_SFP_REMOVED:
6279*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_NO_SFP;
6280*4882a593Smuzhiyun 			break;
6281*4882a593Smuzhiyun 
6282*4882a593Smuzhiyun 		case BFI_DPORT_SCN_DDPORT_DISABLE:
6283*4882a593Smuzhiyun 			bfa_fcport_ddportdisable(dport->bfa);
6284*4882a593Smuzhiyun 
6285*4882a593Smuzhiyun 			if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
6286*4882a593Smuzhiyun 				bfa_sm_set_state(dport,
6287*4882a593Smuzhiyun 					 bfa_dport_sm_dynamic_disabling);
6288*4882a593Smuzhiyun 			else
6289*4882a593Smuzhiyun 				bfa_sm_set_state(dport,
6290*4882a593Smuzhiyun 					 bfa_dport_sm_dynamic_disabling_qwait);
6291*4882a593Smuzhiyun 			break;
6292*4882a593Smuzhiyun 
6293*4882a593Smuzhiyun 		case BFI_DPORT_SCN_FCPORT_DISABLE:
6294*4882a593Smuzhiyun 			bfa_fcport_ddportdisable(dport->bfa);
6295*4882a593Smuzhiyun 
6296*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6297*4882a593Smuzhiyun 			dport->dynamic = BFA_FALSE;
6298*4882a593Smuzhiyun 			break;
6299*4882a593Smuzhiyun 
6300*4882a593Smuzhiyun 		default:
6301*4882a593Smuzhiyun 			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6302*4882a593Smuzhiyun 			bfa_sm_fault(dport->bfa, event);
6303*4882a593Smuzhiyun 		}
6304*4882a593Smuzhiyun 		break;
6305*4882a593Smuzhiyun 	default:
6306*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6307*4882a593Smuzhiyun 	}
6308*4882a593Smuzhiyun }
6309*4882a593Smuzhiyun 
6310*4882a593Smuzhiyun static void
bfa_dport_sm_disabling_qwait(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6311*4882a593Smuzhiyun bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
6312*4882a593Smuzhiyun 			     enum bfa_dport_sm_event event)
6313*4882a593Smuzhiyun {
6314*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6315*4882a593Smuzhiyun 
6316*4882a593Smuzhiyun 	switch (event) {
6317*4882a593Smuzhiyun 	case BFA_DPORT_SM_QRESUME:
6318*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6319*4882a593Smuzhiyun 		bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
6320*4882a593Smuzhiyun 		break;
6321*4882a593Smuzhiyun 
6322*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6323*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6324*4882a593Smuzhiyun 		bfa_reqq_wcancel(&dport->reqq_wait);
6325*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6326*4882a593Smuzhiyun 		break;
6327*4882a593Smuzhiyun 
6328*4882a593Smuzhiyun 	case BFA_DPORT_SM_SCN:
6329*4882a593Smuzhiyun 		/* ignore */
6330*4882a593Smuzhiyun 		break;
6331*4882a593Smuzhiyun 
6332*4882a593Smuzhiyun 	default:
6333*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6334*4882a593Smuzhiyun 	}
6335*4882a593Smuzhiyun }
6336*4882a593Smuzhiyun 
6337*4882a593Smuzhiyun static void
bfa_dport_sm_disabling(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6338*4882a593Smuzhiyun bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6339*4882a593Smuzhiyun {
6340*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6341*4882a593Smuzhiyun 
6342*4882a593Smuzhiyun 	switch (event) {
6343*4882a593Smuzhiyun 	case BFA_DPORT_SM_FWRSP:
6344*4882a593Smuzhiyun 		dport->test_state = BFA_DPORT_ST_DISABLED;
6345*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6346*4882a593Smuzhiyun 		break;
6347*4882a593Smuzhiyun 
6348*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6349*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6350*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6351*4882a593Smuzhiyun 		break;
6352*4882a593Smuzhiyun 
6353*4882a593Smuzhiyun 	case BFA_DPORT_SM_SCN:
6354*4882a593Smuzhiyun 		/* no state change */
6355*4882a593Smuzhiyun 		break;
6356*4882a593Smuzhiyun 
6357*4882a593Smuzhiyun 	default:
6358*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6359*4882a593Smuzhiyun 	}
6360*4882a593Smuzhiyun }
6361*4882a593Smuzhiyun 
6362*4882a593Smuzhiyun static void
bfa_dport_sm_starting_qwait(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6363*4882a593Smuzhiyun bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
6364*4882a593Smuzhiyun 			    enum bfa_dport_sm_event event)
6365*4882a593Smuzhiyun {
6366*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6367*4882a593Smuzhiyun 
6368*4882a593Smuzhiyun 	switch (event) {
6369*4882a593Smuzhiyun 	case BFA_DPORT_SM_QRESUME:
6370*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_starting);
6371*4882a593Smuzhiyun 		bfa_dport_send_req(dport, BFI_DPORT_START);
6372*4882a593Smuzhiyun 		break;
6373*4882a593Smuzhiyun 
6374*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6375*4882a593Smuzhiyun 		bfa_reqq_wcancel(&dport->reqq_wait);
6376*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6377*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6378*4882a593Smuzhiyun 		break;
6379*4882a593Smuzhiyun 
6380*4882a593Smuzhiyun 	default:
6381*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6382*4882a593Smuzhiyun 	}
6383*4882a593Smuzhiyun }
6384*4882a593Smuzhiyun 
6385*4882a593Smuzhiyun static void
bfa_dport_sm_starting(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6386*4882a593Smuzhiyun bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6387*4882a593Smuzhiyun {
6388*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6389*4882a593Smuzhiyun 
6390*4882a593Smuzhiyun 	switch (event) {
6391*4882a593Smuzhiyun 	case BFA_DPORT_SM_FWRSP:
6392*4882a593Smuzhiyun 		memset(&dport->result, 0,
6393*4882a593Smuzhiyun 				sizeof(struct bfa_diag_dport_result_s));
6394*4882a593Smuzhiyun 		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6395*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_NO_SFP;
6396*4882a593Smuzhiyun 		} else {
6397*4882a593Smuzhiyun 			dport->test_state = BFA_DPORT_ST_INP;
6398*4882a593Smuzhiyun 			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
6399*4882a593Smuzhiyun 		}
6400*4882a593Smuzhiyun 		fallthrough;
6401*4882a593Smuzhiyun 
6402*4882a593Smuzhiyun 	case BFA_DPORT_SM_REQFAIL:
6403*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6404*4882a593Smuzhiyun 		break;
6405*4882a593Smuzhiyun 
6406*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6407*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6408*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6409*4882a593Smuzhiyun 		break;
6410*4882a593Smuzhiyun 
6411*4882a593Smuzhiyun 	default:
6412*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6413*4882a593Smuzhiyun 	}
6414*4882a593Smuzhiyun }
6415*4882a593Smuzhiyun 
6416*4882a593Smuzhiyun static void
bfa_dport_sm_dynamic_disabling(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6417*4882a593Smuzhiyun bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
6418*4882a593Smuzhiyun 			       enum bfa_dport_sm_event event)
6419*4882a593Smuzhiyun {
6420*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6421*4882a593Smuzhiyun 
6422*4882a593Smuzhiyun 	switch (event) {
6423*4882a593Smuzhiyun 	case BFA_DPORT_SM_SCN:
6424*4882a593Smuzhiyun 		switch (dport->i2hmsg.scn.state) {
6425*4882a593Smuzhiyun 		case BFI_DPORT_SCN_DDPORT_DISABLED:
6426*4882a593Smuzhiyun 			bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6427*4882a593Smuzhiyun 			dport->dynamic = BFA_FALSE;
6428*4882a593Smuzhiyun 			bfa_fcport_enable(dport->bfa);
6429*4882a593Smuzhiyun 			break;
6430*4882a593Smuzhiyun 
6431*4882a593Smuzhiyun 		default:
6432*4882a593Smuzhiyun 			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6433*4882a593Smuzhiyun 			bfa_sm_fault(dport->bfa, event);
6434*4882a593Smuzhiyun 
6435*4882a593Smuzhiyun 		}
6436*4882a593Smuzhiyun 		break;
6437*4882a593Smuzhiyun 
6438*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6439*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6440*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6441*4882a593Smuzhiyun 		break;
6442*4882a593Smuzhiyun 
6443*4882a593Smuzhiyun 	default:
6444*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6445*4882a593Smuzhiyun 	}
6446*4882a593Smuzhiyun }
6447*4882a593Smuzhiyun 
6448*4882a593Smuzhiyun static void
bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s * dport,enum bfa_dport_sm_event event)6449*4882a593Smuzhiyun bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
6450*4882a593Smuzhiyun 			    enum bfa_dport_sm_event event)
6451*4882a593Smuzhiyun {
6452*4882a593Smuzhiyun 	bfa_trc(dport->bfa, event);
6453*4882a593Smuzhiyun 
6454*4882a593Smuzhiyun 	switch (event) {
6455*4882a593Smuzhiyun 	case BFA_DPORT_SM_QRESUME:
6456*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);
6457*4882a593Smuzhiyun 		bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);
6458*4882a593Smuzhiyun 		break;
6459*4882a593Smuzhiyun 
6460*4882a593Smuzhiyun 	case BFA_DPORT_SM_HWFAIL:
6461*4882a593Smuzhiyun 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6462*4882a593Smuzhiyun 		bfa_reqq_wcancel(&dport->reqq_wait);
6463*4882a593Smuzhiyun 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6464*4882a593Smuzhiyun 		break;
6465*4882a593Smuzhiyun 
6466*4882a593Smuzhiyun 	case BFA_DPORT_SM_SCN:
6467*4882a593Smuzhiyun 		/* ignore */
6468*4882a593Smuzhiyun 		break;
6469*4882a593Smuzhiyun 
6470*4882a593Smuzhiyun 	default:
6471*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, event);
6472*4882a593Smuzhiyun 	}
6473*4882a593Smuzhiyun }
6474*4882a593Smuzhiyun 
6475*4882a593Smuzhiyun static bfa_boolean_t
bfa_dport_send_req(struct bfa_dport_s * dport,enum bfi_dport_req req)6476*4882a593Smuzhiyun bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
6477*4882a593Smuzhiyun {
6478*4882a593Smuzhiyun 	struct bfi_diag_dport_req_s *m;
6479*4882a593Smuzhiyun 
6480*4882a593Smuzhiyun 	/*
6481*4882a593Smuzhiyun 	 * check for room in queue to send request now
6482*4882a593Smuzhiyun 	 */
6483*4882a593Smuzhiyun 	m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
6484*4882a593Smuzhiyun 	if (!m) {
6485*4882a593Smuzhiyun 		bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
6486*4882a593Smuzhiyun 		return BFA_FALSE;
6487*4882a593Smuzhiyun 	}
6488*4882a593Smuzhiyun 
6489*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
6490*4882a593Smuzhiyun 		    bfa_fn_lpu(dport->bfa));
6491*4882a593Smuzhiyun 	m->req  = req;
6492*4882a593Smuzhiyun 	if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
6493*4882a593Smuzhiyun 		m->lpcnt = cpu_to_be32(dport->lpcnt);
6494*4882a593Smuzhiyun 		m->payload = cpu_to_be32(dport->payload);
6495*4882a593Smuzhiyun 	}
6496*4882a593Smuzhiyun 
6497*4882a593Smuzhiyun 	/*
6498*4882a593Smuzhiyun 	 * queue I/O message to firmware
6499*4882a593Smuzhiyun 	 */
6500*4882a593Smuzhiyun 	bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);
6501*4882a593Smuzhiyun 
6502*4882a593Smuzhiyun 	return BFA_TRUE;
6503*4882a593Smuzhiyun }
6504*4882a593Smuzhiyun 
6505*4882a593Smuzhiyun static void
bfa_dport_qresume(void * cbarg)6506*4882a593Smuzhiyun bfa_dport_qresume(void *cbarg)
6507*4882a593Smuzhiyun {
6508*4882a593Smuzhiyun 	struct bfa_dport_s *dport = cbarg;
6509*4882a593Smuzhiyun 
6510*4882a593Smuzhiyun 	bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
6511*4882a593Smuzhiyun }
6512*4882a593Smuzhiyun 
6513*4882a593Smuzhiyun static void
bfa_dport_req_comp(struct bfa_dport_s * dport,struct bfi_diag_dport_rsp_s * msg)6514*4882a593Smuzhiyun bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
6515*4882a593Smuzhiyun {
6516*4882a593Smuzhiyun 	msg->status = cpu_to_be32(msg->status);
6517*4882a593Smuzhiyun 	dport->i2hmsg.rsp.status = msg->status;
6518*4882a593Smuzhiyun 	dport->rp_pwwn = msg->pwwn;
6519*4882a593Smuzhiyun 	dport->rp_nwwn = msg->nwwn;
6520*4882a593Smuzhiyun 
6521*4882a593Smuzhiyun 	if ((msg->status == BFA_STATUS_OK) ||
6522*4882a593Smuzhiyun 	    (msg->status == BFA_STATUS_DPORT_NO_SFP)) {
6523*4882a593Smuzhiyun 		bfa_trc(dport->bfa, msg->status);
6524*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->rp_pwwn);
6525*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->rp_nwwn);
6526*4882a593Smuzhiyun 		bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
6527*4882a593Smuzhiyun 
6528*4882a593Smuzhiyun 	} else {
6529*4882a593Smuzhiyun 		bfa_trc(dport->bfa, msg->status);
6530*4882a593Smuzhiyun 		bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
6531*4882a593Smuzhiyun 	}
6532*4882a593Smuzhiyun 	bfa_cb_fcdiag_dport(dport, msg->status);
6533*4882a593Smuzhiyun }
6534*4882a593Smuzhiyun 
6535*4882a593Smuzhiyun static bfa_boolean_t
bfa_dport_is_sending_req(struct bfa_dport_s * dport)6536*4882a593Smuzhiyun bfa_dport_is_sending_req(struct bfa_dport_s *dport)
6537*4882a593Smuzhiyun {
6538*4882a593Smuzhiyun 	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling)	||
6539*4882a593Smuzhiyun 	    bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
6540*4882a593Smuzhiyun 	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling)	||
6541*4882a593Smuzhiyun 	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||
6542*4882a593Smuzhiyun 	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting)	||
6543*4882a593Smuzhiyun 	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
6544*4882a593Smuzhiyun 		return BFA_TRUE;
6545*4882a593Smuzhiyun 	} else {
6546*4882a593Smuzhiyun 		return BFA_FALSE;
6547*4882a593Smuzhiyun 	}
6548*4882a593Smuzhiyun }
6549*4882a593Smuzhiyun 
6550*4882a593Smuzhiyun static void
bfa_dport_scn(struct bfa_dport_s * dport,struct bfi_diag_dport_scn_s * msg)6551*4882a593Smuzhiyun bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
6552*4882a593Smuzhiyun {
6553*4882a593Smuzhiyun 	int i;
6554*4882a593Smuzhiyun 	uint8_t subtesttype;
6555*4882a593Smuzhiyun 
6556*4882a593Smuzhiyun 	bfa_trc(dport->bfa, msg->state);
6557*4882a593Smuzhiyun 	dport->i2hmsg.scn.state = msg->state;
6558*4882a593Smuzhiyun 
6559*4882a593Smuzhiyun 	switch (dport->i2hmsg.scn.state) {
6560*4882a593Smuzhiyun 	case BFI_DPORT_SCN_TESTCOMP:
6561*4882a593Smuzhiyun 		dport->result.end_time = ktime_get_real_seconds();
6562*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->result.end_time);
6563*4882a593Smuzhiyun 
6564*4882a593Smuzhiyun 		dport->result.status = msg->info.testcomp.status;
6565*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->result.status);
6566*4882a593Smuzhiyun 
6567*4882a593Smuzhiyun 		dport->result.roundtrip_latency =
6568*4882a593Smuzhiyun 			cpu_to_be32(msg->info.testcomp.latency);
6569*4882a593Smuzhiyun 		dport->result.est_cable_distance =
6570*4882a593Smuzhiyun 			cpu_to_be32(msg->info.testcomp.distance);
6571*4882a593Smuzhiyun 		dport->result.buffer_required =
6572*4882a593Smuzhiyun 			be16_to_cpu(msg->info.testcomp.numbuffer);
6573*4882a593Smuzhiyun 
6574*4882a593Smuzhiyun 		dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
6575*4882a593Smuzhiyun 		dport->result.speed = msg->info.testcomp.speed;
6576*4882a593Smuzhiyun 
6577*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->result.roundtrip_latency);
6578*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->result.est_cable_distance);
6579*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->result.buffer_required);
6580*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->result.frmsz);
6581*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->result.speed);
6582*4882a593Smuzhiyun 
6583*4882a593Smuzhiyun 		for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
6584*4882a593Smuzhiyun 			dport->result.subtest[i].status =
6585*4882a593Smuzhiyun 				msg->info.testcomp.subtest_status[i];
6586*4882a593Smuzhiyun 			bfa_trc(dport->bfa, dport->result.subtest[i].status);
6587*4882a593Smuzhiyun 		}
6588*4882a593Smuzhiyun 		break;
6589*4882a593Smuzhiyun 
6590*4882a593Smuzhiyun 	case BFI_DPORT_SCN_TESTSKIP:
6591*4882a593Smuzhiyun 	case BFI_DPORT_SCN_DDPORT_ENABLE:
6592*4882a593Smuzhiyun 		memset(&dport->result, 0,
6593*4882a593Smuzhiyun 				sizeof(struct bfa_diag_dport_result_s));
6594*4882a593Smuzhiyun 		break;
6595*4882a593Smuzhiyun 
6596*4882a593Smuzhiyun 	case BFI_DPORT_SCN_TESTSTART:
6597*4882a593Smuzhiyun 		memset(&dport->result, 0,
6598*4882a593Smuzhiyun 				sizeof(struct bfa_diag_dport_result_s));
6599*4882a593Smuzhiyun 		dport->rp_pwwn = msg->info.teststart.pwwn;
6600*4882a593Smuzhiyun 		dport->rp_nwwn = msg->info.teststart.nwwn;
6601*4882a593Smuzhiyun 		dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
6602*4882a593Smuzhiyun 		bfa_dport_result_start(dport, msg->info.teststart.mode);
6603*4882a593Smuzhiyun 		break;
6604*4882a593Smuzhiyun 
6605*4882a593Smuzhiyun 	case BFI_DPORT_SCN_SUBTESTSTART:
6606*4882a593Smuzhiyun 		subtesttype = msg->info.teststart.type;
6607*4882a593Smuzhiyun 		dport->result.subtest[subtesttype].start_time =
6608*4882a593Smuzhiyun 			ktime_get_real_seconds();
6609*4882a593Smuzhiyun 		dport->result.subtest[subtesttype].status =
6610*4882a593Smuzhiyun 			DPORT_TEST_ST_INPRG;
6611*4882a593Smuzhiyun 
6612*4882a593Smuzhiyun 		bfa_trc(dport->bfa, subtesttype);
6613*4882a593Smuzhiyun 		bfa_trc(dport->bfa,
6614*4882a593Smuzhiyun 			dport->result.subtest[subtesttype].start_time);
6615*4882a593Smuzhiyun 		break;
6616*4882a593Smuzhiyun 
6617*4882a593Smuzhiyun 	case BFI_DPORT_SCN_SFP_REMOVED:
6618*4882a593Smuzhiyun 	case BFI_DPORT_SCN_DDPORT_DISABLED:
6619*4882a593Smuzhiyun 	case BFI_DPORT_SCN_DDPORT_DISABLE:
6620*4882a593Smuzhiyun 	case BFI_DPORT_SCN_FCPORT_DISABLE:
6621*4882a593Smuzhiyun 		dport->result.status = DPORT_TEST_ST_IDLE;
6622*4882a593Smuzhiyun 		break;
6623*4882a593Smuzhiyun 
6624*4882a593Smuzhiyun 	default:
6625*4882a593Smuzhiyun 		bfa_sm_fault(dport->bfa, msg->state);
6626*4882a593Smuzhiyun 	}
6627*4882a593Smuzhiyun 
6628*4882a593Smuzhiyun 	bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
6629*4882a593Smuzhiyun }
6630*4882a593Smuzhiyun 
6631*4882a593Smuzhiyun /*
6632*4882a593Smuzhiyun  * Dport enable
6633*4882a593Smuzhiyun  *
6634*4882a593Smuzhiyun  * @param[in] *bfa            - bfa data struct
6635*4882a593Smuzhiyun  */
6636*4882a593Smuzhiyun bfa_status_t
bfa_dport_enable(struct bfa_s * bfa,u32 lpcnt,u32 pat,bfa_cb_diag_t cbfn,void * cbarg)6637*4882a593Smuzhiyun bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6638*4882a593Smuzhiyun 				bfa_cb_diag_t cbfn, void *cbarg)
6639*4882a593Smuzhiyun {
6640*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6641*4882a593Smuzhiyun 	struct bfa_dport_s  *dport = &fcdiag->dport;
6642*4882a593Smuzhiyun 
6643*4882a593Smuzhiyun 	/*
6644*4882a593Smuzhiyun 	 * Dport is not support in MEZZ card
6645*4882a593Smuzhiyun 	 */
6646*4882a593Smuzhiyun 	if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
6647*4882a593Smuzhiyun 		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6648*4882a593Smuzhiyun 		return BFA_STATUS_CMD_NOTSUPP_MEZZ;
6649*4882a593Smuzhiyun 	}
6650*4882a593Smuzhiyun 
6651*4882a593Smuzhiyun 	/*
6652*4882a593Smuzhiyun 	 * Dport is supported in CT2 or above
6653*4882a593Smuzhiyun 	 */
6654*4882a593Smuzhiyun 	if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
6655*4882a593Smuzhiyun 		bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
6656*4882a593Smuzhiyun 		return BFA_STATUS_FEATURE_NOT_SUPPORTED;
6657*4882a593Smuzhiyun 	}
6658*4882a593Smuzhiyun 
6659*4882a593Smuzhiyun 	/*
6660*4882a593Smuzhiyun 	 * Check to see if IOC is down
6661*4882a593Smuzhiyun 	*/
6662*4882a593Smuzhiyun 	if (!bfa_iocfc_is_operational(bfa))
6663*4882a593Smuzhiyun 		return BFA_STATUS_IOC_NON_OP;
6664*4882a593Smuzhiyun 
6665*4882a593Smuzhiyun 	/* if port is PBC disabled, return error */
6666*4882a593Smuzhiyun 	if (bfa_fcport_is_pbcdisabled(bfa)) {
6667*4882a593Smuzhiyun 		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6668*4882a593Smuzhiyun 		return BFA_STATUS_PBC;
6669*4882a593Smuzhiyun 	}
6670*4882a593Smuzhiyun 
6671*4882a593Smuzhiyun 	/*
6672*4882a593Smuzhiyun 	 * Check if port mode is FC port
6673*4882a593Smuzhiyun 	 */
6674*4882a593Smuzhiyun 	if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
6675*4882a593Smuzhiyun 		bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
6676*4882a593Smuzhiyun 		return BFA_STATUS_CMD_NOTSUPP_CNA;
6677*4882a593Smuzhiyun 	}
6678*4882a593Smuzhiyun 
6679*4882a593Smuzhiyun 	/*
6680*4882a593Smuzhiyun 	 * Check if port is in LOOP mode
6681*4882a593Smuzhiyun 	 */
6682*4882a593Smuzhiyun 	if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
6683*4882a593Smuzhiyun 	    (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
6684*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6685*4882a593Smuzhiyun 		return BFA_STATUS_TOPOLOGY_LOOP;
6686*4882a593Smuzhiyun 	}
6687*4882a593Smuzhiyun 
6688*4882a593Smuzhiyun 	/*
6689*4882a593Smuzhiyun 	 * Check if port is TRUNK mode
6690*4882a593Smuzhiyun 	 */
6691*4882a593Smuzhiyun 	if (bfa_fcport_is_trunk_enabled(bfa)) {
6692*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6693*4882a593Smuzhiyun 		return BFA_STATUS_ERROR_TRUNK_ENABLED;
6694*4882a593Smuzhiyun 	}
6695*4882a593Smuzhiyun 
6696*4882a593Smuzhiyun 	/*
6697*4882a593Smuzhiyun 	 * Check if diag loopback is running
6698*4882a593Smuzhiyun 	 */
6699*4882a593Smuzhiyun 	if (bfa_fcdiag_lb_is_running(bfa)) {
6700*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6701*4882a593Smuzhiyun 		return BFA_STATUS_DIAG_BUSY;
6702*4882a593Smuzhiyun 	}
6703*4882a593Smuzhiyun 
6704*4882a593Smuzhiyun 	/*
6705*4882a593Smuzhiyun 	 * Check to see if port is disable or in dport state
6706*4882a593Smuzhiyun 	 */
6707*4882a593Smuzhiyun 	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6708*4882a593Smuzhiyun 	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6709*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6710*4882a593Smuzhiyun 		return BFA_STATUS_PORT_NOT_DISABLED;
6711*4882a593Smuzhiyun 	}
6712*4882a593Smuzhiyun 
6713*4882a593Smuzhiyun 	/*
6714*4882a593Smuzhiyun 	 * Check if dport is in dynamic mode
6715*4882a593Smuzhiyun 	 */
6716*4882a593Smuzhiyun 	if (dport->dynamic)
6717*4882a593Smuzhiyun 		return BFA_STATUS_DDPORT_ERR;
6718*4882a593Smuzhiyun 
6719*4882a593Smuzhiyun 	/*
6720*4882a593Smuzhiyun 	 * Check if dport is busy
6721*4882a593Smuzhiyun 	 */
6722*4882a593Smuzhiyun 	if (bfa_dport_is_sending_req(dport))
6723*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
6724*4882a593Smuzhiyun 
6725*4882a593Smuzhiyun 	/*
6726*4882a593Smuzhiyun 	 * Check if dport is already enabled
6727*4882a593Smuzhiyun 	 */
6728*4882a593Smuzhiyun 	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6729*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6730*4882a593Smuzhiyun 		return BFA_STATUS_DPORT_ENABLED;
6731*4882a593Smuzhiyun 	}
6732*4882a593Smuzhiyun 
6733*4882a593Smuzhiyun 	bfa_trc(dport->bfa, lpcnt);
6734*4882a593Smuzhiyun 	bfa_trc(dport->bfa, pat);
6735*4882a593Smuzhiyun 	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6736*4882a593Smuzhiyun 	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6737*4882a593Smuzhiyun 	dport->cbfn = cbfn;
6738*4882a593Smuzhiyun 	dport->cbarg = cbarg;
6739*4882a593Smuzhiyun 
6740*4882a593Smuzhiyun 	bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
6741*4882a593Smuzhiyun 	return BFA_STATUS_OK;
6742*4882a593Smuzhiyun }
6743*4882a593Smuzhiyun 
6744*4882a593Smuzhiyun /*
6745*4882a593Smuzhiyun  *	Dport disable
6746*4882a593Smuzhiyun  *
6747*4882a593Smuzhiyun  *	@param[in] *bfa            - bfa data struct
6748*4882a593Smuzhiyun  */
6749*4882a593Smuzhiyun bfa_status_t
bfa_dport_disable(struct bfa_s * bfa,bfa_cb_diag_t cbfn,void * cbarg)6750*4882a593Smuzhiyun bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
6751*4882a593Smuzhiyun {
6752*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6753*4882a593Smuzhiyun 	struct bfa_dport_s *dport = &fcdiag->dport;
6754*4882a593Smuzhiyun 
6755*4882a593Smuzhiyun 	if (bfa_ioc_is_disabled(&bfa->ioc))
6756*4882a593Smuzhiyun 		return BFA_STATUS_IOC_DISABLED;
6757*4882a593Smuzhiyun 
6758*4882a593Smuzhiyun 	/* if port is PBC disabled, return error */
6759*4882a593Smuzhiyun 	if (bfa_fcport_is_pbcdisabled(bfa)) {
6760*4882a593Smuzhiyun 		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6761*4882a593Smuzhiyun 		return BFA_STATUS_PBC;
6762*4882a593Smuzhiyun 	}
6763*4882a593Smuzhiyun 
6764*4882a593Smuzhiyun 	/*
6765*4882a593Smuzhiyun 	 * Check if dport is in dynamic mode
6766*4882a593Smuzhiyun 	 */
6767*4882a593Smuzhiyun 	if (dport->dynamic) {
6768*4882a593Smuzhiyun 		return BFA_STATUS_DDPORT_ERR;
6769*4882a593Smuzhiyun 	}
6770*4882a593Smuzhiyun 
6771*4882a593Smuzhiyun 	/*
6772*4882a593Smuzhiyun 	 * Check to see if port is disable or in dport state
6773*4882a593Smuzhiyun 	 */
6774*4882a593Smuzhiyun 	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6775*4882a593Smuzhiyun 	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6776*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6777*4882a593Smuzhiyun 		return BFA_STATUS_PORT_NOT_DISABLED;
6778*4882a593Smuzhiyun 	}
6779*4882a593Smuzhiyun 
6780*4882a593Smuzhiyun 	/*
6781*4882a593Smuzhiyun 	 * Check if dport is busy
6782*4882a593Smuzhiyun 	 */
6783*4882a593Smuzhiyun 	if (bfa_dport_is_sending_req(dport))
6784*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
6785*4882a593Smuzhiyun 
6786*4882a593Smuzhiyun 	/*
6787*4882a593Smuzhiyun 	 * Check if dport is already disabled
6788*4882a593Smuzhiyun 	 */
6789*4882a593Smuzhiyun 	if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
6790*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6791*4882a593Smuzhiyun 		return BFA_STATUS_DPORT_DISABLED;
6792*4882a593Smuzhiyun 	}
6793*4882a593Smuzhiyun 
6794*4882a593Smuzhiyun 	dport->cbfn = cbfn;
6795*4882a593Smuzhiyun 	dport->cbarg = cbarg;
6796*4882a593Smuzhiyun 
6797*4882a593Smuzhiyun 	bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
6798*4882a593Smuzhiyun 	return BFA_STATUS_OK;
6799*4882a593Smuzhiyun }
6800*4882a593Smuzhiyun 
6801*4882a593Smuzhiyun /*
6802*4882a593Smuzhiyun  * Dport start -- restart dport test
6803*4882a593Smuzhiyun  *
6804*4882a593Smuzhiyun  *   @param[in] *bfa		- bfa data struct
6805*4882a593Smuzhiyun  */
6806*4882a593Smuzhiyun bfa_status_t
bfa_dport_start(struct bfa_s * bfa,u32 lpcnt,u32 pat,bfa_cb_diag_t cbfn,void * cbarg)6807*4882a593Smuzhiyun bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6808*4882a593Smuzhiyun 			bfa_cb_diag_t cbfn, void *cbarg)
6809*4882a593Smuzhiyun {
6810*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6811*4882a593Smuzhiyun 	struct bfa_dport_s *dport = &fcdiag->dport;
6812*4882a593Smuzhiyun 
6813*4882a593Smuzhiyun 	/*
6814*4882a593Smuzhiyun 	 * Check to see if IOC is down
6815*4882a593Smuzhiyun 	 */
6816*4882a593Smuzhiyun 	if (!bfa_iocfc_is_operational(bfa))
6817*4882a593Smuzhiyun 		return BFA_STATUS_IOC_NON_OP;
6818*4882a593Smuzhiyun 
6819*4882a593Smuzhiyun 	/*
6820*4882a593Smuzhiyun 	 * Check if dport is in dynamic mode
6821*4882a593Smuzhiyun 	 */
6822*4882a593Smuzhiyun 	if (dport->dynamic)
6823*4882a593Smuzhiyun 		return BFA_STATUS_DDPORT_ERR;
6824*4882a593Smuzhiyun 
6825*4882a593Smuzhiyun 	/*
6826*4882a593Smuzhiyun 	 * Check if dport is busy
6827*4882a593Smuzhiyun 	 */
6828*4882a593Smuzhiyun 	if (bfa_dport_is_sending_req(dport))
6829*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
6830*4882a593Smuzhiyun 
6831*4882a593Smuzhiyun 	/*
6832*4882a593Smuzhiyun 	 * Check if dport is in enabled state.
6833*4882a593Smuzhiyun 	 * Test can only be restart when previous test has completed
6834*4882a593Smuzhiyun 	 */
6835*4882a593Smuzhiyun 	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6836*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6837*4882a593Smuzhiyun 		return BFA_STATUS_DPORT_DISABLED;
6838*4882a593Smuzhiyun 
6839*4882a593Smuzhiyun 	} else {
6840*4882a593Smuzhiyun 		if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6841*4882a593Smuzhiyun 			return BFA_STATUS_DPORT_INV_SFP;
6842*4882a593Smuzhiyun 
6843*4882a593Smuzhiyun 		if (dport->test_state == BFA_DPORT_ST_INP)
6844*4882a593Smuzhiyun 			return BFA_STATUS_DEVBUSY;
6845*4882a593Smuzhiyun 
6846*4882a593Smuzhiyun 		WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
6847*4882a593Smuzhiyun 	}
6848*4882a593Smuzhiyun 
6849*4882a593Smuzhiyun 	bfa_trc(dport->bfa, lpcnt);
6850*4882a593Smuzhiyun 	bfa_trc(dport->bfa, pat);
6851*4882a593Smuzhiyun 
6852*4882a593Smuzhiyun 	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6853*4882a593Smuzhiyun 	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6854*4882a593Smuzhiyun 
6855*4882a593Smuzhiyun 	dport->cbfn = cbfn;
6856*4882a593Smuzhiyun 	dport->cbarg = cbarg;
6857*4882a593Smuzhiyun 
6858*4882a593Smuzhiyun 	bfa_sm_send_event(dport, BFA_DPORT_SM_START);
6859*4882a593Smuzhiyun 	return BFA_STATUS_OK;
6860*4882a593Smuzhiyun }
6861*4882a593Smuzhiyun 
6862*4882a593Smuzhiyun /*
6863*4882a593Smuzhiyun  * Dport show -- return dport test result
6864*4882a593Smuzhiyun  *
6865*4882a593Smuzhiyun  *   @param[in] *bfa		- bfa data struct
6866*4882a593Smuzhiyun  */
6867*4882a593Smuzhiyun bfa_status_t
bfa_dport_show(struct bfa_s * bfa,struct bfa_diag_dport_result_s * result)6868*4882a593Smuzhiyun bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
6869*4882a593Smuzhiyun {
6870*4882a593Smuzhiyun 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6871*4882a593Smuzhiyun 	struct bfa_dport_s *dport = &fcdiag->dport;
6872*4882a593Smuzhiyun 
6873*4882a593Smuzhiyun 	/*
6874*4882a593Smuzhiyun 	 * Check to see if IOC is down
6875*4882a593Smuzhiyun 	 */
6876*4882a593Smuzhiyun 	if (!bfa_iocfc_is_operational(bfa))
6877*4882a593Smuzhiyun 		return BFA_STATUS_IOC_NON_OP;
6878*4882a593Smuzhiyun 
6879*4882a593Smuzhiyun 	/*
6880*4882a593Smuzhiyun 	 * Check if dport is busy
6881*4882a593Smuzhiyun 	 */
6882*4882a593Smuzhiyun 	if (bfa_dport_is_sending_req(dport))
6883*4882a593Smuzhiyun 		return BFA_STATUS_DEVBUSY;
6884*4882a593Smuzhiyun 
6885*4882a593Smuzhiyun 	/*
6886*4882a593Smuzhiyun 	 * Check if dport is in enabled state.
6887*4882a593Smuzhiyun 	 */
6888*4882a593Smuzhiyun 	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6889*4882a593Smuzhiyun 		bfa_trc(dport->bfa, 0);
6890*4882a593Smuzhiyun 		return BFA_STATUS_DPORT_DISABLED;
6891*4882a593Smuzhiyun 
6892*4882a593Smuzhiyun 	}
6893*4882a593Smuzhiyun 
6894*4882a593Smuzhiyun 	/*
6895*4882a593Smuzhiyun 	 * Check if there is SFP
6896*4882a593Smuzhiyun 	 */
6897*4882a593Smuzhiyun 	if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6898*4882a593Smuzhiyun 		return BFA_STATUS_DPORT_INV_SFP;
6899*4882a593Smuzhiyun 
6900*4882a593Smuzhiyun 	memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
6901*4882a593Smuzhiyun 
6902*4882a593Smuzhiyun 	return BFA_STATUS_OK;
6903*4882a593Smuzhiyun }
6904