• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/scsi/bfa/
1/*
2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 */
17
18#include <bfa.h>
19#include <cs/bfa_debug.h>
20#include <bfa_cb_ioim_macros.h>
21
22BFA_TRC_FILE(HAL, IOIM);
23
24/*
25 * forward declarations.
26 */
27static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
28static bfa_boolean_t	bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
29static void		bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
30static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
31static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
32static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
33static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
34static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
35static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
36static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
37
38/**
39 *  bfa_ioim_sm
40 */
41
42/**
43 * IO state machine events
44 */
45enum bfa_ioim_event {
46	BFA_IOIM_SM_START = 1,		/*  io start request from host */
47	BFA_IOIM_SM_COMP_GOOD = 2,	/*  io good comp, resource free */
48	BFA_IOIM_SM_COMP = 3,		/*  io comp, resource is free */
49	BFA_IOIM_SM_COMP_UTAG = 4,	/*  io comp, resource is free */
50	BFA_IOIM_SM_DONE = 5,		/*  io comp, resource not free */
51	BFA_IOIM_SM_FREE = 6,		/*  io resource is freed */
52	BFA_IOIM_SM_ABORT = 7,		/*  abort request from scsi stack */
53	BFA_IOIM_SM_ABORT_COMP = 8,	/*  abort from f/w */
54	BFA_IOIM_SM_ABORT_DONE = 9,	/*  abort completion from f/w */
55	BFA_IOIM_SM_QRESUME = 10,	/*  CQ space available to queue IO */
56	BFA_IOIM_SM_SGALLOCED = 11,	/*  SG page allocation successful */
57	BFA_IOIM_SM_SQRETRY = 12,	/*  sequence recovery retry */
58	BFA_IOIM_SM_HCB	= 13,		/*  bfa callback complete */
59	BFA_IOIM_SM_CLEANUP = 14,	/*  IO cleanup from itnim */
60	BFA_IOIM_SM_TMSTART = 15,	/*  IO cleanup from tskim */
61	BFA_IOIM_SM_TMDONE = 16,	/*  IO cleanup from tskim */
62	BFA_IOIM_SM_HWFAIL = 17,	/*  IOC h/w failure event */
63	BFA_IOIM_SM_IOTOV = 18,		/*  ITN offline TOV       */
64};
65
66/*
67 * forward declaration of IO state machine
68 */
69static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
70				       enum bfa_ioim_event event);
71static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
72					enum bfa_ioim_event event);
73static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
74				       enum bfa_ioim_event event);
75static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
76				      enum bfa_ioim_event event);
77static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
78					enum bfa_ioim_event event);
79static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
80				      enum bfa_ioim_event event);
81static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
82					    enum bfa_ioim_event event);
83static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
84					      enum bfa_ioim_event event);
85static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
86				    enum bfa_ioim_event event);
87static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
88					 enum bfa_ioim_event event);
89static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
90					enum bfa_ioim_event event);
91
92/**
93 * 		IO is not started (unallocated).
94 */
95static void
96bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
97{
98	bfa_trc_fp(ioim->bfa, ioim->iotag);
99	bfa_trc_fp(ioim->bfa, event);
100
101	switch (event) {
102	case BFA_IOIM_SM_START:
103		if (!bfa_itnim_is_online(ioim->itnim)) {
104			if (!bfa_itnim_hold_io(ioim->itnim)) {
105				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
106				list_del(&ioim->qe);
107				list_add_tail(&ioim->qe,
108						&ioim->fcpim->ioim_comp_q);
109				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
110						__bfa_cb_ioim_pathtov, ioim);
111			} else {
112				list_del(&ioim->qe);
113				list_add_tail(&ioim->qe,
114						&ioim->itnim->pending_q);
115			}
116			break;
117		}
118
119		if (ioim->nsges > BFI_SGE_INLINE) {
120			if (!bfa_ioim_sge_setup(ioim)) {
121				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
122				return;
123			}
124		}
125
126		if (!bfa_ioim_send_ioreq(ioim)) {
127			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
128			break;
129		}
130
131		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
132		break;
133
134	case BFA_IOIM_SM_IOTOV:
135		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
136		list_del(&ioim->qe);
137		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
138		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
139				__bfa_cb_ioim_pathtov, ioim);
140		break;
141
142	case BFA_IOIM_SM_ABORT:
143		/**
144		 * IO in pending queue can get abort requests. Complete abort
145		 * requests immediately.
146		 */
147		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
148		bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
149		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
150				ioim);
151		break;
152
153	default:
154		bfa_sm_fault(ioim->bfa, event);
155	}
156}
157
158/**
159 * 		IO is waiting for SG pages.
160 */
161static void
162bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
163{
164	bfa_trc(ioim->bfa, ioim->iotag);
165	bfa_trc(ioim->bfa, event);
166
167	switch (event) {
168	case BFA_IOIM_SM_SGALLOCED:
169		if (!bfa_ioim_send_ioreq(ioim)) {
170			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
171			break;
172		}
173		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
174		break;
175
176	case BFA_IOIM_SM_CLEANUP:
177		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
178		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
179		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
180			      ioim);
181		bfa_ioim_notify_cleanup(ioim);
182		break;
183
184	case BFA_IOIM_SM_ABORT:
185		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
186		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
187		list_del(&ioim->qe);
188		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
189		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
190			      ioim);
191		break;
192
193	case BFA_IOIM_SM_HWFAIL:
194		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
195		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
196		list_del(&ioim->qe);
197		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
198		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
199			      ioim);
200		break;
201
202	default:
203		bfa_sm_fault(ioim->bfa, event);
204	}
205}
206
207/**
208 * 		IO is active.
209 */
210static void
211bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
212{
213	bfa_trc_fp(ioim->bfa, ioim->iotag);
214	bfa_trc_fp(ioim->bfa, event);
215
216	switch (event) {
217	case BFA_IOIM_SM_COMP_GOOD:
218		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
219		list_del(&ioim->qe);
220		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
221		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
222			      __bfa_cb_ioim_good_comp, ioim);
223		break;
224
225	case BFA_IOIM_SM_COMP:
226		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
227		list_del(&ioim->qe);
228		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
229		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
230			      ioim);
231		break;
232
233	case BFA_IOIM_SM_DONE:
234		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
235		list_del(&ioim->qe);
236		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
237		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
238			      ioim);
239		break;
240
241	case BFA_IOIM_SM_ABORT:
242		ioim->iosp->abort_explicit = BFA_TRUE;
243		ioim->io_cbfn = __bfa_cb_ioim_abort;
244
245		if (bfa_ioim_send_abort(ioim))
246			bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
247		else {
248			bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
249			bfa_reqq_wait(ioim->bfa, ioim->reqq,
250					&ioim->iosp->reqq_wait);
251		}
252		break;
253
254	case BFA_IOIM_SM_CLEANUP:
255		ioim->iosp->abort_explicit = BFA_FALSE;
256		ioim->io_cbfn = __bfa_cb_ioim_failed;
257
258		if (bfa_ioim_send_abort(ioim))
259			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
260		else {
261			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
262			bfa_reqq_wait(ioim->bfa, ioim->reqq,
263					&ioim->iosp->reqq_wait);
264		}
265		break;
266
267	case BFA_IOIM_SM_HWFAIL:
268		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
269		list_del(&ioim->qe);
270		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
271		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
272			      ioim);
273		break;
274
275	default:
276		bfa_sm_fault(ioim->bfa, event);
277	}
278}
279
280/**
281 * 		IO is being aborted, waiting for completion from firmware.
282 */
283static void
284bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
285{
286	bfa_trc(ioim->bfa, ioim->iotag);
287	bfa_trc(ioim->bfa, event);
288
289	switch (event) {
290	case BFA_IOIM_SM_COMP_GOOD:
291	case BFA_IOIM_SM_COMP:
292	case BFA_IOIM_SM_DONE:
293	case BFA_IOIM_SM_FREE:
294		break;
295
296	case BFA_IOIM_SM_ABORT_DONE:
297		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
298		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
299			      ioim);
300		break;
301
302	case BFA_IOIM_SM_ABORT_COMP:
303		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
304		list_del(&ioim->qe);
305		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
306		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
307			      ioim);
308		break;
309
310	case BFA_IOIM_SM_COMP_UTAG:
311		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
312		list_del(&ioim->qe);
313		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
314		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
315			      ioim);
316		break;
317
318	case BFA_IOIM_SM_CLEANUP:
319		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
320		ioim->iosp->abort_explicit = BFA_FALSE;
321
322		if (bfa_ioim_send_abort(ioim))
323			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
324		else {
325			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
326			bfa_reqq_wait(ioim->bfa, ioim->reqq,
327					  &ioim->iosp->reqq_wait);
328		}
329		break;
330
331	case BFA_IOIM_SM_HWFAIL:
332		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
333		list_del(&ioim->qe);
334		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
335		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
336			      ioim);
337		break;
338
339	default:
340		bfa_sm_fault(ioim->bfa, event);
341	}
342}
343
344/**
345 * IO is being cleaned up (implicit abort), waiting for completion from
346 * firmware.
347 */
348static void
349bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
350{
351	bfa_trc(ioim->bfa, ioim->iotag);
352	bfa_trc(ioim->bfa, event);
353
354	switch (event) {
355	case BFA_IOIM_SM_COMP_GOOD:
356	case BFA_IOIM_SM_COMP:
357	case BFA_IOIM_SM_DONE:
358	case BFA_IOIM_SM_FREE:
359		break;
360
361	case BFA_IOIM_SM_ABORT:
362		/**
363		 * IO is already being aborted implicitly
364		 */
365		ioim->io_cbfn = __bfa_cb_ioim_abort;
366		break;
367
368	case BFA_IOIM_SM_ABORT_DONE:
369		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
370		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
371		bfa_ioim_notify_cleanup(ioim);
372		break;
373
374	case BFA_IOIM_SM_ABORT_COMP:
375		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
376		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
377		bfa_ioim_notify_cleanup(ioim);
378		break;
379
380	case BFA_IOIM_SM_COMP_UTAG:
381		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
382		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
383		bfa_ioim_notify_cleanup(ioim);
384		break;
385
386	case BFA_IOIM_SM_HWFAIL:
387		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
388		list_del(&ioim->qe);
389		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
390		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
391			      ioim);
392		break;
393
394	case BFA_IOIM_SM_CLEANUP:
395		/**
396		 * IO can be in cleanup state already due to TM command. 2nd cleanup
397		 * request comes from ITN offline event.
398		 */
399		break;
400
401	default:
402		bfa_sm_fault(ioim->bfa, event);
403	}
404}
405
406/**
407 * 		IO is waiting for room in request CQ
408 */
409static void
410bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
411{
412	bfa_trc(ioim->bfa, ioim->iotag);
413	bfa_trc(ioim->bfa, event);
414
415	switch (event) {
416	case BFA_IOIM_SM_QRESUME:
417		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
418		bfa_ioim_send_ioreq(ioim);
419		break;
420
421	case BFA_IOIM_SM_ABORT:
422		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
423		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
424		list_del(&ioim->qe);
425		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
426		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
427			      ioim);
428		break;
429
430	case BFA_IOIM_SM_CLEANUP:
431		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
432		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
433		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
434			      ioim);
435		bfa_ioim_notify_cleanup(ioim);
436		break;
437
438	case BFA_IOIM_SM_HWFAIL:
439		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
440		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
441		list_del(&ioim->qe);
442		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
443		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
444			      ioim);
445		break;
446
447	default:
448		bfa_sm_fault(ioim->bfa, event);
449	}
450}
451
452/**
453 * 		Active IO is being aborted, waiting for room in request CQ.
454 */
455static void
456bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
457{
458	bfa_trc(ioim->bfa, ioim->iotag);
459	bfa_trc(ioim->bfa, event);
460
461	switch (event) {
462	case BFA_IOIM_SM_QRESUME:
463		bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
464		bfa_ioim_send_abort(ioim);
465		break;
466
467	case BFA_IOIM_SM_CLEANUP:
468		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
469		ioim->iosp->abort_explicit = BFA_FALSE;
470		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
471		break;
472
473	case BFA_IOIM_SM_COMP_GOOD:
474	case BFA_IOIM_SM_COMP:
475		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
476		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
477		list_del(&ioim->qe);
478		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
479		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
480			      ioim);
481		break;
482
483	case BFA_IOIM_SM_DONE:
484		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
485		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
486		list_del(&ioim->qe);
487		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
488		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
489			      ioim);
490		break;
491
492	case BFA_IOIM_SM_HWFAIL:
493		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
494		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
495		list_del(&ioim->qe);
496		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
497		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
498			      ioim);
499		break;
500
501	default:
502		bfa_sm_fault(ioim->bfa, event);
503	}
504}
505
506/**
507 * 		Active IO is being cleaned up, waiting for room in request CQ.
508 */
509static void
510bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
511{
512	bfa_trc(ioim->bfa, ioim->iotag);
513	bfa_trc(ioim->bfa, event);
514
515	switch (event) {
516	case BFA_IOIM_SM_QRESUME:
517		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
518		bfa_ioim_send_abort(ioim);
519		break;
520
521	case BFA_IOIM_SM_ABORT:
522		/**
523		 * IO is already being cleaned up implicitly
524		 */
525		ioim->io_cbfn = __bfa_cb_ioim_abort;
526		break;
527
528	case BFA_IOIM_SM_COMP_GOOD:
529	case BFA_IOIM_SM_COMP:
530		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
531		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
532		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
533		bfa_ioim_notify_cleanup(ioim);
534		break;
535
536	case BFA_IOIM_SM_DONE:
537		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
538		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
539		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
540		bfa_ioim_notify_cleanup(ioim);
541		break;
542
543	case BFA_IOIM_SM_HWFAIL:
544		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
545		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
546		list_del(&ioim->qe);
547		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
548		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
549			      ioim);
550		break;
551
552	default:
553		bfa_sm_fault(ioim->bfa, event);
554	}
555}
556
557/**
558 * IO bfa callback is pending.
559 */
560static void
561bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
562{
563	bfa_trc_fp(ioim->bfa, ioim->iotag);
564	bfa_trc_fp(ioim->bfa, event);
565
566	switch (event) {
567	case BFA_IOIM_SM_HCB:
568		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
569		bfa_ioim_free(ioim);
570		bfa_cb_ioim_resfree(ioim->bfa->bfad);
571		break;
572
573	case BFA_IOIM_SM_CLEANUP:
574		bfa_ioim_notify_cleanup(ioim);
575		break;
576
577	case BFA_IOIM_SM_HWFAIL:
578		break;
579
580	default:
581		bfa_sm_fault(ioim->bfa, event);
582	}
583}
584
585/**
586 * IO bfa callback is pending. IO resource cannot be freed.
587 */
588static void
589bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
590{
591	bfa_trc(ioim->bfa, ioim->iotag);
592	bfa_trc(ioim->bfa, event);
593
594	switch (event) {
595	case BFA_IOIM_SM_HCB:
596		bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
597		list_del(&ioim->qe);
598		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
599		break;
600
601	case BFA_IOIM_SM_FREE:
602		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
603		break;
604
605	case BFA_IOIM_SM_CLEANUP:
606		bfa_ioim_notify_cleanup(ioim);
607		break;
608
609	case BFA_IOIM_SM_HWFAIL:
610		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
611		break;
612
613	default:
614		bfa_sm_fault(ioim->bfa, event);
615	}
616}
617
618/**
619 * IO is completed, waiting resource free from firmware.
620 */
621static void
622bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
623{
624	bfa_trc(ioim->bfa, ioim->iotag);
625	bfa_trc(ioim->bfa, event);
626
627	switch (event) {
628	case BFA_IOIM_SM_FREE:
629		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
630		bfa_ioim_free(ioim);
631		bfa_cb_ioim_resfree(ioim->bfa->bfad);
632		break;
633
634	case BFA_IOIM_SM_CLEANUP:
635		bfa_ioim_notify_cleanup(ioim);
636		break;
637
638	case BFA_IOIM_SM_HWFAIL:
639		break;
640
641	default:
642		bfa_sm_fault(ioim->bfa, event);
643	}
644}
645
646
647
648/**
649 *  bfa_ioim_private
650 */
651
652static void
653__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
654{
655	struct bfa_ioim_s *ioim = cbarg;
656
657	if (!complete) {
658		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
659		return;
660	}
661
662	bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
663}
664
665static void
666__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
667{
668	struct bfa_ioim_s	*ioim = cbarg;
669	struct bfi_ioim_rsp_s *m;
670	u8		*snsinfo = NULL;
671	u8         sns_len = 0;
672	s32         residue = 0;
673
674	if (!complete) {
675		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
676		return;
677	}
678
679	m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
680	if (m->io_status == BFI_IOIM_STS_OK) {
681		/**
682		 * setup sense information, if present
683		 */
684		if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION
685					&& m->sns_len) {
686			sns_len = m->sns_len;
687			snsinfo = ioim->iosp->snsinfo;
688		}
689
690		/**
691		 * setup residue value correctly for normal completions
692		 */
693		if (m->resid_flags == FCP_RESID_UNDER)
694			residue = bfa_os_ntohl(m->residue);
695		if (m->resid_flags == FCP_RESID_OVER) {
696			residue = bfa_os_ntohl(m->residue);
697			residue = -residue;
698		}
699	}
700
701	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
702			  m->scsi_status, sns_len, snsinfo, residue);
703}
704
705static void
706__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
707{
708	struct bfa_ioim_s *ioim = cbarg;
709
710	if (!complete) {
711		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
712		return;
713	}
714
715	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
716			  0, 0, NULL, 0);
717}
718
719static void
720__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
721{
722	struct bfa_ioim_s *ioim = cbarg;
723
724	if (!complete) {
725		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
726		return;
727	}
728
729	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
730			  0, 0, NULL, 0);
731}
732
733static void
734__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
735{
736	struct bfa_ioim_s *ioim = cbarg;
737
738	if (!complete) {
739		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
740		return;
741	}
742
743	bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
744}
745
746static void
747bfa_ioim_sgpg_alloced(void *cbarg)
748{
749	struct bfa_ioim_s *ioim = cbarg;
750
751	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
752	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
753	bfa_ioim_sgpg_setup(ioim);
754	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
755}
756
757/**
758 * Send I/O request to firmware.
759 */
760static          bfa_boolean_t
761bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
762{
763	struct bfa_itnim_s *itnim = ioim->itnim;
764	struct bfi_ioim_req_s *m;
765	static struct fcp_cmnd_s cmnd_z0 = { 0 };
766	struct bfi_sge_s      *sge;
767	u32        pgdlen = 0;
768	u64 addr;
769	struct scatterlist *sg;
770	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
771
772	/**
773	 * check for room in queue to send request now
774	 */
775	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
776	if (!m) {
777		bfa_reqq_wait(ioim->bfa, ioim->reqq,
778				  &ioim->iosp->reqq_wait);
779		return BFA_FALSE;
780	}
781
782	/**
783	 * build i/o request message next
784	 */
785	m->io_tag = bfa_os_htons(ioim->iotag);
786	m->rport_hdl = ioim->itnim->rport->fw_handle;
787	m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
788
789	/**
790	 * build inline IO SG element here
791	 */
792	sge = &m->sges[0];
793	if (ioim->nsges) {
794		sg = (struct scatterlist *)scsi_sglist(cmnd);
795		addr = bfa_os_sgaddr(sg_dma_address(sg));
796		sge->sga = *(union bfi_addr_u *) &addr;
797		pgdlen = sg_dma_len(sg);
798		sge->sg_len = pgdlen;
799		sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
800					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
801		bfa_sge_to_be(sge);
802		sge++;
803	}
804
805	if (ioim->nsges > BFI_SGE_INLINE) {
806		sge->sga = ioim->sgpg->sgpg_pa;
807	} else {
808		sge->sga.a32.addr_lo = 0;
809		sge->sga.a32.addr_hi = 0;
810	}
811	sge->sg_len = pgdlen;
812	sge->flags = BFI_SGE_PGDLEN;
813	bfa_sge_to_be(sge);
814
815	/**
816	 * set up I/O command parameters
817	 */
818	bfa_os_assign(m->cmnd, cmnd_z0);
819	m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
820	m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
821	bfa_os_assign(m->cmnd.cdb,
822			*(struct scsi_cdb_s *)bfa_cb_ioim_get_cdb(ioim->dio));
823	m->cmnd.fcp_dl = bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
824
825	/**
826	 * set up I/O message header
827	 */
828	switch (m->cmnd.iodir) {
829	case FCP_IODIR_READ:
830		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
831		bfa_stats(itnim, input_reqs);
832		break;
833	case FCP_IODIR_WRITE:
834		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
835		bfa_stats(itnim, output_reqs);
836		break;
837	case FCP_IODIR_RW:
838		bfa_stats(itnim, input_reqs);
839		bfa_stats(itnim, output_reqs);
840	default:
841		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
842	}
843	if (itnim->seq_rec ||
844	    (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
845		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
846
847#ifdef IOIM_ADVANCED
848	m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
849	m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
850	m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
851
852	/**
853	 * Handle large CDB (>16 bytes).
854	 */
855	m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
856					FCP_CMND_CDB_LEN) / sizeof(u32);
857	if (m->cmnd.addl_cdb_len) {
858		bfa_os_memcpy(&m->cmnd.cdb + 1, (struct scsi_cdb_s *)
859				bfa_cb_ioim_get_cdb(ioim->dio) + 1,
860				m->cmnd.addl_cdb_len * sizeof(u32));
861		fcp_cmnd_fcpdl(&m->cmnd) =
862				bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
863	}
864#endif
865
866	/**
867	 * queue I/O message to firmware
868	 */
869	bfa_reqq_produce(ioim->bfa, ioim->reqq);
870	return BFA_TRUE;
871}
872
873/**
874 * Setup any additional SG pages needed.Inline SG element is setup
875 * at queuing time.
876 */
877static bfa_boolean_t
878bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
879{
880	u16        nsgpgs;
881
882	bfa_assert(ioim->nsges > BFI_SGE_INLINE);
883
884	/**
885	 * allocate SG pages needed
886	 */
887	nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
888	if (!nsgpgs)
889		return BFA_TRUE;
890
891	if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
892	    != BFA_STATUS_OK) {
893		bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
894		return BFA_FALSE;
895	}
896
897	ioim->nsgpgs = nsgpgs;
898	bfa_ioim_sgpg_setup(ioim);
899
900	return BFA_TRUE;
901}
902
903static void
904bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
905{
906	int             sgeid, nsges, i;
907	struct bfi_sge_s      *sge;
908	struct bfa_sgpg_s *sgpg;
909	u32        pgcumsz;
910	u64        addr;
911	struct scatterlist *sg;
912	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
913
914	sgeid = BFI_SGE_INLINE;
915	ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
916
917	sg = scsi_sglist(cmnd);
918	sg = sg_next(sg);
919
920	do {
921		sge = sgpg->sgpg->sges;
922		nsges = ioim->nsges - sgeid;
923		if (nsges > BFI_SGPG_DATA_SGES)
924			nsges = BFI_SGPG_DATA_SGES;
925
926		pgcumsz = 0;
927		for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
928			addr = bfa_os_sgaddr(sg_dma_address(sg));
929			sge->sga = *(union bfi_addr_u *) &addr;
930			sge->sg_len = sg_dma_len(sg);
931			pgcumsz += sge->sg_len;
932
933			/**
934			 * set flags
935			 */
936			if (i < (nsges - 1))
937				sge->flags = BFI_SGE_DATA;
938			else if (sgeid < (ioim->nsges - 1))
939				sge->flags = BFI_SGE_DATA_CPL;
940			else
941				sge->flags = BFI_SGE_DATA_LAST;
942		}
943
944		sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
945
946		/**
947		 * set the link element of each page
948		 */
949		if (sgeid == ioim->nsges) {
950			sge->flags = BFI_SGE_PGDLEN;
951			sge->sga.a32.addr_lo = 0;
952			sge->sga.a32.addr_hi = 0;
953		} else {
954			sge->flags = BFI_SGE_LINK;
955			sge->sga = sgpg->sgpg_pa;
956		}
957		sge->sg_len = pgcumsz;
958	} while (sgeid < ioim->nsges);
959}
960
961/**
962 * Send I/O abort request to firmware.
963 */
964static          bfa_boolean_t
965bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
966{
967	struct bfi_ioim_abort_req_s *m;
968	enum bfi_ioim_h2i       msgop;
969
970	/**
971	 * check for room in queue to send request now
972	 */
973	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
974	if (!m)
975		return BFA_FALSE;
976
977	/**
978	 * build i/o request message next
979	 */
980	if (ioim->iosp->abort_explicit)
981		msgop = BFI_IOIM_H2I_IOABORT_REQ;
982	else
983		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
984
985	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
986	m->io_tag    = bfa_os_htons(ioim->iotag);
987	m->abort_tag = ++ioim->abort_tag;
988
989	/**
990	 * queue I/O message to firmware
991	 */
992	bfa_reqq_produce(ioim->bfa, ioim->reqq);
993	return BFA_TRUE;
994}
995
996/**
997 * Call to resume any I/O requests waiting for room in request queue.
998 */
999static void
1000bfa_ioim_qresume(void *cbarg)
1001{
1002	struct bfa_ioim_s *ioim = cbarg;
1003
1004	bfa_fcpim_stats(ioim->fcpim, qresumes);
1005	bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
1006}
1007
1008
1009static void
1010bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
1011{
1012	/**
1013	 * Move IO from itnim queue to fcpim global queue since itnim will be
1014	 * freed.
1015	 */
1016	list_del(&ioim->qe);
1017	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
1018
1019	if (!ioim->iosp->tskim) {
1020		if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
1021			bfa_cb_dequeue(&ioim->hcb_qe);
1022			list_del(&ioim->qe);
1023			list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
1024		}
1025		bfa_itnim_iodone(ioim->itnim);
1026	} else
1027		bfa_tskim_iodone(ioim->iosp->tskim);
1028}
1029
1030/**
1031 * 		  or after the link comes back.
1032 */
1033void
1034bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
1035{
1036	/**
1037	 * If path tov timer expired, failback with PATHTOV status - these
1038	 * IO requests are not normally retried by IO stack.
1039	 *
1040	 * Otherwise device cameback online and fail it with normal failed
1041	 * status so that IO stack retries these failed IO requests.
1042	 */
1043	if (iotov)
1044		ioim->io_cbfn = __bfa_cb_ioim_pathtov;
1045	else
1046		ioim->io_cbfn = __bfa_cb_ioim_failed;
1047
1048	bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
1049
1050    /**
1051     * Move IO to fcpim global queue since itnim will be
1052     * freed.
1053     */
1054    list_del(&ioim->qe);
1055    list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
1056}
1057
1058
1059
1060/**
1061 *  bfa_ioim_friend
1062 */
1063
1064/**
1065 * Memory allocation and initialization.
1066 */
1067void
1068bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
1069{
1070	struct bfa_ioim_s		*ioim;
1071	struct bfa_ioim_sp_s	*iosp;
1072	u16		i;
1073	u8			*snsinfo;
1074	u32		snsbufsz;
1075
1076	/**
1077	 * claim memory first
1078	 */
1079	ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
1080	fcpim->ioim_arr = ioim;
1081	bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
1082
1083	iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
1084	fcpim->ioim_sp_arr = iosp;
1085	bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
1086
1087	/**
1088	 * Claim DMA memory for per IO sense data.
1089	 */
1090	snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
1091	fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
1092	bfa_meminfo_dma_phys(minfo) += snsbufsz;
1093
1094	fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
1095	bfa_meminfo_dma_virt(minfo) += snsbufsz;
1096	snsinfo = fcpim->snsbase.kva;
1097	bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
1098
1099	/**
1100	 * Initialize ioim free queues
1101	 */
1102	INIT_LIST_HEAD(&fcpim->ioim_free_q);
1103	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
1104	INIT_LIST_HEAD(&fcpim->ioim_comp_q);
1105
1106	for (i = 0; i < fcpim->num_ioim_reqs;
1107	     i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
1108		/*
1109		 * initialize IOIM
1110		 */
1111		bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
1112		ioim->iotag   = i;
1113		ioim->bfa     = fcpim->bfa;
1114		ioim->fcpim   = fcpim;
1115		ioim->iosp    = iosp;
1116		iosp->snsinfo = snsinfo;
1117		INIT_LIST_HEAD(&ioim->sgpg_q);
1118		bfa_reqq_winit(&ioim->iosp->reqq_wait,
1119				   bfa_ioim_qresume, ioim);
1120		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
1121				   bfa_ioim_sgpg_alloced, ioim);
1122		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
1123
1124		list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
1125	}
1126}
1127
1128/**
1129 * Driver detach time call.
1130 */
1131void
1132bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
1133{
1134}
1135
1136void
1137bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1138{
1139	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
1140	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
1141	struct bfa_ioim_s *ioim;
1142	u16        iotag;
1143	enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
1144
1145	iotag = bfa_os_ntohs(rsp->io_tag);
1146
1147	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
1148	bfa_assert(ioim->iotag == iotag);
1149
1150	bfa_trc(ioim->bfa, ioim->iotag);
1151	bfa_trc(ioim->bfa, rsp->io_status);
1152	bfa_trc(ioim->bfa, rsp->reuse_io_tag);
1153
1154	if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
1155		bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
1156
1157	switch (rsp->io_status) {
1158	case BFI_IOIM_STS_OK:
1159		bfa_fcpim_stats(fcpim, iocomp_ok);
1160		if (rsp->reuse_io_tag == 0)
1161			evt = BFA_IOIM_SM_DONE;
1162		else
1163			evt = BFA_IOIM_SM_COMP;
1164		break;
1165
1166	case BFI_IOIM_STS_TIMEDOUT:
1167	case BFI_IOIM_STS_ABORTED:
1168		rsp->io_status = BFI_IOIM_STS_ABORTED;
1169		bfa_fcpim_stats(fcpim, iocomp_aborted);
1170		if (rsp->reuse_io_tag == 0)
1171			evt = BFA_IOIM_SM_DONE;
1172		else
1173			evt = BFA_IOIM_SM_COMP;
1174		break;
1175
1176	case BFI_IOIM_STS_PROTO_ERR:
1177		bfa_fcpim_stats(fcpim, iocom_proto_err);
1178		bfa_assert(rsp->reuse_io_tag);
1179		evt = BFA_IOIM_SM_COMP;
1180		break;
1181
1182	case BFI_IOIM_STS_SQER_NEEDED:
1183		bfa_fcpim_stats(fcpim, iocom_sqer_needed);
1184		bfa_assert(rsp->reuse_io_tag == 0);
1185		evt = BFA_IOIM_SM_SQRETRY;
1186		break;
1187
1188	case BFI_IOIM_STS_RES_FREE:
1189		bfa_fcpim_stats(fcpim, iocom_res_free);
1190		evt = BFA_IOIM_SM_FREE;
1191		break;
1192
1193	case BFI_IOIM_STS_HOST_ABORTED:
1194		bfa_fcpim_stats(fcpim, iocom_hostabrts);
1195		if (rsp->abort_tag != ioim->abort_tag) {
1196			bfa_trc(ioim->bfa, rsp->abort_tag);
1197			bfa_trc(ioim->bfa, ioim->abort_tag);
1198			return;
1199		}
1200
1201		if (rsp->reuse_io_tag)
1202			evt = BFA_IOIM_SM_ABORT_COMP;
1203		else
1204			evt = BFA_IOIM_SM_ABORT_DONE;
1205		break;
1206
1207	case BFI_IOIM_STS_UTAG:
1208		bfa_fcpim_stats(fcpim, iocom_utags);
1209		evt = BFA_IOIM_SM_COMP_UTAG;
1210		break;
1211
1212	default:
1213		bfa_assert(0);
1214	}
1215
1216	bfa_sm_send_event(ioim, evt);
1217}
1218
1219void
1220bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1221{
1222	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
1223	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
1224	struct bfa_ioim_s *ioim;
1225	u16        iotag;
1226
1227	iotag = bfa_os_ntohs(rsp->io_tag);
1228
1229	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
1230	bfa_assert(ioim->iotag == iotag);
1231
1232	bfa_trc_fp(ioim->bfa, ioim->iotag);
1233	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
1234}
1235
1236/**
1237 * Called by itnim to clean up IO while going offline.
1238 */
1239void
1240bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
1241{
1242	bfa_trc(ioim->bfa, ioim->iotag);
1243	bfa_fcpim_stats(ioim->fcpim, io_cleanups);
1244
1245	ioim->iosp->tskim = NULL;
1246	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
1247}
1248
1249void
1250bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
1251{
1252	bfa_trc(ioim->bfa, ioim->iotag);
1253	bfa_fcpim_stats(ioim->fcpim, io_tmaborts);
1254
1255	ioim->iosp->tskim = tskim;
1256	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
1257}
1258
1259/**
1260 * IOC failure handling.
1261 */
1262void
1263bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
1264{
1265	bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
1266}
1267
1268/**
1269 * IO offline TOV popped. Fail the pending IO.
1270 */
1271void
1272bfa_ioim_tov(struct bfa_ioim_s *ioim)
1273{
1274	bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
1275}
1276
1277
1278
1279/**
1280 *  bfa_ioim_api
1281 */
1282
1283/**
1284 * Allocate IOIM resource for initiator mode I/O request.
1285 */
1286struct bfa_ioim_s *
1287bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
1288		struct bfa_itnim_s *itnim, u16 nsges)
1289{
1290	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
1291	struct bfa_ioim_s *ioim;
1292
1293	/**
1294	 * alocate IOIM resource
1295	 */
1296	bfa_q_deq(&fcpim->ioim_free_q, &ioim);
1297	if (!ioim) {
1298		bfa_fcpim_stats(fcpim, no_iotags);
1299		return NULL;
1300	}
1301
1302	ioim->dio = dio;
1303	ioim->itnim = itnim;
1304	ioim->nsges = nsges;
1305	ioim->nsgpgs = 0;
1306
1307	bfa_stats(fcpim, total_ios);
1308	bfa_stats(itnim, ios);
1309	fcpim->ios_active++;
1310
1311	list_add_tail(&ioim->qe, &itnim->io_q);
1312	bfa_trc_fp(ioim->bfa, ioim->iotag);
1313
1314	return ioim;
1315}
1316
1317void
1318bfa_ioim_free(struct bfa_ioim_s *ioim)
1319{
1320	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
1321
1322	bfa_trc_fp(ioim->bfa, ioim->iotag);
1323	bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
1324
1325	bfa_assert_fp(list_empty(&ioim->sgpg_q)
1326		   || (ioim->nsges > BFI_SGE_INLINE));
1327
1328	if (ioim->nsgpgs > 0)
1329		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
1330
1331	bfa_stats(ioim->itnim, io_comps);
1332	fcpim->ios_active--;
1333
1334	list_del(&ioim->qe);
1335	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
1336}
1337
1338void
1339bfa_ioim_start(struct bfa_ioim_s *ioim)
1340{
1341	bfa_trc_fp(ioim->bfa, ioim->iotag);
1342
1343	/**
1344	 * Obtain the queue over which this request has to be issued
1345	 */
1346	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
1347			bfa_cb_ioim_get_reqq(ioim->dio) :
1348			bfa_itnim_get_reqq(ioim);
1349
1350	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
1351}
1352
1353/**
1354 * Driver I/O abort request.
1355 */
1356void
1357bfa_ioim_abort(struct bfa_ioim_s *ioim)
1358{
1359	bfa_trc(ioim->bfa, ioim->iotag);
1360	bfa_fcpim_stats(ioim->fcpim, io_aborts);
1361	bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
1362}
1363