12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088 |
- /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
- #include <bfa.h>
- #include <bfa_fcpim.h>
- #include "bfa_fcpim_priv.h"
- BFA_TRC_FILE(HAL, ITNIM);
- #define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \
- ((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))
- #define bfa_fcpim_additn(__itnim) \
- list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
- #define bfa_fcpim_delitn(__itnim) do { \
- bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \
- list_del(&(__itnim)->qe); \
- bfa_assert(list_empty(&(__itnim)->io_q)); \
- bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \
- bfa_assert(list_empty(&(__itnim)->pending_q)); \
- } while (0)
- #define bfa_itnim_online_cb(__itnim) do { \
- if ((__itnim)->bfa->fcs) \
- bfa_cb_itnim_online((__itnim)->ditn); \
- else { \
- bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
- __bfa_cb_itnim_online, (__itnim)); \
- } \
- } while (0)
- #define bfa_itnim_offline_cb(__itnim) do { \
- if ((__itnim)->bfa->fcs) \
- bfa_cb_itnim_offline((__itnim)->ditn); \
- else { \
- bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
- __bfa_cb_itnim_offline, (__itnim)); \
- } \
- } while (0)
- #define bfa_itnim_sler_cb(__itnim) do { \
- if ((__itnim)->bfa->fcs) \
- bfa_cb_itnim_sler((__itnim)->ditn); \
- else { \
- bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
- __bfa_cb_itnim_sler, (__itnim)); \
- } \
- } while (0)
- /*
- * forward declarations
- */
- static void bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
- static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
- static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
- static void bfa_itnim_cleanp_comp(void *itnim_cbarg);
- static void bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
- static void __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
- static void __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
- static void __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
- static void bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
- static void bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
- static void bfa_itnim_iotov(void *itnim_arg);
- static void bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
- static void bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
- static void bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
- /**
- * bfa_itnim_sm BFA itnim state machine
- */
- enum bfa_itnim_event {
- BFA_ITNIM_SM_CREATE = 1, /* itnim is created */
- BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */
- BFA_ITNIM_SM_OFFLINE = 3, /* itnim is offline */
- BFA_ITNIM_SM_FWRSP = 4, /* firmware response */
- BFA_ITNIM_SM_DELETE = 5, /* deleting an existing itnim */
- BFA_ITNIM_SM_CLEANUP = 6, /* IO cleanup completion */
- BFA_ITNIM_SM_SLER = 7, /* second level error recovery */
- BFA_ITNIM_SM_HWFAIL = 8, /* IOC h/w failure event */
- BFA_ITNIM_SM_QRESUME = 9, /* queue space available */
- };
- static void bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
- /**
- * Beginning/unallocated state - no events expected.
- */
- static void
- bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_CREATE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_created);
- itnim->is_online = BFA_FALSE;
- bfa_fcpim_additn(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Beginning state, only online event expected.
- */
- static void
- bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_ONLINE:
- if (bfa_itnim_send_fwcreate(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_fcpim_delitn(itnim);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Waiting for itnim create response from firmware.
- */
- static void
- bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- bfa_sm_set_state(itnim, bfa_itnim_sm_online);
- itnim->is_online = BFA_TRUE;
- bfa_itnim_iotov_online(itnim);
- bfa_itnim_online_cb(itnim);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
- break;
- case BFA_ITNIM_SM_OFFLINE:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- break;
- default:
- bfa_assert(0);
- }
- }
- static void
- bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_QRESUME:
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- bfa_itnim_send_fwcreate(itnim);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_fcpim_delitn(itnim);
- break;
- case BFA_ITNIM_SM_OFFLINE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_itnim_offline_cb(itnim);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Waiting for itnim create response from firmware, a delete is pending.
- */
- static void
- bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_fcpim_delitn(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Online state - normal parking state.
- */
- static void
- bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_OFFLINE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_iotov_start(itnim);
- bfa_itnim_cleanup(itnim);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_cleanup(itnim);
- break;
- case BFA_ITNIM_SM_SLER:
- bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_iotov_start(itnim);
- bfa_itnim_sler_cb(itnim);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_iotov_start(itnim);
- bfa_itnim_iocdisable_cleanup(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Second level error recovery need.
- */
- static void
- bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_OFFLINE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
- bfa_itnim_cleanup(itnim);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
- bfa_itnim_cleanup(itnim);
- bfa_itnim_iotov_delete(itnim);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_iocdisable_cleanup(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Going offline. Waiting for active IO cleanup.
- */
- static void
- bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_CLEANUP:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
- bfa_itnim_iotov_delete(itnim);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_iocdisable_cleanup(itnim);
- bfa_itnim_offline_cb(itnim);
- break;
- case BFA_ITNIM_SM_SLER:
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Deleting itnim. Waiting for active IO cleanup.
- */
- static void
- bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_CLEANUP:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_iocdisable_cleanup(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
- */
- static void
- bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
- bfa_itnim_offline_cb(itnim);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_offline_cb(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- static void
- bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_QRESUME:
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
- bfa_itnim_send_fwdelete(itnim);
- break;
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_itnim_offline_cb(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Offline state.
- */
- static void
- bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_itnim_iotov_delete(itnim);
- bfa_fcpim_delitn(itnim);
- break;
- case BFA_ITNIM_SM_ONLINE:
- if (bfa_itnim_send_fwcreate(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * IOC h/w failed state.
- */
- static void
- bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_itnim_iotov_delete(itnim);
- bfa_fcpim_delitn(itnim);
- break;
- case BFA_ITNIM_SM_OFFLINE:
- bfa_itnim_offline_cb(itnim);
- break;
- case BFA_ITNIM_SM_ONLINE:
- if (bfa_itnim_send_fwcreate(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * Itnim is deleted, waiting for firmware response to delete.
- */
- static void
- bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_fcpim_delitn(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- static void
- bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
- {
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
- switch (event) {
- case BFA_ITNIM_SM_QRESUME:
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- bfa_itnim_send_fwdelete(itnim);
- break;
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_fcpim_delitn(itnim);
- break;
- default:
- bfa_assert(0);
- }
- }
- /**
- * bfa_itnim_private
- */
- /**
- * Initiate cleanup of all IOs on an IOC failure.
- */
- static void
- bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
- {
- struct bfa_tskim_s *tskim;
- struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
- list_for_each_safe(qe, qen, &itnim->tsk_q) {
- tskim = (struct bfa_tskim_s *) qe;
- bfa_tskim_iocdisable(tskim);
- }
- list_for_each_safe(qe, qen, &itnim->io_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_ioim_iocdisable(ioim);
- }
- /**
- * For IO request in pending queue, we pretend an early timeout.
- */
- list_for_each_safe(qe, qen, &itnim->pending_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_ioim_tov(ioim);
- }
- list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_ioim_iocdisable(ioim);
- }
- }
- /**
- * IO cleanup completion
- */
- static void
- bfa_itnim_cleanp_comp(void *itnim_cbarg)
- {
- struct bfa_itnim_s *itnim = itnim_cbarg;
- bfa_stats(itnim, cleanup_comps);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
- }
- /**
- * Initiate cleanup of all IOs.
- */
- static void
- bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
- {
- struct bfa_ioim_s *ioim;
- struct bfa_tskim_s *tskim;
- struct list_head *qe, *qen;
- bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
- list_for_each_safe(qe, qen, &itnim->io_q) {
- ioim = (struct bfa_ioim_s *) qe;
- /**
- * Move IO to a cleanup queue from active queue so that a later
- * TM will not pickup this IO.
- */
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
- bfa_wc_up(&itnim->wc);
- bfa_ioim_cleanup(ioim);
- }
- list_for_each_safe(qe, qen, &itnim->tsk_q) {
- tskim = (struct bfa_tskim_s *) qe;
- bfa_wc_up(&itnim->wc);
- bfa_tskim_cleanup(tskim);
- }
- bfa_wc_wait(&itnim->wc);
- }
- static void
- __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
- {
- struct bfa_itnim_s *itnim = cbarg;
- if (complete)
- bfa_cb_itnim_online(itnim->ditn);
- }
- static void
- __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
- {
- struct bfa_itnim_s *itnim = cbarg;
- if (complete)
- bfa_cb_itnim_offline(itnim->ditn);
- }
- static void
- __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
- {
- struct bfa_itnim_s *itnim = cbarg;
- if (complete)
- bfa_cb_itnim_sler(itnim->ditn);
- }
- /**
- * Call to resume any I/O requests waiting for room in request queue.
- */
- static void
- bfa_itnim_qresume(void *cbarg)
- {
- struct bfa_itnim_s *itnim = cbarg;
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
- }
- /**
- * bfa_itnim_public
- */
- void
- bfa_itnim_iodone(struct bfa_itnim_s *itnim)
- {
- bfa_wc_down(&itnim->wc);
- }
- void
- bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
- {
- bfa_wc_down(&itnim->wc);
- }
- void
- bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
- {
- /**
- * ITN memory
- */
- *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
- }
- void
- bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
- {
- struct bfa_s *bfa = fcpim->bfa;
- struct bfa_itnim_s *itnim;
- int i;
- INIT_LIST_HEAD(&fcpim->itnim_q);
- itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
- fcpim->itnim_arr = itnim;
- for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
- bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
- itnim->bfa = bfa;
- itnim->fcpim = fcpim;
- itnim->reqq = BFA_REQQ_QOS_LO;
- itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
- itnim->iotov_active = BFA_FALSE;
- bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
- INIT_LIST_HEAD(&itnim->io_q);
- INIT_LIST_HEAD(&itnim->io_cleanup_q);
- INIT_LIST_HEAD(&itnim->pending_q);
- INIT_LIST_HEAD(&itnim->tsk_q);
- INIT_LIST_HEAD(&itnim->delay_comp_q);
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- }
- bfa_meminfo_kva(minfo) = (u8 *) itnim;
- }
- void
- bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
- {
- bfa_stats(itnim, ioc_disabled);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
- }
- static bfa_boolean_t
- bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
- {
- struct bfi_itnim_create_req_s *m;
- itnim->msg_no++;
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(itnim->bfa, itnim->reqq);
- if (!m) {
- bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
- return BFA_FALSE;
- }
- bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
- bfa_lpuid(itnim->bfa));
- m->fw_handle = itnim->rport->fw_handle;
- m->class = FC_CLASS_3;
- m->seq_rec = itnim->seq_rec;
- m->msg_no = itnim->msg_no;
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(itnim->bfa, itnim->reqq);
- return BFA_TRUE;
- }
- static bfa_boolean_t
- bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
- {
- struct bfi_itnim_delete_req_s *m;
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(itnim->bfa, itnim->reqq);
- if (!m) {
- bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
- return BFA_FALSE;
- }
- bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
- bfa_lpuid(itnim->bfa));
- m->fw_handle = itnim->rport->fw_handle;
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(itnim->bfa, itnim->reqq);
- return BFA_TRUE;
- }
- /**
- * Cleanup all pending failed inflight requests.
- */
- static void
- bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
- {
- struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
- list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
- ioim = (struct bfa_ioim_s *)qe;
- bfa_ioim_delayed_comp(ioim, iotov);
- }
- }
- /**
- * Start all pending IO requests.
- */
- static void
- bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
- {
- struct bfa_ioim_s *ioim;
- bfa_itnim_iotov_stop(itnim);
- /**
- * Abort all inflight IO requests in the queue
- */
- bfa_itnim_delayed_comp(itnim, BFA_FALSE);
- /**
- * Start all pending IO requests.
- */
- while (!list_empty(&itnim->pending_q)) {
- bfa_q_deq(&itnim->pending_q, &ioim);
- list_add_tail(&ioim->qe, &itnim->io_q);
- bfa_ioim_start(ioim);
- }
- }
- /**
- * Fail all pending IO requests
- */
- static void
- bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
- {
- struct bfa_ioim_s *ioim;
- /**
- * Fail all inflight IO requests in the queue
- */
- bfa_itnim_delayed_comp(itnim, BFA_TRUE);
- /**
- * Fail any pending IO requests.
- */
- while (!list_empty(&itnim->pending_q)) {
- bfa_q_deq(&itnim->pending_q, &ioim);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_ioim_tov(ioim);
- }
- }
- /**
- * IO TOV timer callback. Fail any pending IO requests.
- */
- static void
- bfa_itnim_iotov(void *itnim_arg)
- {
- struct bfa_itnim_s *itnim = itnim_arg;
- itnim->iotov_active = BFA_FALSE;
- bfa_cb_itnim_tov_begin(itnim->ditn);
- bfa_itnim_iotov_cleanup(itnim);
- bfa_cb_itnim_tov(itnim->ditn);
- }
- /**
- * Start IO TOV timer for failing back pending IO requests in offline state.
- */
- static void
- bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
- {
- if (itnim->fcpim->path_tov > 0) {
- itnim->iotov_active = BFA_TRUE;
- bfa_assert(bfa_itnim_hold_io(itnim));
- bfa_timer_start(itnim->bfa, &itnim->timer,
- bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
- }
- }
- /**
- * Stop IO TOV timer.
- */
- static void
- bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
- {
- if (itnim->iotov_active) {
- itnim->iotov_active = BFA_FALSE;
- bfa_timer_stop(&itnim->timer);
- }
- }
- /**
- * Stop IO TOV timer.
- */
- static void
- bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
- {
- bfa_boolean_t pathtov_active = BFA_FALSE;
- if (itnim->iotov_active)
- pathtov_active = BFA_TRUE;
- bfa_itnim_iotov_stop(itnim);
- if (pathtov_active)
- bfa_cb_itnim_tov_begin(itnim->ditn);
- bfa_itnim_iotov_cleanup(itnim);
- if (pathtov_active)
- bfa_cb_itnim_tov(itnim->ditn);
- }
- /**
- * bfa_itnim_public
- */
- /**
- * Itnim interrupt processing.
- */
- void
- bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
- {
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- union bfi_itnim_i2h_msg_u msg;
- struct bfa_itnim_s *itnim;
- bfa_trc(bfa, m->mhdr.msg_id);
- msg.msg = m;
- switch (m->mhdr.msg_id) {
- case BFI_ITNIM_I2H_CREATE_RSP:
- itnim = BFA_ITNIM_FROM_TAG(fcpim,
- msg.create_rsp->bfa_handle);
- bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
- bfa_stats(itnim, create_comps);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
- break;
- case BFI_ITNIM_I2H_DELETE_RSP:
- itnim = BFA_ITNIM_FROM_TAG(fcpim,
- msg.delete_rsp->bfa_handle);
- bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
- bfa_stats(itnim, delete_comps);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
- break;
- case BFI_ITNIM_I2H_SLER_EVENT:
- itnim = BFA_ITNIM_FROM_TAG(fcpim,
- msg.sler_event->bfa_handle);
- bfa_stats(itnim, sler_events);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
- break;
- default:
- bfa_trc(bfa, m->mhdr.msg_id);
- bfa_assert(0);
- }
- }
- /**
- * bfa_itnim_api
- */
- struct bfa_itnim_s *
- bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
- {
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct bfa_itnim_s *itnim;
- itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
- bfa_assert(itnim->rport == rport);
- itnim->ditn = ditn;
- bfa_stats(itnim, creates);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
- return itnim;
- }
- void
- bfa_itnim_delete(struct bfa_itnim_s *itnim)
- {
- bfa_stats(itnim, deletes);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
- }
- void
- bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
- {
- itnim->seq_rec = seq_rec;
- bfa_stats(itnim, onlines);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
- }
- void
- bfa_itnim_offline(struct bfa_itnim_s *itnim)
- {
- bfa_stats(itnim, offlines);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
- }
- /**
- * Return true if itnim is considered offline for holding off IO request.
- * IO is not held if itnim is being deleted.
- */
- bfa_boolean_t
- bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
- {
- return
- itnim->fcpim->path_tov && itnim->iotov_active &&
- (bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable))
- ;
- }
- void
- bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
- struct bfa_itnim_hal_stats_s *stats)
- {
- *stats = itnim->stats;
- }
- void
- bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
- {
- bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
- }
|