xref: /OK3568_Linux_fs/kernel/drivers/scsi/bfa/bfa_fcpim.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 "bfa_modules.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun BFA_TRC_FILE(HAL, FCPIM);
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun /*
17*4882a593Smuzhiyun  *  BFA ITNIM Related definitions
18*4882a593Smuzhiyun  */
19*4882a593Smuzhiyun static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                                \
22*4882a593Smuzhiyun 	(((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))))
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define bfa_fcpim_additn(__itnim)					\
25*4882a593Smuzhiyun 	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
26*4882a593Smuzhiyun #define bfa_fcpim_delitn(__itnim)	do {				\
27*4882a593Smuzhiyun 	WARN_ON(!bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));   \
28*4882a593Smuzhiyun 	bfa_itnim_update_del_itn_stats(__itnim);      \
29*4882a593Smuzhiyun 	list_del(&(__itnim)->qe);      \
30*4882a593Smuzhiyun 	WARN_ON(!list_empty(&(__itnim)->io_q));				\
31*4882a593Smuzhiyun 	WARN_ON(!list_empty(&(__itnim)->io_cleanup_q));			\
32*4882a593Smuzhiyun 	WARN_ON(!list_empty(&(__itnim)->pending_q));			\
33*4882a593Smuzhiyun } while (0)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define bfa_itnim_online_cb(__itnim) do {				\
36*4882a593Smuzhiyun 	if ((__itnim)->bfa->fcs)					\
37*4882a593Smuzhiyun 		bfa_cb_itnim_online((__itnim)->ditn);      \
38*4882a593Smuzhiyun 	else {								\
39*4882a593Smuzhiyun 		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
40*4882a593Smuzhiyun 		__bfa_cb_itnim_online, (__itnim));      \
41*4882a593Smuzhiyun 	}								\
42*4882a593Smuzhiyun } while (0)
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define bfa_itnim_offline_cb(__itnim) do {				\
45*4882a593Smuzhiyun 	if ((__itnim)->bfa->fcs)					\
46*4882a593Smuzhiyun 		bfa_cb_itnim_offline((__itnim)->ditn);      \
47*4882a593Smuzhiyun 	else {								\
48*4882a593Smuzhiyun 		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
49*4882a593Smuzhiyun 		__bfa_cb_itnim_offline, (__itnim));      \
50*4882a593Smuzhiyun 	}								\
51*4882a593Smuzhiyun } while (0)
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #define bfa_itnim_sler_cb(__itnim) do {					\
54*4882a593Smuzhiyun 	if ((__itnim)->bfa->fcs)					\
55*4882a593Smuzhiyun 		bfa_cb_itnim_sler((__itnim)->ditn);      \
56*4882a593Smuzhiyun 	else {								\
57*4882a593Smuzhiyun 		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
58*4882a593Smuzhiyun 		__bfa_cb_itnim_sler, (__itnim));      \
59*4882a593Smuzhiyun 	}								\
60*4882a593Smuzhiyun } while (0)
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun enum bfa_ioim_lm_ua_status {
63*4882a593Smuzhiyun 	BFA_IOIM_LM_UA_RESET = 0,
64*4882a593Smuzhiyun 	BFA_IOIM_LM_UA_SET = 1,
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /*
68*4882a593Smuzhiyun  *  itnim state machine event
69*4882a593Smuzhiyun  */
70*4882a593Smuzhiyun enum bfa_itnim_event {
71*4882a593Smuzhiyun 	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */
72*4882a593Smuzhiyun 	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */
73*4882a593Smuzhiyun 	BFA_ITNIM_SM_OFFLINE = 3,	/*  itnim is offline */
74*4882a593Smuzhiyun 	BFA_ITNIM_SM_FWRSP = 4,		/*  firmware response */
75*4882a593Smuzhiyun 	BFA_ITNIM_SM_DELETE = 5,	/*  deleting an existing itnim */
76*4882a593Smuzhiyun 	BFA_ITNIM_SM_CLEANUP = 6,	/*  IO cleanup completion */
77*4882a593Smuzhiyun 	BFA_ITNIM_SM_SLER = 7,		/*  second level error recovery */
78*4882a593Smuzhiyun 	BFA_ITNIM_SM_HWFAIL = 8,	/*  IOC h/w failure event */
79*4882a593Smuzhiyun 	BFA_ITNIM_SM_QRESUME = 9,	/*  queue space available */
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun /*
83*4882a593Smuzhiyun  *  BFA IOIM related definitions
84*4882a593Smuzhiyun  */
85*4882a593Smuzhiyun #define bfa_ioim_move_to_comp_q(__ioim) do {				\
86*4882a593Smuzhiyun 	list_del(&(__ioim)->qe);					\
87*4882a593Smuzhiyun 	list_add_tail(&(__ioim)->qe, &(__ioim)->fcpim->ioim_comp_q);	\
88*4882a593Smuzhiyun } while (0)
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun #define bfa_ioim_cb_profile_comp(__fcpim, __ioim) do {			\
92*4882a593Smuzhiyun 	if ((__fcpim)->profile_comp)					\
93*4882a593Smuzhiyun 		(__fcpim)->profile_comp(__ioim);			\
94*4882a593Smuzhiyun } while (0)
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun #define bfa_ioim_cb_profile_start(__fcpim, __ioim) do {			\
97*4882a593Smuzhiyun 	if ((__fcpim)->profile_start)					\
98*4882a593Smuzhiyun 		(__fcpim)->profile_start(__ioim);			\
99*4882a593Smuzhiyun } while (0)
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun /*
102*4882a593Smuzhiyun  * IO state machine events
103*4882a593Smuzhiyun  */
104*4882a593Smuzhiyun enum bfa_ioim_event {
105*4882a593Smuzhiyun 	BFA_IOIM_SM_START	= 1,	/*  io start request from host */
106*4882a593Smuzhiyun 	BFA_IOIM_SM_COMP_GOOD	= 2,	/*  io good comp, resource free */
107*4882a593Smuzhiyun 	BFA_IOIM_SM_COMP	= 3,	/*  io comp, resource is free */
108*4882a593Smuzhiyun 	BFA_IOIM_SM_COMP_UTAG	= 4,	/*  io comp, resource is free */
109*4882a593Smuzhiyun 	BFA_IOIM_SM_DONE	= 5,	/*  io comp, resource not free */
110*4882a593Smuzhiyun 	BFA_IOIM_SM_FREE	= 6,	/*  io resource is freed */
111*4882a593Smuzhiyun 	BFA_IOIM_SM_ABORT	= 7,	/*  abort request from scsi stack */
112*4882a593Smuzhiyun 	BFA_IOIM_SM_ABORT_COMP	= 8,	/*  abort from f/w */
113*4882a593Smuzhiyun 	BFA_IOIM_SM_ABORT_DONE	= 9,	/*  abort completion from f/w */
114*4882a593Smuzhiyun 	BFA_IOIM_SM_QRESUME	= 10,	/*  CQ space available to queue IO */
115*4882a593Smuzhiyun 	BFA_IOIM_SM_SGALLOCED	= 11,	/*  SG page allocation successful */
116*4882a593Smuzhiyun 	BFA_IOIM_SM_SQRETRY	= 12,	/*  sequence recovery retry */
117*4882a593Smuzhiyun 	BFA_IOIM_SM_HCB		= 13,	/*  bfa callback complete */
118*4882a593Smuzhiyun 	BFA_IOIM_SM_CLEANUP	= 14,	/*  IO cleanup from itnim */
119*4882a593Smuzhiyun 	BFA_IOIM_SM_TMSTART	= 15,	/*  IO cleanup from tskim */
120*4882a593Smuzhiyun 	BFA_IOIM_SM_TMDONE	= 16,	/*  IO cleanup from tskim */
121*4882a593Smuzhiyun 	BFA_IOIM_SM_HWFAIL	= 17,	/*  IOC h/w failure event */
122*4882a593Smuzhiyun 	BFA_IOIM_SM_IOTOV	= 18,	/*  ITN offline TOV */
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /*
127*4882a593Smuzhiyun  *  BFA TSKIM related definitions
128*4882a593Smuzhiyun  */
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /*
131*4882a593Smuzhiyun  * task management completion handling
132*4882a593Smuzhiyun  */
133*4882a593Smuzhiyun #define bfa_tskim_qcomp(__tskim, __cbfn) do {				\
134*4882a593Smuzhiyun 	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim));\
135*4882a593Smuzhiyun 	bfa_tskim_notify_comp(__tskim);      \
136*4882a593Smuzhiyun } while (0)
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun #define bfa_tskim_notify_comp(__tskim) do {				\
139*4882a593Smuzhiyun 	if ((__tskim)->notify)						\
140*4882a593Smuzhiyun 		bfa_itnim_tskdone((__tskim)->itnim);      \
141*4882a593Smuzhiyun } while (0)
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun enum bfa_tskim_event {
145*4882a593Smuzhiyun 	BFA_TSKIM_SM_START	= 1,	/*  TM command start		*/
146*4882a593Smuzhiyun 	BFA_TSKIM_SM_DONE	= 2,	/*  TM completion		*/
147*4882a593Smuzhiyun 	BFA_TSKIM_SM_QRESUME	= 3,	/*  resume after qfull		*/
148*4882a593Smuzhiyun 	BFA_TSKIM_SM_HWFAIL	= 5,	/*  IOC h/w failure event	*/
149*4882a593Smuzhiyun 	BFA_TSKIM_SM_HCB	= 6,	/*  BFA callback completion	*/
150*4882a593Smuzhiyun 	BFA_TSKIM_SM_IOS_DONE	= 7,	/*  IO and sub TM completions	*/
151*4882a593Smuzhiyun 	BFA_TSKIM_SM_CLEANUP	= 8,	/*  TM cleanup on ITN offline	*/
152*4882a593Smuzhiyun 	BFA_TSKIM_SM_CLEANUP_DONE = 9,	/*  TM abort completion	*/
153*4882a593Smuzhiyun 	BFA_TSKIM_SM_UTAG	= 10,	/*  TM completion unknown tag  */
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /*
157*4882a593Smuzhiyun  * forward declaration for BFA ITNIM functions
158*4882a593Smuzhiyun  */
159*4882a593Smuzhiyun static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
160*4882a593Smuzhiyun static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
161*4882a593Smuzhiyun static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
162*4882a593Smuzhiyun static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
163*4882a593Smuzhiyun static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
164*4882a593Smuzhiyun static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
165*4882a593Smuzhiyun static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
166*4882a593Smuzhiyun static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
167*4882a593Smuzhiyun static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
168*4882a593Smuzhiyun static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
169*4882a593Smuzhiyun static void     bfa_itnim_iotov(void *itnim_arg);
170*4882a593Smuzhiyun static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
171*4882a593Smuzhiyun static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
172*4882a593Smuzhiyun static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun /*
175*4882a593Smuzhiyun  * forward declaration of ITNIM state machine
176*4882a593Smuzhiyun  */
177*4882a593Smuzhiyun static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
178*4882a593Smuzhiyun 					enum bfa_itnim_event event);
179*4882a593Smuzhiyun static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
180*4882a593Smuzhiyun 					enum bfa_itnim_event event);
181*4882a593Smuzhiyun static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
182*4882a593Smuzhiyun 					enum bfa_itnim_event event);
183*4882a593Smuzhiyun static void     bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
184*4882a593Smuzhiyun 					enum bfa_itnim_event event);
185*4882a593Smuzhiyun static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
186*4882a593Smuzhiyun 					enum bfa_itnim_event event);
187*4882a593Smuzhiyun static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
188*4882a593Smuzhiyun 					enum bfa_itnim_event event);
189*4882a593Smuzhiyun static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
190*4882a593Smuzhiyun 					enum bfa_itnim_event event);
191*4882a593Smuzhiyun static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
192*4882a593Smuzhiyun 					enum bfa_itnim_event event);
193*4882a593Smuzhiyun static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
194*4882a593Smuzhiyun 					enum bfa_itnim_event event);
195*4882a593Smuzhiyun static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
196*4882a593Smuzhiyun 					enum bfa_itnim_event event);
197*4882a593Smuzhiyun static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
198*4882a593Smuzhiyun 					enum bfa_itnim_event event);
199*4882a593Smuzhiyun static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
200*4882a593Smuzhiyun 					enum bfa_itnim_event event);
201*4882a593Smuzhiyun static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
202*4882a593Smuzhiyun 					enum bfa_itnim_event event);
203*4882a593Smuzhiyun static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
204*4882a593Smuzhiyun 					enum bfa_itnim_event event);
205*4882a593Smuzhiyun static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
206*4882a593Smuzhiyun 					enum bfa_itnim_event event);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun /*
209*4882a593Smuzhiyun  * forward declaration for BFA IOIM functions
210*4882a593Smuzhiyun  */
211*4882a593Smuzhiyun static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
212*4882a593Smuzhiyun static bfa_boolean_t	bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim);
213*4882a593Smuzhiyun static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
214*4882a593Smuzhiyun static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
215*4882a593Smuzhiyun static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
216*4882a593Smuzhiyun static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
217*4882a593Smuzhiyun static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
218*4882a593Smuzhiyun static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
219*4882a593Smuzhiyun static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
220*4882a593Smuzhiyun static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun /*
223*4882a593Smuzhiyun  * forward declaration of BFA IO state machine
224*4882a593Smuzhiyun  */
225*4882a593Smuzhiyun static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
226*4882a593Smuzhiyun 					enum bfa_ioim_event event);
227*4882a593Smuzhiyun static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
228*4882a593Smuzhiyun 					enum bfa_ioim_event event);
229*4882a593Smuzhiyun static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
230*4882a593Smuzhiyun 					enum bfa_ioim_event event);
231*4882a593Smuzhiyun static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
232*4882a593Smuzhiyun 					enum bfa_ioim_event event);
233*4882a593Smuzhiyun static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
234*4882a593Smuzhiyun 					enum bfa_ioim_event event);
235*4882a593Smuzhiyun static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
236*4882a593Smuzhiyun 					enum bfa_ioim_event event);
237*4882a593Smuzhiyun static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
238*4882a593Smuzhiyun 					enum bfa_ioim_event event);
239*4882a593Smuzhiyun static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
240*4882a593Smuzhiyun 					enum bfa_ioim_event event);
241*4882a593Smuzhiyun static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
242*4882a593Smuzhiyun 					enum bfa_ioim_event event);
243*4882a593Smuzhiyun static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
244*4882a593Smuzhiyun 					enum bfa_ioim_event event);
245*4882a593Smuzhiyun static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
246*4882a593Smuzhiyun 					enum bfa_ioim_event event);
247*4882a593Smuzhiyun static void	bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,
248*4882a593Smuzhiyun 					enum bfa_ioim_event event);
249*4882a593Smuzhiyun /*
250*4882a593Smuzhiyun  * forward declaration for BFA TSKIM functions
251*4882a593Smuzhiyun  */
252*4882a593Smuzhiyun static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
253*4882a593Smuzhiyun static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
254*4882a593Smuzhiyun static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
255*4882a593Smuzhiyun 					struct scsi_lun lun);
256*4882a593Smuzhiyun static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
257*4882a593Smuzhiyun static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);
258*4882a593Smuzhiyun static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
259*4882a593Smuzhiyun static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
260*4882a593Smuzhiyun static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
261*4882a593Smuzhiyun static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun /*
264*4882a593Smuzhiyun  * forward declaration of BFA TSKIM state machine
265*4882a593Smuzhiyun  */
266*4882a593Smuzhiyun static void     bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
267*4882a593Smuzhiyun 					enum bfa_tskim_event event);
268*4882a593Smuzhiyun static void     bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
269*4882a593Smuzhiyun 					enum bfa_tskim_event event);
270*4882a593Smuzhiyun static void     bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
271*4882a593Smuzhiyun 					enum bfa_tskim_event event);
272*4882a593Smuzhiyun static void     bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
273*4882a593Smuzhiyun 					enum bfa_tskim_event event);
274*4882a593Smuzhiyun static void     bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
275*4882a593Smuzhiyun 					enum bfa_tskim_event event);
276*4882a593Smuzhiyun static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
277*4882a593Smuzhiyun 					enum bfa_tskim_event event);
278*4882a593Smuzhiyun static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
279*4882a593Smuzhiyun 					enum bfa_tskim_event event);
280*4882a593Smuzhiyun /*
281*4882a593Smuzhiyun  *  BFA FCP Initiator Mode module
282*4882a593Smuzhiyun  */
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun /*
285*4882a593Smuzhiyun  * Compute and return memory needed by FCP(im) module.
286*4882a593Smuzhiyun  */
287*4882a593Smuzhiyun static void
bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s * cfg,u32 * km_len)288*4882a593Smuzhiyun bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	bfa_itnim_meminfo(cfg, km_len);
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	/*
293*4882a593Smuzhiyun 	 * IO memory
294*4882a593Smuzhiyun 	 */
295*4882a593Smuzhiyun 	*km_len += cfg->fwcfg.num_ioim_reqs *
296*4882a593Smuzhiyun 	  (sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s));
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	/*
299*4882a593Smuzhiyun 	 * task management command memory
300*4882a593Smuzhiyun 	 */
301*4882a593Smuzhiyun 	if (cfg->fwcfg.num_tskim_reqs < BFA_TSKIM_MIN)
302*4882a593Smuzhiyun 		cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN;
303*4882a593Smuzhiyun 	*km_len += cfg->fwcfg.num_tskim_reqs * sizeof(struct bfa_tskim_s);
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun static void
bfa_fcpim_attach(struct bfa_fcp_mod_s * fcp,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)308*4882a593Smuzhiyun bfa_fcpim_attach(struct bfa_fcp_mod_s *fcp, void *bfad,
309*4882a593Smuzhiyun 		struct bfa_iocfc_cfg_s *cfg, struct bfa_pcidev_s *pcidev)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = &fcp->fcpim;
312*4882a593Smuzhiyun 	struct bfa_s *bfa = fcp->bfa;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	bfa_trc(bfa, cfg->drvcfg.path_tov);
315*4882a593Smuzhiyun 	bfa_trc(bfa, cfg->fwcfg.num_rports);
316*4882a593Smuzhiyun 	bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
317*4882a593Smuzhiyun 	bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	fcpim->fcp		= fcp;
320*4882a593Smuzhiyun 	fcpim->bfa		= bfa;
321*4882a593Smuzhiyun 	fcpim->num_itnims	= cfg->fwcfg.num_rports;
322*4882a593Smuzhiyun 	fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
323*4882a593Smuzhiyun 	fcpim->path_tov		= cfg->drvcfg.path_tov;
324*4882a593Smuzhiyun 	fcpim->delay_comp	= cfg->drvcfg.delay_comp;
325*4882a593Smuzhiyun 	fcpim->profile_comp = NULL;
326*4882a593Smuzhiyun 	fcpim->profile_start = NULL;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	bfa_itnim_attach(fcpim);
329*4882a593Smuzhiyun 	bfa_tskim_attach(fcpim);
330*4882a593Smuzhiyun 	bfa_ioim_attach(fcpim);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun void
bfa_fcpim_iocdisable(struct bfa_fcp_mod_s * fcp)334*4882a593Smuzhiyun bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *fcp)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = &fcp->fcpim;
337*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim;
338*4882a593Smuzhiyun 	struct list_head *qe, *qen;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/* Enqueue unused ioim resources to free_q */
341*4882a593Smuzhiyun 	list_splice_tail_init(&fcpim->tskim_unused_q, &fcpim->tskim_free_q);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
344*4882a593Smuzhiyun 		itnim = (struct bfa_itnim_s *) qe;
345*4882a593Smuzhiyun 		bfa_itnim_iocdisable(itnim);
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun void
bfa_fcpim_path_tov_set(struct bfa_s * bfa,u16 path_tov)350*4882a593Smuzhiyun bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	fcpim->path_tov = path_tov * 1000;
355*4882a593Smuzhiyun 	if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX)
356*4882a593Smuzhiyun 		fcpim->path_tov = BFA_FCPIM_PATHTOV_MAX;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun u16
bfa_fcpim_path_tov_get(struct bfa_s * bfa)360*4882a593Smuzhiyun bfa_fcpim_path_tov_get(struct bfa_s *bfa)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	return fcpim->path_tov / 1000;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun #define bfa_fcpim_add_iostats(__l, __r, __stats)	\
368*4882a593Smuzhiyun 	(__l->__stats += __r->__stats)
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun void
bfa_fcpim_add_stats(struct bfa_itnim_iostats_s * lstats,struct bfa_itnim_iostats_s * rstats)371*4882a593Smuzhiyun bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
372*4882a593Smuzhiyun 		struct bfa_itnim_iostats_s *rstats)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, total_ios);
375*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, qresumes);
376*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
377*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
378*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
379*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
380*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
381*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
382*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
383*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
384*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
385*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
386*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
387*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
388*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
389*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
390*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
391*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
392*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
393*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, onlines);
394*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, offlines);
395*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, creates);
396*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, deletes);
397*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, create_comps);
398*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
399*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, sler_events);
400*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, fw_create);
401*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
402*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
403*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
404*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
405*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
406*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_success);
407*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
408*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
409*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
410*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
411*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
412*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
413*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, io_comps);
414*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
415*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
416*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
417*4882a593Smuzhiyun 	bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_port_iostats(struct bfa_s * bfa,struct bfa_itnim_iostats_s * stats,u8 lp_tag)421*4882a593Smuzhiyun bfa_fcpim_port_iostats(struct bfa_s *bfa,
422*4882a593Smuzhiyun 		struct bfa_itnim_iostats_s *stats, u8 lp_tag)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
425*4882a593Smuzhiyun 	struct list_head *qe, *qen;
426*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	/* accumulate IO stats from itnim */
429*4882a593Smuzhiyun 	memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
430*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
431*4882a593Smuzhiyun 		itnim = (struct bfa_itnim_s *) qe;
432*4882a593Smuzhiyun 		if (itnim->rport->rport_info.lp_tag != lp_tag)
433*4882a593Smuzhiyun 			continue;
434*4882a593Smuzhiyun 		bfa_fcpim_add_stats(stats, &(itnim->stats));
435*4882a593Smuzhiyun 	}
436*4882a593Smuzhiyun 	return BFA_STATUS_OK;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun static void
bfa_ioim_profile_comp(struct bfa_ioim_s * ioim)440*4882a593Smuzhiyun bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	struct bfa_itnim_latency_s *io_lat =
443*4882a593Smuzhiyun 			&(ioim->itnim->ioprofile.io_latency);
444*4882a593Smuzhiyun 	u32 val, idx;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	val = (u32)(jiffies - ioim->start_time);
447*4882a593Smuzhiyun 	idx = bfa_ioim_get_index(scsi_bufflen((struct scsi_cmnd *)ioim->dio));
448*4882a593Smuzhiyun 	bfa_itnim_ioprofile_update(ioim->itnim, idx);
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	io_lat->count[idx]++;
451*4882a593Smuzhiyun 	io_lat->min[idx] = (io_lat->min[idx] < val) ? io_lat->min[idx] : val;
452*4882a593Smuzhiyun 	io_lat->max[idx] = (io_lat->max[idx] > val) ? io_lat->max[idx] : val;
453*4882a593Smuzhiyun 	io_lat->avg[idx] += val;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun static void
bfa_ioim_profile_start(struct bfa_ioim_s * ioim)457*4882a593Smuzhiyun bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun 	ioim->start_time = jiffies;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_profile_on(struct bfa_s * bfa,time64_t time)463*4882a593Smuzhiyun bfa_fcpim_profile_on(struct bfa_s *bfa, time64_t time)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim;
466*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
467*4882a593Smuzhiyun 	struct list_head *qe, *qen;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	/* accumulate IO stats from itnim */
470*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
471*4882a593Smuzhiyun 		itnim = (struct bfa_itnim_s *) qe;
472*4882a593Smuzhiyun 		bfa_itnim_clear_stats(itnim);
473*4882a593Smuzhiyun 	}
474*4882a593Smuzhiyun 	fcpim->io_profile = BFA_TRUE;
475*4882a593Smuzhiyun 	fcpim->io_profile_start_time = time;
476*4882a593Smuzhiyun 	fcpim->profile_comp = bfa_ioim_profile_comp;
477*4882a593Smuzhiyun 	fcpim->profile_start = bfa_ioim_profile_start;
478*4882a593Smuzhiyun 	return BFA_STATUS_OK;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_profile_off(struct bfa_s * bfa)482*4882a593Smuzhiyun bfa_fcpim_profile_off(struct bfa_s *bfa)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
485*4882a593Smuzhiyun 	fcpim->io_profile = BFA_FALSE;
486*4882a593Smuzhiyun 	fcpim->io_profile_start_time = 0;
487*4882a593Smuzhiyun 	fcpim->profile_comp = NULL;
488*4882a593Smuzhiyun 	fcpim->profile_start = NULL;
489*4882a593Smuzhiyun 	return BFA_STATUS_OK;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun u16
bfa_fcpim_qdepth_get(struct bfa_s * bfa)493*4882a593Smuzhiyun bfa_fcpim_qdepth_get(struct bfa_s *bfa)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	return fcpim->q_depth;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun /*
501*4882a593Smuzhiyun  *  BFA ITNIM module state machine functions
502*4882a593Smuzhiyun  */
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun /*
505*4882a593Smuzhiyun  * Beginning/unallocated state - no events expected.
506*4882a593Smuzhiyun  */
507*4882a593Smuzhiyun static void
bfa_itnim_sm_uninit(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)508*4882a593Smuzhiyun bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
511*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	switch (event) {
514*4882a593Smuzhiyun 	case BFA_ITNIM_SM_CREATE:
515*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_created);
516*4882a593Smuzhiyun 		itnim->is_online = BFA_FALSE;
517*4882a593Smuzhiyun 		bfa_fcpim_additn(itnim);
518*4882a593Smuzhiyun 		break;
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	default:
521*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
522*4882a593Smuzhiyun 	}
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun /*
526*4882a593Smuzhiyun  * Beginning state, only online event expected.
527*4882a593Smuzhiyun  */
528*4882a593Smuzhiyun static void
bfa_itnim_sm_created(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)529*4882a593Smuzhiyun bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
532*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	switch (event) {
535*4882a593Smuzhiyun 	case BFA_ITNIM_SM_ONLINE:
536*4882a593Smuzhiyun 		if (bfa_itnim_send_fwcreate(itnim))
537*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
538*4882a593Smuzhiyun 		else
539*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
540*4882a593Smuzhiyun 		break;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
543*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
544*4882a593Smuzhiyun 		bfa_fcpim_delitn(itnim);
545*4882a593Smuzhiyun 		break;
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
548*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
549*4882a593Smuzhiyun 		break;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	default:
552*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
553*4882a593Smuzhiyun 	}
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun /*
557*4882a593Smuzhiyun  *	Waiting for itnim create response from firmware.
558*4882a593Smuzhiyun  */
559*4882a593Smuzhiyun static void
bfa_itnim_sm_fwcreate(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)560*4882a593Smuzhiyun bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
563*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	switch (event) {
566*4882a593Smuzhiyun 	case BFA_ITNIM_SM_FWRSP:
567*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_online);
568*4882a593Smuzhiyun 		itnim->is_online = BFA_TRUE;
569*4882a593Smuzhiyun 		bfa_itnim_iotov_online(itnim);
570*4882a593Smuzhiyun 		bfa_itnim_online_cb(itnim);
571*4882a593Smuzhiyun 		break;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
574*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
575*4882a593Smuzhiyun 		break;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	case BFA_ITNIM_SM_OFFLINE:
578*4882a593Smuzhiyun 		if (bfa_itnim_send_fwdelete(itnim))
579*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
580*4882a593Smuzhiyun 		else
581*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
582*4882a593Smuzhiyun 		break;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
585*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
586*4882a593Smuzhiyun 		break;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	default:
589*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
590*4882a593Smuzhiyun 	}
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun static void
bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)594*4882a593Smuzhiyun bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
595*4882a593Smuzhiyun 			enum bfa_itnim_event event)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
598*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	switch (event) {
601*4882a593Smuzhiyun 	case BFA_ITNIM_SM_QRESUME:
602*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
603*4882a593Smuzhiyun 		bfa_itnim_send_fwcreate(itnim);
604*4882a593Smuzhiyun 		break;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
607*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
608*4882a593Smuzhiyun 		bfa_reqq_wcancel(&itnim->reqq_wait);
609*4882a593Smuzhiyun 		bfa_fcpim_delitn(itnim);
610*4882a593Smuzhiyun 		break;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	case BFA_ITNIM_SM_OFFLINE:
613*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
614*4882a593Smuzhiyun 		bfa_reqq_wcancel(&itnim->reqq_wait);
615*4882a593Smuzhiyun 		bfa_itnim_offline_cb(itnim);
616*4882a593Smuzhiyun 		break;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
619*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
620*4882a593Smuzhiyun 		bfa_reqq_wcancel(&itnim->reqq_wait);
621*4882a593Smuzhiyun 		break;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	default:
624*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
625*4882a593Smuzhiyun 	}
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun /*
629*4882a593Smuzhiyun  * Waiting for itnim create response from firmware, a delete is pending.
630*4882a593Smuzhiyun  */
631*4882a593Smuzhiyun static void
bfa_itnim_sm_delete_pending(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)632*4882a593Smuzhiyun bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
633*4882a593Smuzhiyun 				enum bfa_itnim_event event)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
636*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	switch (event) {
639*4882a593Smuzhiyun 	case BFA_ITNIM_SM_FWRSP:
640*4882a593Smuzhiyun 		if (bfa_itnim_send_fwdelete(itnim))
641*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
642*4882a593Smuzhiyun 		else
643*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
644*4882a593Smuzhiyun 		break;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
647*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
648*4882a593Smuzhiyun 		bfa_fcpim_delitn(itnim);
649*4882a593Smuzhiyun 		break;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	default:
652*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun /*
657*4882a593Smuzhiyun  * Online state - normal parking state.
658*4882a593Smuzhiyun  */
659*4882a593Smuzhiyun static void
bfa_itnim_sm_online(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)660*4882a593Smuzhiyun bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
661*4882a593Smuzhiyun {
662*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
663*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	switch (event) {
666*4882a593Smuzhiyun 	case BFA_ITNIM_SM_OFFLINE:
667*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
668*4882a593Smuzhiyun 		itnim->is_online = BFA_FALSE;
669*4882a593Smuzhiyun 		bfa_itnim_iotov_start(itnim);
670*4882a593Smuzhiyun 		bfa_itnim_cleanup(itnim);
671*4882a593Smuzhiyun 		break;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
674*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
675*4882a593Smuzhiyun 		itnim->is_online = BFA_FALSE;
676*4882a593Smuzhiyun 		bfa_itnim_cleanup(itnim);
677*4882a593Smuzhiyun 		break;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 	case BFA_ITNIM_SM_SLER:
680*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
681*4882a593Smuzhiyun 		itnim->is_online = BFA_FALSE;
682*4882a593Smuzhiyun 		bfa_itnim_iotov_start(itnim);
683*4882a593Smuzhiyun 		bfa_itnim_sler_cb(itnim);
684*4882a593Smuzhiyun 		break;
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
687*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
688*4882a593Smuzhiyun 		itnim->is_online = BFA_FALSE;
689*4882a593Smuzhiyun 		bfa_itnim_iotov_start(itnim);
690*4882a593Smuzhiyun 		bfa_itnim_iocdisable_cleanup(itnim);
691*4882a593Smuzhiyun 		break;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	default:
694*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
695*4882a593Smuzhiyun 	}
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun /*
699*4882a593Smuzhiyun  * Second level error recovery need.
700*4882a593Smuzhiyun  */
701*4882a593Smuzhiyun static void
bfa_itnim_sm_sler(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)702*4882a593Smuzhiyun bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
703*4882a593Smuzhiyun {
704*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
705*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	switch (event) {
708*4882a593Smuzhiyun 	case BFA_ITNIM_SM_OFFLINE:
709*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
710*4882a593Smuzhiyun 		bfa_itnim_cleanup(itnim);
711*4882a593Smuzhiyun 		break;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
714*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
715*4882a593Smuzhiyun 		bfa_itnim_cleanup(itnim);
716*4882a593Smuzhiyun 		bfa_itnim_iotov_delete(itnim);
717*4882a593Smuzhiyun 		break;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
720*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
721*4882a593Smuzhiyun 		bfa_itnim_iocdisable_cleanup(itnim);
722*4882a593Smuzhiyun 		break;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	default:
725*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
726*4882a593Smuzhiyun 	}
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun /*
730*4882a593Smuzhiyun  * Going offline. Waiting for active IO cleanup.
731*4882a593Smuzhiyun  */
732*4882a593Smuzhiyun static void
bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)733*4882a593Smuzhiyun bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
734*4882a593Smuzhiyun 				 enum bfa_itnim_event event)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
737*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	switch (event) {
740*4882a593Smuzhiyun 	case BFA_ITNIM_SM_CLEANUP:
741*4882a593Smuzhiyun 		if (bfa_itnim_send_fwdelete(itnim))
742*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
743*4882a593Smuzhiyun 		else
744*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
745*4882a593Smuzhiyun 		break;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
748*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
749*4882a593Smuzhiyun 		bfa_itnim_iotov_delete(itnim);
750*4882a593Smuzhiyun 		break;
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
753*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
754*4882a593Smuzhiyun 		bfa_itnim_iocdisable_cleanup(itnim);
755*4882a593Smuzhiyun 		bfa_itnim_offline_cb(itnim);
756*4882a593Smuzhiyun 		break;
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	case BFA_ITNIM_SM_SLER:
759*4882a593Smuzhiyun 		break;
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	default:
762*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun /*
767*4882a593Smuzhiyun  * Deleting itnim. Waiting for active IO cleanup.
768*4882a593Smuzhiyun  */
769*4882a593Smuzhiyun static void
bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)770*4882a593Smuzhiyun bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
771*4882a593Smuzhiyun 				enum bfa_itnim_event event)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
774*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	switch (event) {
777*4882a593Smuzhiyun 	case BFA_ITNIM_SM_CLEANUP:
778*4882a593Smuzhiyun 		if (bfa_itnim_send_fwdelete(itnim))
779*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
780*4882a593Smuzhiyun 		else
781*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
782*4882a593Smuzhiyun 		break;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
785*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
786*4882a593Smuzhiyun 		bfa_itnim_iocdisable_cleanup(itnim);
787*4882a593Smuzhiyun 		break;
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	default:
790*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
791*4882a593Smuzhiyun 	}
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun /*
795*4882a593Smuzhiyun  * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
796*4882a593Smuzhiyun  */
797*4882a593Smuzhiyun static void
bfa_itnim_sm_fwdelete(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)798*4882a593Smuzhiyun bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
799*4882a593Smuzhiyun {
800*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
801*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	switch (event) {
804*4882a593Smuzhiyun 	case BFA_ITNIM_SM_FWRSP:
805*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
806*4882a593Smuzhiyun 		bfa_itnim_offline_cb(itnim);
807*4882a593Smuzhiyun 		break;
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
810*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
811*4882a593Smuzhiyun 		break;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
814*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
815*4882a593Smuzhiyun 		bfa_itnim_offline_cb(itnim);
816*4882a593Smuzhiyun 		break;
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun 	default:
819*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
820*4882a593Smuzhiyun 	}
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun static void
bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)824*4882a593Smuzhiyun bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
825*4882a593Smuzhiyun 			enum bfa_itnim_event event)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
828*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	switch (event) {
831*4882a593Smuzhiyun 	case BFA_ITNIM_SM_QRESUME:
832*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
833*4882a593Smuzhiyun 		bfa_itnim_send_fwdelete(itnim);
834*4882a593Smuzhiyun 		break;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
837*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
838*4882a593Smuzhiyun 		break;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
841*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
842*4882a593Smuzhiyun 		bfa_reqq_wcancel(&itnim->reqq_wait);
843*4882a593Smuzhiyun 		bfa_itnim_offline_cb(itnim);
844*4882a593Smuzhiyun 		break;
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	default:
847*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
848*4882a593Smuzhiyun 	}
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun /*
852*4882a593Smuzhiyun  * Offline state.
853*4882a593Smuzhiyun  */
854*4882a593Smuzhiyun static void
bfa_itnim_sm_offline(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)855*4882a593Smuzhiyun bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
856*4882a593Smuzhiyun {
857*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
858*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	switch (event) {
861*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
862*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
863*4882a593Smuzhiyun 		bfa_itnim_iotov_delete(itnim);
864*4882a593Smuzhiyun 		bfa_fcpim_delitn(itnim);
865*4882a593Smuzhiyun 		break;
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	case BFA_ITNIM_SM_ONLINE:
868*4882a593Smuzhiyun 		if (bfa_itnim_send_fwcreate(itnim))
869*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
870*4882a593Smuzhiyun 		else
871*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
872*4882a593Smuzhiyun 		break;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
875*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
876*4882a593Smuzhiyun 		break;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	default:
879*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
880*4882a593Smuzhiyun 	}
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun static void
bfa_itnim_sm_iocdisable(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)884*4882a593Smuzhiyun bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
885*4882a593Smuzhiyun 				enum bfa_itnim_event event)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
888*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	switch (event) {
891*4882a593Smuzhiyun 	case BFA_ITNIM_SM_DELETE:
892*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
893*4882a593Smuzhiyun 		bfa_itnim_iotov_delete(itnim);
894*4882a593Smuzhiyun 		bfa_fcpim_delitn(itnim);
895*4882a593Smuzhiyun 		break;
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun 	case BFA_ITNIM_SM_OFFLINE:
898*4882a593Smuzhiyun 		bfa_itnim_offline_cb(itnim);
899*4882a593Smuzhiyun 		break;
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun 	case BFA_ITNIM_SM_ONLINE:
902*4882a593Smuzhiyun 		if (bfa_itnim_send_fwcreate(itnim))
903*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
904*4882a593Smuzhiyun 		else
905*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
906*4882a593Smuzhiyun 		break;
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
909*4882a593Smuzhiyun 		break;
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun 	default:
912*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
913*4882a593Smuzhiyun 	}
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun /*
917*4882a593Smuzhiyun  * Itnim is deleted, waiting for firmware response to delete.
918*4882a593Smuzhiyun  */
919*4882a593Smuzhiyun static void
bfa_itnim_sm_deleting(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)920*4882a593Smuzhiyun bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
923*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun 	switch (event) {
926*4882a593Smuzhiyun 	case BFA_ITNIM_SM_FWRSP:
927*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
928*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
929*4882a593Smuzhiyun 		bfa_fcpim_delitn(itnim);
930*4882a593Smuzhiyun 		break;
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 	default:
933*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
934*4882a593Smuzhiyun 	}
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun static void
bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s * itnim,enum bfa_itnim_event event)938*4882a593Smuzhiyun bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
939*4882a593Smuzhiyun 		enum bfa_itnim_event event)
940*4882a593Smuzhiyun {
941*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
942*4882a593Smuzhiyun 	bfa_trc(itnim->bfa, event);
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun 	switch (event) {
945*4882a593Smuzhiyun 	case BFA_ITNIM_SM_QRESUME:
946*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
947*4882a593Smuzhiyun 		bfa_itnim_send_fwdelete(itnim);
948*4882a593Smuzhiyun 		break;
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	case BFA_ITNIM_SM_HWFAIL:
951*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
952*4882a593Smuzhiyun 		bfa_reqq_wcancel(&itnim->reqq_wait);
953*4882a593Smuzhiyun 		bfa_fcpim_delitn(itnim);
954*4882a593Smuzhiyun 		break;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	default:
957*4882a593Smuzhiyun 		bfa_sm_fault(itnim->bfa, event);
958*4882a593Smuzhiyun 	}
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun /*
962*4882a593Smuzhiyun  * Initiate cleanup of all IOs on an IOC failure.
963*4882a593Smuzhiyun  */
964*4882a593Smuzhiyun static void
bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s * itnim)965*4882a593Smuzhiyun bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
966*4882a593Smuzhiyun {
967*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim;
968*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
969*4882a593Smuzhiyun 	struct list_head	*qe, *qen;
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->tsk_q) {
972*4882a593Smuzhiyun 		tskim = (struct bfa_tskim_s *) qe;
973*4882a593Smuzhiyun 		bfa_tskim_iocdisable(tskim);
974*4882a593Smuzhiyun 	}
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->io_q) {
977*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
978*4882a593Smuzhiyun 		bfa_ioim_iocdisable(ioim);
979*4882a593Smuzhiyun 	}
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	/*
982*4882a593Smuzhiyun 	 * For IO request in pending queue, we pretend an early timeout.
983*4882a593Smuzhiyun 	 */
984*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->pending_q) {
985*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
986*4882a593Smuzhiyun 		bfa_ioim_tov(ioim);
987*4882a593Smuzhiyun 	}
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
990*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
991*4882a593Smuzhiyun 		bfa_ioim_iocdisable(ioim);
992*4882a593Smuzhiyun 	}
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun /*
996*4882a593Smuzhiyun  * IO cleanup completion
997*4882a593Smuzhiyun  */
998*4882a593Smuzhiyun static void
bfa_itnim_cleanp_comp(void * itnim_cbarg)999*4882a593Smuzhiyun bfa_itnim_cleanp_comp(void *itnim_cbarg)
1000*4882a593Smuzhiyun {
1001*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = itnim_cbarg;
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun 	bfa_stats(itnim, cleanup_comps);
1004*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun /*
1008*4882a593Smuzhiyun  * Initiate cleanup of all IOs.
1009*4882a593Smuzhiyun  */
1010*4882a593Smuzhiyun static void
bfa_itnim_cleanup(struct bfa_itnim_s * itnim)1011*4882a593Smuzhiyun bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
1012*4882a593Smuzhiyun {
1013*4882a593Smuzhiyun 	struct bfa_ioim_s  *ioim;
1014*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim;
1015*4882a593Smuzhiyun 	struct list_head	*qe, *qen;
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun 	bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->io_q) {
1020*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 		/*
1023*4882a593Smuzhiyun 		 * Move IO to a cleanup queue from active queue so that a later
1024*4882a593Smuzhiyun 		 * TM will not pickup this IO.
1025*4882a593Smuzhiyun 		 */
1026*4882a593Smuzhiyun 		list_del(&ioim->qe);
1027*4882a593Smuzhiyun 		list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 		bfa_wc_up(&itnim->wc);
1030*4882a593Smuzhiyun 		bfa_ioim_cleanup(ioim);
1031*4882a593Smuzhiyun 	}
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->tsk_q) {
1034*4882a593Smuzhiyun 		tskim = (struct bfa_tskim_s *) qe;
1035*4882a593Smuzhiyun 		bfa_wc_up(&itnim->wc);
1036*4882a593Smuzhiyun 		bfa_tskim_cleanup(tskim);
1037*4882a593Smuzhiyun 	}
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun 	bfa_wc_wait(&itnim->wc);
1040*4882a593Smuzhiyun }
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun static void
__bfa_cb_itnim_online(void * cbarg,bfa_boolean_t complete)1043*4882a593Smuzhiyun __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
1044*4882a593Smuzhiyun {
1045*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = cbarg;
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 	if (complete)
1048*4882a593Smuzhiyun 		bfa_cb_itnim_online(itnim->ditn);
1049*4882a593Smuzhiyun }
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun static void
__bfa_cb_itnim_offline(void * cbarg,bfa_boolean_t complete)1052*4882a593Smuzhiyun __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = cbarg;
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 	if (complete)
1057*4882a593Smuzhiyun 		bfa_cb_itnim_offline(itnim->ditn);
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun static void
__bfa_cb_itnim_sler(void * cbarg,bfa_boolean_t complete)1061*4882a593Smuzhiyun __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = cbarg;
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun 	if (complete)
1066*4882a593Smuzhiyun 		bfa_cb_itnim_sler(itnim->ditn);
1067*4882a593Smuzhiyun }
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun /*
1070*4882a593Smuzhiyun  * Call to resume any I/O requests waiting for room in request queue.
1071*4882a593Smuzhiyun  */
1072*4882a593Smuzhiyun static void
bfa_itnim_qresume(void * cbarg)1073*4882a593Smuzhiyun bfa_itnim_qresume(void *cbarg)
1074*4882a593Smuzhiyun {
1075*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = cbarg;
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
1078*4882a593Smuzhiyun }
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun /*
1081*4882a593Smuzhiyun  *  bfa_itnim_public
1082*4882a593Smuzhiyun  */
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun void
bfa_itnim_iodone(struct bfa_itnim_s * itnim)1085*4882a593Smuzhiyun bfa_itnim_iodone(struct bfa_itnim_s *itnim)
1086*4882a593Smuzhiyun {
1087*4882a593Smuzhiyun 	bfa_wc_down(&itnim->wc);
1088*4882a593Smuzhiyun }
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun void
bfa_itnim_tskdone(struct bfa_itnim_s * itnim)1091*4882a593Smuzhiyun bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
1092*4882a593Smuzhiyun {
1093*4882a593Smuzhiyun 	bfa_wc_down(&itnim->wc);
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun void
bfa_itnim_meminfo(struct bfa_iocfc_cfg_s * cfg,u32 * km_len)1097*4882a593Smuzhiyun bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
1098*4882a593Smuzhiyun {
1099*4882a593Smuzhiyun 	/*
1100*4882a593Smuzhiyun 	 * ITN memory
1101*4882a593Smuzhiyun 	 */
1102*4882a593Smuzhiyun 	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
1103*4882a593Smuzhiyun }
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun void
bfa_itnim_attach(struct bfa_fcpim_s * fcpim)1106*4882a593Smuzhiyun bfa_itnim_attach(struct bfa_fcpim_s *fcpim)
1107*4882a593Smuzhiyun {
1108*4882a593Smuzhiyun 	struct bfa_s	*bfa = fcpim->bfa;
1109*4882a593Smuzhiyun 	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;
1110*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim;
1111*4882a593Smuzhiyun 	int	i, j;
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcpim->itnim_q);
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 	itnim = (struct bfa_itnim_s *) bfa_mem_kva_curp(fcp);
1116*4882a593Smuzhiyun 	fcpim->itnim_arr = itnim;
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
1119*4882a593Smuzhiyun 		memset(itnim, 0, sizeof(struct bfa_itnim_s));
1120*4882a593Smuzhiyun 		itnim->bfa = bfa;
1121*4882a593Smuzhiyun 		itnim->fcpim = fcpim;
1122*4882a593Smuzhiyun 		itnim->reqq = BFA_REQQ_QOS_LO;
1123*4882a593Smuzhiyun 		itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
1124*4882a593Smuzhiyun 		itnim->iotov_active = BFA_FALSE;
1125*4882a593Smuzhiyun 		bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 		INIT_LIST_HEAD(&itnim->io_q);
1128*4882a593Smuzhiyun 		INIT_LIST_HEAD(&itnim->io_cleanup_q);
1129*4882a593Smuzhiyun 		INIT_LIST_HEAD(&itnim->pending_q);
1130*4882a593Smuzhiyun 		INIT_LIST_HEAD(&itnim->tsk_q);
1131*4882a593Smuzhiyun 		INIT_LIST_HEAD(&itnim->delay_comp_q);
1132*4882a593Smuzhiyun 		for (j = 0; j < BFA_IOBUCKET_MAX; j++)
1133*4882a593Smuzhiyun 			itnim->ioprofile.io_latency.min[j] = ~0;
1134*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
1135*4882a593Smuzhiyun 	}
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun 	bfa_mem_kva_curp(fcp) = (u8 *) itnim;
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun void
bfa_itnim_iocdisable(struct bfa_itnim_s * itnim)1141*4882a593Smuzhiyun bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
1142*4882a593Smuzhiyun {
1143*4882a593Smuzhiyun 	bfa_stats(itnim, ioc_disabled);
1144*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun static bfa_boolean_t
bfa_itnim_send_fwcreate(struct bfa_itnim_s * itnim)1148*4882a593Smuzhiyun bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
1149*4882a593Smuzhiyun {
1150*4882a593Smuzhiyun 	struct bfi_itn_create_req_s *m;
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	itnim->msg_no++;
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 	/*
1155*4882a593Smuzhiyun 	 * check for room in queue to send request now
1156*4882a593Smuzhiyun 	 */
1157*4882a593Smuzhiyun 	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
1158*4882a593Smuzhiyun 	if (!m) {
1159*4882a593Smuzhiyun 		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
1160*4882a593Smuzhiyun 		return BFA_FALSE;
1161*4882a593Smuzhiyun 	}
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_CREATE_REQ,
1164*4882a593Smuzhiyun 			bfa_fn_lpu(itnim->bfa));
1165*4882a593Smuzhiyun 	m->fw_handle = itnim->rport->fw_handle;
1166*4882a593Smuzhiyun 	m->class = FC_CLASS_3;
1167*4882a593Smuzhiyun 	m->seq_rec = itnim->seq_rec;
1168*4882a593Smuzhiyun 	m->msg_no = itnim->msg_no;
1169*4882a593Smuzhiyun 	bfa_stats(itnim, fw_create);
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun 	/*
1172*4882a593Smuzhiyun 	 * queue I/O message to firmware
1173*4882a593Smuzhiyun 	 */
1174*4882a593Smuzhiyun 	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
1175*4882a593Smuzhiyun 	return BFA_TRUE;
1176*4882a593Smuzhiyun }
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun static bfa_boolean_t
bfa_itnim_send_fwdelete(struct bfa_itnim_s * itnim)1179*4882a593Smuzhiyun bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
1180*4882a593Smuzhiyun {
1181*4882a593Smuzhiyun 	struct bfi_itn_delete_req_s *m;
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun 	/*
1184*4882a593Smuzhiyun 	 * check for room in queue to send request now
1185*4882a593Smuzhiyun 	 */
1186*4882a593Smuzhiyun 	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
1187*4882a593Smuzhiyun 	if (!m) {
1188*4882a593Smuzhiyun 		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
1189*4882a593Smuzhiyun 		return BFA_FALSE;
1190*4882a593Smuzhiyun 	}
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_DELETE_REQ,
1193*4882a593Smuzhiyun 			bfa_fn_lpu(itnim->bfa));
1194*4882a593Smuzhiyun 	m->fw_handle = itnim->rport->fw_handle;
1195*4882a593Smuzhiyun 	bfa_stats(itnim, fw_delete);
1196*4882a593Smuzhiyun 
1197*4882a593Smuzhiyun 	/*
1198*4882a593Smuzhiyun 	 * queue I/O message to firmware
1199*4882a593Smuzhiyun 	 */
1200*4882a593Smuzhiyun 	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
1201*4882a593Smuzhiyun 	return BFA_TRUE;
1202*4882a593Smuzhiyun }
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun /*
1205*4882a593Smuzhiyun  * Cleanup all pending failed inflight requests.
1206*4882a593Smuzhiyun  */
1207*4882a593Smuzhiyun static void
bfa_itnim_delayed_comp(struct bfa_itnim_s * itnim,bfa_boolean_t iotov)1208*4882a593Smuzhiyun bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
1209*4882a593Smuzhiyun {
1210*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
1211*4882a593Smuzhiyun 	struct list_head *qe, *qen;
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
1214*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *)qe;
1215*4882a593Smuzhiyun 		bfa_ioim_delayed_comp(ioim, iotov);
1216*4882a593Smuzhiyun 	}
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun /*
1220*4882a593Smuzhiyun  * Start all pending IO requests.
1221*4882a593Smuzhiyun  */
1222*4882a593Smuzhiyun static void
bfa_itnim_iotov_online(struct bfa_itnim_s * itnim)1223*4882a593Smuzhiyun bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
1224*4882a593Smuzhiyun {
1225*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun 	bfa_itnim_iotov_stop(itnim);
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	/*
1230*4882a593Smuzhiyun 	 * Abort all inflight IO requests in the queue
1231*4882a593Smuzhiyun 	 */
1232*4882a593Smuzhiyun 	bfa_itnim_delayed_comp(itnim, BFA_FALSE);
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	/*
1235*4882a593Smuzhiyun 	 * Start all pending IO requests.
1236*4882a593Smuzhiyun 	 */
1237*4882a593Smuzhiyun 	while (!list_empty(&itnim->pending_q)) {
1238*4882a593Smuzhiyun 		bfa_q_deq(&itnim->pending_q, &ioim);
1239*4882a593Smuzhiyun 		list_add_tail(&ioim->qe, &itnim->io_q);
1240*4882a593Smuzhiyun 		bfa_ioim_start(ioim);
1241*4882a593Smuzhiyun 	}
1242*4882a593Smuzhiyun }
1243*4882a593Smuzhiyun 
1244*4882a593Smuzhiyun /*
1245*4882a593Smuzhiyun  * Fail all pending IO requests
1246*4882a593Smuzhiyun  */
1247*4882a593Smuzhiyun static void
bfa_itnim_iotov_cleanup(struct bfa_itnim_s * itnim)1248*4882a593Smuzhiyun bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
1249*4882a593Smuzhiyun {
1250*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
1251*4882a593Smuzhiyun 
1252*4882a593Smuzhiyun 	/*
1253*4882a593Smuzhiyun 	 * Fail all inflight IO requests in the queue
1254*4882a593Smuzhiyun 	 */
1255*4882a593Smuzhiyun 	bfa_itnim_delayed_comp(itnim, BFA_TRUE);
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	/*
1258*4882a593Smuzhiyun 	 * Fail any pending IO requests.
1259*4882a593Smuzhiyun 	 */
1260*4882a593Smuzhiyun 	while (!list_empty(&itnim->pending_q)) {
1261*4882a593Smuzhiyun 		bfa_q_deq(&itnim->pending_q, &ioim);
1262*4882a593Smuzhiyun 		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
1263*4882a593Smuzhiyun 		bfa_ioim_tov(ioim);
1264*4882a593Smuzhiyun 	}
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun /*
1268*4882a593Smuzhiyun  * IO TOV timer callback. Fail any pending IO requests.
1269*4882a593Smuzhiyun  */
1270*4882a593Smuzhiyun static void
bfa_itnim_iotov(void * itnim_arg)1271*4882a593Smuzhiyun bfa_itnim_iotov(void *itnim_arg)
1272*4882a593Smuzhiyun {
1273*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = itnim_arg;
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun 	itnim->iotov_active = BFA_FALSE;
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun 	bfa_cb_itnim_tov_begin(itnim->ditn);
1278*4882a593Smuzhiyun 	bfa_itnim_iotov_cleanup(itnim);
1279*4882a593Smuzhiyun 	bfa_cb_itnim_tov(itnim->ditn);
1280*4882a593Smuzhiyun }
1281*4882a593Smuzhiyun 
1282*4882a593Smuzhiyun /*
1283*4882a593Smuzhiyun  * Start IO TOV timer for failing back pending IO requests in offline state.
1284*4882a593Smuzhiyun  */
1285*4882a593Smuzhiyun static void
bfa_itnim_iotov_start(struct bfa_itnim_s * itnim)1286*4882a593Smuzhiyun bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
1287*4882a593Smuzhiyun {
1288*4882a593Smuzhiyun 	if (itnim->fcpim->path_tov > 0) {
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun 		itnim->iotov_active = BFA_TRUE;
1291*4882a593Smuzhiyun 		WARN_ON(!bfa_itnim_hold_io(itnim));
1292*4882a593Smuzhiyun 		bfa_timer_start(itnim->bfa, &itnim->timer,
1293*4882a593Smuzhiyun 			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
1294*4882a593Smuzhiyun 	}
1295*4882a593Smuzhiyun }
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun /*
1298*4882a593Smuzhiyun  * Stop IO TOV timer.
1299*4882a593Smuzhiyun  */
1300*4882a593Smuzhiyun static void
bfa_itnim_iotov_stop(struct bfa_itnim_s * itnim)1301*4882a593Smuzhiyun bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
1302*4882a593Smuzhiyun {
1303*4882a593Smuzhiyun 	if (itnim->iotov_active) {
1304*4882a593Smuzhiyun 		itnim->iotov_active = BFA_FALSE;
1305*4882a593Smuzhiyun 		bfa_timer_stop(&itnim->timer);
1306*4882a593Smuzhiyun 	}
1307*4882a593Smuzhiyun }
1308*4882a593Smuzhiyun 
1309*4882a593Smuzhiyun /*
1310*4882a593Smuzhiyun  * Stop IO TOV timer.
1311*4882a593Smuzhiyun  */
1312*4882a593Smuzhiyun static void
bfa_itnim_iotov_delete(struct bfa_itnim_s * itnim)1313*4882a593Smuzhiyun bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
1314*4882a593Smuzhiyun {
1315*4882a593Smuzhiyun 	bfa_boolean_t pathtov_active = BFA_FALSE;
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun 	if (itnim->iotov_active)
1318*4882a593Smuzhiyun 		pathtov_active = BFA_TRUE;
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun 	bfa_itnim_iotov_stop(itnim);
1321*4882a593Smuzhiyun 	if (pathtov_active)
1322*4882a593Smuzhiyun 		bfa_cb_itnim_tov_begin(itnim->ditn);
1323*4882a593Smuzhiyun 	bfa_itnim_iotov_cleanup(itnim);
1324*4882a593Smuzhiyun 	if (pathtov_active)
1325*4882a593Smuzhiyun 		bfa_cb_itnim_tov(itnim->ditn);
1326*4882a593Smuzhiyun }
1327*4882a593Smuzhiyun 
1328*4882a593Smuzhiyun static void
bfa_itnim_update_del_itn_stats(struct bfa_itnim_s * itnim)1329*4882a593Smuzhiyun bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
1330*4882a593Smuzhiyun {
1331*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);
1332*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_itn_iocomp_aborted +=
1333*4882a593Smuzhiyun 		itnim->stats.iocomp_aborted;
1334*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_itn_iocomp_timedout +=
1335*4882a593Smuzhiyun 		itnim->stats.iocomp_timedout;
1336*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_itn_iocom_sqer_needed +=
1337*4882a593Smuzhiyun 		itnim->stats.iocom_sqer_needed;
1338*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_itn_iocom_res_free +=
1339*4882a593Smuzhiyun 		itnim->stats.iocom_res_free;
1340*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_itn_iocom_hostabrts +=
1341*4882a593Smuzhiyun 		itnim->stats.iocom_hostabrts;
1342*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_itn_total_ios += itnim->stats.total_ios;
1343*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_io_iocdowns += itnim->stats.io_iocdowns;
1344*4882a593Smuzhiyun 	fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;
1345*4882a593Smuzhiyun }
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun /*
1348*4882a593Smuzhiyun  * bfa_itnim_public
1349*4882a593Smuzhiyun  */
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun /*
1352*4882a593Smuzhiyun  * Itnim interrupt processing.
1353*4882a593Smuzhiyun  */
1354*4882a593Smuzhiyun void
bfa_itnim_isr(struct bfa_s * bfa,struct bfi_msg_s * m)1355*4882a593Smuzhiyun bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1356*4882a593Smuzhiyun {
1357*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
1358*4882a593Smuzhiyun 	union bfi_itn_i2h_msg_u msg;
1359*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim;
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun 	bfa_trc(bfa, m->mhdr.msg_id);
1362*4882a593Smuzhiyun 
1363*4882a593Smuzhiyun 	msg.msg = m;
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun 	switch (m->mhdr.msg_id) {
1366*4882a593Smuzhiyun 	case BFI_ITN_I2H_CREATE_RSP:
1367*4882a593Smuzhiyun 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
1368*4882a593Smuzhiyun 						msg.create_rsp->bfa_handle);
1369*4882a593Smuzhiyun 		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
1370*4882a593Smuzhiyun 		bfa_stats(itnim, create_comps);
1371*4882a593Smuzhiyun 		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
1372*4882a593Smuzhiyun 		break;
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun 	case BFI_ITN_I2H_DELETE_RSP:
1375*4882a593Smuzhiyun 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
1376*4882a593Smuzhiyun 						msg.delete_rsp->bfa_handle);
1377*4882a593Smuzhiyun 		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
1378*4882a593Smuzhiyun 		bfa_stats(itnim, delete_comps);
1379*4882a593Smuzhiyun 		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
1380*4882a593Smuzhiyun 		break;
1381*4882a593Smuzhiyun 
1382*4882a593Smuzhiyun 	case BFI_ITN_I2H_SLER_EVENT:
1383*4882a593Smuzhiyun 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
1384*4882a593Smuzhiyun 						msg.sler_event->bfa_handle);
1385*4882a593Smuzhiyun 		bfa_stats(itnim, sler_events);
1386*4882a593Smuzhiyun 		bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
1387*4882a593Smuzhiyun 		break;
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun 	default:
1390*4882a593Smuzhiyun 		bfa_trc(bfa, m->mhdr.msg_id);
1391*4882a593Smuzhiyun 		WARN_ON(1);
1392*4882a593Smuzhiyun 	}
1393*4882a593Smuzhiyun }
1394*4882a593Smuzhiyun 
1395*4882a593Smuzhiyun /*
1396*4882a593Smuzhiyun  * bfa_itnim_api
1397*4882a593Smuzhiyun  */
1398*4882a593Smuzhiyun 
1399*4882a593Smuzhiyun struct bfa_itnim_s *
bfa_itnim_create(struct bfa_s * bfa,struct bfa_rport_s * rport,void * ditn)1400*4882a593Smuzhiyun bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
1401*4882a593Smuzhiyun {
1402*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
1403*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim;
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun 	bfa_itn_create(bfa, rport, bfa_itnim_isr);
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun 	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
1408*4882a593Smuzhiyun 	WARN_ON(itnim->rport != rport);
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	itnim->ditn = ditn;
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun 	bfa_stats(itnim, creates);
1413*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
1414*4882a593Smuzhiyun 
1415*4882a593Smuzhiyun 	return itnim;
1416*4882a593Smuzhiyun }
1417*4882a593Smuzhiyun 
1418*4882a593Smuzhiyun void
bfa_itnim_delete(struct bfa_itnim_s * itnim)1419*4882a593Smuzhiyun bfa_itnim_delete(struct bfa_itnim_s *itnim)
1420*4882a593Smuzhiyun {
1421*4882a593Smuzhiyun 	bfa_stats(itnim, deletes);
1422*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
1423*4882a593Smuzhiyun }
1424*4882a593Smuzhiyun 
1425*4882a593Smuzhiyun void
bfa_itnim_online(struct bfa_itnim_s * itnim,bfa_boolean_t seq_rec)1426*4882a593Smuzhiyun bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
1427*4882a593Smuzhiyun {
1428*4882a593Smuzhiyun 	itnim->seq_rec = seq_rec;
1429*4882a593Smuzhiyun 	bfa_stats(itnim, onlines);
1430*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
1431*4882a593Smuzhiyun }
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun void
bfa_itnim_offline(struct bfa_itnim_s * itnim)1434*4882a593Smuzhiyun bfa_itnim_offline(struct bfa_itnim_s *itnim)
1435*4882a593Smuzhiyun {
1436*4882a593Smuzhiyun 	bfa_stats(itnim, offlines);
1437*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
1438*4882a593Smuzhiyun }
1439*4882a593Smuzhiyun 
1440*4882a593Smuzhiyun /*
1441*4882a593Smuzhiyun  * Return true if itnim is considered offline for holding off IO request.
1442*4882a593Smuzhiyun  * IO is not held if itnim is being deleted.
1443*4882a593Smuzhiyun  */
1444*4882a593Smuzhiyun bfa_boolean_t
bfa_itnim_hold_io(struct bfa_itnim_s * itnim)1445*4882a593Smuzhiyun bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
1446*4882a593Smuzhiyun {
1447*4882a593Smuzhiyun 	return itnim->fcpim->path_tov && itnim->iotov_active &&
1448*4882a593Smuzhiyun 		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
1449*4882a593Smuzhiyun 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
1450*4882a593Smuzhiyun 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
1451*4882a593Smuzhiyun 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
1452*4882a593Smuzhiyun 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
1453*4882a593Smuzhiyun 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));
1454*4882a593Smuzhiyun }
1455*4882a593Smuzhiyun 
1456*4882a593Smuzhiyun #define bfa_io_lat_clock_res_div	HZ
1457*4882a593Smuzhiyun #define bfa_io_lat_clock_res_mul	1000
1458*4882a593Smuzhiyun bfa_status_t
bfa_itnim_get_ioprofile(struct bfa_itnim_s * itnim,struct bfa_itnim_ioprofile_s * ioprofile)1459*4882a593Smuzhiyun bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
1460*4882a593Smuzhiyun 			struct bfa_itnim_ioprofile_s *ioprofile)
1461*4882a593Smuzhiyun {
1462*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim;
1463*4882a593Smuzhiyun 
1464*4882a593Smuzhiyun 	if (!itnim)
1465*4882a593Smuzhiyun 		return BFA_STATUS_NO_FCPIM_NEXUS;
1466*4882a593Smuzhiyun 
1467*4882a593Smuzhiyun 	fcpim = BFA_FCPIM(itnim->bfa);
1468*4882a593Smuzhiyun 
1469*4882a593Smuzhiyun 	if (!fcpim->io_profile)
1470*4882a593Smuzhiyun 		return BFA_STATUS_IOPROFILE_OFF;
1471*4882a593Smuzhiyun 
1472*4882a593Smuzhiyun 	itnim->ioprofile.index = BFA_IOBUCKET_MAX;
1473*4882a593Smuzhiyun 	/* unsigned 32-bit time_t overflow here in y2106 */
1474*4882a593Smuzhiyun 	itnim->ioprofile.io_profile_start_time =
1475*4882a593Smuzhiyun 				bfa_io_profile_start_time(itnim->bfa);
1476*4882a593Smuzhiyun 	itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
1477*4882a593Smuzhiyun 	itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
1478*4882a593Smuzhiyun 	*ioprofile = itnim->ioprofile;
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 	return BFA_STATUS_OK;
1481*4882a593Smuzhiyun }
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun void
bfa_itnim_clear_stats(struct bfa_itnim_s * itnim)1484*4882a593Smuzhiyun bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
1485*4882a593Smuzhiyun {
1486*4882a593Smuzhiyun 	int j;
1487*4882a593Smuzhiyun 
1488*4882a593Smuzhiyun 	if (!itnim)
1489*4882a593Smuzhiyun 		return;
1490*4882a593Smuzhiyun 
1491*4882a593Smuzhiyun 	memset(&itnim->stats, 0, sizeof(itnim->stats));
1492*4882a593Smuzhiyun 	memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));
1493*4882a593Smuzhiyun 	for (j = 0; j < BFA_IOBUCKET_MAX; j++)
1494*4882a593Smuzhiyun 		itnim->ioprofile.io_latency.min[j] = ~0;
1495*4882a593Smuzhiyun }
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun /*
1498*4882a593Smuzhiyun  *  BFA IO module state machine functions
1499*4882a593Smuzhiyun  */
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun /*
1502*4882a593Smuzhiyun  * IO is not started (unallocated).
1503*4882a593Smuzhiyun  */
1504*4882a593Smuzhiyun static void
bfa_ioim_sm_uninit(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1505*4882a593Smuzhiyun bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1506*4882a593Smuzhiyun {
1507*4882a593Smuzhiyun 	switch (event) {
1508*4882a593Smuzhiyun 	case BFA_IOIM_SM_START:
1509*4882a593Smuzhiyun 		if (!bfa_itnim_is_online(ioim->itnim)) {
1510*4882a593Smuzhiyun 			if (!bfa_itnim_hold_io(ioim->itnim)) {
1511*4882a593Smuzhiyun 				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1512*4882a593Smuzhiyun 				list_del(&ioim->qe);
1513*4882a593Smuzhiyun 				list_add_tail(&ioim->qe,
1514*4882a593Smuzhiyun 					&ioim->fcpim->ioim_comp_q);
1515*4882a593Smuzhiyun 				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
1516*4882a593Smuzhiyun 						__bfa_cb_ioim_pathtov, ioim);
1517*4882a593Smuzhiyun 			} else {
1518*4882a593Smuzhiyun 				list_del(&ioim->qe);
1519*4882a593Smuzhiyun 				list_add_tail(&ioim->qe,
1520*4882a593Smuzhiyun 					&ioim->itnim->pending_q);
1521*4882a593Smuzhiyun 			}
1522*4882a593Smuzhiyun 			break;
1523*4882a593Smuzhiyun 		}
1524*4882a593Smuzhiyun 
1525*4882a593Smuzhiyun 		if (ioim->nsges > BFI_SGE_INLINE) {
1526*4882a593Smuzhiyun 			if (!bfa_ioim_sgpg_alloc(ioim)) {
1527*4882a593Smuzhiyun 				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
1528*4882a593Smuzhiyun 				return;
1529*4882a593Smuzhiyun 			}
1530*4882a593Smuzhiyun 		}
1531*4882a593Smuzhiyun 
1532*4882a593Smuzhiyun 		if (!bfa_ioim_send_ioreq(ioim)) {
1533*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
1534*4882a593Smuzhiyun 			break;
1535*4882a593Smuzhiyun 		}
1536*4882a593Smuzhiyun 
1537*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
1538*4882a593Smuzhiyun 		break;
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun 	case BFA_IOIM_SM_IOTOV:
1541*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1542*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1543*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
1544*4882a593Smuzhiyun 				__bfa_cb_ioim_pathtov, ioim);
1545*4882a593Smuzhiyun 		break;
1546*4882a593Smuzhiyun 
1547*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT:
1548*4882a593Smuzhiyun 		/*
1549*4882a593Smuzhiyun 		 * IO in pending queue can get abort requests. Complete abort
1550*4882a593Smuzhiyun 		 * requests immediately.
1551*4882a593Smuzhiyun 		 */
1552*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1553*4882a593Smuzhiyun 		WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
1554*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
1555*4882a593Smuzhiyun 			__bfa_cb_ioim_abort, ioim);
1556*4882a593Smuzhiyun 		break;
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun 	default:
1559*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1560*4882a593Smuzhiyun 	}
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun 
1563*4882a593Smuzhiyun /*
1564*4882a593Smuzhiyun  * IO is waiting for SG pages.
1565*4882a593Smuzhiyun  */
1566*4882a593Smuzhiyun static void
bfa_ioim_sm_sgalloc(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1567*4882a593Smuzhiyun bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1568*4882a593Smuzhiyun {
1569*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
1570*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
1571*4882a593Smuzhiyun 
1572*4882a593Smuzhiyun 	switch (event) {
1573*4882a593Smuzhiyun 	case BFA_IOIM_SM_SGALLOCED:
1574*4882a593Smuzhiyun 		if (!bfa_ioim_send_ioreq(ioim)) {
1575*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
1576*4882a593Smuzhiyun 			break;
1577*4882a593Smuzhiyun 		}
1578*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
1579*4882a593Smuzhiyun 		break;
1580*4882a593Smuzhiyun 
1581*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
1582*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1583*4882a593Smuzhiyun 		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
1584*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1585*4882a593Smuzhiyun 			      ioim);
1586*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
1587*4882a593Smuzhiyun 		break;
1588*4882a593Smuzhiyun 
1589*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT:
1590*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1591*4882a593Smuzhiyun 		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
1592*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1593*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1594*4882a593Smuzhiyun 			      ioim);
1595*4882a593Smuzhiyun 		break;
1596*4882a593Smuzhiyun 
1597*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1598*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1599*4882a593Smuzhiyun 		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
1600*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1601*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1602*4882a593Smuzhiyun 			      ioim);
1603*4882a593Smuzhiyun 		break;
1604*4882a593Smuzhiyun 
1605*4882a593Smuzhiyun 	default:
1606*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1607*4882a593Smuzhiyun 	}
1608*4882a593Smuzhiyun }
1609*4882a593Smuzhiyun 
1610*4882a593Smuzhiyun /*
1611*4882a593Smuzhiyun  * IO is active.
1612*4882a593Smuzhiyun  */
1613*4882a593Smuzhiyun static void
bfa_ioim_sm_active(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1614*4882a593Smuzhiyun bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1615*4882a593Smuzhiyun {
1616*4882a593Smuzhiyun 	switch (event) {
1617*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP_GOOD:
1618*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1619*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1620*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
1621*4882a593Smuzhiyun 			      __bfa_cb_ioim_good_comp, ioim);
1622*4882a593Smuzhiyun 		break;
1623*4882a593Smuzhiyun 
1624*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP:
1625*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1626*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1627*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
1628*4882a593Smuzhiyun 			      ioim);
1629*4882a593Smuzhiyun 		break;
1630*4882a593Smuzhiyun 
1631*4882a593Smuzhiyun 	case BFA_IOIM_SM_DONE:
1632*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
1633*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1634*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
1635*4882a593Smuzhiyun 			      ioim);
1636*4882a593Smuzhiyun 		break;
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT:
1639*4882a593Smuzhiyun 		ioim->iosp->abort_explicit = BFA_TRUE;
1640*4882a593Smuzhiyun 		ioim->io_cbfn = __bfa_cb_ioim_abort;
1641*4882a593Smuzhiyun 
1642*4882a593Smuzhiyun 		if (bfa_ioim_send_abort(ioim))
1643*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
1644*4882a593Smuzhiyun 		else {
1645*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
1646*4882a593Smuzhiyun 			bfa_stats(ioim->itnim, qwait);
1647*4882a593Smuzhiyun 			bfa_reqq_wait(ioim->bfa, ioim->reqq,
1648*4882a593Smuzhiyun 					  &ioim->iosp->reqq_wait);
1649*4882a593Smuzhiyun 		}
1650*4882a593Smuzhiyun 		break;
1651*4882a593Smuzhiyun 
1652*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
1653*4882a593Smuzhiyun 		ioim->iosp->abort_explicit = BFA_FALSE;
1654*4882a593Smuzhiyun 		ioim->io_cbfn = __bfa_cb_ioim_failed;
1655*4882a593Smuzhiyun 
1656*4882a593Smuzhiyun 		if (bfa_ioim_send_abort(ioim))
1657*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
1658*4882a593Smuzhiyun 		else {
1659*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
1660*4882a593Smuzhiyun 			bfa_stats(ioim->itnim, qwait);
1661*4882a593Smuzhiyun 			bfa_reqq_wait(ioim->bfa, ioim->reqq,
1662*4882a593Smuzhiyun 					  &ioim->iosp->reqq_wait);
1663*4882a593Smuzhiyun 		}
1664*4882a593Smuzhiyun 		break;
1665*4882a593Smuzhiyun 
1666*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1667*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1668*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1669*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1670*4882a593Smuzhiyun 			      ioim);
1671*4882a593Smuzhiyun 		break;
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 	case BFA_IOIM_SM_SQRETRY:
1674*4882a593Smuzhiyun 		if (bfa_ioim_maxretry_reached(ioim)) {
1675*4882a593Smuzhiyun 			/* max retry reached, free IO */
1676*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
1677*4882a593Smuzhiyun 			bfa_ioim_move_to_comp_q(ioim);
1678*4882a593Smuzhiyun 			bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
1679*4882a593Smuzhiyun 					__bfa_cb_ioim_failed, ioim);
1680*4882a593Smuzhiyun 			break;
1681*4882a593Smuzhiyun 		}
1682*4882a593Smuzhiyun 		/* waiting for IO tag resource free */
1683*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_cmnd_retry);
1684*4882a593Smuzhiyun 		break;
1685*4882a593Smuzhiyun 
1686*4882a593Smuzhiyun 	default:
1687*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1688*4882a593Smuzhiyun 	}
1689*4882a593Smuzhiyun }
1690*4882a593Smuzhiyun 
1691*4882a593Smuzhiyun /*
1692*4882a593Smuzhiyun  * IO is retried with new tag.
1693*4882a593Smuzhiyun  */
1694*4882a593Smuzhiyun static void
bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1695*4882a593Smuzhiyun bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1696*4882a593Smuzhiyun {
1697*4882a593Smuzhiyun 	switch (event) {
1698*4882a593Smuzhiyun 	case BFA_IOIM_SM_FREE:
1699*4882a593Smuzhiyun 		/* abts and rrq done. Now retry the IO with new tag */
1700*4882a593Smuzhiyun 		bfa_ioim_update_iotag(ioim);
1701*4882a593Smuzhiyun 		if (!bfa_ioim_send_ioreq(ioim)) {
1702*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
1703*4882a593Smuzhiyun 			break;
1704*4882a593Smuzhiyun 		}
1705*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
1706*4882a593Smuzhiyun 	break;
1707*4882a593Smuzhiyun 
1708*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
1709*4882a593Smuzhiyun 		ioim->iosp->abort_explicit = BFA_FALSE;
1710*4882a593Smuzhiyun 		ioim->io_cbfn = __bfa_cb_ioim_failed;
1711*4882a593Smuzhiyun 
1712*4882a593Smuzhiyun 		if (bfa_ioim_send_abort(ioim))
1713*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
1714*4882a593Smuzhiyun 		else {
1715*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
1716*4882a593Smuzhiyun 			bfa_stats(ioim->itnim, qwait);
1717*4882a593Smuzhiyun 			bfa_reqq_wait(ioim->bfa, ioim->reqq,
1718*4882a593Smuzhiyun 					  &ioim->iosp->reqq_wait);
1719*4882a593Smuzhiyun 		}
1720*4882a593Smuzhiyun 	break;
1721*4882a593Smuzhiyun 
1722*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1723*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1724*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1725*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
1726*4882a593Smuzhiyun 			 __bfa_cb_ioim_failed, ioim);
1727*4882a593Smuzhiyun 		break;
1728*4882a593Smuzhiyun 
1729*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT:
1730*4882a593Smuzhiyun 		/* in this state IO abort is done.
1731*4882a593Smuzhiyun 		 * Waiting for IO tag resource free.
1732*4882a593Smuzhiyun 		 */
1733*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
1734*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1735*4882a593Smuzhiyun 			      ioim);
1736*4882a593Smuzhiyun 		break;
1737*4882a593Smuzhiyun 
1738*4882a593Smuzhiyun 	default:
1739*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1740*4882a593Smuzhiyun 	}
1741*4882a593Smuzhiyun }
1742*4882a593Smuzhiyun 
1743*4882a593Smuzhiyun /*
1744*4882a593Smuzhiyun  * IO is being aborted, waiting for completion from firmware.
1745*4882a593Smuzhiyun  */
1746*4882a593Smuzhiyun static void
bfa_ioim_sm_abort(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1747*4882a593Smuzhiyun bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1748*4882a593Smuzhiyun {
1749*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
1750*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
1751*4882a593Smuzhiyun 
1752*4882a593Smuzhiyun 	switch (event) {
1753*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP_GOOD:
1754*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP:
1755*4882a593Smuzhiyun 	case BFA_IOIM_SM_DONE:
1756*4882a593Smuzhiyun 	case BFA_IOIM_SM_FREE:
1757*4882a593Smuzhiyun 		break;
1758*4882a593Smuzhiyun 
1759*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT_DONE:
1760*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
1761*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1762*4882a593Smuzhiyun 			      ioim);
1763*4882a593Smuzhiyun 		break;
1764*4882a593Smuzhiyun 
1765*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT_COMP:
1766*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1767*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1768*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1769*4882a593Smuzhiyun 			      ioim);
1770*4882a593Smuzhiyun 		break;
1771*4882a593Smuzhiyun 
1772*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP_UTAG:
1773*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1774*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1775*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1776*4882a593Smuzhiyun 			      ioim);
1777*4882a593Smuzhiyun 		break;
1778*4882a593Smuzhiyun 
1779*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
1780*4882a593Smuzhiyun 		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);
1781*4882a593Smuzhiyun 		ioim->iosp->abort_explicit = BFA_FALSE;
1782*4882a593Smuzhiyun 
1783*4882a593Smuzhiyun 		if (bfa_ioim_send_abort(ioim))
1784*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
1785*4882a593Smuzhiyun 		else {
1786*4882a593Smuzhiyun 			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
1787*4882a593Smuzhiyun 			bfa_stats(ioim->itnim, qwait);
1788*4882a593Smuzhiyun 			bfa_reqq_wait(ioim->bfa, ioim->reqq,
1789*4882a593Smuzhiyun 					  &ioim->iosp->reqq_wait);
1790*4882a593Smuzhiyun 		}
1791*4882a593Smuzhiyun 		break;
1792*4882a593Smuzhiyun 
1793*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1794*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1795*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1796*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1797*4882a593Smuzhiyun 			      ioim);
1798*4882a593Smuzhiyun 		break;
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun 	default:
1801*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1802*4882a593Smuzhiyun 	}
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun 
1805*4882a593Smuzhiyun /*
1806*4882a593Smuzhiyun  * IO is being cleaned up (implicit abort), waiting for completion from
1807*4882a593Smuzhiyun  * firmware.
1808*4882a593Smuzhiyun  */
1809*4882a593Smuzhiyun static void
bfa_ioim_sm_cleanup(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1810*4882a593Smuzhiyun bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1811*4882a593Smuzhiyun {
1812*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
1813*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
1814*4882a593Smuzhiyun 
1815*4882a593Smuzhiyun 	switch (event) {
1816*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP_GOOD:
1817*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP:
1818*4882a593Smuzhiyun 	case BFA_IOIM_SM_DONE:
1819*4882a593Smuzhiyun 	case BFA_IOIM_SM_FREE:
1820*4882a593Smuzhiyun 		break;
1821*4882a593Smuzhiyun 
1822*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT:
1823*4882a593Smuzhiyun 		/*
1824*4882a593Smuzhiyun 		 * IO is already being aborted implicitly
1825*4882a593Smuzhiyun 		 */
1826*4882a593Smuzhiyun 		ioim->io_cbfn = __bfa_cb_ioim_abort;
1827*4882a593Smuzhiyun 		break;
1828*4882a593Smuzhiyun 
1829*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT_DONE:
1830*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
1831*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
1832*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
1833*4882a593Smuzhiyun 		break;
1834*4882a593Smuzhiyun 
1835*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT_COMP:
1836*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1837*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
1838*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
1839*4882a593Smuzhiyun 		break;
1840*4882a593Smuzhiyun 
1841*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP_UTAG:
1842*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1843*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
1844*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
1845*4882a593Smuzhiyun 		break;
1846*4882a593Smuzhiyun 
1847*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1848*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1849*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1850*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1851*4882a593Smuzhiyun 			      ioim);
1852*4882a593Smuzhiyun 		break;
1853*4882a593Smuzhiyun 
1854*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
1855*4882a593Smuzhiyun 		/*
1856*4882a593Smuzhiyun 		 * IO can be in cleanup state already due to TM command.
1857*4882a593Smuzhiyun 		 * 2nd cleanup request comes from ITN offline event.
1858*4882a593Smuzhiyun 		 */
1859*4882a593Smuzhiyun 		break;
1860*4882a593Smuzhiyun 
1861*4882a593Smuzhiyun 	default:
1862*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1863*4882a593Smuzhiyun 	}
1864*4882a593Smuzhiyun }
1865*4882a593Smuzhiyun 
1866*4882a593Smuzhiyun /*
1867*4882a593Smuzhiyun  * IO is waiting for room in request CQ
1868*4882a593Smuzhiyun  */
1869*4882a593Smuzhiyun static void
bfa_ioim_sm_qfull(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1870*4882a593Smuzhiyun bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1871*4882a593Smuzhiyun {
1872*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
1873*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
1874*4882a593Smuzhiyun 
1875*4882a593Smuzhiyun 	switch (event) {
1876*4882a593Smuzhiyun 	case BFA_IOIM_SM_QRESUME:
1877*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
1878*4882a593Smuzhiyun 		bfa_ioim_send_ioreq(ioim);
1879*4882a593Smuzhiyun 		break;
1880*4882a593Smuzhiyun 
1881*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT:
1882*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1883*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1884*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1885*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1886*4882a593Smuzhiyun 			      ioim);
1887*4882a593Smuzhiyun 		break;
1888*4882a593Smuzhiyun 
1889*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
1890*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1891*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1892*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1893*4882a593Smuzhiyun 			      ioim);
1894*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
1895*4882a593Smuzhiyun 		break;
1896*4882a593Smuzhiyun 
1897*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1898*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1899*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1900*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1901*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1902*4882a593Smuzhiyun 			      ioim);
1903*4882a593Smuzhiyun 		break;
1904*4882a593Smuzhiyun 
1905*4882a593Smuzhiyun 	default:
1906*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1907*4882a593Smuzhiyun 	}
1908*4882a593Smuzhiyun }
1909*4882a593Smuzhiyun 
1910*4882a593Smuzhiyun /*
1911*4882a593Smuzhiyun  * Active IO is being aborted, waiting for room in request CQ.
1912*4882a593Smuzhiyun  */
1913*4882a593Smuzhiyun static void
bfa_ioim_sm_abort_qfull(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1914*4882a593Smuzhiyun bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1915*4882a593Smuzhiyun {
1916*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
1917*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
1918*4882a593Smuzhiyun 
1919*4882a593Smuzhiyun 	switch (event) {
1920*4882a593Smuzhiyun 	case BFA_IOIM_SM_QRESUME:
1921*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
1922*4882a593Smuzhiyun 		bfa_ioim_send_abort(ioim);
1923*4882a593Smuzhiyun 		break;
1924*4882a593Smuzhiyun 
1925*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
1926*4882a593Smuzhiyun 		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);
1927*4882a593Smuzhiyun 		ioim->iosp->abort_explicit = BFA_FALSE;
1928*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
1929*4882a593Smuzhiyun 		break;
1930*4882a593Smuzhiyun 
1931*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP_GOOD:
1932*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP:
1933*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1934*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1935*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1936*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1937*4882a593Smuzhiyun 			      ioim);
1938*4882a593Smuzhiyun 		break;
1939*4882a593Smuzhiyun 
1940*4882a593Smuzhiyun 	case BFA_IOIM_SM_DONE:
1941*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
1942*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1943*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1944*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
1945*4882a593Smuzhiyun 			      ioim);
1946*4882a593Smuzhiyun 		break;
1947*4882a593Smuzhiyun 
1948*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1949*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1950*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1951*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
1952*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
1953*4882a593Smuzhiyun 			      ioim);
1954*4882a593Smuzhiyun 		break;
1955*4882a593Smuzhiyun 
1956*4882a593Smuzhiyun 	default:
1957*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
1958*4882a593Smuzhiyun 	}
1959*4882a593Smuzhiyun }
1960*4882a593Smuzhiyun 
1961*4882a593Smuzhiyun /*
1962*4882a593Smuzhiyun  * Active IO is being cleaned up, waiting for room in request CQ.
1963*4882a593Smuzhiyun  */
1964*4882a593Smuzhiyun static void
bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)1965*4882a593Smuzhiyun bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
1966*4882a593Smuzhiyun {
1967*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
1968*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
1969*4882a593Smuzhiyun 
1970*4882a593Smuzhiyun 	switch (event) {
1971*4882a593Smuzhiyun 	case BFA_IOIM_SM_QRESUME:
1972*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
1973*4882a593Smuzhiyun 		bfa_ioim_send_abort(ioim);
1974*4882a593Smuzhiyun 		break;
1975*4882a593Smuzhiyun 
1976*4882a593Smuzhiyun 	case BFA_IOIM_SM_ABORT:
1977*4882a593Smuzhiyun 		/*
1978*4882a593Smuzhiyun 		 * IO is already being cleaned up implicitly
1979*4882a593Smuzhiyun 		 */
1980*4882a593Smuzhiyun 		ioim->io_cbfn = __bfa_cb_ioim_abort;
1981*4882a593Smuzhiyun 		break;
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP_GOOD:
1984*4882a593Smuzhiyun 	case BFA_IOIM_SM_COMP:
1985*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
1986*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1987*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
1988*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
1989*4882a593Smuzhiyun 		break;
1990*4882a593Smuzhiyun 
1991*4882a593Smuzhiyun 	case BFA_IOIM_SM_DONE:
1992*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
1993*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
1994*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
1995*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
1996*4882a593Smuzhiyun 		break;
1997*4882a593Smuzhiyun 
1998*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
1999*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
2000*4882a593Smuzhiyun 		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
2001*4882a593Smuzhiyun 		bfa_ioim_move_to_comp_q(ioim);
2002*4882a593Smuzhiyun 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
2003*4882a593Smuzhiyun 			      ioim);
2004*4882a593Smuzhiyun 		break;
2005*4882a593Smuzhiyun 
2006*4882a593Smuzhiyun 	default:
2007*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
2008*4882a593Smuzhiyun 	}
2009*4882a593Smuzhiyun }
2010*4882a593Smuzhiyun 
2011*4882a593Smuzhiyun /*
2012*4882a593Smuzhiyun  * IO bfa callback is pending.
2013*4882a593Smuzhiyun  */
2014*4882a593Smuzhiyun static void
bfa_ioim_sm_hcb(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)2015*4882a593Smuzhiyun bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
2016*4882a593Smuzhiyun {
2017*4882a593Smuzhiyun 	switch (event) {
2018*4882a593Smuzhiyun 	case BFA_IOIM_SM_HCB:
2019*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
2020*4882a593Smuzhiyun 		bfa_ioim_free(ioim);
2021*4882a593Smuzhiyun 		break;
2022*4882a593Smuzhiyun 
2023*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
2024*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
2025*4882a593Smuzhiyun 		break;
2026*4882a593Smuzhiyun 
2027*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
2028*4882a593Smuzhiyun 		break;
2029*4882a593Smuzhiyun 
2030*4882a593Smuzhiyun 	default:
2031*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
2032*4882a593Smuzhiyun 	}
2033*4882a593Smuzhiyun }
2034*4882a593Smuzhiyun 
2035*4882a593Smuzhiyun /*
2036*4882a593Smuzhiyun  * IO bfa callback is pending. IO resource cannot be freed.
2037*4882a593Smuzhiyun  */
2038*4882a593Smuzhiyun static void
bfa_ioim_sm_hcb_free(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)2039*4882a593Smuzhiyun bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
2040*4882a593Smuzhiyun {
2041*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
2042*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
2043*4882a593Smuzhiyun 
2044*4882a593Smuzhiyun 	switch (event) {
2045*4882a593Smuzhiyun 	case BFA_IOIM_SM_HCB:
2046*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
2047*4882a593Smuzhiyun 		list_del(&ioim->qe);
2048*4882a593Smuzhiyun 		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
2049*4882a593Smuzhiyun 		break;
2050*4882a593Smuzhiyun 
2051*4882a593Smuzhiyun 	case BFA_IOIM_SM_FREE:
2052*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
2053*4882a593Smuzhiyun 		break;
2054*4882a593Smuzhiyun 
2055*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
2056*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
2057*4882a593Smuzhiyun 		break;
2058*4882a593Smuzhiyun 
2059*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
2060*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
2061*4882a593Smuzhiyun 		break;
2062*4882a593Smuzhiyun 
2063*4882a593Smuzhiyun 	default:
2064*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
2065*4882a593Smuzhiyun 	}
2066*4882a593Smuzhiyun }
2067*4882a593Smuzhiyun 
2068*4882a593Smuzhiyun /*
2069*4882a593Smuzhiyun  * IO is completed, waiting resource free from firmware.
2070*4882a593Smuzhiyun  */
2071*4882a593Smuzhiyun static void
bfa_ioim_sm_resfree(struct bfa_ioim_s * ioim,enum bfa_ioim_event event)2072*4882a593Smuzhiyun bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
2073*4882a593Smuzhiyun {
2074*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
2075*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, event);
2076*4882a593Smuzhiyun 
2077*4882a593Smuzhiyun 	switch (event) {
2078*4882a593Smuzhiyun 	case BFA_IOIM_SM_FREE:
2079*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
2080*4882a593Smuzhiyun 		bfa_ioim_free(ioim);
2081*4882a593Smuzhiyun 		break;
2082*4882a593Smuzhiyun 
2083*4882a593Smuzhiyun 	case BFA_IOIM_SM_CLEANUP:
2084*4882a593Smuzhiyun 		bfa_ioim_notify_cleanup(ioim);
2085*4882a593Smuzhiyun 		break;
2086*4882a593Smuzhiyun 
2087*4882a593Smuzhiyun 	case BFA_IOIM_SM_HWFAIL:
2088*4882a593Smuzhiyun 		break;
2089*4882a593Smuzhiyun 
2090*4882a593Smuzhiyun 	default:
2091*4882a593Smuzhiyun 		bfa_sm_fault(ioim->bfa, event);
2092*4882a593Smuzhiyun 	}
2093*4882a593Smuzhiyun }
2094*4882a593Smuzhiyun 
2095*4882a593Smuzhiyun /*
2096*4882a593Smuzhiyun  * This is called from bfa_fcpim_start after the bfa_init() with flash read
2097*4882a593Smuzhiyun  * is complete by driver. now invalidate the stale content of lun mask
2098*4882a593Smuzhiyun  * like unit attention, rp tag and lp tag.
2099*4882a593Smuzhiyun  */
2100*4882a593Smuzhiyun void
bfa_ioim_lm_init(struct bfa_s * bfa)2101*4882a593Smuzhiyun bfa_ioim_lm_init(struct bfa_s *bfa)
2102*4882a593Smuzhiyun {
2103*4882a593Smuzhiyun 	struct bfa_lun_mask_s *lunm_list;
2104*4882a593Smuzhiyun 	int	i;
2105*4882a593Smuzhiyun 
2106*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
2107*4882a593Smuzhiyun 		return;
2108*4882a593Smuzhiyun 
2109*4882a593Smuzhiyun 	lunm_list = bfa_get_lun_mask_list(bfa);
2110*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2111*4882a593Smuzhiyun 		lunm_list[i].ua = BFA_IOIM_LM_UA_RESET;
2112*4882a593Smuzhiyun 		lunm_list[i].lp_tag = BFA_LP_TAG_INVALID;
2113*4882a593Smuzhiyun 		lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID;
2114*4882a593Smuzhiyun 	}
2115*4882a593Smuzhiyun }
2116*4882a593Smuzhiyun 
2117*4882a593Smuzhiyun static void
__bfa_cb_ioim_good_comp(void * cbarg,bfa_boolean_t complete)2118*4882a593Smuzhiyun __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
2119*4882a593Smuzhiyun {
2120*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim = cbarg;
2121*4882a593Smuzhiyun 
2122*4882a593Smuzhiyun 	if (!complete) {
2123*4882a593Smuzhiyun 		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
2124*4882a593Smuzhiyun 		return;
2125*4882a593Smuzhiyun 	}
2126*4882a593Smuzhiyun 
2127*4882a593Smuzhiyun 	bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
2128*4882a593Smuzhiyun }
2129*4882a593Smuzhiyun 
2130*4882a593Smuzhiyun static void
__bfa_cb_ioim_comp(void * cbarg,bfa_boolean_t complete)2131*4882a593Smuzhiyun __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
2132*4882a593Smuzhiyun {
2133*4882a593Smuzhiyun 	struct bfa_ioim_s	*ioim = cbarg;
2134*4882a593Smuzhiyun 	struct bfi_ioim_rsp_s *m;
2135*4882a593Smuzhiyun 	u8	*snsinfo = NULL;
2136*4882a593Smuzhiyun 	u8	sns_len = 0;
2137*4882a593Smuzhiyun 	s32	residue = 0;
2138*4882a593Smuzhiyun 
2139*4882a593Smuzhiyun 	if (!complete) {
2140*4882a593Smuzhiyun 		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
2141*4882a593Smuzhiyun 		return;
2142*4882a593Smuzhiyun 	}
2143*4882a593Smuzhiyun 
2144*4882a593Smuzhiyun 	m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
2145*4882a593Smuzhiyun 	if (m->io_status == BFI_IOIM_STS_OK) {
2146*4882a593Smuzhiyun 		/*
2147*4882a593Smuzhiyun 		 * setup sense information, if present
2148*4882a593Smuzhiyun 		 */
2149*4882a593Smuzhiyun 		if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&
2150*4882a593Smuzhiyun 					m->sns_len) {
2151*4882a593Smuzhiyun 			sns_len = m->sns_len;
2152*4882a593Smuzhiyun 			snsinfo = BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
2153*4882a593Smuzhiyun 						ioim->iotag);
2154*4882a593Smuzhiyun 		}
2155*4882a593Smuzhiyun 
2156*4882a593Smuzhiyun 		/*
2157*4882a593Smuzhiyun 		 * setup residue value correctly for normal completions
2158*4882a593Smuzhiyun 		 */
2159*4882a593Smuzhiyun 		if (m->resid_flags == FCP_RESID_UNDER) {
2160*4882a593Smuzhiyun 			residue = be32_to_cpu(m->residue);
2161*4882a593Smuzhiyun 			bfa_stats(ioim->itnim, iocomp_underrun);
2162*4882a593Smuzhiyun 		}
2163*4882a593Smuzhiyun 		if (m->resid_flags == FCP_RESID_OVER) {
2164*4882a593Smuzhiyun 			residue = be32_to_cpu(m->residue);
2165*4882a593Smuzhiyun 			residue = -residue;
2166*4882a593Smuzhiyun 			bfa_stats(ioim->itnim, iocomp_overrun);
2167*4882a593Smuzhiyun 		}
2168*4882a593Smuzhiyun 	}
2169*4882a593Smuzhiyun 
2170*4882a593Smuzhiyun 	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
2171*4882a593Smuzhiyun 			  m->scsi_status, sns_len, snsinfo, residue);
2172*4882a593Smuzhiyun }
2173*4882a593Smuzhiyun 
2174*4882a593Smuzhiyun void
bfa_fcpim_lunmask_rp_update(struct bfa_s * bfa,wwn_t lp_wwn,wwn_t rp_wwn,u16 rp_tag,u8 lp_tag)2175*4882a593Smuzhiyun bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn,
2176*4882a593Smuzhiyun 			u16 rp_tag, u8 lp_tag)
2177*4882a593Smuzhiyun {
2178*4882a593Smuzhiyun 	struct bfa_lun_mask_s *lun_list;
2179*4882a593Smuzhiyun 	u8	i;
2180*4882a593Smuzhiyun 
2181*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
2182*4882a593Smuzhiyun 		return;
2183*4882a593Smuzhiyun 
2184*4882a593Smuzhiyun 	lun_list = bfa_get_lun_mask_list(bfa);
2185*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2186*4882a593Smuzhiyun 		if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) {
2187*4882a593Smuzhiyun 			if ((lun_list[i].lp_wwn == lp_wwn) &&
2188*4882a593Smuzhiyun 			    (lun_list[i].rp_wwn == rp_wwn)) {
2189*4882a593Smuzhiyun 				lun_list[i].rp_tag = rp_tag;
2190*4882a593Smuzhiyun 				lun_list[i].lp_tag = lp_tag;
2191*4882a593Smuzhiyun 			}
2192*4882a593Smuzhiyun 		}
2193*4882a593Smuzhiyun 	}
2194*4882a593Smuzhiyun }
2195*4882a593Smuzhiyun 
2196*4882a593Smuzhiyun /*
2197*4882a593Smuzhiyun  * set UA for all active luns in LM DB
2198*4882a593Smuzhiyun  */
2199*4882a593Smuzhiyun static void
bfa_ioim_lm_set_ua(struct bfa_s * bfa)2200*4882a593Smuzhiyun bfa_ioim_lm_set_ua(struct bfa_s *bfa)
2201*4882a593Smuzhiyun {
2202*4882a593Smuzhiyun 	struct bfa_lun_mask_s	*lunm_list;
2203*4882a593Smuzhiyun 	int	i;
2204*4882a593Smuzhiyun 
2205*4882a593Smuzhiyun 	lunm_list = bfa_get_lun_mask_list(bfa);
2206*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2207*4882a593Smuzhiyun 		if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
2208*4882a593Smuzhiyun 			continue;
2209*4882a593Smuzhiyun 		lunm_list[i].ua = BFA_IOIM_LM_UA_SET;
2210*4882a593Smuzhiyun 	}
2211*4882a593Smuzhiyun }
2212*4882a593Smuzhiyun 
2213*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_lunmask_update(struct bfa_s * bfa,u32 update)2214*4882a593Smuzhiyun bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 update)
2215*4882a593Smuzhiyun {
2216*4882a593Smuzhiyun 	struct bfa_lunmask_cfg_s	*lun_mask;
2217*4882a593Smuzhiyun 
2218*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
2219*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
2220*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
2221*4882a593Smuzhiyun 
2222*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == update)
2223*4882a593Smuzhiyun 		return BFA_STATUS_NO_CHANGE;
2224*4882a593Smuzhiyun 
2225*4882a593Smuzhiyun 	lun_mask = bfa_get_lun_mask(bfa);
2226*4882a593Smuzhiyun 	lun_mask->status = update;
2227*4882a593Smuzhiyun 
2228*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED)
2229*4882a593Smuzhiyun 		bfa_ioim_lm_set_ua(bfa);
2230*4882a593Smuzhiyun 
2231*4882a593Smuzhiyun 	return  bfa_dconf_update(bfa);
2232*4882a593Smuzhiyun }
2233*4882a593Smuzhiyun 
2234*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_lunmask_clear(struct bfa_s * bfa)2235*4882a593Smuzhiyun bfa_fcpim_lunmask_clear(struct bfa_s *bfa)
2236*4882a593Smuzhiyun {
2237*4882a593Smuzhiyun 	int i;
2238*4882a593Smuzhiyun 	struct bfa_lun_mask_s	*lunm_list;
2239*4882a593Smuzhiyun 
2240*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
2241*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
2242*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
2243*4882a593Smuzhiyun 
2244*4882a593Smuzhiyun 	lunm_list = bfa_get_lun_mask_list(bfa);
2245*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2246*4882a593Smuzhiyun 		if (lunm_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) {
2247*4882a593Smuzhiyun 			if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID)
2248*4882a593Smuzhiyun 				bfa_rport_unset_lunmask(bfa,
2249*4882a593Smuzhiyun 				  BFA_RPORT_FROM_TAG(bfa, lunm_list[i].rp_tag));
2250*4882a593Smuzhiyun 		}
2251*4882a593Smuzhiyun 	}
2252*4882a593Smuzhiyun 
2253*4882a593Smuzhiyun 	memset(lunm_list, 0, sizeof(struct bfa_lun_mask_s) * MAX_LUN_MASK_CFG);
2254*4882a593Smuzhiyun 	return bfa_dconf_update(bfa);
2255*4882a593Smuzhiyun }
2256*4882a593Smuzhiyun 
2257*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_lunmask_query(struct bfa_s * bfa,void * buf)2258*4882a593Smuzhiyun bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf)
2259*4882a593Smuzhiyun {
2260*4882a593Smuzhiyun 	struct bfa_lunmask_cfg_s *lun_mask;
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
2263*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
2264*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
2265*4882a593Smuzhiyun 
2266*4882a593Smuzhiyun 	lun_mask = bfa_get_lun_mask(bfa);
2267*4882a593Smuzhiyun 	memcpy(buf, lun_mask, sizeof(struct bfa_lunmask_cfg_s));
2268*4882a593Smuzhiyun 	return BFA_STATUS_OK;
2269*4882a593Smuzhiyun }
2270*4882a593Smuzhiyun 
2271*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_lunmask_add(struct bfa_s * bfa,u16 vf_id,wwn_t * pwwn,wwn_t rpwwn,struct scsi_lun lun)2272*4882a593Smuzhiyun bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
2273*4882a593Smuzhiyun 		      wwn_t rpwwn, struct scsi_lun lun)
2274*4882a593Smuzhiyun {
2275*4882a593Smuzhiyun 	struct bfa_lun_mask_s *lunm_list;
2276*4882a593Smuzhiyun 	struct bfa_rport_s *rp = NULL;
2277*4882a593Smuzhiyun 	int i, free_index = MAX_LUN_MASK_CFG + 1;
2278*4882a593Smuzhiyun 	struct bfa_fcs_lport_s *port = NULL;
2279*4882a593Smuzhiyun 	struct bfa_fcs_rport_s *rp_fcs;
2280*4882a593Smuzhiyun 
2281*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
2282*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
2283*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
2284*4882a593Smuzhiyun 
2285*4882a593Smuzhiyun 	port = bfa_fcs_lookup_port(&((struct bfad_s *)bfa->bfad)->bfa_fcs,
2286*4882a593Smuzhiyun 				   vf_id, *pwwn);
2287*4882a593Smuzhiyun 	if (port) {
2288*4882a593Smuzhiyun 		*pwwn = port->port_cfg.pwwn;
2289*4882a593Smuzhiyun 		rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
2290*4882a593Smuzhiyun 		if (rp_fcs)
2291*4882a593Smuzhiyun 			rp = rp_fcs->bfa_rport;
2292*4882a593Smuzhiyun 	}
2293*4882a593Smuzhiyun 
2294*4882a593Smuzhiyun 	lunm_list = bfa_get_lun_mask_list(bfa);
2295*4882a593Smuzhiyun 	/* if entry exists */
2296*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2297*4882a593Smuzhiyun 		if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
2298*4882a593Smuzhiyun 			free_index = i;
2299*4882a593Smuzhiyun 		if ((lunm_list[i].lp_wwn == *pwwn) &&
2300*4882a593Smuzhiyun 		    (lunm_list[i].rp_wwn == rpwwn) &&
2301*4882a593Smuzhiyun 		    (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) ==
2302*4882a593Smuzhiyun 		     scsilun_to_int((struct scsi_lun *)&lun)))
2303*4882a593Smuzhiyun 			return  BFA_STATUS_ENTRY_EXISTS;
2304*4882a593Smuzhiyun 	}
2305*4882a593Smuzhiyun 
2306*4882a593Smuzhiyun 	if (free_index > MAX_LUN_MASK_CFG)
2307*4882a593Smuzhiyun 		return BFA_STATUS_MAX_ENTRY_REACHED;
2308*4882a593Smuzhiyun 
2309*4882a593Smuzhiyun 	if (rp) {
2310*4882a593Smuzhiyun 		lunm_list[free_index].lp_tag = bfa_lps_get_tag_from_pid(bfa,
2311*4882a593Smuzhiyun 						   rp->rport_info.local_pid);
2312*4882a593Smuzhiyun 		lunm_list[free_index].rp_tag = rp->rport_tag;
2313*4882a593Smuzhiyun 	} else {
2314*4882a593Smuzhiyun 		lunm_list[free_index].lp_tag = BFA_LP_TAG_INVALID;
2315*4882a593Smuzhiyun 		lunm_list[free_index].rp_tag = BFA_RPORT_TAG_INVALID;
2316*4882a593Smuzhiyun 	}
2317*4882a593Smuzhiyun 
2318*4882a593Smuzhiyun 	lunm_list[free_index].lp_wwn = *pwwn;
2319*4882a593Smuzhiyun 	lunm_list[free_index].rp_wwn = rpwwn;
2320*4882a593Smuzhiyun 	lunm_list[free_index].lun = lun;
2321*4882a593Smuzhiyun 	lunm_list[free_index].state = BFA_IOIM_LUN_MASK_ACTIVE;
2322*4882a593Smuzhiyun 
2323*4882a593Smuzhiyun 	/* set for all luns in this rp */
2324*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2325*4882a593Smuzhiyun 		if ((lunm_list[i].lp_wwn == *pwwn) &&
2326*4882a593Smuzhiyun 		    (lunm_list[i].rp_wwn == rpwwn))
2327*4882a593Smuzhiyun 			lunm_list[i].ua = BFA_IOIM_LM_UA_SET;
2328*4882a593Smuzhiyun 	}
2329*4882a593Smuzhiyun 
2330*4882a593Smuzhiyun 	return bfa_dconf_update(bfa);
2331*4882a593Smuzhiyun }
2332*4882a593Smuzhiyun 
2333*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_lunmask_delete(struct bfa_s * bfa,u16 vf_id,wwn_t * pwwn,wwn_t rpwwn,struct scsi_lun lun)2334*4882a593Smuzhiyun bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
2335*4882a593Smuzhiyun 			 wwn_t rpwwn, struct scsi_lun lun)
2336*4882a593Smuzhiyun {
2337*4882a593Smuzhiyun 	struct bfa_lun_mask_s	*lunm_list;
2338*4882a593Smuzhiyun 	struct bfa_fcs_lport_s *port = NULL;
2339*4882a593Smuzhiyun 	int	i;
2340*4882a593Smuzhiyun 
2341*4882a593Smuzhiyun 	/* in min cfg lunm_list could be NULL but  no commands should run. */
2342*4882a593Smuzhiyun 	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
2343*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
2344*4882a593Smuzhiyun 
2345*4882a593Smuzhiyun 	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
2346*4882a593Smuzhiyun 	bfa_trc(bfa, *pwwn);
2347*4882a593Smuzhiyun 	bfa_trc(bfa, rpwwn);
2348*4882a593Smuzhiyun 	bfa_trc(bfa, scsilun_to_int((struct scsi_lun *)&lun));
2349*4882a593Smuzhiyun 
2350*4882a593Smuzhiyun 	if (*pwwn == 0) {
2351*4882a593Smuzhiyun 		port = bfa_fcs_lookup_port(
2352*4882a593Smuzhiyun 				&((struct bfad_s *)bfa->bfad)->bfa_fcs,
2353*4882a593Smuzhiyun 				vf_id, *pwwn);
2354*4882a593Smuzhiyun 		if (port)
2355*4882a593Smuzhiyun 			*pwwn = port->port_cfg.pwwn;
2356*4882a593Smuzhiyun 	}
2357*4882a593Smuzhiyun 
2358*4882a593Smuzhiyun 	lunm_list = bfa_get_lun_mask_list(bfa);
2359*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2360*4882a593Smuzhiyun 		if ((lunm_list[i].lp_wwn == *pwwn) &&
2361*4882a593Smuzhiyun 		    (lunm_list[i].rp_wwn == rpwwn) &&
2362*4882a593Smuzhiyun 		    (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) ==
2363*4882a593Smuzhiyun 		     scsilun_to_int((struct scsi_lun *)&lun))) {
2364*4882a593Smuzhiyun 			lunm_list[i].lp_wwn = 0;
2365*4882a593Smuzhiyun 			lunm_list[i].rp_wwn = 0;
2366*4882a593Smuzhiyun 			int_to_scsilun(0, &lunm_list[i].lun);
2367*4882a593Smuzhiyun 			lunm_list[i].state = BFA_IOIM_LUN_MASK_INACTIVE;
2368*4882a593Smuzhiyun 			if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID) {
2369*4882a593Smuzhiyun 				lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID;
2370*4882a593Smuzhiyun 				lunm_list[i].lp_tag = BFA_LP_TAG_INVALID;
2371*4882a593Smuzhiyun 			}
2372*4882a593Smuzhiyun 			return bfa_dconf_update(bfa);
2373*4882a593Smuzhiyun 		}
2374*4882a593Smuzhiyun 	}
2375*4882a593Smuzhiyun 
2376*4882a593Smuzhiyun 	/* set for all luns in this rp */
2377*4882a593Smuzhiyun 	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
2378*4882a593Smuzhiyun 		if ((lunm_list[i].lp_wwn == *pwwn) &&
2379*4882a593Smuzhiyun 		    (lunm_list[i].rp_wwn == rpwwn))
2380*4882a593Smuzhiyun 			lunm_list[i].ua = BFA_IOIM_LM_UA_SET;
2381*4882a593Smuzhiyun 	}
2382*4882a593Smuzhiyun 
2383*4882a593Smuzhiyun 	return BFA_STATUS_ENTRY_NOT_EXISTS;
2384*4882a593Smuzhiyun }
2385*4882a593Smuzhiyun 
2386*4882a593Smuzhiyun static void
__bfa_cb_ioim_failed(void * cbarg,bfa_boolean_t complete)2387*4882a593Smuzhiyun __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
2388*4882a593Smuzhiyun {
2389*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim = cbarg;
2390*4882a593Smuzhiyun 
2391*4882a593Smuzhiyun 	if (!complete) {
2392*4882a593Smuzhiyun 		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
2393*4882a593Smuzhiyun 		return;
2394*4882a593Smuzhiyun 	}
2395*4882a593Smuzhiyun 
2396*4882a593Smuzhiyun 	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
2397*4882a593Smuzhiyun 			  0, 0, NULL, 0);
2398*4882a593Smuzhiyun }
2399*4882a593Smuzhiyun 
2400*4882a593Smuzhiyun static void
__bfa_cb_ioim_pathtov(void * cbarg,bfa_boolean_t complete)2401*4882a593Smuzhiyun __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
2402*4882a593Smuzhiyun {
2403*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim = cbarg;
2404*4882a593Smuzhiyun 
2405*4882a593Smuzhiyun 	bfa_stats(ioim->itnim, path_tov_expired);
2406*4882a593Smuzhiyun 	if (!complete) {
2407*4882a593Smuzhiyun 		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
2408*4882a593Smuzhiyun 		return;
2409*4882a593Smuzhiyun 	}
2410*4882a593Smuzhiyun 
2411*4882a593Smuzhiyun 	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
2412*4882a593Smuzhiyun 			  0, 0, NULL, 0);
2413*4882a593Smuzhiyun }
2414*4882a593Smuzhiyun 
2415*4882a593Smuzhiyun static void
__bfa_cb_ioim_abort(void * cbarg,bfa_boolean_t complete)2416*4882a593Smuzhiyun __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
2417*4882a593Smuzhiyun {
2418*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim = cbarg;
2419*4882a593Smuzhiyun 
2420*4882a593Smuzhiyun 	if (!complete) {
2421*4882a593Smuzhiyun 		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
2422*4882a593Smuzhiyun 		return;
2423*4882a593Smuzhiyun 	}
2424*4882a593Smuzhiyun 
2425*4882a593Smuzhiyun 	bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
2426*4882a593Smuzhiyun }
2427*4882a593Smuzhiyun 
2428*4882a593Smuzhiyun static void
bfa_ioim_sgpg_alloced(void * cbarg)2429*4882a593Smuzhiyun bfa_ioim_sgpg_alloced(void *cbarg)
2430*4882a593Smuzhiyun {
2431*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim = cbarg;
2432*4882a593Smuzhiyun 
2433*4882a593Smuzhiyun 	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
2434*4882a593Smuzhiyun 	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
2435*4882a593Smuzhiyun 	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);
2436*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
2437*4882a593Smuzhiyun }
2438*4882a593Smuzhiyun 
2439*4882a593Smuzhiyun /*
2440*4882a593Smuzhiyun  * Send I/O request to firmware.
2441*4882a593Smuzhiyun  */
2442*4882a593Smuzhiyun static	bfa_boolean_t
bfa_ioim_send_ioreq(struct bfa_ioim_s * ioim)2443*4882a593Smuzhiyun bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
2444*4882a593Smuzhiyun {
2445*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = ioim->itnim;
2446*4882a593Smuzhiyun 	struct bfi_ioim_req_s *m;
2447*4882a593Smuzhiyun 	static struct fcp_cmnd_s cmnd_z0 = { { { 0 } } };
2448*4882a593Smuzhiyun 	struct bfi_sge_s *sge, *sgpge;
2449*4882a593Smuzhiyun 	u32	pgdlen = 0;
2450*4882a593Smuzhiyun 	u32	fcp_dl;
2451*4882a593Smuzhiyun 	u64 addr;
2452*4882a593Smuzhiyun 	struct scatterlist *sg;
2453*4882a593Smuzhiyun 	struct bfa_sgpg_s *sgpg;
2454*4882a593Smuzhiyun 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
2455*4882a593Smuzhiyun 	u32 i, sge_id, pgcumsz;
2456*4882a593Smuzhiyun 	enum dma_data_direction dmadir;
2457*4882a593Smuzhiyun 
2458*4882a593Smuzhiyun 	/*
2459*4882a593Smuzhiyun 	 * check for room in queue to send request now
2460*4882a593Smuzhiyun 	 */
2461*4882a593Smuzhiyun 	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
2462*4882a593Smuzhiyun 	if (!m) {
2463*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, qwait);
2464*4882a593Smuzhiyun 		bfa_reqq_wait(ioim->bfa, ioim->reqq,
2465*4882a593Smuzhiyun 				  &ioim->iosp->reqq_wait);
2466*4882a593Smuzhiyun 		return BFA_FALSE;
2467*4882a593Smuzhiyun 	}
2468*4882a593Smuzhiyun 
2469*4882a593Smuzhiyun 	/*
2470*4882a593Smuzhiyun 	 * build i/o request message next
2471*4882a593Smuzhiyun 	 */
2472*4882a593Smuzhiyun 	m->io_tag = cpu_to_be16(ioim->iotag);
2473*4882a593Smuzhiyun 	m->rport_hdl = ioim->itnim->rport->fw_handle;
2474*4882a593Smuzhiyun 	m->io_timeout = 0;
2475*4882a593Smuzhiyun 
2476*4882a593Smuzhiyun 	sge = &m->sges[0];
2477*4882a593Smuzhiyun 	sgpg = ioim->sgpg;
2478*4882a593Smuzhiyun 	sge_id = 0;
2479*4882a593Smuzhiyun 	sgpge = NULL;
2480*4882a593Smuzhiyun 	pgcumsz = 0;
2481*4882a593Smuzhiyun 	scsi_for_each_sg(cmnd, sg, ioim->nsges, i) {
2482*4882a593Smuzhiyun 		if (i == 0) {
2483*4882a593Smuzhiyun 			/* build inline IO SG element */
2484*4882a593Smuzhiyun 			addr = bfa_sgaddr_le(sg_dma_address(sg));
2485*4882a593Smuzhiyun 			sge->sga = *(union bfi_addr_u *) &addr;
2486*4882a593Smuzhiyun 			pgdlen = sg_dma_len(sg);
2487*4882a593Smuzhiyun 			sge->sg_len = pgdlen;
2488*4882a593Smuzhiyun 			sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
2489*4882a593Smuzhiyun 					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
2490*4882a593Smuzhiyun 			bfa_sge_to_be(sge);
2491*4882a593Smuzhiyun 			sge++;
2492*4882a593Smuzhiyun 		} else {
2493*4882a593Smuzhiyun 			if (sge_id == 0)
2494*4882a593Smuzhiyun 				sgpge = sgpg->sgpg->sges;
2495*4882a593Smuzhiyun 
2496*4882a593Smuzhiyun 			addr = bfa_sgaddr_le(sg_dma_address(sg));
2497*4882a593Smuzhiyun 			sgpge->sga = *(union bfi_addr_u *) &addr;
2498*4882a593Smuzhiyun 			sgpge->sg_len = sg_dma_len(sg);
2499*4882a593Smuzhiyun 			pgcumsz += sgpge->sg_len;
2500*4882a593Smuzhiyun 
2501*4882a593Smuzhiyun 			/* set flags */
2502*4882a593Smuzhiyun 			if (i < (ioim->nsges - 1) &&
2503*4882a593Smuzhiyun 					sge_id < (BFI_SGPG_DATA_SGES - 1))
2504*4882a593Smuzhiyun 				sgpge->flags = BFI_SGE_DATA;
2505*4882a593Smuzhiyun 			else if (i < (ioim->nsges - 1))
2506*4882a593Smuzhiyun 				sgpge->flags = BFI_SGE_DATA_CPL;
2507*4882a593Smuzhiyun 			else
2508*4882a593Smuzhiyun 				sgpge->flags = BFI_SGE_DATA_LAST;
2509*4882a593Smuzhiyun 
2510*4882a593Smuzhiyun 			bfa_sge_to_le(sgpge);
2511*4882a593Smuzhiyun 
2512*4882a593Smuzhiyun 			sgpge++;
2513*4882a593Smuzhiyun 			if (i == (ioim->nsges - 1)) {
2514*4882a593Smuzhiyun 				sgpge->flags = BFI_SGE_PGDLEN;
2515*4882a593Smuzhiyun 				sgpge->sga.a32.addr_lo = 0;
2516*4882a593Smuzhiyun 				sgpge->sga.a32.addr_hi = 0;
2517*4882a593Smuzhiyun 				sgpge->sg_len = pgcumsz;
2518*4882a593Smuzhiyun 				bfa_sge_to_le(sgpge);
2519*4882a593Smuzhiyun 			} else if (++sge_id == BFI_SGPG_DATA_SGES) {
2520*4882a593Smuzhiyun 				sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
2521*4882a593Smuzhiyun 				sgpge->flags = BFI_SGE_LINK;
2522*4882a593Smuzhiyun 				sgpge->sga = sgpg->sgpg_pa;
2523*4882a593Smuzhiyun 				sgpge->sg_len = pgcumsz;
2524*4882a593Smuzhiyun 				bfa_sge_to_le(sgpge);
2525*4882a593Smuzhiyun 				sge_id = 0;
2526*4882a593Smuzhiyun 				pgcumsz = 0;
2527*4882a593Smuzhiyun 			}
2528*4882a593Smuzhiyun 		}
2529*4882a593Smuzhiyun 	}
2530*4882a593Smuzhiyun 
2531*4882a593Smuzhiyun 	if (ioim->nsges > BFI_SGE_INLINE) {
2532*4882a593Smuzhiyun 		sge->sga = ioim->sgpg->sgpg_pa;
2533*4882a593Smuzhiyun 	} else {
2534*4882a593Smuzhiyun 		sge->sga.a32.addr_lo = 0;
2535*4882a593Smuzhiyun 		sge->sga.a32.addr_hi = 0;
2536*4882a593Smuzhiyun 	}
2537*4882a593Smuzhiyun 	sge->sg_len = pgdlen;
2538*4882a593Smuzhiyun 	sge->flags = BFI_SGE_PGDLEN;
2539*4882a593Smuzhiyun 	bfa_sge_to_be(sge);
2540*4882a593Smuzhiyun 
2541*4882a593Smuzhiyun 	/*
2542*4882a593Smuzhiyun 	 * set up I/O command parameters
2543*4882a593Smuzhiyun 	 */
2544*4882a593Smuzhiyun 	m->cmnd = cmnd_z0;
2545*4882a593Smuzhiyun 	int_to_scsilun(cmnd->device->lun, &m->cmnd.lun);
2546*4882a593Smuzhiyun 	dmadir = cmnd->sc_data_direction;
2547*4882a593Smuzhiyun 	if (dmadir == DMA_TO_DEVICE)
2548*4882a593Smuzhiyun 		m->cmnd.iodir = FCP_IODIR_WRITE;
2549*4882a593Smuzhiyun 	else if (dmadir == DMA_FROM_DEVICE)
2550*4882a593Smuzhiyun 		m->cmnd.iodir = FCP_IODIR_READ;
2551*4882a593Smuzhiyun 	else
2552*4882a593Smuzhiyun 		m->cmnd.iodir = FCP_IODIR_NONE;
2553*4882a593Smuzhiyun 
2554*4882a593Smuzhiyun 	m->cmnd.cdb = *(struct scsi_cdb_s *) cmnd->cmnd;
2555*4882a593Smuzhiyun 	fcp_dl = scsi_bufflen(cmnd);
2556*4882a593Smuzhiyun 	m->cmnd.fcp_dl = cpu_to_be32(fcp_dl);
2557*4882a593Smuzhiyun 
2558*4882a593Smuzhiyun 	/*
2559*4882a593Smuzhiyun 	 * set up I/O message header
2560*4882a593Smuzhiyun 	 */
2561*4882a593Smuzhiyun 	switch (m->cmnd.iodir) {
2562*4882a593Smuzhiyun 	case FCP_IODIR_READ:
2563*4882a593Smuzhiyun 		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_fn_lpu(ioim->bfa));
2564*4882a593Smuzhiyun 		bfa_stats(itnim, input_reqs);
2565*4882a593Smuzhiyun 		ioim->itnim->stats.rd_throughput += fcp_dl;
2566*4882a593Smuzhiyun 		break;
2567*4882a593Smuzhiyun 	case FCP_IODIR_WRITE:
2568*4882a593Smuzhiyun 		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_fn_lpu(ioim->bfa));
2569*4882a593Smuzhiyun 		bfa_stats(itnim, output_reqs);
2570*4882a593Smuzhiyun 		ioim->itnim->stats.wr_throughput += fcp_dl;
2571*4882a593Smuzhiyun 		break;
2572*4882a593Smuzhiyun 	case FCP_IODIR_RW:
2573*4882a593Smuzhiyun 		bfa_stats(itnim, input_reqs);
2574*4882a593Smuzhiyun 		bfa_stats(itnim, output_reqs);
2575*4882a593Smuzhiyun 		fallthrough;
2576*4882a593Smuzhiyun 	default:
2577*4882a593Smuzhiyun 		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
2578*4882a593Smuzhiyun 	}
2579*4882a593Smuzhiyun 	if (itnim->seq_rec ||
2580*4882a593Smuzhiyun 	    (scsi_bufflen(cmnd) & (sizeof(u32) - 1)))
2581*4882a593Smuzhiyun 		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
2582*4882a593Smuzhiyun 
2583*4882a593Smuzhiyun 	/*
2584*4882a593Smuzhiyun 	 * queue I/O message to firmware
2585*4882a593Smuzhiyun 	 */
2586*4882a593Smuzhiyun 	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
2587*4882a593Smuzhiyun 	return BFA_TRUE;
2588*4882a593Smuzhiyun }
2589*4882a593Smuzhiyun 
2590*4882a593Smuzhiyun /*
2591*4882a593Smuzhiyun  * Setup any additional SG pages needed.Inline SG element is setup
2592*4882a593Smuzhiyun  * at queuing time.
2593*4882a593Smuzhiyun  */
2594*4882a593Smuzhiyun static bfa_boolean_t
bfa_ioim_sgpg_alloc(struct bfa_ioim_s * ioim)2595*4882a593Smuzhiyun bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim)
2596*4882a593Smuzhiyun {
2597*4882a593Smuzhiyun 	u16	nsgpgs;
2598*4882a593Smuzhiyun 
2599*4882a593Smuzhiyun 	WARN_ON(ioim->nsges <= BFI_SGE_INLINE);
2600*4882a593Smuzhiyun 
2601*4882a593Smuzhiyun 	/*
2602*4882a593Smuzhiyun 	 * allocate SG pages needed
2603*4882a593Smuzhiyun 	 */
2604*4882a593Smuzhiyun 	nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
2605*4882a593Smuzhiyun 	if (!nsgpgs)
2606*4882a593Smuzhiyun 		return BFA_TRUE;
2607*4882a593Smuzhiyun 
2608*4882a593Smuzhiyun 	if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
2609*4882a593Smuzhiyun 	    != BFA_STATUS_OK) {
2610*4882a593Smuzhiyun 		bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
2611*4882a593Smuzhiyun 		return BFA_FALSE;
2612*4882a593Smuzhiyun 	}
2613*4882a593Smuzhiyun 
2614*4882a593Smuzhiyun 	ioim->nsgpgs = nsgpgs;
2615*4882a593Smuzhiyun 	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);
2616*4882a593Smuzhiyun 
2617*4882a593Smuzhiyun 	return BFA_TRUE;
2618*4882a593Smuzhiyun }
2619*4882a593Smuzhiyun 
2620*4882a593Smuzhiyun /*
2621*4882a593Smuzhiyun  * Send I/O abort request to firmware.
2622*4882a593Smuzhiyun  */
2623*4882a593Smuzhiyun static	bfa_boolean_t
bfa_ioim_send_abort(struct bfa_ioim_s * ioim)2624*4882a593Smuzhiyun bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
2625*4882a593Smuzhiyun {
2626*4882a593Smuzhiyun 	struct bfi_ioim_abort_req_s *m;
2627*4882a593Smuzhiyun 	enum bfi_ioim_h2i	msgop;
2628*4882a593Smuzhiyun 
2629*4882a593Smuzhiyun 	/*
2630*4882a593Smuzhiyun 	 * check for room in queue to send request now
2631*4882a593Smuzhiyun 	 */
2632*4882a593Smuzhiyun 	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
2633*4882a593Smuzhiyun 	if (!m)
2634*4882a593Smuzhiyun 		return BFA_FALSE;
2635*4882a593Smuzhiyun 
2636*4882a593Smuzhiyun 	/*
2637*4882a593Smuzhiyun 	 * build i/o request message next
2638*4882a593Smuzhiyun 	 */
2639*4882a593Smuzhiyun 	if (ioim->iosp->abort_explicit)
2640*4882a593Smuzhiyun 		msgop = BFI_IOIM_H2I_IOABORT_REQ;
2641*4882a593Smuzhiyun 	else
2642*4882a593Smuzhiyun 		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
2643*4882a593Smuzhiyun 
2644*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_fn_lpu(ioim->bfa));
2645*4882a593Smuzhiyun 	m->io_tag    = cpu_to_be16(ioim->iotag);
2646*4882a593Smuzhiyun 	m->abort_tag = ++ioim->abort_tag;
2647*4882a593Smuzhiyun 
2648*4882a593Smuzhiyun 	/*
2649*4882a593Smuzhiyun 	 * queue I/O message to firmware
2650*4882a593Smuzhiyun 	 */
2651*4882a593Smuzhiyun 	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
2652*4882a593Smuzhiyun 	return BFA_TRUE;
2653*4882a593Smuzhiyun }
2654*4882a593Smuzhiyun 
2655*4882a593Smuzhiyun /*
2656*4882a593Smuzhiyun  * Call to resume any I/O requests waiting for room in request queue.
2657*4882a593Smuzhiyun  */
2658*4882a593Smuzhiyun static void
bfa_ioim_qresume(void * cbarg)2659*4882a593Smuzhiyun bfa_ioim_qresume(void *cbarg)
2660*4882a593Smuzhiyun {
2661*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim = cbarg;
2662*4882a593Smuzhiyun 
2663*4882a593Smuzhiyun 	bfa_stats(ioim->itnim, qresumes);
2664*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
2665*4882a593Smuzhiyun }
2666*4882a593Smuzhiyun 
2667*4882a593Smuzhiyun 
2668*4882a593Smuzhiyun static void
bfa_ioim_notify_cleanup(struct bfa_ioim_s * ioim)2669*4882a593Smuzhiyun bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
2670*4882a593Smuzhiyun {
2671*4882a593Smuzhiyun 	/*
2672*4882a593Smuzhiyun 	 * Move IO from itnim queue to fcpim global queue since itnim will be
2673*4882a593Smuzhiyun 	 * freed.
2674*4882a593Smuzhiyun 	 */
2675*4882a593Smuzhiyun 	list_del(&ioim->qe);
2676*4882a593Smuzhiyun 	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
2677*4882a593Smuzhiyun 
2678*4882a593Smuzhiyun 	if (!ioim->iosp->tskim) {
2679*4882a593Smuzhiyun 		if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
2680*4882a593Smuzhiyun 			bfa_cb_dequeue(&ioim->hcb_qe);
2681*4882a593Smuzhiyun 			list_del(&ioim->qe);
2682*4882a593Smuzhiyun 			list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
2683*4882a593Smuzhiyun 		}
2684*4882a593Smuzhiyun 		bfa_itnim_iodone(ioim->itnim);
2685*4882a593Smuzhiyun 	} else
2686*4882a593Smuzhiyun 		bfa_wc_down(&ioim->iosp->tskim->wc);
2687*4882a593Smuzhiyun }
2688*4882a593Smuzhiyun 
2689*4882a593Smuzhiyun static bfa_boolean_t
bfa_ioim_is_abortable(struct bfa_ioim_s * ioim)2690*4882a593Smuzhiyun bfa_ioim_is_abortable(struct bfa_ioim_s *ioim)
2691*4882a593Smuzhiyun {
2692*4882a593Smuzhiyun 	if ((bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit) &&
2693*4882a593Smuzhiyun 	    (!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)))	||
2694*4882a593Smuzhiyun 	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort))		||
2695*4882a593Smuzhiyun 	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort_qfull))	||
2696*4882a593Smuzhiyun 	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb))		||
2697*4882a593Smuzhiyun 	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb_free))	||
2698*4882a593Smuzhiyun 	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_resfree)))
2699*4882a593Smuzhiyun 		return BFA_FALSE;
2700*4882a593Smuzhiyun 
2701*4882a593Smuzhiyun 	return BFA_TRUE;
2702*4882a593Smuzhiyun }
2703*4882a593Smuzhiyun 
2704*4882a593Smuzhiyun void
bfa_ioim_delayed_comp(struct bfa_ioim_s * ioim,bfa_boolean_t iotov)2705*4882a593Smuzhiyun bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
2706*4882a593Smuzhiyun {
2707*4882a593Smuzhiyun 	/*
2708*4882a593Smuzhiyun 	 * If path tov timer expired, failback with PATHTOV status - these
2709*4882a593Smuzhiyun 	 * IO requests are not normally retried by IO stack.
2710*4882a593Smuzhiyun 	 *
2711*4882a593Smuzhiyun 	 * Otherwise device cameback online and fail it with normal failed
2712*4882a593Smuzhiyun 	 * status so that IO stack retries these failed IO requests.
2713*4882a593Smuzhiyun 	 */
2714*4882a593Smuzhiyun 	if (iotov)
2715*4882a593Smuzhiyun 		ioim->io_cbfn = __bfa_cb_ioim_pathtov;
2716*4882a593Smuzhiyun 	else {
2717*4882a593Smuzhiyun 		ioim->io_cbfn = __bfa_cb_ioim_failed;
2718*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocom_nexus_abort);
2719*4882a593Smuzhiyun 	}
2720*4882a593Smuzhiyun 	bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
2721*4882a593Smuzhiyun 
2722*4882a593Smuzhiyun 	/*
2723*4882a593Smuzhiyun 	 * Move IO to fcpim global queue since itnim will be
2724*4882a593Smuzhiyun 	 * freed.
2725*4882a593Smuzhiyun 	 */
2726*4882a593Smuzhiyun 	list_del(&ioim->qe);
2727*4882a593Smuzhiyun 	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
2728*4882a593Smuzhiyun }
2729*4882a593Smuzhiyun 
2730*4882a593Smuzhiyun 
2731*4882a593Smuzhiyun /*
2732*4882a593Smuzhiyun  * Memory allocation and initialization.
2733*4882a593Smuzhiyun  */
2734*4882a593Smuzhiyun void
bfa_ioim_attach(struct bfa_fcpim_s * fcpim)2735*4882a593Smuzhiyun bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
2736*4882a593Smuzhiyun {
2737*4882a593Smuzhiyun 	struct bfa_ioim_s		*ioim;
2738*4882a593Smuzhiyun 	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;
2739*4882a593Smuzhiyun 	struct bfa_ioim_sp_s	*iosp;
2740*4882a593Smuzhiyun 	u16		i;
2741*4882a593Smuzhiyun 
2742*4882a593Smuzhiyun 	/*
2743*4882a593Smuzhiyun 	 * claim memory first
2744*4882a593Smuzhiyun 	 */
2745*4882a593Smuzhiyun 	ioim = (struct bfa_ioim_s *) bfa_mem_kva_curp(fcp);
2746*4882a593Smuzhiyun 	fcpim->ioim_arr = ioim;
2747*4882a593Smuzhiyun 	bfa_mem_kva_curp(fcp) = (u8 *) (ioim + fcpim->fcp->num_ioim_reqs);
2748*4882a593Smuzhiyun 
2749*4882a593Smuzhiyun 	iosp = (struct bfa_ioim_sp_s *) bfa_mem_kva_curp(fcp);
2750*4882a593Smuzhiyun 	fcpim->ioim_sp_arr = iosp;
2751*4882a593Smuzhiyun 	bfa_mem_kva_curp(fcp) = (u8 *) (iosp + fcpim->fcp->num_ioim_reqs);
2752*4882a593Smuzhiyun 
2753*4882a593Smuzhiyun 	/*
2754*4882a593Smuzhiyun 	 * Initialize ioim free queues
2755*4882a593Smuzhiyun 	 */
2756*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
2757*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcpim->ioim_comp_q);
2758*4882a593Smuzhiyun 
2759*4882a593Smuzhiyun 	for (i = 0; i < fcpim->fcp->num_ioim_reqs;
2760*4882a593Smuzhiyun 	     i++, ioim++, iosp++) {
2761*4882a593Smuzhiyun 		/*
2762*4882a593Smuzhiyun 		 * initialize IOIM
2763*4882a593Smuzhiyun 		 */
2764*4882a593Smuzhiyun 		memset(ioim, 0, sizeof(struct bfa_ioim_s));
2765*4882a593Smuzhiyun 		ioim->iotag   = i;
2766*4882a593Smuzhiyun 		ioim->bfa     = fcpim->bfa;
2767*4882a593Smuzhiyun 		ioim->fcpim   = fcpim;
2768*4882a593Smuzhiyun 		ioim->iosp    = iosp;
2769*4882a593Smuzhiyun 		INIT_LIST_HEAD(&ioim->sgpg_q);
2770*4882a593Smuzhiyun 		bfa_reqq_winit(&ioim->iosp->reqq_wait,
2771*4882a593Smuzhiyun 				   bfa_ioim_qresume, ioim);
2772*4882a593Smuzhiyun 		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
2773*4882a593Smuzhiyun 				   bfa_ioim_sgpg_alloced, ioim);
2774*4882a593Smuzhiyun 		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
2775*4882a593Smuzhiyun 	}
2776*4882a593Smuzhiyun }
2777*4882a593Smuzhiyun 
2778*4882a593Smuzhiyun void
bfa_ioim_isr(struct bfa_s * bfa,struct bfi_msg_s * m)2779*4882a593Smuzhiyun bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
2780*4882a593Smuzhiyun {
2781*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
2782*4882a593Smuzhiyun 	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
2783*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
2784*4882a593Smuzhiyun 	u16	iotag;
2785*4882a593Smuzhiyun 	enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
2786*4882a593Smuzhiyun 
2787*4882a593Smuzhiyun 	iotag = be16_to_cpu(rsp->io_tag);
2788*4882a593Smuzhiyun 
2789*4882a593Smuzhiyun 	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
2790*4882a593Smuzhiyun 	WARN_ON(ioim->iotag != iotag);
2791*4882a593Smuzhiyun 
2792*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
2793*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, rsp->io_status);
2794*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, rsp->reuse_io_tag);
2795*4882a593Smuzhiyun 
2796*4882a593Smuzhiyun 	if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
2797*4882a593Smuzhiyun 		ioim->iosp->comp_rspmsg = *m;
2798*4882a593Smuzhiyun 
2799*4882a593Smuzhiyun 	switch (rsp->io_status) {
2800*4882a593Smuzhiyun 	case BFI_IOIM_STS_OK:
2801*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocomp_ok);
2802*4882a593Smuzhiyun 		if (rsp->reuse_io_tag == 0)
2803*4882a593Smuzhiyun 			evt = BFA_IOIM_SM_DONE;
2804*4882a593Smuzhiyun 		else
2805*4882a593Smuzhiyun 			evt = BFA_IOIM_SM_COMP;
2806*4882a593Smuzhiyun 		break;
2807*4882a593Smuzhiyun 
2808*4882a593Smuzhiyun 	case BFI_IOIM_STS_TIMEDOUT:
2809*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocomp_timedout);
2810*4882a593Smuzhiyun 		fallthrough;
2811*4882a593Smuzhiyun 	case BFI_IOIM_STS_ABORTED:
2812*4882a593Smuzhiyun 		rsp->io_status = BFI_IOIM_STS_ABORTED;
2813*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocomp_aborted);
2814*4882a593Smuzhiyun 		if (rsp->reuse_io_tag == 0)
2815*4882a593Smuzhiyun 			evt = BFA_IOIM_SM_DONE;
2816*4882a593Smuzhiyun 		else
2817*4882a593Smuzhiyun 			evt = BFA_IOIM_SM_COMP;
2818*4882a593Smuzhiyun 		break;
2819*4882a593Smuzhiyun 
2820*4882a593Smuzhiyun 	case BFI_IOIM_STS_PROTO_ERR:
2821*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocom_proto_err);
2822*4882a593Smuzhiyun 		WARN_ON(!rsp->reuse_io_tag);
2823*4882a593Smuzhiyun 		evt = BFA_IOIM_SM_COMP;
2824*4882a593Smuzhiyun 		break;
2825*4882a593Smuzhiyun 
2826*4882a593Smuzhiyun 	case BFI_IOIM_STS_SQER_NEEDED:
2827*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocom_sqer_needed);
2828*4882a593Smuzhiyun 		WARN_ON(rsp->reuse_io_tag != 0);
2829*4882a593Smuzhiyun 		evt = BFA_IOIM_SM_SQRETRY;
2830*4882a593Smuzhiyun 		break;
2831*4882a593Smuzhiyun 
2832*4882a593Smuzhiyun 	case BFI_IOIM_STS_RES_FREE:
2833*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocom_res_free);
2834*4882a593Smuzhiyun 		evt = BFA_IOIM_SM_FREE;
2835*4882a593Smuzhiyun 		break;
2836*4882a593Smuzhiyun 
2837*4882a593Smuzhiyun 	case BFI_IOIM_STS_HOST_ABORTED:
2838*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocom_hostabrts);
2839*4882a593Smuzhiyun 		if (rsp->abort_tag != ioim->abort_tag) {
2840*4882a593Smuzhiyun 			bfa_trc(ioim->bfa, rsp->abort_tag);
2841*4882a593Smuzhiyun 			bfa_trc(ioim->bfa, ioim->abort_tag);
2842*4882a593Smuzhiyun 			return;
2843*4882a593Smuzhiyun 		}
2844*4882a593Smuzhiyun 
2845*4882a593Smuzhiyun 		if (rsp->reuse_io_tag)
2846*4882a593Smuzhiyun 			evt = BFA_IOIM_SM_ABORT_COMP;
2847*4882a593Smuzhiyun 		else
2848*4882a593Smuzhiyun 			evt = BFA_IOIM_SM_ABORT_DONE;
2849*4882a593Smuzhiyun 		break;
2850*4882a593Smuzhiyun 
2851*4882a593Smuzhiyun 	case BFI_IOIM_STS_UTAG:
2852*4882a593Smuzhiyun 		bfa_stats(ioim->itnim, iocom_utags);
2853*4882a593Smuzhiyun 		evt = BFA_IOIM_SM_COMP_UTAG;
2854*4882a593Smuzhiyun 		break;
2855*4882a593Smuzhiyun 
2856*4882a593Smuzhiyun 	default:
2857*4882a593Smuzhiyun 		WARN_ON(1);
2858*4882a593Smuzhiyun 	}
2859*4882a593Smuzhiyun 
2860*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, evt);
2861*4882a593Smuzhiyun }
2862*4882a593Smuzhiyun 
2863*4882a593Smuzhiyun void
bfa_ioim_good_comp_isr(struct bfa_s * bfa,struct bfi_msg_s * m)2864*4882a593Smuzhiyun bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
2865*4882a593Smuzhiyun {
2866*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
2867*4882a593Smuzhiyun 	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
2868*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
2869*4882a593Smuzhiyun 	u16	iotag;
2870*4882a593Smuzhiyun 
2871*4882a593Smuzhiyun 	iotag = be16_to_cpu(rsp->io_tag);
2872*4882a593Smuzhiyun 
2873*4882a593Smuzhiyun 	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
2874*4882a593Smuzhiyun 	WARN_ON(ioim->iotag != iotag);
2875*4882a593Smuzhiyun 
2876*4882a593Smuzhiyun 	bfa_ioim_cb_profile_comp(fcpim, ioim);
2877*4882a593Smuzhiyun 
2878*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
2879*4882a593Smuzhiyun }
2880*4882a593Smuzhiyun 
2881*4882a593Smuzhiyun /*
2882*4882a593Smuzhiyun  * Called by itnim to clean up IO while going offline.
2883*4882a593Smuzhiyun  */
2884*4882a593Smuzhiyun void
bfa_ioim_cleanup(struct bfa_ioim_s * ioim)2885*4882a593Smuzhiyun bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
2886*4882a593Smuzhiyun {
2887*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
2888*4882a593Smuzhiyun 	bfa_stats(ioim->itnim, io_cleanups);
2889*4882a593Smuzhiyun 
2890*4882a593Smuzhiyun 	ioim->iosp->tskim = NULL;
2891*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
2892*4882a593Smuzhiyun }
2893*4882a593Smuzhiyun 
2894*4882a593Smuzhiyun void
bfa_ioim_cleanup_tm(struct bfa_ioim_s * ioim,struct bfa_tskim_s * tskim)2895*4882a593Smuzhiyun bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
2896*4882a593Smuzhiyun {
2897*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
2898*4882a593Smuzhiyun 	bfa_stats(ioim->itnim, io_tmaborts);
2899*4882a593Smuzhiyun 
2900*4882a593Smuzhiyun 	ioim->iosp->tskim = tskim;
2901*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
2902*4882a593Smuzhiyun }
2903*4882a593Smuzhiyun 
2904*4882a593Smuzhiyun /*
2905*4882a593Smuzhiyun  * IOC failure handling.
2906*4882a593Smuzhiyun  */
2907*4882a593Smuzhiyun void
bfa_ioim_iocdisable(struct bfa_ioim_s * ioim)2908*4882a593Smuzhiyun bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
2909*4882a593Smuzhiyun {
2910*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
2911*4882a593Smuzhiyun 	bfa_stats(ioim->itnim, io_iocdowns);
2912*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
2913*4882a593Smuzhiyun }
2914*4882a593Smuzhiyun 
2915*4882a593Smuzhiyun /*
2916*4882a593Smuzhiyun  * IO offline TOV popped. Fail the pending IO.
2917*4882a593Smuzhiyun  */
2918*4882a593Smuzhiyun void
bfa_ioim_tov(struct bfa_ioim_s * ioim)2919*4882a593Smuzhiyun bfa_ioim_tov(struct bfa_ioim_s *ioim)
2920*4882a593Smuzhiyun {
2921*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
2922*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
2923*4882a593Smuzhiyun }
2924*4882a593Smuzhiyun 
2925*4882a593Smuzhiyun 
2926*4882a593Smuzhiyun /*
2927*4882a593Smuzhiyun  * Allocate IOIM resource for initiator mode I/O request.
2928*4882a593Smuzhiyun  */
2929*4882a593Smuzhiyun struct bfa_ioim_s *
bfa_ioim_alloc(struct bfa_s * bfa,struct bfad_ioim_s * dio,struct bfa_itnim_s * itnim,u16 nsges)2930*4882a593Smuzhiyun bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
2931*4882a593Smuzhiyun 		struct bfa_itnim_s *itnim, u16 nsges)
2932*4882a593Smuzhiyun {
2933*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
2934*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
2935*4882a593Smuzhiyun 	struct bfa_iotag_s *iotag = NULL;
2936*4882a593Smuzhiyun 
2937*4882a593Smuzhiyun 	/*
2938*4882a593Smuzhiyun 	 * alocate IOIM resource
2939*4882a593Smuzhiyun 	 */
2940*4882a593Smuzhiyun 	bfa_q_deq(&fcpim->fcp->iotag_ioim_free_q, &iotag);
2941*4882a593Smuzhiyun 	if (!iotag) {
2942*4882a593Smuzhiyun 		bfa_stats(itnim, no_iotags);
2943*4882a593Smuzhiyun 		return NULL;
2944*4882a593Smuzhiyun 	}
2945*4882a593Smuzhiyun 
2946*4882a593Smuzhiyun 	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag->tag);
2947*4882a593Smuzhiyun 
2948*4882a593Smuzhiyun 	ioim->dio = dio;
2949*4882a593Smuzhiyun 	ioim->itnim = itnim;
2950*4882a593Smuzhiyun 	ioim->nsges = nsges;
2951*4882a593Smuzhiyun 	ioim->nsgpgs = 0;
2952*4882a593Smuzhiyun 
2953*4882a593Smuzhiyun 	bfa_stats(itnim, total_ios);
2954*4882a593Smuzhiyun 	fcpim->ios_active++;
2955*4882a593Smuzhiyun 
2956*4882a593Smuzhiyun 	list_add_tail(&ioim->qe, &itnim->io_q);
2957*4882a593Smuzhiyun 
2958*4882a593Smuzhiyun 	return ioim;
2959*4882a593Smuzhiyun }
2960*4882a593Smuzhiyun 
2961*4882a593Smuzhiyun void
bfa_ioim_free(struct bfa_ioim_s * ioim)2962*4882a593Smuzhiyun bfa_ioim_free(struct bfa_ioim_s *ioim)
2963*4882a593Smuzhiyun {
2964*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = ioim->fcpim;
2965*4882a593Smuzhiyun 	struct bfa_iotag_s *iotag;
2966*4882a593Smuzhiyun 
2967*4882a593Smuzhiyun 	if (ioim->nsgpgs > 0)
2968*4882a593Smuzhiyun 		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
2969*4882a593Smuzhiyun 
2970*4882a593Smuzhiyun 	bfa_stats(ioim->itnim, io_comps);
2971*4882a593Smuzhiyun 	fcpim->ios_active--;
2972*4882a593Smuzhiyun 
2973*4882a593Smuzhiyun 	ioim->iotag &= BFA_IOIM_IOTAG_MASK;
2974*4882a593Smuzhiyun 
2975*4882a593Smuzhiyun 	WARN_ON(!(ioim->iotag <
2976*4882a593Smuzhiyun 		(fcpim->fcp->num_ioim_reqs + fcpim->fcp->num_fwtio_reqs)));
2977*4882a593Smuzhiyun 	iotag = BFA_IOTAG_FROM_TAG(fcpim->fcp, ioim->iotag);
2978*4882a593Smuzhiyun 
2979*4882a593Smuzhiyun 	if (ioim->iotag < fcpim->fcp->num_ioim_reqs)
2980*4882a593Smuzhiyun 		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_ioim_free_q);
2981*4882a593Smuzhiyun 	else
2982*4882a593Smuzhiyun 		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_tio_free_q);
2983*4882a593Smuzhiyun 
2984*4882a593Smuzhiyun 	list_del(&ioim->qe);
2985*4882a593Smuzhiyun }
2986*4882a593Smuzhiyun 
2987*4882a593Smuzhiyun void
bfa_ioim_start(struct bfa_ioim_s * ioim)2988*4882a593Smuzhiyun bfa_ioim_start(struct bfa_ioim_s *ioim)
2989*4882a593Smuzhiyun {
2990*4882a593Smuzhiyun 	bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
2991*4882a593Smuzhiyun 
2992*4882a593Smuzhiyun 	/*
2993*4882a593Smuzhiyun 	 * Obtain the queue over which this request has to be issued
2994*4882a593Smuzhiyun 	 */
2995*4882a593Smuzhiyun 	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
2996*4882a593Smuzhiyun 			BFA_FALSE : bfa_itnim_get_reqq(ioim);
2997*4882a593Smuzhiyun 
2998*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
2999*4882a593Smuzhiyun }
3000*4882a593Smuzhiyun 
3001*4882a593Smuzhiyun /*
3002*4882a593Smuzhiyun  * Driver I/O abort request.
3003*4882a593Smuzhiyun  */
3004*4882a593Smuzhiyun bfa_status_t
bfa_ioim_abort(struct bfa_ioim_s * ioim)3005*4882a593Smuzhiyun bfa_ioim_abort(struct bfa_ioim_s *ioim)
3006*4882a593Smuzhiyun {
3007*4882a593Smuzhiyun 
3008*4882a593Smuzhiyun 	bfa_trc(ioim->bfa, ioim->iotag);
3009*4882a593Smuzhiyun 
3010*4882a593Smuzhiyun 	if (!bfa_ioim_is_abortable(ioim))
3011*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
3012*4882a593Smuzhiyun 
3013*4882a593Smuzhiyun 	bfa_stats(ioim->itnim, io_aborts);
3014*4882a593Smuzhiyun 	bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
3015*4882a593Smuzhiyun 
3016*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3017*4882a593Smuzhiyun }
3018*4882a593Smuzhiyun 
3019*4882a593Smuzhiyun /*
3020*4882a593Smuzhiyun  *  BFA TSKIM state machine functions
3021*4882a593Smuzhiyun  */
3022*4882a593Smuzhiyun 
3023*4882a593Smuzhiyun /*
3024*4882a593Smuzhiyun  * Task management command beginning state.
3025*4882a593Smuzhiyun  */
3026*4882a593Smuzhiyun static void
bfa_tskim_sm_uninit(struct bfa_tskim_s * tskim,enum bfa_tskim_event event)3027*4882a593Smuzhiyun bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
3028*4882a593Smuzhiyun {
3029*4882a593Smuzhiyun 	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
3030*4882a593Smuzhiyun 
3031*4882a593Smuzhiyun 	switch (event) {
3032*4882a593Smuzhiyun 	case BFA_TSKIM_SM_START:
3033*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
3034*4882a593Smuzhiyun 		bfa_tskim_gather_ios(tskim);
3035*4882a593Smuzhiyun 
3036*4882a593Smuzhiyun 		/*
3037*4882a593Smuzhiyun 		 * If device is offline, do not send TM on wire. Just cleanup
3038*4882a593Smuzhiyun 		 * any pending IO requests and complete TM request.
3039*4882a593Smuzhiyun 		 */
3040*4882a593Smuzhiyun 		if (!bfa_itnim_is_online(tskim->itnim)) {
3041*4882a593Smuzhiyun 			bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
3042*4882a593Smuzhiyun 			tskim->tsk_status = BFI_TSKIM_STS_OK;
3043*4882a593Smuzhiyun 			bfa_tskim_cleanup_ios(tskim);
3044*4882a593Smuzhiyun 			return;
3045*4882a593Smuzhiyun 		}
3046*4882a593Smuzhiyun 
3047*4882a593Smuzhiyun 		if (!bfa_tskim_send(tskim)) {
3048*4882a593Smuzhiyun 			bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
3049*4882a593Smuzhiyun 			bfa_stats(tskim->itnim, tm_qwait);
3050*4882a593Smuzhiyun 			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
3051*4882a593Smuzhiyun 					  &tskim->reqq_wait);
3052*4882a593Smuzhiyun 		}
3053*4882a593Smuzhiyun 		break;
3054*4882a593Smuzhiyun 
3055*4882a593Smuzhiyun 	default:
3056*4882a593Smuzhiyun 		bfa_sm_fault(tskim->bfa, event);
3057*4882a593Smuzhiyun 	}
3058*4882a593Smuzhiyun }
3059*4882a593Smuzhiyun 
3060*4882a593Smuzhiyun /*
3061*4882a593Smuzhiyun  * TM command is active, awaiting completion from firmware to
3062*4882a593Smuzhiyun  * cleanup IO requests in TM scope.
3063*4882a593Smuzhiyun  */
3064*4882a593Smuzhiyun static void
bfa_tskim_sm_active(struct bfa_tskim_s * tskim,enum bfa_tskim_event event)3065*4882a593Smuzhiyun bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
3066*4882a593Smuzhiyun {
3067*4882a593Smuzhiyun 	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
3068*4882a593Smuzhiyun 
3069*4882a593Smuzhiyun 	switch (event) {
3070*4882a593Smuzhiyun 	case BFA_TSKIM_SM_DONE:
3071*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
3072*4882a593Smuzhiyun 		bfa_tskim_cleanup_ios(tskim);
3073*4882a593Smuzhiyun 		break;
3074*4882a593Smuzhiyun 
3075*4882a593Smuzhiyun 	case BFA_TSKIM_SM_CLEANUP:
3076*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
3077*4882a593Smuzhiyun 		if (!bfa_tskim_send_abort(tskim)) {
3078*4882a593Smuzhiyun 			bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
3079*4882a593Smuzhiyun 			bfa_stats(tskim->itnim, tm_qwait);
3080*4882a593Smuzhiyun 			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
3081*4882a593Smuzhiyun 				&tskim->reqq_wait);
3082*4882a593Smuzhiyun 		}
3083*4882a593Smuzhiyun 		break;
3084*4882a593Smuzhiyun 
3085*4882a593Smuzhiyun 	case BFA_TSKIM_SM_HWFAIL:
3086*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
3087*4882a593Smuzhiyun 		bfa_tskim_iocdisable_ios(tskim);
3088*4882a593Smuzhiyun 		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
3089*4882a593Smuzhiyun 		break;
3090*4882a593Smuzhiyun 
3091*4882a593Smuzhiyun 	default:
3092*4882a593Smuzhiyun 		bfa_sm_fault(tskim->bfa, event);
3093*4882a593Smuzhiyun 	}
3094*4882a593Smuzhiyun }
3095*4882a593Smuzhiyun 
3096*4882a593Smuzhiyun /*
3097*4882a593Smuzhiyun  * An active TM is being cleaned up since ITN is offline. Awaiting cleanup
3098*4882a593Smuzhiyun  * completion event from firmware.
3099*4882a593Smuzhiyun  */
3100*4882a593Smuzhiyun static void
bfa_tskim_sm_cleanup(struct bfa_tskim_s * tskim,enum bfa_tskim_event event)3101*4882a593Smuzhiyun bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
3102*4882a593Smuzhiyun {
3103*4882a593Smuzhiyun 	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
3104*4882a593Smuzhiyun 
3105*4882a593Smuzhiyun 	switch (event) {
3106*4882a593Smuzhiyun 	case BFA_TSKIM_SM_DONE:
3107*4882a593Smuzhiyun 		/*
3108*4882a593Smuzhiyun 		 * Ignore and wait for ABORT completion from firmware.
3109*4882a593Smuzhiyun 		 */
3110*4882a593Smuzhiyun 		break;
3111*4882a593Smuzhiyun 
3112*4882a593Smuzhiyun 	case BFA_TSKIM_SM_UTAG:
3113*4882a593Smuzhiyun 	case BFA_TSKIM_SM_CLEANUP_DONE:
3114*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
3115*4882a593Smuzhiyun 		bfa_tskim_cleanup_ios(tskim);
3116*4882a593Smuzhiyun 		break;
3117*4882a593Smuzhiyun 
3118*4882a593Smuzhiyun 	case BFA_TSKIM_SM_HWFAIL:
3119*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
3120*4882a593Smuzhiyun 		bfa_tskim_iocdisable_ios(tskim);
3121*4882a593Smuzhiyun 		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
3122*4882a593Smuzhiyun 		break;
3123*4882a593Smuzhiyun 
3124*4882a593Smuzhiyun 	default:
3125*4882a593Smuzhiyun 		bfa_sm_fault(tskim->bfa, event);
3126*4882a593Smuzhiyun 	}
3127*4882a593Smuzhiyun }
3128*4882a593Smuzhiyun 
3129*4882a593Smuzhiyun static void
bfa_tskim_sm_iocleanup(struct bfa_tskim_s * tskim,enum bfa_tskim_event event)3130*4882a593Smuzhiyun bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
3131*4882a593Smuzhiyun {
3132*4882a593Smuzhiyun 	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
3133*4882a593Smuzhiyun 
3134*4882a593Smuzhiyun 	switch (event) {
3135*4882a593Smuzhiyun 	case BFA_TSKIM_SM_IOS_DONE:
3136*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
3137*4882a593Smuzhiyun 		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
3138*4882a593Smuzhiyun 		break;
3139*4882a593Smuzhiyun 
3140*4882a593Smuzhiyun 	case BFA_TSKIM_SM_CLEANUP:
3141*4882a593Smuzhiyun 		/*
3142*4882a593Smuzhiyun 		 * Ignore, TM command completed on wire.
3143*4882a593Smuzhiyun 		 * Notify TM conmpletion on IO cleanup completion.
3144*4882a593Smuzhiyun 		 */
3145*4882a593Smuzhiyun 		break;
3146*4882a593Smuzhiyun 
3147*4882a593Smuzhiyun 	case BFA_TSKIM_SM_HWFAIL:
3148*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
3149*4882a593Smuzhiyun 		bfa_tskim_iocdisable_ios(tskim);
3150*4882a593Smuzhiyun 		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
3151*4882a593Smuzhiyun 		break;
3152*4882a593Smuzhiyun 
3153*4882a593Smuzhiyun 	default:
3154*4882a593Smuzhiyun 		bfa_sm_fault(tskim->bfa, event);
3155*4882a593Smuzhiyun 	}
3156*4882a593Smuzhiyun }
3157*4882a593Smuzhiyun 
3158*4882a593Smuzhiyun /*
3159*4882a593Smuzhiyun  * Task management command is waiting for room in request CQ
3160*4882a593Smuzhiyun  */
3161*4882a593Smuzhiyun static void
bfa_tskim_sm_qfull(struct bfa_tskim_s * tskim,enum bfa_tskim_event event)3162*4882a593Smuzhiyun bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
3163*4882a593Smuzhiyun {
3164*4882a593Smuzhiyun 	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
3165*4882a593Smuzhiyun 
3166*4882a593Smuzhiyun 	switch (event) {
3167*4882a593Smuzhiyun 	case BFA_TSKIM_SM_QRESUME:
3168*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
3169*4882a593Smuzhiyun 		bfa_tskim_send(tskim);
3170*4882a593Smuzhiyun 		break;
3171*4882a593Smuzhiyun 
3172*4882a593Smuzhiyun 	case BFA_TSKIM_SM_CLEANUP:
3173*4882a593Smuzhiyun 		/*
3174*4882a593Smuzhiyun 		 * No need to send TM on wire since ITN is offline.
3175*4882a593Smuzhiyun 		 */
3176*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
3177*4882a593Smuzhiyun 		bfa_reqq_wcancel(&tskim->reqq_wait);
3178*4882a593Smuzhiyun 		bfa_tskim_cleanup_ios(tskim);
3179*4882a593Smuzhiyun 		break;
3180*4882a593Smuzhiyun 
3181*4882a593Smuzhiyun 	case BFA_TSKIM_SM_HWFAIL:
3182*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
3183*4882a593Smuzhiyun 		bfa_reqq_wcancel(&tskim->reqq_wait);
3184*4882a593Smuzhiyun 		bfa_tskim_iocdisable_ios(tskim);
3185*4882a593Smuzhiyun 		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
3186*4882a593Smuzhiyun 		break;
3187*4882a593Smuzhiyun 
3188*4882a593Smuzhiyun 	default:
3189*4882a593Smuzhiyun 		bfa_sm_fault(tskim->bfa, event);
3190*4882a593Smuzhiyun 	}
3191*4882a593Smuzhiyun }
3192*4882a593Smuzhiyun 
3193*4882a593Smuzhiyun /*
3194*4882a593Smuzhiyun  * Task management command is active, awaiting for room in request CQ
3195*4882a593Smuzhiyun  * to send clean up request.
3196*4882a593Smuzhiyun  */
3197*4882a593Smuzhiyun static void
bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s * tskim,enum bfa_tskim_event event)3198*4882a593Smuzhiyun bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
3199*4882a593Smuzhiyun 		enum bfa_tskim_event event)
3200*4882a593Smuzhiyun {
3201*4882a593Smuzhiyun 	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
3202*4882a593Smuzhiyun 
3203*4882a593Smuzhiyun 	switch (event) {
3204*4882a593Smuzhiyun 	case BFA_TSKIM_SM_DONE:
3205*4882a593Smuzhiyun 		bfa_reqq_wcancel(&tskim->reqq_wait);
3206*4882a593Smuzhiyun 		fallthrough;
3207*4882a593Smuzhiyun 	case BFA_TSKIM_SM_QRESUME:
3208*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
3209*4882a593Smuzhiyun 		bfa_tskim_send_abort(tskim);
3210*4882a593Smuzhiyun 		break;
3211*4882a593Smuzhiyun 
3212*4882a593Smuzhiyun 	case BFA_TSKIM_SM_HWFAIL:
3213*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
3214*4882a593Smuzhiyun 		bfa_reqq_wcancel(&tskim->reqq_wait);
3215*4882a593Smuzhiyun 		bfa_tskim_iocdisable_ios(tskim);
3216*4882a593Smuzhiyun 		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
3217*4882a593Smuzhiyun 		break;
3218*4882a593Smuzhiyun 
3219*4882a593Smuzhiyun 	default:
3220*4882a593Smuzhiyun 		bfa_sm_fault(tskim->bfa, event);
3221*4882a593Smuzhiyun 	}
3222*4882a593Smuzhiyun }
3223*4882a593Smuzhiyun 
3224*4882a593Smuzhiyun /*
3225*4882a593Smuzhiyun  * BFA callback is pending
3226*4882a593Smuzhiyun  */
3227*4882a593Smuzhiyun static void
bfa_tskim_sm_hcb(struct bfa_tskim_s * tskim,enum bfa_tskim_event event)3228*4882a593Smuzhiyun bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
3229*4882a593Smuzhiyun {
3230*4882a593Smuzhiyun 	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
3231*4882a593Smuzhiyun 
3232*4882a593Smuzhiyun 	switch (event) {
3233*4882a593Smuzhiyun 	case BFA_TSKIM_SM_HCB:
3234*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
3235*4882a593Smuzhiyun 		bfa_tskim_free(tskim);
3236*4882a593Smuzhiyun 		break;
3237*4882a593Smuzhiyun 
3238*4882a593Smuzhiyun 	case BFA_TSKIM_SM_CLEANUP:
3239*4882a593Smuzhiyun 		bfa_tskim_notify_comp(tskim);
3240*4882a593Smuzhiyun 		break;
3241*4882a593Smuzhiyun 
3242*4882a593Smuzhiyun 	case BFA_TSKIM_SM_HWFAIL:
3243*4882a593Smuzhiyun 		break;
3244*4882a593Smuzhiyun 
3245*4882a593Smuzhiyun 	default:
3246*4882a593Smuzhiyun 		bfa_sm_fault(tskim->bfa, event);
3247*4882a593Smuzhiyun 	}
3248*4882a593Smuzhiyun }
3249*4882a593Smuzhiyun 
3250*4882a593Smuzhiyun static void
__bfa_cb_tskim_done(void * cbarg,bfa_boolean_t complete)3251*4882a593Smuzhiyun __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
3252*4882a593Smuzhiyun {
3253*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim = cbarg;
3254*4882a593Smuzhiyun 
3255*4882a593Smuzhiyun 	if (!complete) {
3256*4882a593Smuzhiyun 		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
3257*4882a593Smuzhiyun 		return;
3258*4882a593Smuzhiyun 	}
3259*4882a593Smuzhiyun 
3260*4882a593Smuzhiyun 	bfa_stats(tskim->itnim, tm_success);
3261*4882a593Smuzhiyun 	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
3262*4882a593Smuzhiyun }
3263*4882a593Smuzhiyun 
3264*4882a593Smuzhiyun static void
__bfa_cb_tskim_failed(void * cbarg,bfa_boolean_t complete)3265*4882a593Smuzhiyun __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
3266*4882a593Smuzhiyun {
3267*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim = cbarg;
3268*4882a593Smuzhiyun 
3269*4882a593Smuzhiyun 	if (!complete) {
3270*4882a593Smuzhiyun 		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
3271*4882a593Smuzhiyun 		return;
3272*4882a593Smuzhiyun 	}
3273*4882a593Smuzhiyun 
3274*4882a593Smuzhiyun 	bfa_stats(tskim->itnim, tm_failures);
3275*4882a593Smuzhiyun 	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
3276*4882a593Smuzhiyun 				BFI_TSKIM_STS_FAILED);
3277*4882a593Smuzhiyun }
3278*4882a593Smuzhiyun 
3279*4882a593Smuzhiyun static bfa_boolean_t
bfa_tskim_match_scope(struct bfa_tskim_s * tskim,struct scsi_lun lun)3280*4882a593Smuzhiyun bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun)
3281*4882a593Smuzhiyun {
3282*4882a593Smuzhiyun 	switch (tskim->tm_cmnd) {
3283*4882a593Smuzhiyun 	case FCP_TM_TARGET_RESET:
3284*4882a593Smuzhiyun 		return BFA_TRUE;
3285*4882a593Smuzhiyun 
3286*4882a593Smuzhiyun 	case FCP_TM_ABORT_TASK_SET:
3287*4882a593Smuzhiyun 	case FCP_TM_CLEAR_TASK_SET:
3288*4882a593Smuzhiyun 	case FCP_TM_LUN_RESET:
3289*4882a593Smuzhiyun 	case FCP_TM_CLEAR_ACA:
3290*4882a593Smuzhiyun 		return !memcmp(&tskim->lun, &lun, sizeof(lun));
3291*4882a593Smuzhiyun 
3292*4882a593Smuzhiyun 	default:
3293*4882a593Smuzhiyun 		WARN_ON(1);
3294*4882a593Smuzhiyun 	}
3295*4882a593Smuzhiyun 
3296*4882a593Smuzhiyun 	return BFA_FALSE;
3297*4882a593Smuzhiyun }
3298*4882a593Smuzhiyun 
3299*4882a593Smuzhiyun /*
3300*4882a593Smuzhiyun  * Gather affected IO requests and task management commands.
3301*4882a593Smuzhiyun  */
3302*4882a593Smuzhiyun static void
bfa_tskim_gather_ios(struct bfa_tskim_s * tskim)3303*4882a593Smuzhiyun bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
3304*4882a593Smuzhiyun {
3305*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = tskim->itnim;
3306*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
3307*4882a593Smuzhiyun 	struct list_head *qe, *qen;
3308*4882a593Smuzhiyun 	struct scsi_cmnd *cmnd;
3309*4882a593Smuzhiyun 	struct scsi_lun scsilun;
3310*4882a593Smuzhiyun 
3311*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tskim->io_q);
3312*4882a593Smuzhiyun 
3313*4882a593Smuzhiyun 	/*
3314*4882a593Smuzhiyun 	 * Gather any active IO requests first.
3315*4882a593Smuzhiyun 	 */
3316*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->io_q) {
3317*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
3318*4882a593Smuzhiyun 		cmnd = (struct scsi_cmnd *) ioim->dio;
3319*4882a593Smuzhiyun 		int_to_scsilun(cmnd->device->lun, &scsilun);
3320*4882a593Smuzhiyun 		if (bfa_tskim_match_scope(tskim, scsilun)) {
3321*4882a593Smuzhiyun 			list_del(&ioim->qe);
3322*4882a593Smuzhiyun 			list_add_tail(&ioim->qe, &tskim->io_q);
3323*4882a593Smuzhiyun 		}
3324*4882a593Smuzhiyun 	}
3325*4882a593Smuzhiyun 
3326*4882a593Smuzhiyun 	/*
3327*4882a593Smuzhiyun 	 * Failback any pending IO requests immediately.
3328*4882a593Smuzhiyun 	 */
3329*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &itnim->pending_q) {
3330*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
3331*4882a593Smuzhiyun 		cmnd = (struct scsi_cmnd *) ioim->dio;
3332*4882a593Smuzhiyun 		int_to_scsilun(cmnd->device->lun, &scsilun);
3333*4882a593Smuzhiyun 		if (bfa_tskim_match_scope(tskim, scsilun)) {
3334*4882a593Smuzhiyun 			list_del(&ioim->qe);
3335*4882a593Smuzhiyun 			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
3336*4882a593Smuzhiyun 			bfa_ioim_tov(ioim);
3337*4882a593Smuzhiyun 		}
3338*4882a593Smuzhiyun 	}
3339*4882a593Smuzhiyun }
3340*4882a593Smuzhiyun 
3341*4882a593Smuzhiyun /*
3342*4882a593Smuzhiyun  * IO cleanup completion
3343*4882a593Smuzhiyun  */
3344*4882a593Smuzhiyun static void
bfa_tskim_cleanp_comp(void * tskim_cbarg)3345*4882a593Smuzhiyun bfa_tskim_cleanp_comp(void *tskim_cbarg)
3346*4882a593Smuzhiyun {
3347*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim = tskim_cbarg;
3348*4882a593Smuzhiyun 
3349*4882a593Smuzhiyun 	bfa_stats(tskim->itnim, tm_io_comps);
3350*4882a593Smuzhiyun 	bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
3351*4882a593Smuzhiyun }
3352*4882a593Smuzhiyun 
3353*4882a593Smuzhiyun /*
3354*4882a593Smuzhiyun  * Gather affected IO requests and task management commands.
3355*4882a593Smuzhiyun  */
3356*4882a593Smuzhiyun static void
bfa_tskim_cleanup_ios(struct bfa_tskim_s * tskim)3357*4882a593Smuzhiyun bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
3358*4882a593Smuzhiyun {
3359*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
3360*4882a593Smuzhiyun 	struct list_head	*qe, *qen;
3361*4882a593Smuzhiyun 
3362*4882a593Smuzhiyun 	bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
3363*4882a593Smuzhiyun 
3364*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &tskim->io_q) {
3365*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
3366*4882a593Smuzhiyun 		bfa_wc_up(&tskim->wc);
3367*4882a593Smuzhiyun 		bfa_ioim_cleanup_tm(ioim, tskim);
3368*4882a593Smuzhiyun 	}
3369*4882a593Smuzhiyun 
3370*4882a593Smuzhiyun 	bfa_wc_wait(&tskim->wc);
3371*4882a593Smuzhiyun }
3372*4882a593Smuzhiyun 
3373*4882a593Smuzhiyun /*
3374*4882a593Smuzhiyun  * Send task management request to firmware.
3375*4882a593Smuzhiyun  */
3376*4882a593Smuzhiyun static bfa_boolean_t
bfa_tskim_send(struct bfa_tskim_s * tskim)3377*4882a593Smuzhiyun bfa_tskim_send(struct bfa_tskim_s *tskim)
3378*4882a593Smuzhiyun {
3379*4882a593Smuzhiyun 	struct bfa_itnim_s *itnim = tskim->itnim;
3380*4882a593Smuzhiyun 	struct bfi_tskim_req_s *m;
3381*4882a593Smuzhiyun 
3382*4882a593Smuzhiyun 	/*
3383*4882a593Smuzhiyun 	 * check for room in queue to send request now
3384*4882a593Smuzhiyun 	 */
3385*4882a593Smuzhiyun 	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
3386*4882a593Smuzhiyun 	if (!m)
3387*4882a593Smuzhiyun 		return BFA_FALSE;
3388*4882a593Smuzhiyun 
3389*4882a593Smuzhiyun 	/*
3390*4882a593Smuzhiyun 	 * build i/o request message next
3391*4882a593Smuzhiyun 	 */
3392*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
3393*4882a593Smuzhiyun 			bfa_fn_lpu(tskim->bfa));
3394*4882a593Smuzhiyun 
3395*4882a593Smuzhiyun 	m->tsk_tag = cpu_to_be16(tskim->tsk_tag);
3396*4882a593Smuzhiyun 	m->itn_fhdl = tskim->itnim->rport->fw_handle;
3397*4882a593Smuzhiyun 	m->t_secs = tskim->tsecs;
3398*4882a593Smuzhiyun 	m->lun = tskim->lun;
3399*4882a593Smuzhiyun 	m->tm_flags = tskim->tm_cmnd;
3400*4882a593Smuzhiyun 
3401*4882a593Smuzhiyun 	/*
3402*4882a593Smuzhiyun 	 * queue I/O message to firmware
3403*4882a593Smuzhiyun 	 */
3404*4882a593Smuzhiyun 	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
3405*4882a593Smuzhiyun 	return BFA_TRUE;
3406*4882a593Smuzhiyun }
3407*4882a593Smuzhiyun 
3408*4882a593Smuzhiyun /*
3409*4882a593Smuzhiyun  * Send abort request to cleanup an active TM to firmware.
3410*4882a593Smuzhiyun  */
3411*4882a593Smuzhiyun static bfa_boolean_t
bfa_tskim_send_abort(struct bfa_tskim_s * tskim)3412*4882a593Smuzhiyun bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
3413*4882a593Smuzhiyun {
3414*4882a593Smuzhiyun 	struct bfa_itnim_s	*itnim = tskim->itnim;
3415*4882a593Smuzhiyun 	struct bfi_tskim_abortreq_s	*m;
3416*4882a593Smuzhiyun 
3417*4882a593Smuzhiyun 	/*
3418*4882a593Smuzhiyun 	 * check for room in queue to send request now
3419*4882a593Smuzhiyun 	 */
3420*4882a593Smuzhiyun 	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
3421*4882a593Smuzhiyun 	if (!m)
3422*4882a593Smuzhiyun 		return BFA_FALSE;
3423*4882a593Smuzhiyun 
3424*4882a593Smuzhiyun 	/*
3425*4882a593Smuzhiyun 	 * build i/o request message next
3426*4882a593Smuzhiyun 	 */
3427*4882a593Smuzhiyun 	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
3428*4882a593Smuzhiyun 			bfa_fn_lpu(tskim->bfa));
3429*4882a593Smuzhiyun 
3430*4882a593Smuzhiyun 	m->tsk_tag  = cpu_to_be16(tskim->tsk_tag);
3431*4882a593Smuzhiyun 
3432*4882a593Smuzhiyun 	/*
3433*4882a593Smuzhiyun 	 * queue I/O message to firmware
3434*4882a593Smuzhiyun 	 */
3435*4882a593Smuzhiyun 	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
3436*4882a593Smuzhiyun 	return BFA_TRUE;
3437*4882a593Smuzhiyun }
3438*4882a593Smuzhiyun 
3439*4882a593Smuzhiyun /*
3440*4882a593Smuzhiyun  * Call to resume task management cmnd waiting for room in request queue.
3441*4882a593Smuzhiyun  */
3442*4882a593Smuzhiyun static void
bfa_tskim_qresume(void * cbarg)3443*4882a593Smuzhiyun bfa_tskim_qresume(void *cbarg)
3444*4882a593Smuzhiyun {
3445*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim = cbarg;
3446*4882a593Smuzhiyun 
3447*4882a593Smuzhiyun 	bfa_stats(tskim->itnim, tm_qresumes);
3448*4882a593Smuzhiyun 	bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
3449*4882a593Smuzhiyun }
3450*4882a593Smuzhiyun 
3451*4882a593Smuzhiyun /*
3452*4882a593Smuzhiyun  * Cleanup IOs associated with a task mangement command on IOC failures.
3453*4882a593Smuzhiyun  */
3454*4882a593Smuzhiyun static void
bfa_tskim_iocdisable_ios(struct bfa_tskim_s * tskim)3455*4882a593Smuzhiyun bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
3456*4882a593Smuzhiyun {
3457*4882a593Smuzhiyun 	struct bfa_ioim_s *ioim;
3458*4882a593Smuzhiyun 	struct list_head	*qe, *qen;
3459*4882a593Smuzhiyun 
3460*4882a593Smuzhiyun 	list_for_each_safe(qe, qen, &tskim->io_q) {
3461*4882a593Smuzhiyun 		ioim = (struct bfa_ioim_s *) qe;
3462*4882a593Smuzhiyun 		bfa_ioim_iocdisable(ioim);
3463*4882a593Smuzhiyun 	}
3464*4882a593Smuzhiyun }
3465*4882a593Smuzhiyun 
3466*4882a593Smuzhiyun /*
3467*4882a593Smuzhiyun  * Notification on completions from related ioim.
3468*4882a593Smuzhiyun  */
3469*4882a593Smuzhiyun void
bfa_tskim_iodone(struct bfa_tskim_s * tskim)3470*4882a593Smuzhiyun bfa_tskim_iodone(struct bfa_tskim_s *tskim)
3471*4882a593Smuzhiyun {
3472*4882a593Smuzhiyun 	bfa_wc_down(&tskim->wc);
3473*4882a593Smuzhiyun }
3474*4882a593Smuzhiyun 
3475*4882a593Smuzhiyun /*
3476*4882a593Smuzhiyun  * Handle IOC h/w failure notification from itnim.
3477*4882a593Smuzhiyun  */
3478*4882a593Smuzhiyun void
bfa_tskim_iocdisable(struct bfa_tskim_s * tskim)3479*4882a593Smuzhiyun bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
3480*4882a593Smuzhiyun {
3481*4882a593Smuzhiyun 	tskim->notify = BFA_FALSE;
3482*4882a593Smuzhiyun 	bfa_stats(tskim->itnim, tm_iocdowns);
3483*4882a593Smuzhiyun 	bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
3484*4882a593Smuzhiyun }
3485*4882a593Smuzhiyun 
3486*4882a593Smuzhiyun /*
3487*4882a593Smuzhiyun  * Cleanup TM command and associated IOs as part of ITNIM offline.
3488*4882a593Smuzhiyun  */
3489*4882a593Smuzhiyun void
bfa_tskim_cleanup(struct bfa_tskim_s * tskim)3490*4882a593Smuzhiyun bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
3491*4882a593Smuzhiyun {
3492*4882a593Smuzhiyun 	tskim->notify = BFA_TRUE;
3493*4882a593Smuzhiyun 	bfa_stats(tskim->itnim, tm_cleanups);
3494*4882a593Smuzhiyun 	bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
3495*4882a593Smuzhiyun }
3496*4882a593Smuzhiyun 
3497*4882a593Smuzhiyun /*
3498*4882a593Smuzhiyun  * Memory allocation and initialization.
3499*4882a593Smuzhiyun  */
3500*4882a593Smuzhiyun void
bfa_tskim_attach(struct bfa_fcpim_s * fcpim)3501*4882a593Smuzhiyun bfa_tskim_attach(struct bfa_fcpim_s *fcpim)
3502*4882a593Smuzhiyun {
3503*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim;
3504*4882a593Smuzhiyun 	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;
3505*4882a593Smuzhiyun 	u16	i;
3506*4882a593Smuzhiyun 
3507*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcpim->tskim_free_q);
3508*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcpim->tskim_unused_q);
3509*4882a593Smuzhiyun 
3510*4882a593Smuzhiyun 	tskim = (struct bfa_tskim_s *) bfa_mem_kva_curp(fcp);
3511*4882a593Smuzhiyun 	fcpim->tskim_arr = tskim;
3512*4882a593Smuzhiyun 
3513*4882a593Smuzhiyun 	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
3514*4882a593Smuzhiyun 		/*
3515*4882a593Smuzhiyun 		 * initialize TSKIM
3516*4882a593Smuzhiyun 		 */
3517*4882a593Smuzhiyun 		memset(tskim, 0, sizeof(struct bfa_tskim_s));
3518*4882a593Smuzhiyun 		tskim->tsk_tag = i;
3519*4882a593Smuzhiyun 		tskim->bfa	= fcpim->bfa;
3520*4882a593Smuzhiyun 		tskim->fcpim	= fcpim;
3521*4882a593Smuzhiyun 		tskim->notify  = BFA_FALSE;
3522*4882a593Smuzhiyun 		bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
3523*4882a593Smuzhiyun 					tskim);
3524*4882a593Smuzhiyun 		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
3525*4882a593Smuzhiyun 
3526*4882a593Smuzhiyun 		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
3527*4882a593Smuzhiyun 	}
3528*4882a593Smuzhiyun 
3529*4882a593Smuzhiyun 	bfa_mem_kva_curp(fcp) = (u8 *) tskim;
3530*4882a593Smuzhiyun }
3531*4882a593Smuzhiyun 
3532*4882a593Smuzhiyun void
bfa_tskim_isr(struct bfa_s * bfa,struct bfi_msg_s * m)3533*4882a593Smuzhiyun bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
3534*4882a593Smuzhiyun {
3535*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
3536*4882a593Smuzhiyun 	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
3537*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim;
3538*4882a593Smuzhiyun 	u16	tsk_tag = be16_to_cpu(rsp->tsk_tag);
3539*4882a593Smuzhiyun 
3540*4882a593Smuzhiyun 	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
3541*4882a593Smuzhiyun 	WARN_ON(tskim->tsk_tag != tsk_tag);
3542*4882a593Smuzhiyun 
3543*4882a593Smuzhiyun 	tskim->tsk_status = rsp->tsk_status;
3544*4882a593Smuzhiyun 
3545*4882a593Smuzhiyun 	/*
3546*4882a593Smuzhiyun 	 * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
3547*4882a593Smuzhiyun 	 * requests. All other statuses are for normal completions.
3548*4882a593Smuzhiyun 	 */
3549*4882a593Smuzhiyun 	if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
3550*4882a593Smuzhiyun 		bfa_stats(tskim->itnim, tm_cleanup_comps);
3551*4882a593Smuzhiyun 		bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
3552*4882a593Smuzhiyun 	} else if (rsp->tsk_status == BFI_TSKIM_STS_UTAG) {
3553*4882a593Smuzhiyun 		bfa_sm_send_event(tskim, BFA_TSKIM_SM_UTAG);
3554*4882a593Smuzhiyun 	} else {
3555*4882a593Smuzhiyun 		bfa_stats(tskim->itnim, tm_fw_rsps);
3556*4882a593Smuzhiyun 		bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
3557*4882a593Smuzhiyun 	}
3558*4882a593Smuzhiyun }
3559*4882a593Smuzhiyun 
3560*4882a593Smuzhiyun 
3561*4882a593Smuzhiyun struct bfa_tskim_s *
bfa_tskim_alloc(struct bfa_s * bfa,struct bfad_tskim_s * dtsk)3562*4882a593Smuzhiyun bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
3563*4882a593Smuzhiyun {
3564*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
3565*4882a593Smuzhiyun 	struct bfa_tskim_s *tskim;
3566*4882a593Smuzhiyun 
3567*4882a593Smuzhiyun 	bfa_q_deq(&fcpim->tskim_free_q, &tskim);
3568*4882a593Smuzhiyun 
3569*4882a593Smuzhiyun 	if (tskim)
3570*4882a593Smuzhiyun 		tskim->dtsk = dtsk;
3571*4882a593Smuzhiyun 
3572*4882a593Smuzhiyun 	return tskim;
3573*4882a593Smuzhiyun }
3574*4882a593Smuzhiyun 
3575*4882a593Smuzhiyun void
bfa_tskim_free(struct bfa_tskim_s * tskim)3576*4882a593Smuzhiyun bfa_tskim_free(struct bfa_tskim_s *tskim)
3577*4882a593Smuzhiyun {
3578*4882a593Smuzhiyun 	WARN_ON(!bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
3579*4882a593Smuzhiyun 	list_del(&tskim->qe);
3580*4882a593Smuzhiyun 	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
3581*4882a593Smuzhiyun }
3582*4882a593Smuzhiyun 
3583*4882a593Smuzhiyun /*
3584*4882a593Smuzhiyun  * Start a task management command.
3585*4882a593Smuzhiyun  *
3586*4882a593Smuzhiyun  * @param[in]	tskim	BFA task management command instance
3587*4882a593Smuzhiyun  * @param[in]	itnim	i-t nexus for the task management command
3588*4882a593Smuzhiyun  * @param[in]	lun	lun, if applicable
3589*4882a593Smuzhiyun  * @param[in]	tm_cmnd	Task management command code.
3590*4882a593Smuzhiyun  * @param[in]	t_secs	Timeout in seconds
3591*4882a593Smuzhiyun  *
3592*4882a593Smuzhiyun  * @return None.
3593*4882a593Smuzhiyun  */
3594*4882a593Smuzhiyun void
bfa_tskim_start(struct bfa_tskim_s * tskim,struct bfa_itnim_s * itnim,struct scsi_lun lun,enum fcp_tm_cmnd tm_cmnd,u8 tsecs)3595*4882a593Smuzhiyun bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim,
3596*4882a593Smuzhiyun 			struct scsi_lun lun,
3597*4882a593Smuzhiyun 			enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
3598*4882a593Smuzhiyun {
3599*4882a593Smuzhiyun 	tskim->itnim	= itnim;
3600*4882a593Smuzhiyun 	tskim->lun	= lun;
3601*4882a593Smuzhiyun 	tskim->tm_cmnd = tm_cmnd;
3602*4882a593Smuzhiyun 	tskim->tsecs	= tsecs;
3603*4882a593Smuzhiyun 	tskim->notify  = BFA_FALSE;
3604*4882a593Smuzhiyun 	bfa_stats(itnim, tm_cmnds);
3605*4882a593Smuzhiyun 
3606*4882a593Smuzhiyun 	list_add_tail(&tskim->qe, &itnim->tsk_q);
3607*4882a593Smuzhiyun 	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
3608*4882a593Smuzhiyun }
3609*4882a593Smuzhiyun 
3610*4882a593Smuzhiyun void
bfa_tskim_res_recfg(struct bfa_s * bfa,u16 num_tskim_fw)3611*4882a593Smuzhiyun bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw)
3612*4882a593Smuzhiyun {
3613*4882a593Smuzhiyun 	struct bfa_fcpim_s	*fcpim = BFA_FCPIM(bfa);
3614*4882a593Smuzhiyun 	struct list_head	*qe;
3615*4882a593Smuzhiyun 	int	i;
3616*4882a593Smuzhiyun 
3617*4882a593Smuzhiyun 	for (i = 0; i < (fcpim->num_tskim_reqs - num_tskim_fw); i++) {
3618*4882a593Smuzhiyun 		bfa_q_deq_tail(&fcpim->tskim_free_q, &qe);
3619*4882a593Smuzhiyun 		list_add_tail(qe, &fcpim->tskim_unused_q);
3620*4882a593Smuzhiyun 	}
3621*4882a593Smuzhiyun }
3622*4882a593Smuzhiyun 
3623*4882a593Smuzhiyun void
bfa_fcp_meminfo(struct bfa_iocfc_cfg_s * cfg,struct bfa_meminfo_s * minfo,struct bfa_s * bfa)3624*4882a593Smuzhiyun bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
3625*4882a593Smuzhiyun 		struct bfa_s *bfa)
3626*4882a593Smuzhiyun {
3627*4882a593Smuzhiyun 	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
3628*4882a593Smuzhiyun 	struct bfa_mem_kva_s *fcp_kva = BFA_MEM_FCP_KVA(bfa);
3629*4882a593Smuzhiyun 	struct bfa_mem_dma_s *seg_ptr;
3630*4882a593Smuzhiyun 	u16	nsegs, idx, per_seg_ios, num_io_req;
3631*4882a593Smuzhiyun 	u32	km_len = 0;
3632*4882a593Smuzhiyun 
3633*4882a593Smuzhiyun 	/*
3634*4882a593Smuzhiyun 	 * ZERO for num_ioim_reqs and num_fwtio_reqs is allowed config value.
3635*4882a593Smuzhiyun 	 * So if the values are non zero, adjust them appropriately.
3636*4882a593Smuzhiyun 	 */
3637*4882a593Smuzhiyun 	if (cfg->fwcfg.num_ioim_reqs &&
3638*4882a593Smuzhiyun 	    cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
3639*4882a593Smuzhiyun 		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
3640*4882a593Smuzhiyun 	else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
3641*4882a593Smuzhiyun 		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
3642*4882a593Smuzhiyun 
3643*4882a593Smuzhiyun 	if (cfg->fwcfg.num_fwtio_reqs > BFA_FWTIO_MAX)
3644*4882a593Smuzhiyun 		cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
3645*4882a593Smuzhiyun 
3646*4882a593Smuzhiyun 	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
3647*4882a593Smuzhiyun 	if (num_io_req > BFA_IO_MAX) {
3648*4882a593Smuzhiyun 		if (cfg->fwcfg.num_ioim_reqs && cfg->fwcfg.num_fwtio_reqs) {
3649*4882a593Smuzhiyun 			cfg->fwcfg.num_ioim_reqs = BFA_IO_MAX/2;
3650*4882a593Smuzhiyun 			cfg->fwcfg.num_fwtio_reqs = BFA_IO_MAX/2;
3651*4882a593Smuzhiyun 		} else if (cfg->fwcfg.num_fwtio_reqs)
3652*4882a593Smuzhiyun 			cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
3653*4882a593Smuzhiyun 		else
3654*4882a593Smuzhiyun 			cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
3655*4882a593Smuzhiyun 	}
3656*4882a593Smuzhiyun 
3657*4882a593Smuzhiyun 	bfa_fcpim_meminfo(cfg, &km_len);
3658*4882a593Smuzhiyun 
3659*4882a593Smuzhiyun 	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
3660*4882a593Smuzhiyun 	km_len += num_io_req * sizeof(struct bfa_iotag_s);
3661*4882a593Smuzhiyun 	km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itn_s);
3662*4882a593Smuzhiyun 
3663*4882a593Smuzhiyun 	/* dma memory */
3664*4882a593Smuzhiyun 	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
3665*4882a593Smuzhiyun 	per_seg_ios = BFI_MEM_NREQS_SEG(BFI_IOIM_SNSLEN);
3666*4882a593Smuzhiyun 
3667*4882a593Smuzhiyun 	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
3668*4882a593Smuzhiyun 		if (num_io_req >= per_seg_ios) {
3669*4882a593Smuzhiyun 			num_io_req -= per_seg_ios;
3670*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
3671*4882a593Smuzhiyun 				per_seg_ios * BFI_IOIM_SNSLEN);
3672*4882a593Smuzhiyun 		} else
3673*4882a593Smuzhiyun 			bfa_mem_dma_setup(minfo, seg_ptr,
3674*4882a593Smuzhiyun 				num_io_req * BFI_IOIM_SNSLEN);
3675*4882a593Smuzhiyun 	}
3676*4882a593Smuzhiyun 
3677*4882a593Smuzhiyun 	/* kva memory */
3678*4882a593Smuzhiyun 	bfa_mem_kva_setup(minfo, fcp_kva, km_len);
3679*4882a593Smuzhiyun }
3680*4882a593Smuzhiyun 
3681*4882a593Smuzhiyun void
bfa_fcp_attach(struct bfa_s * bfa,void * bfad,struct bfa_iocfc_cfg_s * cfg,struct bfa_pcidev_s * pcidev)3682*4882a593Smuzhiyun bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
3683*4882a593Smuzhiyun 		struct bfa_pcidev_s *pcidev)
3684*4882a593Smuzhiyun {
3685*4882a593Smuzhiyun 	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
3686*4882a593Smuzhiyun 	struct bfa_mem_dma_s *seg_ptr;
3687*4882a593Smuzhiyun 	u16	idx, nsegs, num_io_req;
3688*4882a593Smuzhiyun 
3689*4882a593Smuzhiyun 	fcp->max_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
3690*4882a593Smuzhiyun 	fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
3691*4882a593Smuzhiyun 	fcp->num_fwtio_reqs  = cfg->fwcfg.num_fwtio_reqs;
3692*4882a593Smuzhiyun 	fcp->num_itns   = cfg->fwcfg.num_rports;
3693*4882a593Smuzhiyun 	fcp->bfa = bfa;
3694*4882a593Smuzhiyun 
3695*4882a593Smuzhiyun 	/*
3696*4882a593Smuzhiyun 	 * Setup the pool of snsbase addr's, that is passed to fw as
3697*4882a593Smuzhiyun 	 * part of bfi_iocfc_cfg_s.
3698*4882a593Smuzhiyun 	 */
3699*4882a593Smuzhiyun 	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
3700*4882a593Smuzhiyun 	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
3701*4882a593Smuzhiyun 
3702*4882a593Smuzhiyun 	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
3703*4882a593Smuzhiyun 
3704*4882a593Smuzhiyun 		if (!bfa_mem_dma_virt(seg_ptr))
3705*4882a593Smuzhiyun 			break;
3706*4882a593Smuzhiyun 
3707*4882a593Smuzhiyun 		fcp->snsbase[idx].pa = bfa_mem_dma_phys(seg_ptr);
3708*4882a593Smuzhiyun 		fcp->snsbase[idx].kva = bfa_mem_dma_virt(seg_ptr);
3709*4882a593Smuzhiyun 		bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
3710*4882a593Smuzhiyun 	}
3711*4882a593Smuzhiyun 
3712*4882a593Smuzhiyun 	fcp->throttle_update_required = 1;
3713*4882a593Smuzhiyun 	bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
3714*4882a593Smuzhiyun 
3715*4882a593Smuzhiyun 	bfa_iotag_attach(fcp);
3716*4882a593Smuzhiyun 
3717*4882a593Smuzhiyun 	fcp->itn_arr = (struct bfa_itn_s *) bfa_mem_kva_curp(fcp);
3718*4882a593Smuzhiyun 	bfa_mem_kva_curp(fcp) = (u8 *)fcp->itn_arr +
3719*4882a593Smuzhiyun 			(fcp->num_itns * sizeof(struct bfa_itn_s));
3720*4882a593Smuzhiyun 	memset(fcp->itn_arr, 0,
3721*4882a593Smuzhiyun 			(fcp->num_itns * sizeof(struct bfa_itn_s)));
3722*4882a593Smuzhiyun }
3723*4882a593Smuzhiyun 
3724*4882a593Smuzhiyun void
bfa_fcp_iocdisable(struct bfa_s * bfa)3725*4882a593Smuzhiyun bfa_fcp_iocdisable(struct bfa_s *bfa)
3726*4882a593Smuzhiyun {
3727*4882a593Smuzhiyun 	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
3728*4882a593Smuzhiyun 
3729*4882a593Smuzhiyun 	bfa_fcpim_iocdisable(fcp);
3730*4882a593Smuzhiyun }
3731*4882a593Smuzhiyun 
3732*4882a593Smuzhiyun void
bfa_fcp_res_recfg(struct bfa_s * bfa,u16 num_ioim_fw,u16 max_ioim_fw)3733*4882a593Smuzhiyun bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw)
3734*4882a593Smuzhiyun {
3735*4882a593Smuzhiyun 	struct bfa_fcp_mod_s	*mod = BFA_FCP_MOD(bfa);
3736*4882a593Smuzhiyun 	struct list_head	*qe;
3737*4882a593Smuzhiyun 	int	i;
3738*4882a593Smuzhiyun 
3739*4882a593Smuzhiyun 	/* Update io throttle value only once during driver load time */
3740*4882a593Smuzhiyun 	if (!mod->throttle_update_required)
3741*4882a593Smuzhiyun 		return;
3742*4882a593Smuzhiyun 
3743*4882a593Smuzhiyun 	for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
3744*4882a593Smuzhiyun 		bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
3745*4882a593Smuzhiyun 		list_add_tail(qe, &mod->iotag_unused_q);
3746*4882a593Smuzhiyun 	}
3747*4882a593Smuzhiyun 
3748*4882a593Smuzhiyun 	if (mod->num_ioim_reqs != num_ioim_fw) {
3749*4882a593Smuzhiyun 		bfa_trc(bfa, mod->num_ioim_reqs);
3750*4882a593Smuzhiyun 		bfa_trc(bfa, num_ioim_fw);
3751*4882a593Smuzhiyun 	}
3752*4882a593Smuzhiyun 
3753*4882a593Smuzhiyun 	mod->max_ioim_reqs = max_ioim_fw;
3754*4882a593Smuzhiyun 	mod->num_ioim_reqs = num_ioim_fw;
3755*4882a593Smuzhiyun 	mod->throttle_update_required = 0;
3756*4882a593Smuzhiyun }
3757*4882a593Smuzhiyun 
3758*4882a593Smuzhiyun void
bfa_itn_create(struct bfa_s * bfa,struct bfa_rport_s * rport,void (* isr)(struct bfa_s * bfa,struct bfi_msg_s * m))3759*4882a593Smuzhiyun bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
3760*4882a593Smuzhiyun 		void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m))
3761*4882a593Smuzhiyun {
3762*4882a593Smuzhiyun 	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
3763*4882a593Smuzhiyun 	struct bfa_itn_s *itn;
3764*4882a593Smuzhiyun 
3765*4882a593Smuzhiyun 	itn =  BFA_ITN_FROM_TAG(fcp, rport->rport_tag);
3766*4882a593Smuzhiyun 	itn->isr = isr;
3767*4882a593Smuzhiyun }
3768*4882a593Smuzhiyun 
3769*4882a593Smuzhiyun /*
3770*4882a593Smuzhiyun  * Itn interrupt processing.
3771*4882a593Smuzhiyun  */
3772*4882a593Smuzhiyun void
bfa_itn_isr(struct bfa_s * bfa,struct bfi_msg_s * m)3773*4882a593Smuzhiyun bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
3774*4882a593Smuzhiyun {
3775*4882a593Smuzhiyun 	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
3776*4882a593Smuzhiyun 	union bfi_itn_i2h_msg_u msg;
3777*4882a593Smuzhiyun 	struct bfa_itn_s *itn;
3778*4882a593Smuzhiyun 
3779*4882a593Smuzhiyun 	msg.msg = m;
3780*4882a593Smuzhiyun 	itn =  BFA_ITN_FROM_TAG(fcp, msg.create_rsp->bfa_handle);
3781*4882a593Smuzhiyun 
3782*4882a593Smuzhiyun 	if (itn->isr)
3783*4882a593Smuzhiyun 		itn->isr(bfa, m);
3784*4882a593Smuzhiyun 	else
3785*4882a593Smuzhiyun 		WARN_ON(1);
3786*4882a593Smuzhiyun }
3787*4882a593Smuzhiyun 
3788*4882a593Smuzhiyun void
bfa_iotag_attach(struct bfa_fcp_mod_s * fcp)3789*4882a593Smuzhiyun bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
3790*4882a593Smuzhiyun {
3791*4882a593Smuzhiyun 	struct bfa_iotag_s *iotag;
3792*4882a593Smuzhiyun 	u16	num_io_req, i;
3793*4882a593Smuzhiyun 
3794*4882a593Smuzhiyun 	iotag = (struct bfa_iotag_s *) bfa_mem_kva_curp(fcp);
3795*4882a593Smuzhiyun 	fcp->iotag_arr = iotag;
3796*4882a593Smuzhiyun 
3797*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcp->iotag_ioim_free_q);
3798*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcp->iotag_tio_free_q);
3799*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fcp->iotag_unused_q);
3800*4882a593Smuzhiyun 
3801*4882a593Smuzhiyun 	num_io_req = fcp->num_ioim_reqs + fcp->num_fwtio_reqs;
3802*4882a593Smuzhiyun 	for (i = 0; i < num_io_req; i++, iotag++) {
3803*4882a593Smuzhiyun 		memset(iotag, 0, sizeof(struct bfa_iotag_s));
3804*4882a593Smuzhiyun 		iotag->tag = i;
3805*4882a593Smuzhiyun 		if (i < fcp->num_ioim_reqs)
3806*4882a593Smuzhiyun 			list_add_tail(&iotag->qe, &fcp->iotag_ioim_free_q);
3807*4882a593Smuzhiyun 		else
3808*4882a593Smuzhiyun 			list_add_tail(&iotag->qe, &fcp->iotag_tio_free_q);
3809*4882a593Smuzhiyun 	}
3810*4882a593Smuzhiyun 
3811*4882a593Smuzhiyun 	bfa_mem_kva_curp(fcp) = (u8 *) iotag;
3812*4882a593Smuzhiyun }
3813*4882a593Smuzhiyun 
3814*4882a593Smuzhiyun 
3815*4882a593Smuzhiyun /*
3816*4882a593Smuzhiyun  * To send config req, first try to use throttle value from flash
3817*4882a593Smuzhiyun  * If 0, then use driver parameter
3818*4882a593Smuzhiyun  * We need to use min(flash_val, drv_val) because
3819*4882a593Smuzhiyun  * memory allocation was done based on this cfg'd value
3820*4882a593Smuzhiyun  */
3821*4882a593Smuzhiyun u16
bfa_fcpim_get_throttle_cfg(struct bfa_s * bfa,u16 drv_cfg_param)3822*4882a593Smuzhiyun bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param)
3823*4882a593Smuzhiyun {
3824*4882a593Smuzhiyun 	u16 tmp;
3825*4882a593Smuzhiyun 	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
3826*4882a593Smuzhiyun 
3827*4882a593Smuzhiyun 	/*
3828*4882a593Smuzhiyun 	 * If throttle value from flash is already in effect after driver is
3829*4882a593Smuzhiyun 	 * loaded then until next load, always return current value instead
3830*4882a593Smuzhiyun 	 * of actual flash value
3831*4882a593Smuzhiyun 	 */
3832*4882a593Smuzhiyun 	if (!fcp->throttle_update_required)
3833*4882a593Smuzhiyun 		return (u16)fcp->num_ioim_reqs;
3834*4882a593Smuzhiyun 
3835*4882a593Smuzhiyun 	tmp = bfa_dconf_read_data_valid(bfa) ? bfa_fcpim_read_throttle(bfa) : 0;
3836*4882a593Smuzhiyun 	if (!tmp || (tmp > drv_cfg_param))
3837*4882a593Smuzhiyun 		tmp = drv_cfg_param;
3838*4882a593Smuzhiyun 
3839*4882a593Smuzhiyun 	return tmp;
3840*4882a593Smuzhiyun }
3841*4882a593Smuzhiyun 
3842*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_write_throttle(struct bfa_s * bfa,u16 value)3843*4882a593Smuzhiyun bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value)
3844*4882a593Smuzhiyun {
3845*4882a593Smuzhiyun 	if (!bfa_dconf_get_min_cfg(bfa)) {
3846*4882a593Smuzhiyun 		BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.value = value;
3847*4882a593Smuzhiyun 		BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.is_valid = 1;
3848*4882a593Smuzhiyun 		return BFA_STATUS_OK;
3849*4882a593Smuzhiyun 	}
3850*4882a593Smuzhiyun 
3851*4882a593Smuzhiyun 	return BFA_STATUS_FAILED;
3852*4882a593Smuzhiyun }
3853*4882a593Smuzhiyun 
3854*4882a593Smuzhiyun u16
bfa_fcpim_read_throttle(struct bfa_s * bfa)3855*4882a593Smuzhiyun bfa_fcpim_read_throttle(struct bfa_s *bfa)
3856*4882a593Smuzhiyun {
3857*4882a593Smuzhiyun 	struct bfa_throttle_cfg_s *throttle_cfg =
3858*4882a593Smuzhiyun 			&(BFA_DCONF_MOD(bfa)->dconf->throttle_cfg);
3859*4882a593Smuzhiyun 
3860*4882a593Smuzhiyun 	return ((!bfa_dconf_get_min_cfg(bfa)) ?
3861*4882a593Smuzhiyun 	       ((throttle_cfg->is_valid == 1) ? (throttle_cfg->value) : 0) : 0);
3862*4882a593Smuzhiyun }
3863*4882a593Smuzhiyun 
3864*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_throttle_set(struct bfa_s * bfa,u16 value)3865*4882a593Smuzhiyun bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value)
3866*4882a593Smuzhiyun {
3867*4882a593Smuzhiyun 	/* in min cfg no commands should run. */
3868*4882a593Smuzhiyun 	if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
3869*4882a593Smuzhiyun 	    (!bfa_dconf_read_data_valid(bfa)))
3870*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
3871*4882a593Smuzhiyun 
3872*4882a593Smuzhiyun 	bfa_fcpim_write_throttle(bfa, value);
3873*4882a593Smuzhiyun 
3874*4882a593Smuzhiyun 	return bfa_dconf_update(bfa);
3875*4882a593Smuzhiyun }
3876*4882a593Smuzhiyun 
3877*4882a593Smuzhiyun bfa_status_t
bfa_fcpim_throttle_get(struct bfa_s * bfa,void * buf)3878*4882a593Smuzhiyun bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf)
3879*4882a593Smuzhiyun {
3880*4882a593Smuzhiyun 	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
3881*4882a593Smuzhiyun 	struct bfa_defs_fcpim_throttle_s throttle;
3882*4882a593Smuzhiyun 
3883*4882a593Smuzhiyun 	if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
3884*4882a593Smuzhiyun 	    (!bfa_dconf_read_data_valid(bfa)))
3885*4882a593Smuzhiyun 		return BFA_STATUS_FAILED;
3886*4882a593Smuzhiyun 
3887*4882a593Smuzhiyun 	memset(&throttle, 0, sizeof(struct bfa_defs_fcpim_throttle_s));
3888*4882a593Smuzhiyun 
3889*4882a593Smuzhiyun 	throttle.cur_value = (u16)(fcpim->fcp->num_ioim_reqs);
3890*4882a593Smuzhiyun 	throttle.cfg_value = bfa_fcpim_read_throttle(bfa);
3891*4882a593Smuzhiyun 	if (!throttle.cfg_value)
3892*4882a593Smuzhiyun 		throttle.cfg_value = throttle.cur_value;
3893*4882a593Smuzhiyun 	throttle.max_value = (u16)(fcpim->fcp->max_ioim_reqs);
3894*4882a593Smuzhiyun 	memcpy(buf, &throttle, sizeof(struct bfa_defs_fcpim_throttle_s));
3895*4882a593Smuzhiyun 
3896*4882a593Smuzhiyun 	return BFA_STATUS_OK;
3897*4882a593Smuzhiyun }
3898