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