libata-sff: separate out BMDMA qc_issue
[safe/jmp/linux-2.6] / drivers / scsi / bfa / bfa_itnim.c
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
22 BFA_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  */
67 static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
68 static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
69 static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
70 static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
71 static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
72 static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
73 static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
74 static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
75 static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
76 static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
77 static void     bfa_itnim_iotov(void *itnim_arg);
78 static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
79 static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
80 static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
81
82 /**
83  *  bfa_itnim_sm BFA itnim state machine
84  */
85
86
87 enum 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
99 static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
100                                         enum bfa_itnim_event event);
101 static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
102                                          enum bfa_itnim_event event);
103 static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
104                                           enum bfa_itnim_event event);
105 static void     bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
106                                 enum bfa_itnim_event event);
107 static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
108                                         enum bfa_itnim_event event);
109 static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
110                                       enum bfa_itnim_event event);
111 static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
112                                                  enum bfa_itnim_event event);
113 static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
114                                                 enum bfa_itnim_event event);
115 static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
116                                           enum bfa_itnim_event event);
117 static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
118                                          enum bfa_itnim_event event);
119 static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
120                                             enum bfa_itnim_event event);
121 static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
122                                           enum bfa_itnim_event event);
123 static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
124                                           enum bfa_itnim_event event);
125 static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
126                                           enum bfa_itnim_event event);
127 static 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  */
133 static void
134 bfa_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  */
154 static void
155 bfa_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  */
185 static void
186 bfa_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
219 static void
220 bfa_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  */
257 static void
258 bfa_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  */
285 static void
286 bfa_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  */
327 static void
328 bfa_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  */
358 static void
359 bfa_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  */
395 static void
396 bfa_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  */
423 static void
424 bfa_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
449 static void
450 bfa_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  */
480 static void
481 bfa_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  */
512 static void
513 bfa_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  */
548 static void
549 bfa_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
566 static void
567 bfa_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  */
599 static void
600 bfa_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  */
633 static void
634 bfa_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  */
645 static void
646 bfa_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
677 static 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
686 static 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
695 static 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  */
707 static void
708 bfa_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
722 void
723 bfa_itnim_iodone(struct bfa_itnim_s *itnim)
724 {
725         bfa_wc_down(&itnim->wc);
726 }
727
728 void
729 bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
730 {
731         bfa_wc_down(&itnim->wc);
732 }
733
734 void
735 bfa_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
744 void
745 bfa_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
776 void
777 bfa_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
783 static bfa_boolean_t
784 bfa_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
813 static bfa_boolean_t
814 bfa_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  */
841 static void
842 bfa_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  */
856 static void
857 bfa_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  */
881 static void
882 bfa_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  */
904 static void
905 bfa_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  */
919 static void
920 bfa_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  */
934 static void
935 bfa_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  */
946 static void
947 bfa_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  */
971 void
972 bfa_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
1018 struct bfa_itnim_s *
1019 bfa_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
1035 void
1036 bfa_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
1042 void
1043 bfa_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
1050 void
1051 bfa_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  */
1061 bfa_boolean_t
1062 bfa_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
1075 void
1076 bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
1077         struct bfa_itnim_hal_stats_s *stats)
1078 {
1079         *stats = itnim->stats;
1080 }
1081
1082 void
1083 bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
1084 {
1085         bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
1086 }
1087
1088