brintos

brintos / linux-shallow public Read only

0
0
Text · 92.1 KiB · 28ae4dc Raw
3847 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.4 * Copyright (c) 2014- QLogic Corporation.5 * All rights reserved6 * www.qlogic.com7 *8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.9 */10 11#include "bfad_drv.h"12#include "bfa_modules.h"13 14BFA_TRC_FILE(HAL, FCPIM);15 16/*17 *  BFA ITNIM Related definitions18 */19static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);20 21#define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                                \22	(((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))))23 24#define bfa_fcpim_additn(__itnim)					\25	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)26#define bfa_fcpim_delitn(__itnim)	do {				\27	WARN_ON(!bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));   \28	bfa_itnim_update_del_itn_stats(__itnim);      \29	list_del(&(__itnim)->qe);      \30	WARN_ON(!list_empty(&(__itnim)->io_q));				\31	WARN_ON(!list_empty(&(__itnim)->io_cleanup_q));			\32	WARN_ON(!list_empty(&(__itnim)->pending_q));			\33} while (0)34 35#define bfa_itnim_online_cb(__itnim) do {				\36	if ((__itnim)->bfa->fcs)					\37		bfa_cb_itnim_online((__itnim)->ditn);      \38	else {								\39		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\40		__bfa_cb_itnim_online, (__itnim));      \41	}								\42} while (0)43 44#define bfa_itnim_offline_cb(__itnim) do {				\45	if ((__itnim)->bfa->fcs)					\46		bfa_cb_itnim_offline((__itnim)->ditn);      \47	else {								\48		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\49		__bfa_cb_itnim_offline, (__itnim));      \50	}								\51} while (0)52 53#define bfa_itnim_sler_cb(__itnim) do {					\54	if ((__itnim)->bfa->fcs)					\55		bfa_cb_itnim_sler((__itnim)->ditn);      \56	else {								\57		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\58		__bfa_cb_itnim_sler, (__itnim));      \59	}								\60} while (0)61 62enum bfa_ioim_lm_ua_status {63	BFA_IOIM_LM_UA_RESET = 0,64	BFA_IOIM_LM_UA_SET = 1,65};66 67/*68 *  BFA IOIM related definitions69 */70#define bfa_ioim_move_to_comp_q(__ioim) do {				\71	list_del(&(__ioim)->qe);					\72	list_add_tail(&(__ioim)->qe, &(__ioim)->fcpim->ioim_comp_q);	\73} while (0)74 75 76#define bfa_ioim_cb_profile_comp(__fcpim, __ioim) do {			\77	if ((__fcpim)->profile_comp)					\78		(__fcpim)->profile_comp(__ioim);			\79} while (0)80 81#define bfa_ioim_cb_profile_start(__fcpim, __ioim) do {			\82	if ((__fcpim)->profile_start)					\83		(__fcpim)->profile_start(__ioim);			\84} while (0)85 86 87/*88 *  BFA TSKIM related definitions89 */90 91/*92 * task management completion handling93 */94#define bfa_tskim_qcomp(__tskim, __cbfn) do {				\95	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim));\96	bfa_tskim_notify_comp(__tskim);      \97} while (0)98 99#define bfa_tskim_notify_comp(__tskim) do {				\100	if ((__tskim)->notify)						\101		bfa_itnim_tskdone((__tskim)->itnim);      \102} while (0)103 104 105/*106 * forward declaration for BFA ITNIM functions107 */108static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);109static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);110static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);111static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);112static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);113static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);114static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);115static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);116static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);117static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);118static void     bfa_itnim_iotov(void *itnim_arg);119static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);120static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);121static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);122 123/*124 * forward declaration of ITNIM state machine125 */126static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,127					enum bfa_itnim_event event);128static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,129					enum bfa_itnim_event event);130static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,131					enum bfa_itnim_event event);132static void     bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,133					enum bfa_itnim_event event);134static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,135					enum bfa_itnim_event event);136static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,137					enum bfa_itnim_event event);138static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,139					enum bfa_itnim_event event);140static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,141					enum bfa_itnim_event event);142static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,143					enum bfa_itnim_event event);144static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,145					enum bfa_itnim_event event);146static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,147					enum bfa_itnim_event event);148static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,149					enum bfa_itnim_event event);150static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,151					enum bfa_itnim_event event);152static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,153					enum bfa_itnim_event event);154static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,155					enum bfa_itnim_event event);156 157/*158 * forward declaration for BFA IOIM functions159 */160static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);161static bfa_boolean_t	bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim);162static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);163static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);164static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);165static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);166static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);167static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);168static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);169static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);170 171/*172 * forward declaration of BFA IO state machine173 */174static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,175					enum bfa_ioim_event event);176static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,177					enum bfa_ioim_event event);178static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,179					enum bfa_ioim_event event);180static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,181					enum bfa_ioim_event event);182static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,183					enum bfa_ioim_event event);184static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,185					enum bfa_ioim_event event);186static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,187					enum bfa_ioim_event event);188static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,189					enum bfa_ioim_event event);190static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,191					enum bfa_ioim_event event);192static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,193					enum bfa_ioim_event event);194static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,195					enum bfa_ioim_event event);196static void	bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,197					enum bfa_ioim_event event);198/*199 * forward declaration for BFA TSKIM functions200 */201static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);202static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);203static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,204					struct scsi_lun lun);205static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);206static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);207static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);208static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);209static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);210static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);211 212/*213 * forward declaration of BFA TSKIM state machine214 */215static void     bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,216					enum bfa_tskim_event event);217static void     bfa_tskim_sm_active(struct bfa_tskim_s *tskim,218					enum bfa_tskim_event event);219static void     bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,220					enum bfa_tskim_event event);221static void     bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,222					enum bfa_tskim_event event);223static void     bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,224					enum bfa_tskim_event event);225static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,226					enum bfa_tskim_event event);227static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,228					enum bfa_tskim_event event);229/*230 *  BFA FCP Initiator Mode module231 */232 233/*234 * Compute and return memory needed by FCP(im) module.235 */236static void237bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)238{239	bfa_itnim_meminfo(cfg, km_len);240 241	/*242	 * IO memory243	 */244	*km_len += cfg->fwcfg.num_ioim_reqs *245	  (sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s));246 247	/*248	 * task management command memory249	 */250	if (cfg->fwcfg.num_tskim_reqs < BFA_TSKIM_MIN)251		cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN;252	*km_len += cfg->fwcfg.num_tskim_reqs * sizeof(struct bfa_tskim_s);253}254 255 256static void257bfa_fcpim_attach(struct bfa_fcp_mod_s *fcp, void *bfad,258		struct bfa_iocfc_cfg_s *cfg, struct bfa_pcidev_s *pcidev)259{260	struct bfa_fcpim_s *fcpim = &fcp->fcpim;261	struct bfa_s *bfa = fcp->bfa;262 263	bfa_trc(bfa, cfg->drvcfg.path_tov);264	bfa_trc(bfa, cfg->fwcfg.num_rports);265	bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);266	bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);267 268	fcpim->fcp		= fcp;269	fcpim->bfa		= bfa;270	fcpim->num_itnims	= cfg->fwcfg.num_rports;271	fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;272	fcpim->path_tov		= cfg->drvcfg.path_tov;273	fcpim->delay_comp	= cfg->drvcfg.delay_comp;274	fcpim->profile_comp = NULL;275	fcpim->profile_start = NULL;276 277	bfa_itnim_attach(fcpim);278	bfa_tskim_attach(fcpim);279	bfa_ioim_attach(fcpim);280}281 282void283bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *fcp)284{285	struct bfa_fcpim_s *fcpim = &fcp->fcpim;286	struct bfa_itnim_s *itnim;287	struct list_head *qe, *qen;288 289	/* Enqueue unused ioim resources to free_q */290	list_splice_tail_init(&fcpim->tskim_unused_q, &fcpim->tskim_free_q);291 292	list_for_each_safe(qe, qen, &fcpim->itnim_q) {293		itnim = (struct bfa_itnim_s *) qe;294		bfa_itnim_iocdisable(itnim);295	}296}297 298void299bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)300{301	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);302 303	fcpim->path_tov = path_tov * 1000;304	if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX)305		fcpim->path_tov = BFA_FCPIM_PATHTOV_MAX;306}307 308u16309bfa_fcpim_path_tov_get(struct bfa_s *bfa)310{311	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);312 313	return fcpim->path_tov / 1000;314}315 316#define bfa_fcpim_add_iostats(__l, __r, __stats)	\317	(__l->__stats += __r->__stats)318 319void320bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,321		struct bfa_itnim_iostats_s *rstats)322{323	bfa_fcpim_add_iostats(lstats, rstats, total_ios);324	bfa_fcpim_add_iostats(lstats, rstats, qresumes);325	bfa_fcpim_add_iostats(lstats, rstats, no_iotags);326	bfa_fcpim_add_iostats(lstats, rstats, io_aborts);327	bfa_fcpim_add_iostats(lstats, rstats, no_tskims);328	bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);329	bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);330	bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);331	bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);332	bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);333	bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);334	bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);335	bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);336	bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);337	bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);338	bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);339	bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);340	bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);341	bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);342	bfa_fcpim_add_iostats(lstats, rstats, onlines);343	bfa_fcpim_add_iostats(lstats, rstats, offlines);344	bfa_fcpim_add_iostats(lstats, rstats, creates);345	bfa_fcpim_add_iostats(lstats, rstats, deletes);346	bfa_fcpim_add_iostats(lstats, rstats, create_comps);347	bfa_fcpim_add_iostats(lstats, rstats, delete_comps);348	bfa_fcpim_add_iostats(lstats, rstats, sler_events);349	bfa_fcpim_add_iostats(lstats, rstats, fw_create);350	bfa_fcpim_add_iostats(lstats, rstats, fw_delete);351	bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);352	bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);353	bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);354	bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);355	bfa_fcpim_add_iostats(lstats, rstats, tm_success);356	bfa_fcpim_add_iostats(lstats, rstats, tm_failures);357	bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);358	bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);359	bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);360	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);361	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);362	bfa_fcpim_add_iostats(lstats, rstats, io_comps);363	bfa_fcpim_add_iostats(lstats, rstats, input_reqs);364	bfa_fcpim_add_iostats(lstats, rstats, output_reqs);365	bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);366	bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);367}368 369bfa_status_t370bfa_fcpim_port_iostats(struct bfa_s *bfa,371		struct bfa_itnim_iostats_s *stats, u8 lp_tag)372{373	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);374	struct list_head *qe, *qen;375	struct bfa_itnim_s *itnim;376 377	/* accumulate IO stats from itnim */378	memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));379	list_for_each_safe(qe, qen, &fcpim->itnim_q) {380		itnim = (struct bfa_itnim_s *) qe;381		if (itnim->rport->rport_info.lp_tag != lp_tag)382			continue;383		bfa_fcpim_add_stats(stats, &(itnim->stats));384	}385	return BFA_STATUS_OK;386}387 388static void389bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)390{391	struct bfa_itnim_latency_s *io_lat =392			&(ioim->itnim->ioprofile.io_latency);393	u32 val, idx;394 395	val = (u32)(jiffies - ioim->start_time);396	idx = bfa_ioim_get_index(scsi_bufflen((struct scsi_cmnd *)ioim->dio));397	bfa_itnim_ioprofile_update(ioim->itnim, idx);398 399	io_lat->count[idx]++;400	io_lat->min[idx] = (io_lat->min[idx] < val) ? io_lat->min[idx] : val;401	io_lat->max[idx] = (io_lat->max[idx] > val) ? io_lat->max[idx] : val;402	io_lat->avg[idx] += val;403}404 405static void406bfa_ioim_profile_start(struct bfa_ioim_s *ioim)407{408	ioim->start_time = jiffies;409}410 411bfa_status_t412bfa_fcpim_profile_on(struct bfa_s *bfa, time64_t time)413{414	struct bfa_itnim_s *itnim;415	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);416	struct list_head *qe, *qen;417 418	/* accumulate IO stats from itnim */419	list_for_each_safe(qe, qen, &fcpim->itnim_q) {420		itnim = (struct bfa_itnim_s *) qe;421		bfa_itnim_clear_stats(itnim);422	}423	fcpim->io_profile = BFA_TRUE;424	fcpim->io_profile_start_time = time;425	fcpim->profile_comp = bfa_ioim_profile_comp;426	fcpim->profile_start = bfa_ioim_profile_start;427	return BFA_STATUS_OK;428}429 430bfa_status_t431bfa_fcpim_profile_off(struct bfa_s *bfa)432{433	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);434	fcpim->io_profile = BFA_FALSE;435	fcpim->io_profile_start_time = 0;436	fcpim->profile_comp = NULL;437	fcpim->profile_start = NULL;438	return BFA_STATUS_OK;439}440 441u16442bfa_fcpim_qdepth_get(struct bfa_s *bfa)443{444	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);445 446	return fcpim->q_depth;447}448 449/*450 *  BFA ITNIM module state machine functions451 */452 453/*454 * Beginning/unallocated state - no events expected.455 */456static void457bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)458{459	bfa_trc(itnim->bfa, itnim->rport->rport_tag);460	bfa_trc(itnim->bfa, event);461 462	switch (event) {463	case BFA_ITNIM_SM_CREATE:464		bfa_sm_set_state(itnim, bfa_itnim_sm_created);465		itnim->is_online = BFA_FALSE;466		bfa_fcpim_additn(itnim);467		break;468 469	default:470		bfa_sm_fault(itnim->bfa, event);471	}472}473 474/*475 * Beginning state, only online event expected.476 */477static void478bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)479{480	bfa_trc(itnim->bfa, itnim->rport->rport_tag);481	bfa_trc(itnim->bfa, event);482 483	switch (event) {484	case BFA_ITNIM_SM_ONLINE:485		if (bfa_itnim_send_fwcreate(itnim))486			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);487		else488			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);489		break;490 491	case BFA_ITNIM_SM_DELETE:492		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);493		bfa_fcpim_delitn(itnim);494		break;495 496	case BFA_ITNIM_SM_HWFAIL:497		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);498		break;499 500	default:501		bfa_sm_fault(itnim->bfa, event);502	}503}504 505/*506 *	Waiting for itnim create response from firmware.507 */508static void509bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)510{511	bfa_trc(itnim->bfa, itnim->rport->rport_tag);512	bfa_trc(itnim->bfa, event);513 514	switch (event) {515	case BFA_ITNIM_SM_FWRSP:516		bfa_sm_set_state(itnim, bfa_itnim_sm_online);517		itnim->is_online = BFA_TRUE;518		bfa_itnim_iotov_online(itnim);519		bfa_itnim_online_cb(itnim);520		break;521 522	case BFA_ITNIM_SM_DELETE:523		bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);524		break;525 526	case BFA_ITNIM_SM_OFFLINE:527		if (bfa_itnim_send_fwdelete(itnim))528			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);529		else530			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);531		break;532 533	case BFA_ITNIM_SM_HWFAIL:534		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);535		break;536 537	default:538		bfa_sm_fault(itnim->bfa, event);539	}540}541 542static void543bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,544			enum bfa_itnim_event event)545{546	bfa_trc(itnim->bfa, itnim->rport->rport_tag);547	bfa_trc(itnim->bfa, event);548 549	switch (event) {550	case BFA_ITNIM_SM_QRESUME:551		bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);552		bfa_itnim_send_fwcreate(itnim);553		break;554 555	case BFA_ITNIM_SM_DELETE:556		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);557		bfa_reqq_wcancel(&itnim->reqq_wait);558		bfa_fcpim_delitn(itnim);559		break;560 561	case BFA_ITNIM_SM_OFFLINE:562		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);563		bfa_reqq_wcancel(&itnim->reqq_wait);564		bfa_itnim_offline_cb(itnim);565		break;566 567	case BFA_ITNIM_SM_HWFAIL:568		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);569		bfa_reqq_wcancel(&itnim->reqq_wait);570		break;571 572	default:573		bfa_sm_fault(itnim->bfa, event);574	}575}576 577/*578 * Waiting for itnim create response from firmware, a delete is pending.579 */580static void581bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,582				enum bfa_itnim_event event)583{584	bfa_trc(itnim->bfa, itnim->rport->rport_tag);585	bfa_trc(itnim->bfa, event);586 587	switch (event) {588	case BFA_ITNIM_SM_FWRSP:589		if (bfa_itnim_send_fwdelete(itnim))590			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);591		else592			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);593		break;594 595	case BFA_ITNIM_SM_HWFAIL:596		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);597		bfa_fcpim_delitn(itnim);598		break;599 600	default:601		bfa_sm_fault(itnim->bfa, event);602	}603}604 605/*606 * Online state - normal parking state.607 */608static void609bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)610{611	bfa_trc(itnim->bfa, itnim->rport->rport_tag);612	bfa_trc(itnim->bfa, event);613 614	switch (event) {615	case BFA_ITNIM_SM_OFFLINE:616		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);617		itnim->is_online = BFA_FALSE;618		bfa_itnim_iotov_start(itnim);619		bfa_itnim_cleanup(itnim);620		break;621 622	case BFA_ITNIM_SM_DELETE:623		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);624		itnim->is_online = BFA_FALSE;625		bfa_itnim_cleanup(itnim);626		break;627 628	case BFA_ITNIM_SM_SLER:629		bfa_sm_set_state(itnim, bfa_itnim_sm_sler);630		itnim->is_online = BFA_FALSE;631		bfa_itnim_iotov_start(itnim);632		bfa_itnim_sler_cb(itnim);633		break;634 635	case BFA_ITNIM_SM_HWFAIL:636		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);637		itnim->is_online = BFA_FALSE;638		bfa_itnim_iotov_start(itnim);639		bfa_itnim_iocdisable_cleanup(itnim);640		break;641 642	default:643		bfa_sm_fault(itnim->bfa, event);644	}645}646 647/*648 * Second level error recovery need.649 */650static void651bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)652{653	bfa_trc(itnim->bfa, itnim->rport->rport_tag);654	bfa_trc(itnim->bfa, event);655 656	switch (event) {657	case BFA_ITNIM_SM_OFFLINE:658		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);659		bfa_itnim_cleanup(itnim);660		break;661 662	case BFA_ITNIM_SM_DELETE:663		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);664		bfa_itnim_cleanup(itnim);665		bfa_itnim_iotov_delete(itnim);666		break;667 668	case BFA_ITNIM_SM_HWFAIL:669		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);670		bfa_itnim_iocdisable_cleanup(itnim);671		break;672 673	default:674		bfa_sm_fault(itnim->bfa, event);675	}676}677 678/*679 * Going offline. Waiting for active IO cleanup.680 */681static void682bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,683				 enum bfa_itnim_event event)684{685	bfa_trc(itnim->bfa, itnim->rport->rport_tag);686	bfa_trc(itnim->bfa, event);687 688	switch (event) {689	case BFA_ITNIM_SM_CLEANUP:690		if (bfa_itnim_send_fwdelete(itnim))691			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);692		else693			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);694		break;695 696	case BFA_ITNIM_SM_DELETE:697		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);698		bfa_itnim_iotov_delete(itnim);699		break;700 701	case BFA_ITNIM_SM_HWFAIL:702		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);703		bfa_itnim_iocdisable_cleanup(itnim);704		bfa_itnim_offline_cb(itnim);705		break;706 707	case BFA_ITNIM_SM_SLER:708		break;709 710	default:711		bfa_sm_fault(itnim->bfa, event);712	}713}714 715/*716 * Deleting itnim. Waiting for active IO cleanup.717 */718static void719bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,720				enum bfa_itnim_event event)721{722	bfa_trc(itnim->bfa, itnim->rport->rport_tag);723	bfa_trc(itnim->bfa, event);724 725	switch (event) {726	case BFA_ITNIM_SM_CLEANUP:727		if (bfa_itnim_send_fwdelete(itnim))728			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);729		else730			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);731		break;732 733	case BFA_ITNIM_SM_HWFAIL:734		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);735		bfa_itnim_iocdisable_cleanup(itnim);736		break;737 738	default:739		bfa_sm_fault(itnim->bfa, event);740	}741}742 743/*744 * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.745 */746static void747bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)748{749	bfa_trc(itnim->bfa, itnim->rport->rport_tag);750	bfa_trc(itnim->bfa, event);751 752	switch (event) {753	case BFA_ITNIM_SM_FWRSP:754		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);755		bfa_itnim_offline_cb(itnim);756		break;757 758	case BFA_ITNIM_SM_DELETE:759		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);760		break;761 762	case BFA_ITNIM_SM_HWFAIL:763		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);764		bfa_itnim_offline_cb(itnim);765		break;766 767	default:768		bfa_sm_fault(itnim->bfa, event);769	}770}771 772static void773bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,774			enum bfa_itnim_event event)775{776	bfa_trc(itnim->bfa, itnim->rport->rport_tag);777	bfa_trc(itnim->bfa, event);778 779	switch (event) {780	case BFA_ITNIM_SM_QRESUME:781		bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);782		bfa_itnim_send_fwdelete(itnim);783		break;784 785	case BFA_ITNIM_SM_DELETE:786		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);787		break;788 789	case BFA_ITNIM_SM_HWFAIL:790		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);791		bfa_reqq_wcancel(&itnim->reqq_wait);792		bfa_itnim_offline_cb(itnim);793		break;794 795	default:796		bfa_sm_fault(itnim->bfa, event);797	}798}799 800/*801 * Offline state.802 */803static void804bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)805{806	bfa_trc(itnim->bfa, itnim->rport->rport_tag);807	bfa_trc(itnim->bfa, event);808 809	switch (event) {810	case BFA_ITNIM_SM_DELETE:811		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);812		bfa_itnim_iotov_delete(itnim);813		bfa_fcpim_delitn(itnim);814		break;815 816	case BFA_ITNIM_SM_ONLINE:817		if (bfa_itnim_send_fwcreate(itnim))818			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);819		else820			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);821		break;822 823	case BFA_ITNIM_SM_HWFAIL:824		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);825		break;826 827	default:828		bfa_sm_fault(itnim->bfa, event);829	}830}831 832static void833bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,834				enum bfa_itnim_event event)835{836	bfa_trc(itnim->bfa, itnim->rport->rport_tag);837	bfa_trc(itnim->bfa, event);838 839	switch (event) {840	case BFA_ITNIM_SM_DELETE:841		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);842		bfa_itnim_iotov_delete(itnim);843		bfa_fcpim_delitn(itnim);844		break;845 846	case BFA_ITNIM_SM_OFFLINE:847		bfa_itnim_offline_cb(itnim);848		break;849 850	case BFA_ITNIM_SM_ONLINE:851		if (bfa_itnim_send_fwcreate(itnim))852			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);853		else854			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);855		break;856 857	case BFA_ITNIM_SM_HWFAIL:858		break;859 860	default:861		bfa_sm_fault(itnim->bfa, event);862	}863}864 865/*866 * Itnim is deleted, waiting for firmware response to delete.867 */868static void869bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)870{871	bfa_trc(itnim->bfa, itnim->rport->rport_tag);872	bfa_trc(itnim->bfa, event);873 874	switch (event) {875	case BFA_ITNIM_SM_FWRSP:876	case BFA_ITNIM_SM_HWFAIL:877		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);878		bfa_fcpim_delitn(itnim);879		break;880 881	default:882		bfa_sm_fault(itnim->bfa, event);883	}884}885 886static void887bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,888		enum bfa_itnim_event event)889{890	bfa_trc(itnim->bfa, itnim->rport->rport_tag);891	bfa_trc(itnim->bfa, event);892 893	switch (event) {894	case BFA_ITNIM_SM_QRESUME:895		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);896		bfa_itnim_send_fwdelete(itnim);897		break;898 899	case BFA_ITNIM_SM_HWFAIL:900		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);901		bfa_reqq_wcancel(&itnim->reqq_wait);902		bfa_fcpim_delitn(itnim);903		break;904 905	default:906		bfa_sm_fault(itnim->bfa, event);907	}908}909 910/*911 * Initiate cleanup of all IOs on an IOC failure.912 */913static void914bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)915{916	struct bfa_tskim_s *tskim;917	struct bfa_ioim_s *ioim;918	struct list_head	*qe, *qen;919 920	list_for_each_safe(qe, qen, &itnim->tsk_q) {921		tskim = (struct bfa_tskim_s *) qe;922		bfa_tskim_iocdisable(tskim);923	}924 925	list_for_each_safe(qe, qen, &itnim->io_q) {926		ioim = (struct bfa_ioim_s *) qe;927		bfa_ioim_iocdisable(ioim);928	}929 930	/*931	 * For IO request in pending queue, we pretend an early timeout.932	 */933	list_for_each_safe(qe, qen, &itnim->pending_q) {934		ioim = (struct bfa_ioim_s *) qe;935		bfa_ioim_tov(ioim);936	}937 938	list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {939		ioim = (struct bfa_ioim_s *) qe;940		bfa_ioim_iocdisable(ioim);941	}942}943 944/*945 * IO cleanup completion946 */947static void948bfa_itnim_cleanp_comp(void *itnim_cbarg)949{950	struct bfa_itnim_s *itnim = itnim_cbarg;951 952	bfa_stats(itnim, cleanup_comps);953	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);954}955 956/*957 * Initiate cleanup of all IOs.958 */959static void960bfa_itnim_cleanup(struct bfa_itnim_s *itnim)961{962	struct bfa_ioim_s  *ioim;963	struct bfa_tskim_s *tskim;964	struct list_head	*qe, *qen;965 966	bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);967 968	list_for_each_safe(qe, qen, &itnim->io_q) {969		ioim = (struct bfa_ioim_s *) qe;970 971		/*972		 * Move IO to a cleanup queue from active queue so that a later973		 * TM will not pickup this IO.974		 */975		list_del(&ioim->qe);976		list_add_tail(&ioim->qe, &itnim->io_cleanup_q);977 978		bfa_wc_up(&itnim->wc);979		bfa_ioim_cleanup(ioim);980	}981 982	list_for_each_safe(qe, qen, &itnim->tsk_q) {983		tskim = (struct bfa_tskim_s *) qe;984		bfa_wc_up(&itnim->wc);985		bfa_tskim_cleanup(tskim);986	}987 988	bfa_wc_wait(&itnim->wc);989}990 991static void992__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)993{994	struct bfa_itnim_s *itnim = cbarg;995 996	if (complete)997		bfa_cb_itnim_online(itnim->ditn);998}999 1000static void1001__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)1002{1003	struct bfa_itnim_s *itnim = cbarg;1004 1005	if (complete)1006		bfa_cb_itnim_offline(itnim->ditn);1007}1008 1009static void1010__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)1011{1012	struct bfa_itnim_s *itnim = cbarg;1013 1014	if (complete)1015		bfa_cb_itnim_sler(itnim->ditn);1016}1017 1018/*1019 * Call to resume any I/O requests waiting for room in request queue.1020 */1021static void1022bfa_itnim_qresume(void *cbarg)1023{1024	struct bfa_itnim_s *itnim = cbarg;1025 1026	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);1027}1028 1029/*1030 *  bfa_itnim_public1031 */1032 1033void1034bfa_itnim_iodone(struct bfa_itnim_s *itnim)1035{1036	bfa_wc_down(&itnim->wc);1037}1038 1039void1040bfa_itnim_tskdone(struct bfa_itnim_s *itnim)1041{1042	bfa_wc_down(&itnim->wc);1043}1044 1045void1046bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)1047{1048	/*1049	 * ITN memory1050	 */1051	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);1052}1053 1054void1055bfa_itnim_attach(struct bfa_fcpim_s *fcpim)1056{1057	struct bfa_s	*bfa = fcpim->bfa;1058	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;1059	struct bfa_itnim_s *itnim;1060	int	i, j;1061 1062	INIT_LIST_HEAD(&fcpim->itnim_q);1063 1064	itnim = (struct bfa_itnim_s *) bfa_mem_kva_curp(fcp);1065	fcpim->itnim_arr = itnim;1066 1067	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {1068		memset(itnim, 0, sizeof(struct bfa_itnim_s));1069		itnim->bfa = bfa;1070		itnim->fcpim = fcpim;1071		itnim->reqq = BFA_REQQ_QOS_LO;1072		itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);1073		itnim->iotov_active = BFA_FALSE;1074		bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);1075 1076		INIT_LIST_HEAD(&itnim->io_q);1077		INIT_LIST_HEAD(&itnim->io_cleanup_q);1078		INIT_LIST_HEAD(&itnim->pending_q);1079		INIT_LIST_HEAD(&itnim->tsk_q);1080		INIT_LIST_HEAD(&itnim->delay_comp_q);1081		for (j = 0; j < BFA_IOBUCKET_MAX; j++)1082			itnim->ioprofile.io_latency.min[j] = ~0;1083		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);1084	}1085 1086	bfa_mem_kva_curp(fcp) = (u8 *) itnim;1087}1088 1089void1090bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)1091{1092	bfa_stats(itnim, ioc_disabled);1093	bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);1094}1095 1096static bfa_boolean_t1097bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)1098{1099	struct bfi_itn_create_req_s *m;1100 1101	itnim->msg_no++;1102 1103	/*1104	 * check for room in queue to send request now1105	 */1106	m = bfa_reqq_next(itnim->bfa, itnim->reqq);1107	if (!m) {1108		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);1109		return BFA_FALSE;1110	}1111 1112	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_CREATE_REQ,1113			bfa_fn_lpu(itnim->bfa));1114	m->fw_handle = itnim->rport->fw_handle;1115	m->class = FC_CLASS_3;1116	m->seq_rec = itnim->seq_rec;1117	m->msg_no = itnim->msg_no;1118	bfa_stats(itnim, fw_create);1119 1120	/*1121	 * queue I/O message to firmware1122	 */1123	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);1124	return BFA_TRUE;1125}1126 1127static bfa_boolean_t1128bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)1129{1130	struct bfi_itn_delete_req_s *m;1131 1132	/*1133	 * check for room in queue to send request now1134	 */1135	m = bfa_reqq_next(itnim->bfa, itnim->reqq);1136	if (!m) {1137		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);1138		return BFA_FALSE;1139	}1140 1141	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_DELETE_REQ,1142			bfa_fn_lpu(itnim->bfa));1143	m->fw_handle = itnim->rport->fw_handle;1144	bfa_stats(itnim, fw_delete);1145 1146	/*1147	 * queue I/O message to firmware1148	 */1149	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);1150	return BFA_TRUE;1151}1152 1153/*1154 * Cleanup all pending failed inflight requests.1155 */1156static void1157bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)1158{1159	struct bfa_ioim_s *ioim;1160	struct list_head *qe, *qen;1161 1162	list_for_each_safe(qe, qen, &itnim->delay_comp_q) {1163		ioim = (struct bfa_ioim_s *)qe;1164		bfa_ioim_delayed_comp(ioim, iotov);1165	}1166}1167 1168/*1169 * Start all pending IO requests.1170 */1171static void1172bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)1173{1174	struct bfa_ioim_s *ioim;1175 1176	bfa_itnim_iotov_stop(itnim);1177 1178	/*1179	 * Abort all inflight IO requests in the queue1180	 */1181	bfa_itnim_delayed_comp(itnim, BFA_FALSE);1182 1183	/*1184	 * Start all pending IO requests.1185	 */1186	while (!list_empty(&itnim->pending_q)) {1187		bfa_q_deq(&itnim->pending_q, &ioim);1188		list_add_tail(&ioim->qe, &itnim->io_q);1189		bfa_ioim_start(ioim);1190	}1191}1192 1193/*1194 * Fail all pending IO requests1195 */1196static void1197bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)1198{1199	struct bfa_ioim_s *ioim;1200 1201	/*1202	 * Fail all inflight IO requests in the queue1203	 */1204	bfa_itnim_delayed_comp(itnim, BFA_TRUE);1205 1206	/*1207	 * Fail any pending IO requests.1208	 */1209	while (!list_empty(&itnim->pending_q)) {1210		bfa_q_deq(&itnim->pending_q, &ioim);1211		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);1212		bfa_ioim_tov(ioim);1213	}1214}1215 1216/*1217 * IO TOV timer callback. Fail any pending IO requests.1218 */1219static void1220bfa_itnim_iotov(void *itnim_arg)1221{1222	struct bfa_itnim_s *itnim = itnim_arg;1223 1224	itnim->iotov_active = BFA_FALSE;1225 1226	bfa_cb_itnim_tov_begin(itnim->ditn);1227	bfa_itnim_iotov_cleanup(itnim);1228	bfa_cb_itnim_tov(itnim->ditn);1229}1230 1231/*1232 * Start IO TOV timer for failing back pending IO requests in offline state.1233 */1234static void1235bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)1236{1237	if (itnim->fcpim->path_tov > 0) {1238 1239		itnim->iotov_active = BFA_TRUE;1240		WARN_ON(!bfa_itnim_hold_io(itnim));1241		bfa_timer_start(itnim->bfa, &itnim->timer,1242			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);1243	}1244}1245 1246/*1247 * Stop IO TOV timer.1248 */1249static void1250bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)1251{1252	if (itnim->iotov_active) {1253		itnim->iotov_active = BFA_FALSE;1254		bfa_timer_stop(&itnim->timer);1255	}1256}1257 1258/*1259 * Stop IO TOV timer.1260 */1261static void1262bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)1263{1264	bfa_boolean_t pathtov_active = BFA_FALSE;1265 1266	if (itnim->iotov_active)1267		pathtov_active = BFA_TRUE;1268 1269	bfa_itnim_iotov_stop(itnim);1270	if (pathtov_active)1271		bfa_cb_itnim_tov_begin(itnim->ditn);1272	bfa_itnim_iotov_cleanup(itnim);1273	if (pathtov_active)1274		bfa_cb_itnim_tov(itnim->ditn);1275}1276 1277static void1278bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)1279{1280	struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);1281	fcpim->del_itn_stats.del_itn_iocomp_aborted +=1282		itnim->stats.iocomp_aborted;1283	fcpim->del_itn_stats.del_itn_iocomp_timedout +=1284		itnim->stats.iocomp_timedout;1285	fcpim->del_itn_stats.del_itn_iocom_sqer_needed +=1286		itnim->stats.iocom_sqer_needed;1287	fcpim->del_itn_stats.del_itn_iocom_res_free +=1288		itnim->stats.iocom_res_free;1289	fcpim->del_itn_stats.del_itn_iocom_hostabrts +=1290		itnim->stats.iocom_hostabrts;1291	fcpim->del_itn_stats.del_itn_total_ios += itnim->stats.total_ios;1292	fcpim->del_itn_stats.del_io_iocdowns += itnim->stats.io_iocdowns;1293	fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;1294}1295 1296/*1297 * bfa_itnim_public1298 */1299 1300/*1301 * Itnim interrupt processing.1302 */1303void1304bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)1305{1306	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);1307	union bfi_itn_i2h_msg_u msg;1308	struct bfa_itnim_s *itnim;1309 1310	bfa_trc(bfa, m->mhdr.msg_id);1311 1312	msg.msg = m;1313 1314	switch (m->mhdr.msg_id) {1315	case BFI_ITN_I2H_CREATE_RSP:1316		itnim = BFA_ITNIM_FROM_TAG(fcpim,1317						msg.create_rsp->bfa_handle);1318		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);1319		bfa_stats(itnim, create_comps);1320		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);1321		break;1322 1323	case BFI_ITN_I2H_DELETE_RSP:1324		itnim = BFA_ITNIM_FROM_TAG(fcpim,1325						msg.delete_rsp->bfa_handle);1326		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);1327		bfa_stats(itnim, delete_comps);1328		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);1329		break;1330 1331	case BFI_ITN_I2H_SLER_EVENT:1332		itnim = BFA_ITNIM_FROM_TAG(fcpim,1333						msg.sler_event->bfa_handle);1334		bfa_stats(itnim, sler_events);1335		bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);1336		break;1337 1338	default:1339		bfa_trc(bfa, m->mhdr.msg_id);1340		WARN_ON(1);1341	}1342}1343 1344/*1345 * bfa_itnim_api1346 */1347 1348struct bfa_itnim_s *1349bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)1350{1351	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);1352	struct bfa_itnim_s *itnim;1353 1354	bfa_itn_create(bfa, rport, bfa_itnim_isr);1355 1356	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);1357	WARN_ON(itnim->rport != rport);1358 1359	itnim->ditn = ditn;1360 1361	bfa_stats(itnim, creates);1362	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);1363 1364	return itnim;1365}1366 1367void1368bfa_itnim_delete(struct bfa_itnim_s *itnim)1369{1370	bfa_stats(itnim, deletes);1371	bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);1372}1373 1374void1375bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)1376{1377	itnim->seq_rec = seq_rec;1378	bfa_stats(itnim, onlines);1379	bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);1380}1381 1382void1383bfa_itnim_offline(struct bfa_itnim_s *itnim)1384{1385	bfa_stats(itnim, offlines);1386	bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);1387}1388 1389/*1390 * Return true if itnim is considered offline for holding off IO request.1391 * IO is not held if itnim is being deleted.1392 */1393bfa_boolean_t1394bfa_itnim_hold_io(struct bfa_itnim_s *itnim)1395{1396	return itnim->fcpim->path_tov && itnim->iotov_active &&1397		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||1398		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||1399		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||1400		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||1401		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||1402		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));1403}1404 1405#define bfa_io_lat_clock_res_div	HZ1406#define bfa_io_lat_clock_res_mul	10001407bfa_status_t1408bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,1409			struct bfa_itnim_ioprofile_s *ioprofile)1410{1411	struct bfa_fcpim_s *fcpim;1412 1413	if (!itnim)1414		return BFA_STATUS_NO_FCPIM_NEXUS;1415 1416	fcpim = BFA_FCPIM(itnim->bfa);1417 1418	if (!fcpim->io_profile)1419		return BFA_STATUS_IOPROFILE_OFF;1420 1421	itnim->ioprofile.index = BFA_IOBUCKET_MAX;1422	/* unsigned 32-bit time_t overflow here in y2106 */1423	itnim->ioprofile.io_profile_start_time =1424				bfa_io_profile_start_time(itnim->bfa);1425	itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;1426	itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;1427	*ioprofile = itnim->ioprofile;1428 1429	return BFA_STATUS_OK;1430}1431 1432void1433bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)1434{1435	int j;1436 1437	if (!itnim)1438		return;1439 1440	memset(&itnim->stats, 0, sizeof(itnim->stats));1441	memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));1442	for (j = 0; j < BFA_IOBUCKET_MAX; j++)1443		itnim->ioprofile.io_latency.min[j] = ~0;1444}1445 1446/*1447 *  BFA IO module state machine functions1448 */1449 1450/*1451 * IO is not started (unallocated).1452 */1453static void1454bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1455{1456	switch (event) {1457	case BFA_IOIM_SM_START:1458		if (!bfa_itnim_is_online(ioim->itnim)) {1459			if (!bfa_itnim_hold_io(ioim->itnim)) {1460				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1461				list_del(&ioim->qe);1462				list_add_tail(&ioim->qe,1463					&ioim->fcpim->ioim_comp_q);1464				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,1465						__bfa_cb_ioim_pathtov, ioim);1466			} else {1467				list_del(&ioim->qe);1468				list_add_tail(&ioim->qe,1469					&ioim->itnim->pending_q);1470			}1471			break;1472		}1473 1474		if (ioim->nsges > BFI_SGE_INLINE) {1475			if (!bfa_ioim_sgpg_alloc(ioim)) {1476				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);1477				return;1478			}1479		}1480 1481		if (!bfa_ioim_send_ioreq(ioim)) {1482			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);1483			break;1484		}1485 1486		bfa_sm_set_state(ioim, bfa_ioim_sm_active);1487		break;1488 1489	case BFA_IOIM_SM_IOTOV:1490		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1491		bfa_ioim_move_to_comp_q(ioim);1492		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,1493				__bfa_cb_ioim_pathtov, ioim);1494		break;1495 1496	case BFA_IOIM_SM_ABORT:1497		/*1498		 * IO in pending queue can get abort requests. Complete abort1499		 * requests immediately.1500		 */1501		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1502		WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));1503		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,1504			__bfa_cb_ioim_abort, ioim);1505		break;1506 1507	default:1508		bfa_sm_fault(ioim->bfa, event);1509	}1510}1511 1512/*1513 * IO is waiting for SG pages.1514 */1515static void1516bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1517{1518	bfa_trc(ioim->bfa, ioim->iotag);1519	bfa_trc(ioim->bfa, event);1520 1521	switch (event) {1522	case BFA_IOIM_SM_SGALLOCED:1523		if (!bfa_ioim_send_ioreq(ioim)) {1524			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);1525			break;1526		}1527		bfa_sm_set_state(ioim, bfa_ioim_sm_active);1528		break;1529 1530	case BFA_IOIM_SM_CLEANUP:1531		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1532		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);1533		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1534			      ioim);1535		bfa_ioim_notify_cleanup(ioim);1536		break;1537 1538	case BFA_IOIM_SM_ABORT:1539		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1540		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);1541		bfa_ioim_move_to_comp_q(ioim);1542		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1543			      ioim);1544		break;1545 1546	case BFA_IOIM_SM_HWFAIL:1547		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1548		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);1549		bfa_ioim_move_to_comp_q(ioim);1550		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1551			      ioim);1552		break;1553 1554	default:1555		bfa_sm_fault(ioim->bfa, event);1556	}1557}1558 1559/*1560 * IO is active.1561 */1562static void1563bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1564{1565	switch (event) {1566	case BFA_IOIM_SM_COMP_GOOD:1567		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1568		bfa_ioim_move_to_comp_q(ioim);1569		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,1570			      __bfa_cb_ioim_good_comp, ioim);1571		break;1572 1573	case BFA_IOIM_SM_COMP:1574		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1575		bfa_ioim_move_to_comp_q(ioim);1576		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,1577			      ioim);1578		break;1579 1580	case BFA_IOIM_SM_DONE:1581		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);1582		bfa_ioim_move_to_comp_q(ioim);1583		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,1584			      ioim);1585		break;1586 1587	case BFA_IOIM_SM_ABORT:1588		ioim->iosp->abort_explicit = BFA_TRUE;1589		ioim->io_cbfn = __bfa_cb_ioim_abort;1590 1591		if (bfa_ioim_send_abort(ioim))1592			bfa_sm_set_state(ioim, bfa_ioim_sm_abort);1593		else {1594			bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);1595			bfa_stats(ioim->itnim, qwait);1596			bfa_reqq_wait(ioim->bfa, ioim->reqq,1597					  &ioim->iosp->reqq_wait);1598		}1599		break;1600 1601	case BFA_IOIM_SM_CLEANUP:1602		ioim->iosp->abort_explicit = BFA_FALSE;1603		ioim->io_cbfn = __bfa_cb_ioim_failed;1604 1605		if (bfa_ioim_send_abort(ioim))1606			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);1607		else {1608			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);1609			bfa_stats(ioim->itnim, qwait);1610			bfa_reqq_wait(ioim->bfa, ioim->reqq,1611					  &ioim->iosp->reqq_wait);1612		}1613		break;1614 1615	case BFA_IOIM_SM_HWFAIL:1616		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1617		bfa_ioim_move_to_comp_q(ioim);1618		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1619			      ioim);1620		break;1621 1622	case BFA_IOIM_SM_SQRETRY:1623		if (bfa_ioim_maxretry_reached(ioim)) {1624			/* max retry reached, free IO */1625			bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);1626			bfa_ioim_move_to_comp_q(ioim);1627			bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,1628					__bfa_cb_ioim_failed, ioim);1629			break;1630		}1631		/* waiting for IO tag resource free */1632		bfa_sm_set_state(ioim, bfa_ioim_sm_cmnd_retry);1633		break;1634 1635	default:1636		bfa_sm_fault(ioim->bfa, event);1637	}1638}1639 1640/*1641 * IO is retried with new tag.1642 */1643static void1644bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1645{1646	switch (event) {1647	case BFA_IOIM_SM_FREE:1648		/* abts and rrq done. Now retry the IO with new tag */1649		bfa_ioim_update_iotag(ioim);1650		if (!bfa_ioim_send_ioreq(ioim)) {1651			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);1652			break;1653		}1654		bfa_sm_set_state(ioim, bfa_ioim_sm_active);1655	break;1656 1657	case BFA_IOIM_SM_CLEANUP:1658		ioim->iosp->abort_explicit = BFA_FALSE;1659		ioim->io_cbfn = __bfa_cb_ioim_failed;1660 1661		if (bfa_ioim_send_abort(ioim))1662			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);1663		else {1664			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);1665			bfa_stats(ioim->itnim, qwait);1666			bfa_reqq_wait(ioim->bfa, ioim->reqq,1667					  &ioim->iosp->reqq_wait);1668		}1669	break;1670 1671	case BFA_IOIM_SM_HWFAIL:1672		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1673		bfa_ioim_move_to_comp_q(ioim);1674		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,1675			 __bfa_cb_ioim_failed, ioim);1676		break;1677 1678	case BFA_IOIM_SM_ABORT:1679		/* in this state IO abort is done.1680		 * Waiting for IO tag resource free.1681		 */1682		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);1683		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1684			      ioim);1685		break;1686 1687	default:1688		bfa_sm_fault(ioim->bfa, event);1689	}1690}1691 1692/*1693 * IO is being aborted, waiting for completion from firmware.1694 */1695static void1696bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1697{1698	bfa_trc(ioim->bfa, ioim->iotag);1699	bfa_trc(ioim->bfa, event);1700 1701	switch (event) {1702	case BFA_IOIM_SM_COMP_GOOD:1703	case BFA_IOIM_SM_COMP:1704	case BFA_IOIM_SM_DONE:1705	case BFA_IOIM_SM_FREE:1706		break;1707 1708	case BFA_IOIM_SM_ABORT_DONE:1709		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);1710		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1711			      ioim);1712		break;1713 1714	case BFA_IOIM_SM_ABORT_COMP:1715		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1716		bfa_ioim_move_to_comp_q(ioim);1717		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1718			      ioim);1719		break;1720 1721	case BFA_IOIM_SM_COMP_UTAG:1722		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1723		bfa_ioim_move_to_comp_q(ioim);1724		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1725			      ioim);1726		break;1727 1728	case BFA_IOIM_SM_CLEANUP:1729		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);1730		ioim->iosp->abort_explicit = BFA_FALSE;1731 1732		if (bfa_ioim_send_abort(ioim))1733			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);1734		else {1735			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);1736			bfa_stats(ioim->itnim, qwait);1737			bfa_reqq_wait(ioim->bfa, ioim->reqq,1738					  &ioim->iosp->reqq_wait);1739		}1740		break;1741 1742	case BFA_IOIM_SM_HWFAIL:1743		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1744		bfa_ioim_move_to_comp_q(ioim);1745		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1746			      ioim);1747		break;1748 1749	default:1750		bfa_sm_fault(ioim->bfa, event);1751	}1752}1753 1754/*1755 * IO is being cleaned up (implicit abort), waiting for completion from1756 * firmware.1757 */1758static void1759bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1760{1761	bfa_trc(ioim->bfa, ioim->iotag);1762	bfa_trc(ioim->bfa, event);1763 1764	switch (event) {1765	case BFA_IOIM_SM_COMP_GOOD:1766	case BFA_IOIM_SM_COMP:1767	case BFA_IOIM_SM_DONE:1768	case BFA_IOIM_SM_FREE:1769		break;1770 1771	case BFA_IOIM_SM_ABORT:1772		/*1773		 * IO is already being aborted implicitly1774		 */1775		ioim->io_cbfn = __bfa_cb_ioim_abort;1776		break;1777 1778	case BFA_IOIM_SM_ABORT_DONE:1779		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);1780		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);1781		bfa_ioim_notify_cleanup(ioim);1782		break;1783 1784	case BFA_IOIM_SM_ABORT_COMP:1785		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1786		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);1787		bfa_ioim_notify_cleanup(ioim);1788		break;1789 1790	case BFA_IOIM_SM_COMP_UTAG:1791		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1792		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);1793		bfa_ioim_notify_cleanup(ioim);1794		break;1795 1796	case BFA_IOIM_SM_HWFAIL:1797		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1798		bfa_ioim_move_to_comp_q(ioim);1799		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1800			      ioim);1801		break;1802 1803	case BFA_IOIM_SM_CLEANUP:1804		/*1805		 * IO can be in cleanup state already due to TM command.1806		 * 2nd cleanup request comes from ITN offline event.1807		 */1808		break;1809 1810	default:1811		bfa_sm_fault(ioim->bfa, event);1812	}1813}1814 1815/*1816 * IO is waiting for room in request CQ1817 */1818static void1819bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1820{1821	bfa_trc(ioim->bfa, ioim->iotag);1822	bfa_trc(ioim->bfa, event);1823 1824	switch (event) {1825	case BFA_IOIM_SM_QRESUME:1826		bfa_sm_set_state(ioim, bfa_ioim_sm_active);1827		bfa_ioim_send_ioreq(ioim);1828		break;1829 1830	case BFA_IOIM_SM_ABORT:1831		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1832		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1833		bfa_ioim_move_to_comp_q(ioim);1834		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1835			      ioim);1836		break;1837 1838	case BFA_IOIM_SM_CLEANUP:1839		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1840		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1841		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1842			      ioim);1843		bfa_ioim_notify_cleanup(ioim);1844		break;1845 1846	case BFA_IOIM_SM_HWFAIL:1847		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1848		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1849		bfa_ioim_move_to_comp_q(ioim);1850		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1851			      ioim);1852		break;1853 1854	default:1855		bfa_sm_fault(ioim->bfa, event);1856	}1857}1858 1859/*1860 * Active IO is being aborted, waiting for room in request CQ.1861 */1862static void1863bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1864{1865	bfa_trc(ioim->bfa, ioim->iotag);1866	bfa_trc(ioim->bfa, event);1867 1868	switch (event) {1869	case BFA_IOIM_SM_QRESUME:1870		bfa_sm_set_state(ioim, bfa_ioim_sm_abort);1871		bfa_ioim_send_abort(ioim);1872		break;1873 1874	case BFA_IOIM_SM_CLEANUP:1875		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);1876		ioim->iosp->abort_explicit = BFA_FALSE;1877		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);1878		break;1879 1880	case BFA_IOIM_SM_COMP_GOOD:1881	case BFA_IOIM_SM_COMP:1882		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1883		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1884		bfa_ioim_move_to_comp_q(ioim);1885		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1886			      ioim);1887		break;1888 1889	case BFA_IOIM_SM_DONE:1890		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);1891		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1892		bfa_ioim_move_to_comp_q(ioim);1893		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,1894			      ioim);1895		break;1896 1897	case BFA_IOIM_SM_HWFAIL:1898		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1899		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1900		bfa_ioim_move_to_comp_q(ioim);1901		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1902			      ioim);1903		break;1904 1905	default:1906		bfa_sm_fault(ioim->bfa, event);1907	}1908}1909 1910/*1911 * Active IO is being cleaned up, waiting for room in request CQ.1912 */1913static void1914bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1915{1916	bfa_trc(ioim->bfa, ioim->iotag);1917	bfa_trc(ioim->bfa, event);1918 1919	switch (event) {1920	case BFA_IOIM_SM_QRESUME:1921		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);1922		bfa_ioim_send_abort(ioim);1923		break;1924 1925	case BFA_IOIM_SM_ABORT:1926		/*1927		 * IO is already being cleaned up implicitly1928		 */1929		ioim->io_cbfn = __bfa_cb_ioim_abort;1930		break;1931 1932	case BFA_IOIM_SM_COMP_GOOD:1933	case BFA_IOIM_SM_COMP:1934		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1935		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1936		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);1937		bfa_ioim_notify_cleanup(ioim);1938		break;1939 1940	case BFA_IOIM_SM_DONE:1941		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);1942		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1943		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);1944		bfa_ioim_notify_cleanup(ioim);1945		break;1946 1947	case BFA_IOIM_SM_HWFAIL:1948		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);1949		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);1950		bfa_ioim_move_to_comp_q(ioim);1951		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,1952			      ioim);1953		break;1954 1955	default:1956		bfa_sm_fault(ioim->bfa, event);1957	}1958}1959 1960/*1961 * IO bfa callback is pending.1962 */1963static void1964bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1965{1966	switch (event) {1967	case BFA_IOIM_SM_HCB:1968		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);1969		bfa_ioim_free(ioim);1970		break;1971 1972	case BFA_IOIM_SM_CLEANUP:1973		bfa_ioim_notify_cleanup(ioim);1974		break;1975 1976	case BFA_IOIM_SM_HWFAIL:1977		break;1978 1979	default:1980		bfa_sm_fault(ioim->bfa, event);1981	}1982}1983 1984/*1985 * IO bfa callback is pending. IO resource cannot be freed.1986 */1987static void1988bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)1989{1990	bfa_trc(ioim->bfa, ioim->iotag);1991	bfa_trc(ioim->bfa, event);1992 1993	switch (event) {1994	case BFA_IOIM_SM_HCB:1995		bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);1996		list_del(&ioim->qe);1997		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);1998		break;1999 2000	case BFA_IOIM_SM_FREE:2001		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);2002		break;2003 2004	case BFA_IOIM_SM_CLEANUP:2005		bfa_ioim_notify_cleanup(ioim);2006		break;2007 2008	case BFA_IOIM_SM_HWFAIL:2009		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);2010		break;2011 2012	default:2013		bfa_sm_fault(ioim->bfa, event);2014	}2015}2016 2017/*2018 * IO is completed, waiting resource free from firmware.2019 */2020static void2021bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)2022{2023	bfa_trc(ioim->bfa, ioim->iotag);2024	bfa_trc(ioim->bfa, event);2025 2026	switch (event) {2027	case BFA_IOIM_SM_FREE:2028		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);2029		bfa_ioim_free(ioim);2030		break;2031 2032	case BFA_IOIM_SM_CLEANUP:2033		bfa_ioim_notify_cleanup(ioim);2034		break;2035 2036	case BFA_IOIM_SM_HWFAIL:2037		break;2038 2039	default:2040		bfa_sm_fault(ioim->bfa, event);2041	}2042}2043 2044/*2045 * This is called from bfa_fcpim_start after the bfa_init() with flash read2046 * is complete by driver. now invalidate the stale content of lun mask2047 * like unit attention, rp tag and lp tag.2048 */2049void2050bfa_ioim_lm_init(struct bfa_s *bfa)2051{2052	struct bfa_lun_mask_s *lunm_list;2053	int	i;2054 2055	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)2056		return;2057 2058	lunm_list = bfa_get_lun_mask_list(bfa);2059	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2060		lunm_list[i].ua = BFA_IOIM_LM_UA_RESET;2061		lunm_list[i].lp_tag = BFA_LP_TAG_INVALID;2062		lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID;2063	}2064}2065 2066static void2067__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)2068{2069	struct bfa_ioim_s *ioim = cbarg;2070 2071	if (!complete) {2072		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);2073		return;2074	}2075 2076	bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);2077}2078 2079static void2080__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)2081{2082	struct bfa_ioim_s	*ioim = cbarg;2083	struct bfi_ioim_rsp_s *m;2084	u8	*snsinfo = NULL;2085	u8	sns_len = 0;2086	s32	residue = 0;2087 2088	if (!complete) {2089		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);2090		return;2091	}2092 2093	m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;2094	if (m->io_status == BFI_IOIM_STS_OK) {2095		/*2096		 * setup sense information, if present2097		 */2098		if ((m->scsi_status == SAM_STAT_CHECK_CONDITION) &&2099					m->sns_len) {2100			sns_len = m->sns_len;2101			snsinfo = BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,2102						ioim->iotag);2103		}2104 2105		/*2106		 * setup residue value correctly for normal completions2107		 */2108		if (m->resid_flags == FCP_RESID_UNDER) {2109			residue = be32_to_cpu(m->residue);2110			bfa_stats(ioim->itnim, iocomp_underrun);2111		}2112		if (m->resid_flags == FCP_RESID_OVER) {2113			residue = be32_to_cpu(m->residue);2114			residue = -residue;2115			bfa_stats(ioim->itnim, iocomp_overrun);2116		}2117	}2118 2119	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,2120			  m->scsi_status, sns_len, snsinfo, residue);2121}2122 2123void2124bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn,2125			u16 rp_tag, u8 lp_tag)2126{2127	struct bfa_lun_mask_s *lun_list;2128	u8	i;2129 2130	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)2131		return;2132 2133	lun_list = bfa_get_lun_mask_list(bfa);2134	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2135		if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) {2136			if ((lun_list[i].lp_wwn == lp_wwn) &&2137			    (lun_list[i].rp_wwn == rp_wwn)) {2138				lun_list[i].rp_tag = rp_tag;2139				lun_list[i].lp_tag = lp_tag;2140			}2141		}2142	}2143}2144 2145/*2146 * set UA for all active luns in LM DB2147 */2148static void2149bfa_ioim_lm_set_ua(struct bfa_s *bfa)2150{2151	struct bfa_lun_mask_s	*lunm_list;2152	int	i;2153 2154	lunm_list = bfa_get_lun_mask_list(bfa);2155	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2156		if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)2157			continue;2158		lunm_list[i].ua = BFA_IOIM_LM_UA_SET;2159	}2160}2161 2162bfa_status_t2163bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 update)2164{2165	struct bfa_lunmask_cfg_s	*lun_mask;2166 2167	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));2168	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)2169		return BFA_STATUS_FAILED;2170 2171	if (bfa_get_lun_mask_status(bfa) == update)2172		return BFA_STATUS_NO_CHANGE;2173 2174	lun_mask = bfa_get_lun_mask(bfa);2175	lun_mask->status = update;2176 2177	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED)2178		bfa_ioim_lm_set_ua(bfa);2179 2180	return  bfa_dconf_update(bfa);2181}2182 2183bfa_status_t2184bfa_fcpim_lunmask_clear(struct bfa_s *bfa)2185{2186	int i;2187	struct bfa_lun_mask_s	*lunm_list;2188 2189	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));2190	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)2191		return BFA_STATUS_FAILED;2192 2193	lunm_list = bfa_get_lun_mask_list(bfa);2194	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2195		if (lunm_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) {2196			if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID)2197				bfa_rport_unset_lunmask(bfa,2198				  BFA_RPORT_FROM_TAG(bfa, lunm_list[i].rp_tag));2199		}2200	}2201 2202	memset(lunm_list, 0, sizeof(struct bfa_lun_mask_s) * MAX_LUN_MASK_CFG);2203	return bfa_dconf_update(bfa);2204}2205 2206bfa_status_t2207bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf)2208{2209	struct bfa_lunmask_cfg_s *lun_mask;2210 2211	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));2212	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)2213		return BFA_STATUS_FAILED;2214 2215	lun_mask = bfa_get_lun_mask(bfa);2216	memcpy(buf, lun_mask, sizeof(struct bfa_lunmask_cfg_s));2217	return BFA_STATUS_OK;2218}2219 2220bfa_status_t2221bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,2222		      wwn_t rpwwn, struct scsi_lun lun)2223{2224	struct bfa_lun_mask_s *lunm_list;2225	struct bfa_rport_s *rp = NULL;2226	int i, free_index = MAX_LUN_MASK_CFG + 1;2227	struct bfa_fcs_lport_s *port = NULL;2228	struct bfa_fcs_rport_s *rp_fcs;2229 2230	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));2231	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)2232		return BFA_STATUS_FAILED;2233 2234	port = bfa_fcs_lookup_port(&((struct bfad_s *)bfa->bfad)->bfa_fcs,2235				   vf_id, *pwwn);2236	if (port) {2237		*pwwn = port->port_cfg.pwwn;2238		rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);2239		if (rp_fcs)2240			rp = rp_fcs->bfa_rport;2241	}2242 2243	lunm_list = bfa_get_lun_mask_list(bfa);2244	/* if entry exists */2245	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2246		if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)2247			free_index = i;2248		if ((lunm_list[i].lp_wwn == *pwwn) &&2249		    (lunm_list[i].rp_wwn == rpwwn) &&2250		    (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) ==2251		     scsilun_to_int((struct scsi_lun *)&lun)))2252			return  BFA_STATUS_ENTRY_EXISTS;2253	}2254 2255	if (free_index > MAX_LUN_MASK_CFG)2256		return BFA_STATUS_MAX_ENTRY_REACHED;2257 2258	if (rp) {2259		lunm_list[free_index].lp_tag = bfa_lps_get_tag_from_pid(bfa,2260						   rp->rport_info.local_pid);2261		lunm_list[free_index].rp_tag = rp->rport_tag;2262	} else {2263		lunm_list[free_index].lp_tag = BFA_LP_TAG_INVALID;2264		lunm_list[free_index].rp_tag = BFA_RPORT_TAG_INVALID;2265	}2266 2267	lunm_list[free_index].lp_wwn = *pwwn;2268	lunm_list[free_index].rp_wwn = rpwwn;2269	lunm_list[free_index].lun = lun;2270	lunm_list[free_index].state = BFA_IOIM_LUN_MASK_ACTIVE;2271 2272	/* set for all luns in this rp */2273	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2274		if ((lunm_list[i].lp_wwn == *pwwn) &&2275		    (lunm_list[i].rp_wwn == rpwwn))2276			lunm_list[i].ua = BFA_IOIM_LM_UA_SET;2277	}2278 2279	return bfa_dconf_update(bfa);2280}2281 2282bfa_status_t2283bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,2284			 wwn_t rpwwn, struct scsi_lun lun)2285{2286	struct bfa_lun_mask_s	*lunm_list;2287	struct bfa_fcs_lport_s *port = NULL;2288	int	i;2289 2290	/* in min cfg lunm_list could be NULL but  no commands should run. */2291	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)2292		return BFA_STATUS_FAILED;2293 2294	bfa_trc(bfa, bfa_get_lun_mask_status(bfa));2295	bfa_trc(bfa, *pwwn);2296	bfa_trc(bfa, rpwwn);2297	bfa_trc(bfa, scsilun_to_int((struct scsi_lun *)&lun));2298 2299	if (*pwwn == 0) {2300		port = bfa_fcs_lookup_port(2301				&((struct bfad_s *)bfa->bfad)->bfa_fcs,2302				vf_id, *pwwn);2303		if (port)2304			*pwwn = port->port_cfg.pwwn;2305	}2306 2307	lunm_list = bfa_get_lun_mask_list(bfa);2308	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2309		if ((lunm_list[i].lp_wwn == *pwwn) &&2310		    (lunm_list[i].rp_wwn == rpwwn) &&2311		    (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) ==2312		     scsilun_to_int((struct scsi_lun *)&lun))) {2313			lunm_list[i].lp_wwn = 0;2314			lunm_list[i].rp_wwn = 0;2315			int_to_scsilun(0, &lunm_list[i].lun);2316			lunm_list[i].state = BFA_IOIM_LUN_MASK_INACTIVE;2317			if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID) {2318				lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID;2319				lunm_list[i].lp_tag = BFA_LP_TAG_INVALID;2320			}2321			return bfa_dconf_update(bfa);2322		}2323	}2324 2325	/* set for all luns in this rp */2326	for (i = 0; i < MAX_LUN_MASK_CFG; i++) {2327		if ((lunm_list[i].lp_wwn == *pwwn) &&2328		    (lunm_list[i].rp_wwn == rpwwn))2329			lunm_list[i].ua = BFA_IOIM_LM_UA_SET;2330	}2331 2332	return BFA_STATUS_ENTRY_NOT_EXISTS;2333}2334 2335static void2336__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)2337{2338	struct bfa_ioim_s *ioim = cbarg;2339 2340	if (!complete) {2341		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);2342		return;2343	}2344 2345	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,2346			  0, 0, NULL, 0);2347}2348 2349static void2350__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)2351{2352	struct bfa_ioim_s *ioim = cbarg;2353 2354	bfa_stats(ioim->itnim, path_tov_expired);2355	if (!complete) {2356		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);2357		return;2358	}2359 2360	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,2361			  0, 0, NULL, 0);2362}2363 2364static void2365__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)2366{2367	struct bfa_ioim_s *ioim = cbarg;2368 2369	if (!complete) {2370		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);2371		return;2372	}2373 2374	bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);2375}2376 2377static void2378bfa_ioim_sgpg_alloced(void *cbarg)2379{2380	struct bfa_ioim_s *ioim = cbarg;2381 2382	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);2383	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);2384	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);2385	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);2386}2387 2388/*2389 * Send I/O request to firmware.2390 */2391static	bfa_boolean_t2392bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)2393{2394	struct bfa_itnim_s *itnim = ioim->itnim;2395	struct bfi_ioim_req_s *m;2396	static struct fcp_cmnd_s cmnd_z0 = { { { 0 } } };2397	struct bfi_sge_s *sge, *sgpge;2398	u32	pgdlen = 0;2399	u32	fcp_dl;2400	u64 addr;2401	struct scatterlist *sg;2402	struct bfa_sgpg_s *sgpg;2403	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;2404	u32 i, sge_id, pgcumsz;2405	enum dma_data_direction dmadir;2406 2407	/*2408	 * check for room in queue to send request now2409	 */2410	m = bfa_reqq_next(ioim->bfa, ioim->reqq);2411	if (!m) {2412		bfa_stats(ioim->itnim, qwait);2413		bfa_reqq_wait(ioim->bfa, ioim->reqq,2414				  &ioim->iosp->reqq_wait);2415		return BFA_FALSE;2416	}2417 2418	/*2419	 * build i/o request message next2420	 */2421	m->io_tag = cpu_to_be16(ioim->iotag);2422	m->rport_hdl = ioim->itnim->rport->fw_handle;2423	m->io_timeout = 0;2424 2425	sge = &m->sges[0];2426	sgpg = ioim->sgpg;2427	sge_id = 0;2428	sgpge = NULL;2429	pgcumsz = 0;2430	scsi_for_each_sg(cmnd, sg, ioim->nsges, i) {2431		if (i == 0) {2432			/* build inline IO SG element */2433			addr = bfa_sgaddr_le(sg_dma_address(sg));2434			sge->sga = *(union bfi_addr_u *) &addr;2435			pgdlen = sg_dma_len(sg);2436			sge->sg_len = pgdlen;2437			sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?2438					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;2439			bfa_sge_to_be(sge);2440			sge++;2441		} else {2442			if (sge_id == 0)2443				sgpge = sgpg->sgpg->sges;2444 2445			addr = bfa_sgaddr_le(sg_dma_address(sg));2446			sgpge->sga = *(union bfi_addr_u *) &addr;2447			sgpge->sg_len = sg_dma_len(sg);2448			pgcumsz += sgpge->sg_len;2449 2450			/* set flags */2451			if (i < (ioim->nsges - 1) &&2452					sge_id < (BFI_SGPG_DATA_SGES - 1))2453				sgpge->flags = BFI_SGE_DATA;2454			else if (i < (ioim->nsges - 1))2455				sgpge->flags = BFI_SGE_DATA_CPL;2456			else2457				sgpge->flags = BFI_SGE_DATA_LAST;2458 2459			bfa_sge_to_le(sgpge);2460 2461			sgpge++;2462			if (i == (ioim->nsges - 1)) {2463				sgpge->flags = BFI_SGE_PGDLEN;2464				sgpge->sga.a32.addr_lo = 0;2465				sgpge->sga.a32.addr_hi = 0;2466				sgpge->sg_len = pgcumsz;2467				bfa_sge_to_le(sgpge);2468			} else if (++sge_id == BFI_SGPG_DATA_SGES) {2469				sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);2470				sgpge->flags = BFI_SGE_LINK;2471				sgpge->sga = sgpg->sgpg_pa;2472				sgpge->sg_len = pgcumsz;2473				bfa_sge_to_le(sgpge);2474				sge_id = 0;2475				pgcumsz = 0;2476			}2477		}2478	}2479 2480	if (ioim->nsges > BFI_SGE_INLINE) {2481		sge->sga = ioim->sgpg->sgpg_pa;2482	} else {2483		sge->sga.a32.addr_lo = 0;2484		sge->sga.a32.addr_hi = 0;2485	}2486	sge->sg_len = pgdlen;2487	sge->flags = BFI_SGE_PGDLEN;2488	bfa_sge_to_be(sge);2489 2490	/*2491	 * set up I/O command parameters2492	 */2493	m->cmnd = cmnd_z0;2494	int_to_scsilun(cmnd->device->lun, &m->cmnd.lun);2495	dmadir = cmnd->sc_data_direction;2496	if (dmadir == DMA_TO_DEVICE)2497		m->cmnd.iodir = FCP_IODIR_WRITE;2498	else if (dmadir == DMA_FROM_DEVICE)2499		m->cmnd.iodir = FCP_IODIR_READ;2500	else2501		m->cmnd.iodir = FCP_IODIR_NONE;2502 2503	m->cmnd.cdb = *(struct scsi_cdb_s *) cmnd->cmnd;2504	fcp_dl = scsi_bufflen(cmnd);2505	m->cmnd.fcp_dl = cpu_to_be32(fcp_dl);2506 2507	/*2508	 * set up I/O message header2509	 */2510	switch (m->cmnd.iodir) {2511	case FCP_IODIR_READ:2512		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_fn_lpu(ioim->bfa));2513		bfa_stats(itnim, input_reqs);2514		ioim->itnim->stats.rd_throughput += fcp_dl;2515		break;2516	case FCP_IODIR_WRITE:2517		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_fn_lpu(ioim->bfa));2518		bfa_stats(itnim, output_reqs);2519		ioim->itnim->stats.wr_throughput += fcp_dl;2520		break;2521	case FCP_IODIR_RW:2522		bfa_stats(itnim, input_reqs);2523		bfa_stats(itnim, output_reqs);2524		fallthrough;2525	default:2526		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));2527	}2528	if (itnim->seq_rec ||2529	    (scsi_bufflen(cmnd) & (sizeof(u32) - 1)))2530		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));2531 2532	/*2533	 * queue I/O message to firmware2534	 */2535	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);2536	return BFA_TRUE;2537}2538 2539/*2540 * Setup any additional SG pages needed.Inline SG element is setup2541 * at queuing time.2542 */2543static bfa_boolean_t2544bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim)2545{2546	u16	nsgpgs;2547 2548	WARN_ON(ioim->nsges <= BFI_SGE_INLINE);2549 2550	/*2551	 * allocate SG pages needed2552	 */2553	nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);2554	if (!nsgpgs)2555		return BFA_TRUE;2556 2557	if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)2558	    != BFA_STATUS_OK) {2559		bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);2560		return BFA_FALSE;2561	}2562 2563	ioim->nsgpgs = nsgpgs;2564	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);2565 2566	return BFA_TRUE;2567}2568 2569/*2570 * Send I/O abort request to firmware.2571 */2572static	bfa_boolean_t2573bfa_ioim_send_abort(struct bfa_ioim_s *ioim)2574{2575	struct bfi_ioim_abort_req_s *m;2576	enum bfi_ioim_h2i	msgop;2577 2578	/*2579	 * check for room in queue to send request now2580	 */2581	m = bfa_reqq_next(ioim->bfa, ioim->reqq);2582	if (!m)2583		return BFA_FALSE;2584 2585	/*2586	 * build i/o request message next2587	 */2588	if (ioim->iosp->abort_explicit)2589		msgop = BFI_IOIM_H2I_IOABORT_REQ;2590	else2591		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;2592 2593	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_fn_lpu(ioim->bfa));2594	m->io_tag    = cpu_to_be16(ioim->iotag);2595	m->abort_tag = ++ioim->abort_tag;2596 2597	/*2598	 * queue I/O message to firmware2599	 */2600	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);2601	return BFA_TRUE;2602}2603 2604/*2605 * Call to resume any I/O requests waiting for room in request queue.2606 */2607static void2608bfa_ioim_qresume(void *cbarg)2609{2610	struct bfa_ioim_s *ioim = cbarg;2611 2612	bfa_stats(ioim->itnim, qresumes);2613	bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);2614}2615 2616 2617static void2618bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)2619{2620	/*2621	 * Move IO from itnim queue to fcpim global queue since itnim will be2622	 * freed.2623	 */2624	list_del(&ioim->qe);2625	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);2626 2627	if (!ioim->iosp->tskim) {2628		if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {2629			bfa_cb_dequeue(&ioim->hcb_qe);2630			list_del(&ioim->qe);2631			list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);2632		}2633		bfa_itnim_iodone(ioim->itnim);2634	} else2635		bfa_wc_down(&ioim->iosp->tskim->wc);2636}2637 2638static bfa_boolean_t2639bfa_ioim_is_abortable(struct bfa_ioim_s *ioim)2640{2641	if ((bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit) &&2642	    (!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)))	||2643	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort))		||2644	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort_qfull))	||2645	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb))		||2646	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb_free))	||2647	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_resfree)))2648		return BFA_FALSE;2649 2650	return BFA_TRUE;2651}2652 2653void2654bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)2655{2656	/*2657	 * If path tov timer expired, failback with PATHTOV status - these2658	 * IO requests are not normally retried by IO stack.2659	 *2660	 * Otherwise device cameback online and fail it with normal failed2661	 * status so that IO stack retries these failed IO requests.2662	 */2663	if (iotov)2664		ioim->io_cbfn = __bfa_cb_ioim_pathtov;2665	else {2666		ioim->io_cbfn = __bfa_cb_ioim_failed;2667		bfa_stats(ioim->itnim, iocom_nexus_abort);2668	}2669	bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);2670 2671	/*2672	 * Move IO to fcpim global queue since itnim will be2673	 * freed.2674	 */2675	list_del(&ioim->qe);2676	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);2677}2678 2679 2680/*2681 * Memory allocation and initialization.2682 */2683void2684bfa_ioim_attach(struct bfa_fcpim_s *fcpim)2685{2686	struct bfa_ioim_s		*ioim;2687	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;2688	struct bfa_ioim_sp_s	*iosp;2689	u16		i;2690 2691	/*2692	 * claim memory first2693	 */2694	ioim = (struct bfa_ioim_s *) bfa_mem_kva_curp(fcp);2695	fcpim->ioim_arr = ioim;2696	bfa_mem_kva_curp(fcp) = (u8 *) (ioim + fcpim->fcp->num_ioim_reqs);2697 2698	iosp = (struct bfa_ioim_sp_s *) bfa_mem_kva_curp(fcp);2699	fcpim->ioim_sp_arr = iosp;2700	bfa_mem_kva_curp(fcp) = (u8 *) (iosp + fcpim->fcp->num_ioim_reqs);2701 2702	/*2703	 * Initialize ioim free queues2704	 */2705	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);2706	INIT_LIST_HEAD(&fcpim->ioim_comp_q);2707 2708	for (i = 0; i < fcpim->fcp->num_ioim_reqs;2709	     i++, ioim++, iosp++) {2710		/*2711		 * initialize IOIM2712		 */2713		memset(ioim, 0, sizeof(struct bfa_ioim_s));2714		ioim->iotag   = i;2715		ioim->bfa     = fcpim->bfa;2716		ioim->fcpim   = fcpim;2717		ioim->iosp    = iosp;2718		INIT_LIST_HEAD(&ioim->sgpg_q);2719		bfa_reqq_winit(&ioim->iosp->reqq_wait,2720				   bfa_ioim_qresume, ioim);2721		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,2722				   bfa_ioim_sgpg_alloced, ioim);2723		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);2724	}2725}2726 2727void2728bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)2729{2730	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);2731	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;2732	struct bfa_ioim_s *ioim;2733	u16	iotag;2734	enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;2735 2736	iotag = be16_to_cpu(rsp->io_tag);2737 2738	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);2739	WARN_ON(ioim->iotag != iotag);2740 2741	bfa_trc(ioim->bfa, ioim->iotag);2742	bfa_trc(ioim->bfa, rsp->io_status);2743	bfa_trc(ioim->bfa, rsp->reuse_io_tag);2744 2745	if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))2746		ioim->iosp->comp_rspmsg = *m;2747 2748	switch (rsp->io_status) {2749	case BFI_IOIM_STS_OK:2750		bfa_stats(ioim->itnim, iocomp_ok);2751		if (rsp->reuse_io_tag == 0)2752			evt = BFA_IOIM_SM_DONE;2753		else2754			evt = BFA_IOIM_SM_COMP;2755		break;2756 2757	case BFI_IOIM_STS_TIMEDOUT:2758		bfa_stats(ioim->itnim, iocomp_timedout);2759		fallthrough;2760	case BFI_IOIM_STS_ABORTED:2761		rsp->io_status = BFI_IOIM_STS_ABORTED;2762		bfa_stats(ioim->itnim, iocomp_aborted);2763		if (rsp->reuse_io_tag == 0)2764			evt = BFA_IOIM_SM_DONE;2765		else2766			evt = BFA_IOIM_SM_COMP;2767		break;2768 2769	case BFI_IOIM_STS_PROTO_ERR:2770		bfa_stats(ioim->itnim, iocom_proto_err);2771		WARN_ON(!rsp->reuse_io_tag);2772		evt = BFA_IOIM_SM_COMP;2773		break;2774 2775	case BFI_IOIM_STS_SQER_NEEDED:2776		bfa_stats(ioim->itnim, iocom_sqer_needed);2777		WARN_ON(rsp->reuse_io_tag != 0);2778		evt = BFA_IOIM_SM_SQRETRY;2779		break;2780 2781	case BFI_IOIM_STS_RES_FREE:2782		bfa_stats(ioim->itnim, iocom_res_free);2783		evt = BFA_IOIM_SM_FREE;2784		break;2785 2786	case BFI_IOIM_STS_HOST_ABORTED:2787		bfa_stats(ioim->itnim, iocom_hostabrts);2788		if (rsp->abort_tag != ioim->abort_tag) {2789			bfa_trc(ioim->bfa, rsp->abort_tag);2790			bfa_trc(ioim->bfa, ioim->abort_tag);2791			return;2792		}2793 2794		if (rsp->reuse_io_tag)2795			evt = BFA_IOIM_SM_ABORT_COMP;2796		else2797			evt = BFA_IOIM_SM_ABORT_DONE;2798		break;2799 2800	case BFI_IOIM_STS_UTAG:2801		bfa_stats(ioim->itnim, iocom_utags);2802		evt = BFA_IOIM_SM_COMP_UTAG;2803		break;2804 2805	default:2806		WARN_ON(1);2807	}2808 2809	bfa_sm_send_event(ioim, evt);2810}2811 2812void2813bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)2814{2815	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);2816	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;2817	struct bfa_ioim_s *ioim;2818	u16	iotag;2819 2820	iotag = be16_to_cpu(rsp->io_tag);2821 2822	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);2823	WARN_ON(ioim->iotag != iotag);2824 2825	bfa_ioim_cb_profile_comp(fcpim, ioim);2826 2827	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);2828}2829 2830/*2831 * Called by itnim to clean up IO while going offline.2832 */2833void2834bfa_ioim_cleanup(struct bfa_ioim_s *ioim)2835{2836	bfa_trc(ioim->bfa, ioim->iotag);2837	bfa_stats(ioim->itnim, io_cleanups);2838 2839	ioim->iosp->tskim = NULL;2840	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);2841}2842 2843void2844bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)2845{2846	bfa_trc(ioim->bfa, ioim->iotag);2847	bfa_stats(ioim->itnim, io_tmaborts);2848 2849	ioim->iosp->tskim = tskim;2850	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);2851}2852 2853/*2854 * IOC failure handling.2855 */2856void2857bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)2858{2859	bfa_trc(ioim->bfa, ioim->iotag);2860	bfa_stats(ioim->itnim, io_iocdowns);2861	bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);2862}2863 2864/*2865 * IO offline TOV popped. Fail the pending IO.2866 */2867void2868bfa_ioim_tov(struct bfa_ioim_s *ioim)2869{2870	bfa_trc(ioim->bfa, ioim->iotag);2871	bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);2872}2873 2874 2875/*2876 * Allocate IOIM resource for initiator mode I/O request.2877 */2878struct bfa_ioim_s *2879bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,2880		struct bfa_itnim_s *itnim, u16 nsges)2881{2882	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);2883	struct bfa_ioim_s *ioim;2884	struct bfa_iotag_s *iotag = NULL;2885 2886	/*2887	 * alocate IOIM resource2888	 */2889	bfa_q_deq(&fcpim->fcp->iotag_ioim_free_q, &iotag);2890	if (!iotag) {2891		bfa_stats(itnim, no_iotags);2892		return NULL;2893	}2894 2895	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag->tag);2896 2897	ioim->dio = dio;2898	ioim->itnim = itnim;2899	ioim->nsges = nsges;2900	ioim->nsgpgs = 0;2901 2902	bfa_stats(itnim, total_ios);2903	fcpim->ios_active++;2904 2905	list_add_tail(&ioim->qe, &itnim->io_q);2906 2907	return ioim;2908}2909 2910void2911bfa_ioim_free(struct bfa_ioim_s *ioim)2912{2913	struct bfa_fcpim_s *fcpim = ioim->fcpim;2914	struct bfa_iotag_s *iotag;2915 2916	if (ioim->nsgpgs > 0)2917		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);2918 2919	bfa_stats(ioim->itnim, io_comps);2920	fcpim->ios_active--;2921 2922	ioim->iotag &= BFA_IOIM_IOTAG_MASK;2923 2924	WARN_ON(!(ioim->iotag <2925		(fcpim->fcp->num_ioim_reqs + fcpim->fcp->num_fwtio_reqs)));2926	iotag = BFA_IOTAG_FROM_TAG(fcpim->fcp, ioim->iotag);2927 2928	if (ioim->iotag < fcpim->fcp->num_ioim_reqs)2929		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_ioim_free_q);2930	else2931		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_tio_free_q);2932 2933	list_del(&ioim->qe);2934}2935 2936void2937bfa_ioim_start(struct bfa_ioim_s *ioim)2938{2939	bfa_ioim_cb_profile_start(ioim->fcpim, ioim);2940 2941	/*2942	 * Obtain the queue over which this request has to be issued2943	 */2944	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?2945			BFA_FALSE : bfa_itnim_get_reqq(ioim);2946 2947	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);2948}2949 2950/*2951 * Driver I/O abort request.2952 */2953bfa_status_t2954bfa_ioim_abort(struct bfa_ioim_s *ioim)2955{2956 2957	bfa_trc(ioim->bfa, ioim->iotag);2958 2959	if (!bfa_ioim_is_abortable(ioim))2960		return BFA_STATUS_FAILED;2961 2962	bfa_stats(ioim->itnim, io_aborts);2963	bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);2964 2965	return BFA_STATUS_OK;2966}2967 2968/*2969 *  BFA TSKIM state machine functions2970 */2971 2972/*2973 * Task management command beginning state.2974 */2975static void2976bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)2977{2978	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);2979 2980	switch (event) {2981	case BFA_TSKIM_SM_START:2982		bfa_sm_set_state(tskim, bfa_tskim_sm_active);2983		bfa_tskim_gather_ios(tskim);2984 2985		/*2986		 * If device is offline, do not send TM on wire. Just cleanup2987		 * any pending IO requests and complete TM request.2988		 */2989		if (!bfa_itnim_is_online(tskim->itnim)) {2990			bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);2991			tskim->tsk_status = BFI_TSKIM_STS_OK;2992			bfa_tskim_cleanup_ios(tskim);2993			return;2994		}2995 2996		if (!bfa_tskim_send(tskim)) {2997			bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);2998			bfa_stats(tskim->itnim, tm_qwait);2999			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,3000					  &tskim->reqq_wait);3001		}3002		break;3003 3004	default:3005		bfa_sm_fault(tskim->bfa, event);3006	}3007}3008 3009/*3010 * TM command is active, awaiting completion from firmware to3011 * cleanup IO requests in TM scope.3012 */3013static void3014bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)3015{3016	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);3017 3018	switch (event) {3019	case BFA_TSKIM_SM_DONE:3020		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);3021		bfa_tskim_cleanup_ios(tskim);3022		break;3023 3024	case BFA_TSKIM_SM_CLEANUP:3025		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);3026		if (!bfa_tskim_send_abort(tskim)) {3027			bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);3028			bfa_stats(tskim->itnim, tm_qwait);3029			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,3030				&tskim->reqq_wait);3031		}3032		break;3033 3034	case BFA_TSKIM_SM_HWFAIL:3035		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);3036		bfa_tskim_iocdisable_ios(tskim);3037		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);3038		break;3039 3040	default:3041		bfa_sm_fault(tskim->bfa, event);3042	}3043}3044 3045/*3046 * An active TM is being cleaned up since ITN is offline. Awaiting cleanup3047 * completion event from firmware.3048 */3049static void3050bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)3051{3052	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);3053 3054	switch (event) {3055	case BFA_TSKIM_SM_DONE:3056		/*3057		 * Ignore and wait for ABORT completion from firmware.3058		 */3059		break;3060 3061	case BFA_TSKIM_SM_UTAG:3062	case BFA_TSKIM_SM_CLEANUP_DONE:3063		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);3064		bfa_tskim_cleanup_ios(tskim);3065		break;3066 3067	case BFA_TSKIM_SM_HWFAIL:3068		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);3069		bfa_tskim_iocdisable_ios(tskim);3070		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);3071		break;3072 3073	default:3074		bfa_sm_fault(tskim->bfa, event);3075	}3076}3077 3078static void3079bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)3080{3081	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);3082 3083	switch (event) {3084	case BFA_TSKIM_SM_IOS_DONE:3085		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);3086		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);3087		break;3088 3089	case BFA_TSKIM_SM_CLEANUP:3090		/*3091		 * Ignore, TM command completed on wire.3092		 * Notify TM conmpletion on IO cleanup completion.3093		 */3094		break;3095 3096	case BFA_TSKIM_SM_HWFAIL:3097		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);3098		bfa_tskim_iocdisable_ios(tskim);3099		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);3100		break;3101 3102	default:3103		bfa_sm_fault(tskim->bfa, event);3104	}3105}3106 3107/*3108 * Task management command is waiting for room in request CQ3109 */3110static void3111bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)3112{3113	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);3114 3115	switch (event) {3116	case BFA_TSKIM_SM_QRESUME:3117		bfa_sm_set_state(tskim, bfa_tskim_sm_active);3118		bfa_tskim_send(tskim);3119		break;3120 3121	case BFA_TSKIM_SM_CLEANUP:3122		/*3123		 * No need to send TM on wire since ITN is offline.3124		 */3125		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);3126		bfa_reqq_wcancel(&tskim->reqq_wait);3127		bfa_tskim_cleanup_ios(tskim);3128		break;3129 3130	case BFA_TSKIM_SM_HWFAIL:3131		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);3132		bfa_reqq_wcancel(&tskim->reqq_wait);3133		bfa_tskim_iocdisable_ios(tskim);3134		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);3135		break;3136 3137	default:3138		bfa_sm_fault(tskim->bfa, event);3139	}3140}3141 3142/*3143 * Task management command is active, awaiting for room in request CQ3144 * to send clean up request.3145 */3146static void3147bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,3148		enum bfa_tskim_event event)3149{3150	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);3151 3152	switch (event) {3153	case BFA_TSKIM_SM_DONE:3154		bfa_reqq_wcancel(&tskim->reqq_wait);3155		fallthrough;3156	case BFA_TSKIM_SM_QRESUME:3157		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);3158		bfa_tskim_send_abort(tskim);3159		break;3160 3161	case BFA_TSKIM_SM_HWFAIL:3162		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);3163		bfa_reqq_wcancel(&tskim->reqq_wait);3164		bfa_tskim_iocdisable_ios(tskim);3165		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);3166		break;3167 3168	default:3169		bfa_sm_fault(tskim->bfa, event);3170	}3171}3172 3173/*3174 * BFA callback is pending3175 */3176static void3177bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)3178{3179	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);3180 3181	switch (event) {3182	case BFA_TSKIM_SM_HCB:3183		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);3184		bfa_tskim_free(tskim);3185		break;3186 3187	case BFA_TSKIM_SM_CLEANUP:3188		bfa_tskim_notify_comp(tskim);3189		break;3190 3191	case BFA_TSKIM_SM_HWFAIL:3192		break;3193 3194	default:3195		bfa_sm_fault(tskim->bfa, event);3196	}3197}3198 3199static void3200__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)3201{3202	struct bfa_tskim_s *tskim = cbarg;3203 3204	if (!complete) {3205		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);3206		return;3207	}3208 3209	bfa_stats(tskim->itnim, tm_success);3210	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);3211}3212 3213static void3214__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)3215{3216	struct bfa_tskim_s *tskim = cbarg;3217 3218	if (!complete) {3219		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);3220		return;3221	}3222 3223	bfa_stats(tskim->itnim, tm_failures);3224	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,3225				BFI_TSKIM_STS_FAILED);3226}3227 3228static bfa_boolean_t3229bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun)3230{3231	switch (tskim->tm_cmnd) {3232	case FCP_TM_TARGET_RESET:3233		return BFA_TRUE;3234 3235	case FCP_TM_ABORT_TASK_SET:3236	case FCP_TM_CLEAR_TASK_SET:3237	case FCP_TM_LUN_RESET:3238	case FCP_TM_CLEAR_ACA:3239		return !memcmp(&tskim->lun, &lun, sizeof(lun));3240 3241	default:3242		WARN_ON(1);3243	}3244 3245	return BFA_FALSE;3246}3247 3248/*3249 * Gather affected IO requests and task management commands.3250 */3251static void3252bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)3253{3254	struct bfa_itnim_s *itnim = tskim->itnim;3255	struct bfa_ioim_s *ioim;3256	struct list_head *qe, *qen;3257	struct scsi_cmnd *cmnd;3258	struct scsi_lun scsilun;3259 3260	INIT_LIST_HEAD(&tskim->io_q);3261 3262	/*3263	 * Gather any active IO requests first.3264	 */3265	list_for_each_safe(qe, qen, &itnim->io_q) {3266		ioim = (struct bfa_ioim_s *) qe;3267		cmnd = (struct scsi_cmnd *) ioim->dio;3268		int_to_scsilun(cmnd->device->lun, &scsilun);3269		if (bfa_tskim_match_scope(tskim, scsilun)) {3270			list_del(&ioim->qe);3271			list_add_tail(&ioim->qe, &tskim->io_q);3272		}3273	}3274 3275	/*3276	 * Failback any pending IO requests immediately.3277	 */3278	list_for_each_safe(qe, qen, &itnim->pending_q) {3279		ioim = (struct bfa_ioim_s *) qe;3280		cmnd = (struct scsi_cmnd *) ioim->dio;3281		int_to_scsilun(cmnd->device->lun, &scsilun);3282		if (bfa_tskim_match_scope(tskim, scsilun)) {3283			list_del(&ioim->qe);3284			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);3285			bfa_ioim_tov(ioim);3286		}3287	}3288}3289 3290/*3291 * IO cleanup completion3292 */3293static void3294bfa_tskim_cleanp_comp(void *tskim_cbarg)3295{3296	struct bfa_tskim_s *tskim = tskim_cbarg;3297 3298	bfa_stats(tskim->itnim, tm_io_comps);3299	bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);3300}3301 3302/*3303 * Gather affected IO requests and task management commands.3304 */3305static void3306bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)3307{3308	struct bfa_ioim_s *ioim;3309	struct list_head	*qe, *qen;3310 3311	bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);3312 3313	list_for_each_safe(qe, qen, &tskim->io_q) {3314		ioim = (struct bfa_ioim_s *) qe;3315		bfa_wc_up(&tskim->wc);3316		bfa_ioim_cleanup_tm(ioim, tskim);3317	}3318 3319	bfa_wc_wait(&tskim->wc);3320}3321 3322/*3323 * Send task management request to firmware.3324 */3325static bfa_boolean_t3326bfa_tskim_send(struct bfa_tskim_s *tskim)3327{3328	struct bfa_itnim_s *itnim = tskim->itnim;3329	struct bfi_tskim_req_s *m;3330 3331	/*3332	 * check for room in queue to send request now3333	 */3334	m = bfa_reqq_next(tskim->bfa, itnim->reqq);3335	if (!m)3336		return BFA_FALSE;3337 3338	/*3339	 * build i/o request message next3340	 */3341	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,3342			bfa_fn_lpu(tskim->bfa));3343 3344	m->tsk_tag = cpu_to_be16(tskim->tsk_tag);3345	m->itn_fhdl = tskim->itnim->rport->fw_handle;3346	m->t_secs = tskim->tsecs;3347	m->lun = tskim->lun;3348	m->tm_flags = tskim->tm_cmnd;3349 3350	/*3351	 * queue I/O message to firmware3352	 */3353	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);3354	return BFA_TRUE;3355}3356 3357/*3358 * Send abort request to cleanup an active TM to firmware.3359 */3360static bfa_boolean_t3361bfa_tskim_send_abort(struct bfa_tskim_s *tskim)3362{3363	struct bfa_itnim_s	*itnim = tskim->itnim;3364	struct bfi_tskim_abortreq_s	*m;3365 3366	/*3367	 * check for room in queue to send request now3368	 */3369	m = bfa_reqq_next(tskim->bfa, itnim->reqq);3370	if (!m)3371		return BFA_FALSE;3372 3373	/*3374	 * build i/o request message next3375	 */3376	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,3377			bfa_fn_lpu(tskim->bfa));3378 3379	m->tsk_tag  = cpu_to_be16(tskim->tsk_tag);3380 3381	/*3382	 * queue I/O message to firmware3383	 */3384	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);3385	return BFA_TRUE;3386}3387 3388/*3389 * Call to resume task management cmnd waiting for room in request queue.3390 */3391static void3392bfa_tskim_qresume(void *cbarg)3393{3394	struct bfa_tskim_s *tskim = cbarg;3395 3396	bfa_stats(tskim->itnim, tm_qresumes);3397	bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);3398}3399 3400/*3401 * Cleanup IOs associated with a task mangement command on IOC failures.3402 */3403static void3404bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)3405{3406	struct bfa_ioim_s *ioim;3407	struct list_head	*qe, *qen;3408 3409	list_for_each_safe(qe, qen, &tskim->io_q) {3410		ioim = (struct bfa_ioim_s *) qe;3411		bfa_ioim_iocdisable(ioim);3412	}3413}3414 3415/*3416 * Notification on completions from related ioim.3417 */3418void3419bfa_tskim_iodone(struct bfa_tskim_s *tskim)3420{3421	bfa_wc_down(&tskim->wc);3422}3423 3424/*3425 * Handle IOC h/w failure notification from itnim.3426 */3427void3428bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)3429{3430	tskim->notify = BFA_FALSE;3431	bfa_stats(tskim->itnim, tm_iocdowns);3432	bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);3433}3434 3435/*3436 * Cleanup TM command and associated IOs as part of ITNIM offline.3437 */3438void3439bfa_tskim_cleanup(struct bfa_tskim_s *tskim)3440{3441	tskim->notify = BFA_TRUE;3442	bfa_stats(tskim->itnim, tm_cleanups);3443	bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);3444}3445 3446/*3447 * Memory allocation and initialization.3448 */3449void3450bfa_tskim_attach(struct bfa_fcpim_s *fcpim)3451{3452	struct bfa_tskim_s *tskim;3453	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;3454	u16	i;3455 3456	INIT_LIST_HEAD(&fcpim->tskim_free_q);3457	INIT_LIST_HEAD(&fcpim->tskim_unused_q);3458 3459	tskim = (struct bfa_tskim_s *) bfa_mem_kva_curp(fcp);3460	fcpim->tskim_arr = tskim;3461 3462	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {3463		/*3464		 * initialize TSKIM3465		 */3466		memset(tskim, 0, sizeof(struct bfa_tskim_s));3467		tskim->tsk_tag = i;3468		tskim->bfa	= fcpim->bfa;3469		tskim->fcpim	= fcpim;3470		tskim->notify  = BFA_FALSE;3471		bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,3472					tskim);3473		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);3474 3475		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);3476	}3477 3478	bfa_mem_kva_curp(fcp) = (u8 *) tskim;3479}3480 3481void3482bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)3483{3484	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);3485	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;3486	struct bfa_tskim_s *tskim;3487	u16	tsk_tag = be16_to_cpu(rsp->tsk_tag);3488 3489	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);3490	WARN_ON(tskim->tsk_tag != tsk_tag);3491 3492	tskim->tsk_status = rsp->tsk_status;3493 3494	/*3495	 * Firmware sends BFI_TSKIM_STS_ABORTED status for abort3496	 * requests. All other statuses are for normal completions.3497	 */3498	if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {3499		bfa_stats(tskim->itnim, tm_cleanup_comps);3500		bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);3501	} else if (rsp->tsk_status == BFI_TSKIM_STS_UTAG) {3502		bfa_sm_send_event(tskim, BFA_TSKIM_SM_UTAG);3503	} else {3504		bfa_stats(tskim->itnim, tm_fw_rsps);3505		bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);3506	}3507}3508 3509 3510struct bfa_tskim_s *3511bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)3512{3513	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);3514	struct bfa_tskim_s *tskim;3515 3516	bfa_q_deq(&fcpim->tskim_free_q, &tskim);3517 3518	if (tskim)3519		tskim->dtsk = dtsk;3520 3521	return tskim;3522}3523 3524void3525bfa_tskim_free(struct bfa_tskim_s *tskim)3526{3527	WARN_ON(!bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));3528	list_del(&tskim->qe);3529	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);3530}3531 3532/*3533 * Start a task management command.3534 *3535 * @param[in]	tskim	BFA task management command instance3536 * @param[in]	itnim	i-t nexus for the task management command3537 * @param[in]	lun	lun, if applicable3538 * @param[in]	tm_cmnd	Task management command code.3539 * @param[in]	t_secs	Timeout in seconds3540 *3541 * @return None.3542 */3543void3544bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim,3545			struct scsi_lun lun,3546			enum fcp_tm_cmnd tm_cmnd, u8 tsecs)3547{3548	tskim->itnim	= itnim;3549	tskim->lun	= lun;3550	tskim->tm_cmnd = tm_cmnd;3551	tskim->tsecs	= tsecs;3552	tskim->notify  = BFA_FALSE;3553	bfa_stats(itnim, tm_cmnds);3554 3555	list_add_tail(&tskim->qe, &itnim->tsk_q);3556	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);3557}3558 3559void3560bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw)3561{3562	struct bfa_fcpim_s	*fcpim = BFA_FCPIM(bfa);3563	struct list_head	*qe;3564	int	i;3565 3566	for (i = 0; i < (fcpim->num_tskim_reqs - num_tskim_fw); i++) {3567		bfa_q_deq_tail(&fcpim->tskim_free_q, &qe);3568		list_add_tail(qe, &fcpim->tskim_unused_q);3569	}3570}3571 3572void3573bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,3574		struct bfa_s *bfa)3575{3576	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);3577	struct bfa_mem_kva_s *fcp_kva = BFA_MEM_FCP_KVA(bfa);3578	struct bfa_mem_dma_s *seg_ptr;3579	u16	nsegs, idx, per_seg_ios, num_io_req;3580	u32	km_len = 0;3581 3582	/*3583	 * ZERO for num_ioim_reqs and num_fwtio_reqs is allowed config value.3584	 * So if the values are non zero, adjust them appropriately.3585	 */3586	if (cfg->fwcfg.num_ioim_reqs &&3587	    cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)3588		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;3589	else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)3590		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;3591 3592	if (cfg->fwcfg.num_fwtio_reqs > BFA_FWTIO_MAX)3593		cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;3594 3595	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);3596	if (num_io_req > BFA_IO_MAX) {3597		if (cfg->fwcfg.num_ioim_reqs && cfg->fwcfg.num_fwtio_reqs) {3598			cfg->fwcfg.num_ioim_reqs = BFA_IO_MAX/2;3599			cfg->fwcfg.num_fwtio_reqs = BFA_IO_MAX/2;3600		} else if (cfg->fwcfg.num_fwtio_reqs)3601			cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;3602		else3603			cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;3604	}3605 3606	bfa_fcpim_meminfo(cfg, &km_len);3607 3608	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);3609	km_len += num_io_req * sizeof(struct bfa_iotag_s);3610	km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itn_s);3611 3612	/* dma memory */3613	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);3614	per_seg_ios = BFI_MEM_NREQS_SEG(BFI_IOIM_SNSLEN);3615 3616	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {3617		if (num_io_req >= per_seg_ios) {3618			num_io_req -= per_seg_ios;3619			bfa_mem_dma_setup(minfo, seg_ptr,3620				per_seg_ios * BFI_IOIM_SNSLEN);3621		} else3622			bfa_mem_dma_setup(minfo, seg_ptr,3623				num_io_req * BFI_IOIM_SNSLEN);3624	}3625 3626	/* kva memory */3627	bfa_mem_kva_setup(minfo, fcp_kva, km_len);3628}3629 3630void3631bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,3632		struct bfa_pcidev_s *pcidev)3633{3634	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);3635	struct bfa_mem_dma_s *seg_ptr;3636	u16	idx, nsegs, num_io_req;3637 3638	fcp->max_ioim_reqs = cfg->fwcfg.num_ioim_reqs;3639	fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;3640	fcp->num_fwtio_reqs  = cfg->fwcfg.num_fwtio_reqs;3641	fcp->num_itns   = cfg->fwcfg.num_rports;3642	fcp->bfa = bfa;3643 3644	/*3645	 * Setup the pool of snsbase addr's, that is passed to fw as3646	 * part of bfi_iocfc_cfg_s.3647	 */3648	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);3649	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);3650 3651	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {3652 3653		if (!bfa_mem_dma_virt(seg_ptr))3654			break;3655 3656		fcp->snsbase[idx].pa = bfa_mem_dma_phys(seg_ptr);3657		fcp->snsbase[idx].kva = bfa_mem_dma_virt(seg_ptr);3658		bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);3659	}3660 3661	fcp->throttle_update_required = 1;3662	bfa_fcpim_attach(fcp, bfad, cfg, pcidev);3663 3664	bfa_iotag_attach(fcp);3665 3666	fcp->itn_arr = (struct bfa_itn_s *) bfa_mem_kva_curp(fcp);3667	bfa_mem_kva_curp(fcp) = (u8 *)fcp->itn_arr +3668			(fcp->num_itns * sizeof(struct bfa_itn_s));3669	memset(fcp->itn_arr, 0,3670			(fcp->num_itns * sizeof(struct bfa_itn_s)));3671}3672 3673void3674bfa_fcp_iocdisable(struct bfa_s *bfa)3675{3676	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);3677 3678	bfa_fcpim_iocdisable(fcp);3679}3680 3681void3682bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw)3683{3684	struct bfa_fcp_mod_s	*mod = BFA_FCP_MOD(bfa);3685	struct list_head	*qe;3686	int	i;3687 3688	/* Update io throttle value only once during driver load time */3689	if (!mod->throttle_update_required)3690		return;3691 3692	for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {3693		bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);3694		list_add_tail(qe, &mod->iotag_unused_q);3695	}3696 3697	if (mod->num_ioim_reqs != num_ioim_fw) {3698		bfa_trc(bfa, mod->num_ioim_reqs);3699		bfa_trc(bfa, num_ioim_fw);3700	}3701 3702	mod->max_ioim_reqs = max_ioim_fw;3703	mod->num_ioim_reqs = num_ioim_fw;3704	mod->throttle_update_required = 0;3705}3706 3707void3708bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,3709		void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m))3710{3711	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);3712	struct bfa_itn_s *itn;3713 3714	itn =  BFA_ITN_FROM_TAG(fcp, rport->rport_tag);3715	itn->isr = isr;3716}3717 3718/*3719 * Itn interrupt processing.3720 */3721void3722bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m)3723{3724	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);3725	union bfi_itn_i2h_msg_u msg;3726	struct bfa_itn_s *itn;3727 3728	msg.msg = m;3729	itn =  BFA_ITN_FROM_TAG(fcp, msg.create_rsp->bfa_handle);3730 3731	if (itn->isr)3732		itn->isr(bfa, m);3733	else3734		WARN_ON(1);3735}3736 3737void3738bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)3739{3740	struct bfa_iotag_s *iotag;3741	u16	num_io_req, i;3742 3743	iotag = (struct bfa_iotag_s *) bfa_mem_kva_curp(fcp);3744	fcp->iotag_arr = iotag;3745 3746	INIT_LIST_HEAD(&fcp->iotag_ioim_free_q);3747	INIT_LIST_HEAD(&fcp->iotag_tio_free_q);3748	INIT_LIST_HEAD(&fcp->iotag_unused_q);3749 3750	num_io_req = fcp->num_ioim_reqs + fcp->num_fwtio_reqs;3751	for (i = 0; i < num_io_req; i++, iotag++) {3752		memset(iotag, 0, sizeof(struct bfa_iotag_s));3753		iotag->tag = i;3754		if (i < fcp->num_ioim_reqs)3755			list_add_tail(&iotag->qe, &fcp->iotag_ioim_free_q);3756		else3757			list_add_tail(&iotag->qe, &fcp->iotag_tio_free_q);3758	}3759 3760	bfa_mem_kva_curp(fcp) = (u8 *) iotag;3761}3762 3763 3764/*3765 * To send config req, first try to use throttle value from flash3766 * If 0, then use driver parameter3767 * We need to use min(flash_val, drv_val) because3768 * memory allocation was done based on this cfg'd value3769 */3770u163771bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param)3772{3773	u16 tmp;3774	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);3775 3776	/*3777	 * If throttle value from flash is already in effect after driver is3778	 * loaded then until next load, always return current value instead3779	 * of actual flash value3780	 */3781	if (!fcp->throttle_update_required)3782		return (u16)fcp->num_ioim_reqs;3783 3784	tmp = bfa_dconf_read_data_valid(bfa) ? bfa_fcpim_read_throttle(bfa) : 0;3785	if (!tmp || (tmp > drv_cfg_param))3786		tmp = drv_cfg_param;3787 3788	return tmp;3789}3790 3791bfa_status_t3792bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value)3793{3794	if (!bfa_dconf_get_min_cfg(bfa)) {3795		BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.value = value;3796		BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.is_valid = 1;3797		return BFA_STATUS_OK;3798	}3799 3800	return BFA_STATUS_FAILED;3801}3802 3803u163804bfa_fcpim_read_throttle(struct bfa_s *bfa)3805{3806	struct bfa_throttle_cfg_s *throttle_cfg =3807			&(BFA_DCONF_MOD(bfa)->dconf->throttle_cfg);3808 3809	return ((!bfa_dconf_get_min_cfg(bfa)) ?3810	       ((throttle_cfg->is_valid == 1) ? (throttle_cfg->value) : 0) : 0);3811}3812 3813bfa_status_t3814bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value)3815{3816	/* in min cfg no commands should run. */3817	if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||3818	    (!bfa_dconf_read_data_valid(bfa)))3819		return BFA_STATUS_FAILED;3820 3821	bfa_fcpim_write_throttle(bfa, value);3822 3823	return bfa_dconf_update(bfa);3824}3825 3826bfa_status_t3827bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf)3828{3829	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);3830	struct bfa_defs_fcpim_throttle_s throttle;3831 3832	if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||3833	    (!bfa_dconf_read_data_valid(bfa)))3834		return BFA_STATUS_FAILED;3835 3836	memset(&throttle, 0, sizeof(struct bfa_defs_fcpim_throttle_s));3837 3838	throttle.cur_value = (u16)(fcpim->fcp->num_ioim_reqs);3839	throttle.cfg_value = bfa_fcpim_read_throttle(bfa);3840	if (!throttle.cfg_value)3841		throttle.cfg_value = throttle.cur_value;3842	throttle.max_value = (u16)(fcpim->fcp->max_ioim_reqs);3843	memcpy(buf, &throttle, sizeof(struct bfa_defs_fcpim_throttle_s));3844 3845	return BFA_STATUS_OK;3846}3847