• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/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 <bfa_fcpim.h>
20#include "bfa_fcpim_priv.h"
21
22BFA_TRC_FILE(HAL, ITNIM);
23
24#define BFA_ITNIM_FROM_TAG(_fcpim, _tag)				\
25	((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))
26
27#define bfa_fcpim_additn(__itnim)					\
28	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
29#define bfa_fcpim_delitn(__itnim)	do {				\
30	bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \
31	list_del(&(__itnim)->qe);      \
32	bfa_assert(list_empty(&(__itnim)->io_q));      \
33	bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \
34	bfa_assert(list_empty(&(__itnim)->pending_q));      \
35} while (0)
36
37#define bfa_itnim_online_cb(__itnim) do {				\
38	if ((__itnim)->bfa->fcs)					\
39		bfa_cb_itnim_online((__itnim)->ditn);      \
40	else {								\
41		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
42		__bfa_cb_itnim_online, (__itnim));      \
43	}								\
44} while (0)
45
46#define bfa_itnim_offline_cb(__itnim) do {				\
47	if ((__itnim)->bfa->fcs)					\
48		bfa_cb_itnim_offline((__itnim)->ditn);      \
49	else {								\
50		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
51		__bfa_cb_itnim_offline, (__itnim));      \
52	}								\
53} while (0)
54
55#define bfa_itnim_sler_cb(__itnim) do {					\
56	if ((__itnim)->bfa->fcs)					\
57		bfa_cb_itnim_sler((__itnim)->ditn);      \
58	else {								\
59		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
60		__bfa_cb_itnim_sler, (__itnim));      \
61	}								\
62} while (0)
63
64/*
65 * forward declarations
66 */
67static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
68static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
69static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
70static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
71static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
72static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
73static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
74static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
75static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
76static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
77static void     bfa_itnim_iotov(void *itnim_arg);
78static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
79static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
80static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
81
82/**
83 *  bfa_itnim_sm BFA itnim state machine
84 */
85
86
87enum bfa_itnim_event {
88	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */
89	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */
90	BFA_ITNIM_SM_OFFLINE = 3,	/*  itnim is offline */
91	BFA_ITNIM_SM_FWRSP = 4,		/*  firmware response */
92	BFA_ITNIM_SM_DELETE = 5,	/*  deleting an existing itnim */
93	BFA_ITNIM_SM_CLEANUP = 6,	/*  IO cleanup completion */
94	BFA_ITNIM_SM_SLER = 7,		/*  second level error recovery */
95	BFA_ITNIM_SM_HWFAIL = 8,	/*  IOC h/w failure event */
96	BFA_ITNIM_SM_QRESUME = 9,	/*  queue space available */
97};
98
99static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
100					enum bfa_itnim_event event);
101static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
102					 enum bfa_itnim_event event);
103static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
104					  enum bfa_itnim_event event);
105static void	bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
106				enum bfa_itnim_event event);
107static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
108					enum bfa_itnim_event event);
109static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
110				      enum bfa_itnim_event event);
111static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
112						 enum bfa_itnim_event event);
113static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
114						enum bfa_itnim_event event);
115static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
116					  enum bfa_itnim_event event);
117static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
118					 enum bfa_itnim_event event);
119static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
120					    enum bfa_itnim_event event);
121static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
122					  enum bfa_itnim_event event);
123static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
124					  enum bfa_itnim_event event);
125static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
126					  enum bfa_itnim_event event);
127static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
128					  enum bfa_itnim_event event);
129
130/**
131 * 		Beginning/unallocated state - no events expected.
132 */
133static void
134bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
135{
136	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
137	bfa_trc(itnim->bfa, event);
138
139	switch (event) {
140	case BFA_ITNIM_SM_CREATE:
141		bfa_sm_set_state(itnim, bfa_itnim_sm_created);
142		itnim->is_online = BFA_FALSE;
143		bfa_fcpim_additn(itnim);
144		break;
145
146	default:
147		bfa_sm_fault(itnim->bfa, event);
148	}
149}
150
151/**
152 * 		Beginning state, only online event expected.
153 */
154static void
155bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
156{
157	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
158	bfa_trc(itnim->bfa, event);
159
160	switch (event) {
161	case BFA_ITNIM_SM_ONLINE:
162		if (bfa_itnim_send_fwcreate(itnim))
163			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
164		else
165			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
166		break;
167
168	case BFA_ITNIM_SM_DELETE:
169		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
170		bfa_fcpim_delitn(itnim);
171		break;
172
173	case BFA_ITNIM_SM_HWFAIL:
174		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
175		break;
176
177	default:
178		bfa_sm_fault(itnim->bfa, event);
179	}
180}
181
182/**
183 * 		Waiting for itnim create response from firmware.
184 */
185static void
186bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
187{
188	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
189	bfa_trc(itnim->bfa, event);
190
191	switch (event) {
192	case BFA_ITNIM_SM_FWRSP:
193		bfa_sm_set_state(itnim, bfa_itnim_sm_online);
194		itnim->is_online = BFA_TRUE;
195		bfa_itnim_iotov_online(itnim);
196		bfa_itnim_online_cb(itnim);
197		break;
198
199	case BFA_ITNIM_SM_DELETE:
200		bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
201		break;
202
203	case BFA_ITNIM_SM_OFFLINE:
204		if (bfa_itnim_send_fwdelete(itnim))
205			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
206		else
207			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
208		break;
209
210	case BFA_ITNIM_SM_HWFAIL:
211		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
212		break;
213
214	default:
215		bfa_sm_fault(itnim->bfa, event);
216	}
217}
218
219static void
220bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
221			enum bfa_itnim_event event)
222{
223	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
224	bfa_trc(itnim->bfa, event);
225
226	switch (event) {
227	case BFA_ITNIM_SM_QRESUME:
228		bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
229		bfa_itnim_send_fwcreate(itnim);
230		break;
231
232	case BFA_ITNIM_SM_DELETE:
233		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
234		bfa_reqq_wcancel(&itnim->reqq_wait);
235		bfa_fcpim_delitn(itnim);
236		break;
237
238	case BFA_ITNIM_SM_OFFLINE:
239		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
240		bfa_reqq_wcancel(&itnim->reqq_wait);
241		bfa_itnim_offline_cb(itnim);
242		break;
243
244	case BFA_ITNIM_SM_HWFAIL:
245		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
246		bfa_reqq_wcancel(&itnim->reqq_wait);
247		break;
248
249	default:
250		bfa_sm_fault(itnim->bfa, event);
251	}
252}
253
254/**
255 * 	Waiting for itnim create response from firmware, a delete is pending.
256 */
257static void
258bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
259				enum bfa_itnim_event event)
260{
261	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
262	bfa_trc(itnim->bfa, event);
263
264	switch (event) {
265	case BFA_ITNIM_SM_FWRSP:
266		if (bfa_itnim_send_fwdelete(itnim))
267			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
268		else
269			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
270		break;
271
272	case BFA_ITNIM_SM_HWFAIL:
273		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
274		bfa_fcpim_delitn(itnim);
275		break;
276
277	default:
278		bfa_sm_fault(itnim->bfa, event);
279	}
280}
281
282/**
283 * 		Online state - normal parking state.
284 */
285static void
286bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
287{
288	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
289	bfa_trc(itnim->bfa, event);
290
291	switch (event) {
292	case BFA_ITNIM_SM_OFFLINE:
293		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
294		itnim->is_online = BFA_FALSE;
295		bfa_itnim_iotov_start(itnim);
296		bfa_itnim_cleanup(itnim);
297		break;
298
299	case BFA_ITNIM_SM_DELETE:
300		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
301		itnim->is_online = BFA_FALSE;
302		bfa_itnim_cleanup(itnim);
303		break;
304
305	case BFA_ITNIM_SM_SLER:
306		bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
307		itnim->is_online = BFA_FALSE;
308		bfa_itnim_iotov_start(itnim);
309		bfa_itnim_sler_cb(itnim);
310		break;
311
312	case BFA_ITNIM_SM_HWFAIL:
313		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
314		itnim->is_online = BFA_FALSE;
315		bfa_itnim_iotov_start(itnim);
316		bfa_itnim_iocdisable_cleanup(itnim);
317		break;
318
319	default:
320		bfa_sm_fault(itnim->bfa, event);
321	}
322}
323
324/**
325 * 		Second level error recovery need.
326 */
327static void
328bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
329{
330	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
331	bfa_trc(itnim->bfa, event);
332
333	switch (event) {
334	case BFA_ITNIM_SM_OFFLINE:
335		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
336		bfa_itnim_cleanup(itnim);
337		break;
338
339	case BFA_ITNIM_SM_DELETE:
340		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
341		bfa_itnim_cleanup(itnim);
342		bfa_itnim_iotov_delete(itnim);
343		break;
344
345	case BFA_ITNIM_SM_HWFAIL:
346		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
347		bfa_itnim_iocdisable_cleanup(itnim);
348		break;
349
350	default:
351		bfa_sm_fault(itnim->bfa, event);
352	}
353}
354
355/**
356 * 		Going offline. Waiting for active IO cleanup.
357 */
358static void
359bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
360				 enum bfa_itnim_event event)
361{
362	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
363	bfa_trc(itnim->bfa, event);
364
365	switch (event) {
366	case BFA_ITNIM_SM_CLEANUP:
367		if (bfa_itnim_send_fwdelete(itnim))
368			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
369		else
370			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
371		break;
372
373	case BFA_ITNIM_SM_DELETE:
374		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
375		bfa_itnim_iotov_delete(itnim);
376		break;
377
378	case BFA_ITNIM_SM_HWFAIL:
379		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
380		bfa_itnim_iocdisable_cleanup(itnim);
381		bfa_itnim_offline_cb(itnim);
382		break;
383
384	case BFA_ITNIM_SM_SLER:
385		break;
386
387	default:
388		bfa_sm_fault(itnim->bfa, event);
389	}
390}
391
392/**
393 * 		Deleting itnim. Waiting for active IO cleanup.
394 */
395static void
396bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
397				enum bfa_itnim_event event)
398{
399	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
400	bfa_trc(itnim->bfa, event);
401
402	switch (event) {
403	case BFA_ITNIM_SM_CLEANUP:
404		if (bfa_itnim_send_fwdelete(itnim))
405			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
406		else
407			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
408		break;
409
410	case BFA_ITNIM_SM_HWFAIL:
411		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
412		bfa_itnim_iocdisable_cleanup(itnim);
413		break;
414
415	default:
416		bfa_sm_fault(itnim->bfa, event);
417	}
418}
419
420/**
421 * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
422 */
423static void
424bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
425{
426	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
427	bfa_trc(itnim->bfa, event);
428
429	switch (event) {
430	case BFA_ITNIM_SM_FWRSP:
431		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
432		bfa_itnim_offline_cb(itnim);
433		break;
434
435	case BFA_ITNIM_SM_DELETE:
436		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
437		break;
438
439	case BFA_ITNIM_SM_HWFAIL:
440		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
441		bfa_itnim_offline_cb(itnim);
442		break;
443
444	default:
445		bfa_sm_fault(itnim->bfa, event);
446	}
447}
448
449static void
450bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
451			enum bfa_itnim_event event)
452{
453	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
454	bfa_trc(itnim->bfa, event);
455
456	switch (event) {
457	case BFA_ITNIM_SM_QRESUME:
458		bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
459		bfa_itnim_send_fwdelete(itnim);
460		break;
461
462	case BFA_ITNIM_SM_DELETE:
463		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
464		break;
465
466	case BFA_ITNIM_SM_HWFAIL:
467		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
468		bfa_reqq_wcancel(&itnim->reqq_wait);
469		bfa_itnim_offline_cb(itnim);
470		break;
471
472	default:
473		bfa_sm_fault(itnim->bfa, event);
474	}
475}
476
477/**
478 * 		Offline state.
479 */
480static void
481bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
482{
483	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
484	bfa_trc(itnim->bfa, event);
485
486	switch (event) {
487	case BFA_ITNIM_SM_DELETE:
488		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
489		bfa_itnim_iotov_delete(itnim);
490		bfa_fcpim_delitn(itnim);
491		break;
492
493	case BFA_ITNIM_SM_ONLINE:
494		if (bfa_itnim_send_fwcreate(itnim))
495			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
496		else
497			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
498		break;
499
500	case BFA_ITNIM_SM_HWFAIL:
501		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
502		break;
503
504	default:
505		bfa_sm_fault(itnim->bfa, event);
506	}
507}
508
509/**
510 * 		IOC h/w failed state.
511 */
512static void
513bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
514			    enum bfa_itnim_event event)
515{
516	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
517	bfa_trc(itnim->bfa, event);
518
519	switch (event) {
520	case BFA_ITNIM_SM_DELETE:
521		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
522		bfa_itnim_iotov_delete(itnim);
523		bfa_fcpim_delitn(itnim);
524		break;
525
526	case BFA_ITNIM_SM_OFFLINE:
527		bfa_itnim_offline_cb(itnim);
528		break;
529
530	case BFA_ITNIM_SM_ONLINE:
531		if (bfa_itnim_send_fwcreate(itnim))
532			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
533		else
534			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
535		break;
536
537	case BFA_ITNIM_SM_HWFAIL:
538		break;
539
540	default:
541		bfa_sm_fault(itnim->bfa, event);
542	}
543}
544
545/**
546 * 		Itnim is deleted, waiting for firmware response to delete.
547 */
548static void
549bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
550{
551	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
552	bfa_trc(itnim->bfa, event);
553
554	switch (event) {
555	case BFA_ITNIM_SM_FWRSP:
556	case BFA_ITNIM_SM_HWFAIL:
557		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
558		bfa_fcpim_delitn(itnim);
559		break;
560
561	default:
562		bfa_sm_fault(itnim->bfa, event);
563	}
564}
565
566static void
567bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
568			enum bfa_itnim_event event)
569{
570	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
571	bfa_trc(itnim->bfa, event);
572
573	switch (event) {
574	case BFA_ITNIM_SM_QRESUME:
575		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
576		bfa_itnim_send_fwdelete(itnim);
577		break;
578
579	case BFA_ITNIM_SM_HWFAIL:
580		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
581		bfa_reqq_wcancel(&itnim->reqq_wait);
582		bfa_fcpim_delitn(itnim);
583		break;
584
585	default:
586		bfa_sm_fault(itnim->bfa, event);
587	}
588}
589
590
591
592/**
593 *  bfa_itnim_private
594 */
595
596/**
597 * 		Initiate cleanup of all IOs on an IOC failure.
598 */
599static void
600bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
601{
602	struct bfa_tskim_s *tskim;
603	struct bfa_ioim_s *ioim;
604	struct list_head        *qe, *qen;
605
606	list_for_each_safe(qe, qen, &itnim->tsk_q) {
607		tskim = (struct bfa_tskim_s *) qe;
608		bfa_tskim_iocdisable(tskim);
609	}
610
611	list_for_each_safe(qe, qen, &itnim->io_q) {
612		ioim = (struct bfa_ioim_s *) qe;
613		bfa_ioim_iocdisable(ioim);
614	}
615
616	/**
617	 * For IO request in pending queue, we pretend an early timeout.
618	 */
619	list_for_each_safe(qe, qen, &itnim->pending_q) {
620		ioim = (struct bfa_ioim_s *) qe;
621		bfa_ioim_tov(ioim);
622	}
623
624	list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
625		ioim = (struct bfa_ioim_s *) qe;
626		bfa_ioim_iocdisable(ioim);
627	}
628}
629
630/**
631 * 		IO cleanup completion
632 */
633static void
634bfa_itnim_cleanp_comp(void *itnim_cbarg)
635{
636	struct bfa_itnim_s *itnim = itnim_cbarg;
637
638	bfa_stats(itnim, cleanup_comps);
639	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
640}
641
642/**
643 * 		Initiate cleanup of all IOs.
644 */
645static void
646bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
647{
648	struct bfa_ioim_s  *ioim;
649	struct bfa_tskim_s *tskim;
650	struct list_head         *qe, *qen;
651
652	bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
653
654	list_for_each_safe(qe, qen, &itnim->io_q) {
655		ioim = (struct bfa_ioim_s *) qe;
656
657		/**
658		 * Move IO to a cleanup queue from active queue so that a later
659		 * TM will not pickup this IO.
660		 */
661		list_del(&ioim->qe);
662		list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
663
664		bfa_wc_up(&itnim->wc);
665		bfa_ioim_cleanup(ioim);
666	}
667
668	list_for_each_safe(qe, qen, &itnim->tsk_q) {
669		tskim = (struct bfa_tskim_s *) qe;
670		bfa_wc_up(&itnim->wc);
671		bfa_tskim_cleanup(tskim);
672	}
673
674	bfa_wc_wait(&itnim->wc);
675}
676
677static void
678__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
679{
680	struct bfa_itnim_s *itnim = cbarg;
681
682	if (complete)
683		bfa_cb_itnim_online(itnim->ditn);
684}
685
686static void
687__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
688{
689	struct bfa_itnim_s *itnim = cbarg;
690
691	if (complete)
692		bfa_cb_itnim_offline(itnim->ditn);
693}
694
695static void
696__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
697{
698	struct bfa_itnim_s *itnim = cbarg;
699
700	if (complete)
701		bfa_cb_itnim_sler(itnim->ditn);
702}
703
704/**
705 * Call to resume any I/O requests waiting for room in request queue.
706 */
707static void
708bfa_itnim_qresume(void *cbarg)
709{
710	struct bfa_itnim_s *itnim = cbarg;
711
712	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
713}
714
715
716
717
718/**
719 *  bfa_itnim_public
720 */
721
722void
723bfa_itnim_iodone(struct bfa_itnim_s *itnim)
724{
725	bfa_wc_down(&itnim->wc);
726}
727
728void
729bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
730{
731	bfa_wc_down(&itnim->wc);
732}
733
734void
735bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
736		u32 *dm_len)
737{
738	/**
739	 * ITN memory
740	 */
741	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
742}
743
744void
745bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
746{
747	struct bfa_s      *bfa = fcpim->bfa;
748	struct bfa_itnim_s *itnim;
749	int             i;
750
751	INIT_LIST_HEAD(&fcpim->itnim_q);
752
753	itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
754	fcpim->itnim_arr = itnim;
755
756	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
757		bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
758		itnim->bfa = bfa;
759		itnim->fcpim = fcpim;
760		itnim->reqq = BFA_REQQ_QOS_LO;
761		itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
762		itnim->iotov_active = BFA_FALSE;
763		bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
764
765		INIT_LIST_HEAD(&itnim->io_q);
766		INIT_LIST_HEAD(&itnim->io_cleanup_q);
767		INIT_LIST_HEAD(&itnim->pending_q);
768		INIT_LIST_HEAD(&itnim->tsk_q);
769		INIT_LIST_HEAD(&itnim->delay_comp_q);
770		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
771	}
772
773	bfa_meminfo_kva(minfo) = (u8 *) itnim;
774}
775
776void
777bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
778{
779	bfa_stats(itnim, ioc_disabled);
780	bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
781}
782
783static bfa_boolean_t
784bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
785{
786	struct bfi_itnim_create_req_s *m;
787
788	itnim->msg_no++;
789
790	/**
791	 * check for room in queue to send request now
792	 */
793	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
794	if (!m) {
795		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
796		return BFA_FALSE;
797	}
798
799	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
800			bfa_lpuid(itnim->bfa));
801	m->fw_handle = itnim->rport->fw_handle;
802	m->class = FC_CLASS_3;
803	m->seq_rec = itnim->seq_rec;
804	m->msg_no = itnim->msg_no;
805
806	/**
807	 * queue I/O message to firmware
808	 */
809	bfa_reqq_produce(itnim->bfa, itnim->reqq);
810	return BFA_TRUE;
811}
812
813static bfa_boolean_t
814bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
815{
816	struct bfi_itnim_delete_req_s *m;
817
818	/**
819	 * check for room in queue to send request now
820	 */
821	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
822	if (!m) {
823		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
824		return BFA_FALSE;
825	}
826
827	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
828			bfa_lpuid(itnim->bfa));
829	m->fw_handle = itnim->rport->fw_handle;
830
831	/**
832	 * queue I/O message to firmware
833	 */
834	bfa_reqq_produce(itnim->bfa, itnim->reqq);
835	return BFA_TRUE;
836}
837
838/**
839 * Cleanup all pending failed inflight requests.
840 */
841static void
842bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
843{
844	struct bfa_ioim_s *ioim;
845	struct list_head *qe, *qen;
846
847	list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
848		ioim = (struct bfa_ioim_s *)qe;
849		bfa_ioim_delayed_comp(ioim, iotov);
850	}
851}
852
853/**
854 * Start all pending IO requests.
855 */
856static void
857bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
858{
859	struct bfa_ioim_s *ioim;
860
861	bfa_itnim_iotov_stop(itnim);
862
863	/**
864	 * Abort all inflight IO requests in the queue
865	 */
866	bfa_itnim_delayed_comp(itnim, BFA_FALSE);
867
868	/**
869	 * Start all pending IO requests.
870	 */
871	while (!list_empty(&itnim->pending_q)) {
872		bfa_q_deq(&itnim->pending_q, &ioim);
873		list_add_tail(&ioim->qe, &itnim->io_q);
874		bfa_ioim_start(ioim);
875	}
876}
877
878/**
879 * Fail all pending IO requests
880 */
881static void
882bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
883{
884	struct bfa_ioim_s *ioim;
885
886	/**
887	 * Fail all inflight IO requests in the queue
888	 */
889	bfa_itnim_delayed_comp(itnim, BFA_TRUE);
890
891	/**
892	 * Fail any pending IO requests.
893	 */
894	while (!list_empty(&itnim->pending_q)) {
895		bfa_q_deq(&itnim->pending_q, &ioim);
896		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
897		bfa_ioim_tov(ioim);
898	}
899}
900
901/**
902 * IO TOV timer callback. Fail any pending IO requests.
903 */
904static void
905bfa_itnim_iotov(void *itnim_arg)
906{
907	struct bfa_itnim_s *itnim = itnim_arg;
908
909	itnim->iotov_active = BFA_FALSE;
910
911	bfa_cb_itnim_tov_begin(itnim->ditn);
912	bfa_itnim_iotov_cleanup(itnim);
913	bfa_cb_itnim_tov(itnim->ditn);
914}
915
916/**
917 * Start IO TOV timer for failing back pending IO requests in offline state.
918 */
919static void
920bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
921{
922	if (itnim->fcpim->path_tov > 0) {
923
924		itnim->iotov_active = BFA_TRUE;
925		bfa_assert(bfa_itnim_hold_io(itnim));
926		bfa_timer_start(itnim->bfa, &itnim->timer,
927			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
928	}
929}
930
931/**
932 * Stop IO TOV timer.
933 */
934static void
935bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
936{
937	if (itnim->iotov_active) {
938		itnim->iotov_active = BFA_FALSE;
939		bfa_timer_stop(&itnim->timer);
940	}
941}
942
943/**
944 * Stop IO TOV timer.
945 */
946static void
947bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
948{
949    bfa_boolean_t pathtov_active = BFA_FALSE;
950
951    if (itnim->iotov_active)
952		pathtov_active = BFA_TRUE;
953
954	bfa_itnim_iotov_stop(itnim);
955	if (pathtov_active)
956		bfa_cb_itnim_tov_begin(itnim->ditn);
957	bfa_itnim_iotov_cleanup(itnim);
958	if (pathtov_active)
959		bfa_cb_itnim_tov(itnim->ditn);
960}
961
962
963
964/**
965 *  bfa_itnim_public
966 */
967
968/**
969 * 		Itnim interrupt processing.
970 */
971void
972bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
973{
974	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
975	union bfi_itnim_i2h_msg_u msg;
976	struct bfa_itnim_s *itnim;
977
978	bfa_trc(bfa, m->mhdr.msg_id);
979
980	msg.msg = m;
981
982	switch (m->mhdr.msg_id) {
983	case BFI_ITNIM_I2H_CREATE_RSP:
984		itnim = BFA_ITNIM_FROM_TAG(fcpim,
985					       msg.create_rsp->bfa_handle);
986		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
987		bfa_stats(itnim, create_comps);
988		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
989		break;
990
991	case BFI_ITNIM_I2H_DELETE_RSP:
992		itnim = BFA_ITNIM_FROM_TAG(fcpim,
993					       msg.delete_rsp->bfa_handle);
994		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
995		bfa_stats(itnim, delete_comps);
996		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
997		break;
998
999	case BFI_ITNIM_I2H_SLER_EVENT:
1000		itnim = BFA_ITNIM_FROM_TAG(fcpim,
1001					       msg.sler_event->bfa_handle);
1002		bfa_stats(itnim, sler_events);
1003		bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
1004		break;
1005
1006	default:
1007		bfa_trc(bfa, m->mhdr.msg_id);
1008		bfa_assert(0);
1009	}
1010}
1011
1012
1013
1014/**
1015 *  bfa_itnim_api
1016 */
1017
1018struct bfa_itnim_s *
1019bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
1020{
1021	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
1022	struct bfa_itnim_s *itnim;
1023
1024	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
1025	bfa_assert(itnim->rport == rport);
1026
1027	itnim->ditn = ditn;
1028
1029	bfa_stats(itnim, creates);
1030	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
1031
1032	return itnim;
1033}
1034
1035void
1036bfa_itnim_delete(struct bfa_itnim_s *itnim)
1037{
1038	bfa_stats(itnim, deletes);
1039	bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
1040}
1041
1042void
1043bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
1044{
1045	itnim->seq_rec = seq_rec;
1046	bfa_stats(itnim, onlines);
1047	bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
1048}
1049
1050void
1051bfa_itnim_offline(struct bfa_itnim_s *itnim)
1052{
1053	bfa_stats(itnim, offlines);
1054	bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
1055}
1056
1057/**
1058 * Return true if itnim is considered offline for holding off IO request.
1059 * IO is not held if itnim is being deleted.
1060 */
1061bfa_boolean_t
1062bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
1063{
1064	return
1065		itnim->fcpim->path_tov && itnim->iotov_active &&
1066		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
1067		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
1068		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
1069		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
1070		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
1071		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable))
1072	;
1073}
1074
1075void
1076bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
1077	struct bfa_itnim_hal_stats_s *stats)
1078{
1079	*stats = itnim->stats;
1080}
1081
1082void
1083bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
1084{
1085	bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
1086}
1087