brintos

brintos / linux-shallow public Read only

0
0
Text · 21.6 KiB · 40e65ab Raw
851 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/*12 *  fcpim.c - FCP initiator mode i-t nexus state machine13 */14 15#include "bfad_drv.h"16#include "bfa_fcs.h"17#include "bfa_fcbuild.h"18#include "bfad_im.h"19#include "bfa_fcpim.h"20 21BFA_TRC_FILE(FCS, FCPIM);22 23/*24 * forward declarations25 */26static void	bfa_fcs_itnim_timeout(void *arg);27static void	bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);28static void	bfa_fcs_itnim_send_prli(void *itnim_cbarg,29					struct bfa_fcxp_s *fcxp_alloced);30static void	bfa_fcs_itnim_prli_response(void *fcsarg,31			 struct bfa_fcxp_s *fcxp, void *cbarg,32			    bfa_status_t req_status, u32 rsp_len,33			    u32 resid_len, struct fchs_s *rsp_fchs);34static void	bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,35			enum bfa_itnim_aen_event event);36 37static void	bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,38					 enum bfa_fcs_itnim_event event);39static void	bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,40					   enum bfa_fcs_itnim_event event);41static void	bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,42				      enum bfa_fcs_itnim_event event);43static void	bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,44					    enum bfa_fcs_itnim_event event);45static void	bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,46					    enum bfa_fcs_itnim_event event);47static void	bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,48					enum bfa_fcs_itnim_event event);49static void	bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,50					enum bfa_fcs_itnim_event event);51static void	bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,52					     enum bfa_fcs_itnim_event event);53static void	bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,54					   enum bfa_fcs_itnim_event event);55 56struct bfa_fcs_itnim_sm_table_s {57	bfa_fcs_itnim_sm_t sm;		/*  state machine function	*/58	enum bfa_itnim_state state;	/*  state machine encoding	*/59	char		*name;		/*  state name for display	*/60};61 62static inline enum bfa_itnim_state63bfa_fcs_itnim_sm_to_state(struct bfa_fcs_itnim_sm_table_s *smt, bfa_fcs_itnim_sm_t sm)64{65	int i = 0;66 67	while (smt[i].sm && smt[i].sm != sm)68		i++;69	return smt[i].state;70}71 72static struct bfa_fcs_itnim_sm_table_s itnim_sm_table[] = {73	{BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},74	{BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},75	{BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},76	{BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},77	{BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},78	{BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},79	{BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},80	{BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},81};82 83/*84 *  fcs_itnim_sm FCS itnim state machine85 */86 87static void88bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,89		 enum bfa_fcs_itnim_event event)90{91	bfa_trc(itnim->fcs, itnim->rport->pwwn);92	bfa_trc(itnim->fcs, event);93 94	switch (event) {95	case BFA_FCS_ITNIM_SM_FCS_ONLINE:96		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);97		itnim->prli_retries = 0;98		bfa_fcs_itnim_send_prli(itnim, NULL);99		break;100 101	case BFA_FCS_ITNIM_SM_OFFLINE:102		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);103		break;104 105	case BFA_FCS_ITNIM_SM_INITIATOR:106		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);107		break;108 109	case BFA_FCS_ITNIM_SM_DELETE:110		bfa_fcs_itnim_free(itnim);111		break;112 113	default:114		bfa_sm_fault(itnim->fcs, event);115	}116 117}118 119static void120bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,121		 enum bfa_fcs_itnim_event event)122{123	bfa_trc(itnim->fcs, itnim->rport->pwwn);124	bfa_trc(itnim->fcs, event);125 126	switch (event) {127	case BFA_FCS_ITNIM_SM_FRMSENT:128		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);129		break;130 131	case BFA_FCS_ITNIM_SM_INITIATOR:132		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);133		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);134		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);135		break;136 137	case BFA_FCS_ITNIM_SM_OFFLINE:138		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);139		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);140		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);141		break;142 143	case BFA_FCS_ITNIM_SM_DELETE:144		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);145		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);146		bfa_fcs_itnim_free(itnim);147		break;148 149	default:150		bfa_sm_fault(itnim->fcs, event);151	}152}153 154static void155bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,156		 enum bfa_fcs_itnim_event event)157{158	bfa_trc(itnim->fcs, itnim->rport->pwwn);159	bfa_trc(itnim->fcs, event);160 161	switch (event) {162	case BFA_FCS_ITNIM_SM_RSP_OK:163		if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR)164			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);165		else166			bfa_sm_set_state(itnim,167				bfa_fcs_itnim_sm_hal_rport_online);168 169		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);170		break;171 172	case BFA_FCS_ITNIM_SM_RSP_ERROR:173		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);174		bfa_timer_start(itnim->fcs->bfa, &itnim->timer,175				bfa_fcs_itnim_timeout, itnim,176				BFA_FCS_RETRY_TIMEOUT);177		break;178 179	case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:180		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);181		break;182 183	case BFA_FCS_ITNIM_SM_OFFLINE:184		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);185		bfa_fcxp_discard(itnim->fcxp);186		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);187		break;188 189	case BFA_FCS_ITNIM_SM_INITIATOR:190		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);191		bfa_fcxp_discard(itnim->fcxp);192		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);193		break;194 195	case BFA_FCS_ITNIM_SM_DELETE:196		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);197		bfa_fcxp_discard(itnim->fcxp);198		bfa_fcs_itnim_free(itnim);199		break;200 201	default:202		bfa_sm_fault(itnim->fcs, event);203	}204}205 206static void207bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,208				enum bfa_fcs_itnim_event event)209{210	bfa_trc(itnim->fcs, itnim->rport->pwwn);211	bfa_trc(itnim->fcs, event);212 213	switch (event) {214	case BFA_FCS_ITNIM_SM_HAL_ONLINE:215		if (!itnim->bfa_itnim)216			itnim->bfa_itnim = bfa_itnim_create(itnim->fcs->bfa,217					itnim->rport->bfa_rport, itnim);218 219		if (itnim->bfa_itnim) {220			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);221			bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);222		} else {223			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);224			bfa_sm_send_event(itnim->rport, RPSM_EVENT_DELETE);225		}226 227		break;228 229	case BFA_FCS_ITNIM_SM_OFFLINE:230		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);231		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);232		break;233 234	case BFA_FCS_ITNIM_SM_DELETE:235		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);236		bfa_fcs_itnim_free(itnim);237		break;238 239	default:240		bfa_sm_fault(itnim->fcs, event);241	}242}243 244static void245bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,246			    enum bfa_fcs_itnim_event event)247{248	bfa_trc(itnim->fcs, itnim->rport->pwwn);249	bfa_trc(itnim->fcs, event);250 251	switch (event) {252	case BFA_FCS_ITNIM_SM_TIMEOUT:253		if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {254			itnim->prli_retries++;255			bfa_trc(itnim->fcs, itnim->prli_retries);256			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);257			bfa_fcs_itnim_send_prli(itnim, NULL);258		} else {259			/* invoke target offline */260			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);261			bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);262		}263		break;264 265 266	case BFA_FCS_ITNIM_SM_OFFLINE:267		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);268		bfa_timer_stop(&itnim->timer);269		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);270		break;271 272	case BFA_FCS_ITNIM_SM_INITIATOR:273		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);274		bfa_timer_stop(&itnim->timer);275		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);276		break;277 278	case BFA_FCS_ITNIM_SM_DELETE:279		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);280		bfa_timer_stop(&itnim->timer);281		bfa_fcs_itnim_free(itnim);282		break;283 284	default:285		bfa_sm_fault(itnim->fcs, event);286	}287}288 289static void290bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,291			    enum bfa_fcs_itnim_event event)292{293	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;294	char	lpwwn_buf[BFA_STRING_32];295	char	rpwwn_buf[BFA_STRING_32];296 297	bfa_trc(itnim->fcs, itnim->rport->pwwn);298	bfa_trc(itnim->fcs, event);299 300	switch (event) {301	case BFA_FCS_ITNIM_SM_HCB_ONLINE:302		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);303		bfa_fcb_itnim_online(itnim->itnim_drv);304		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));305		wwn2str(rpwwn_buf, itnim->rport->pwwn);306		BFA_LOG(KERN_INFO, bfad, bfa_log_level,307		"Target (WWN = %s) is online for initiator (WWN = %s)\n",308		rpwwn_buf, lpwwn_buf);309		bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);310		break;311 312	case BFA_FCS_ITNIM_SM_OFFLINE:313		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);314		bfa_itnim_offline(itnim->bfa_itnim);315		break;316 317	case BFA_FCS_ITNIM_SM_DELETE:318		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);319		bfa_fcs_itnim_free(itnim);320		break;321 322	default:323		bfa_sm_fault(itnim->fcs, event);324	}325}326 327static void328bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,329		 enum bfa_fcs_itnim_event event)330{331	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;332	char	lpwwn_buf[BFA_STRING_32];333	char	rpwwn_buf[BFA_STRING_32];334 335	bfa_trc(itnim->fcs, itnim->rport->pwwn);336	bfa_trc(itnim->fcs, event);337 338	switch (event) {339	case BFA_FCS_ITNIM_SM_OFFLINE:340		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);341		bfa_fcb_itnim_offline(itnim->itnim_drv);342		bfa_itnim_offline(itnim->bfa_itnim);343		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));344		wwn2str(rpwwn_buf, itnim->rport->pwwn);345		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) {346			BFA_LOG(KERN_ERR, bfad, bfa_log_level,347			"Target (WWN = %s) connectivity lost for "348			"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);349			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);350		} else {351			BFA_LOG(KERN_INFO, bfad, bfa_log_level,352			"Target (WWN = %s) offlined by initiator (WWN = %s)\n",353			rpwwn_buf, lpwwn_buf);354			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);355		}356		break;357 358	case BFA_FCS_ITNIM_SM_DELETE:359		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);360		bfa_fcs_itnim_free(itnim);361		break;362 363	default:364		bfa_sm_fault(itnim->fcs, event);365	}366}367 368static void369bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,370			     enum bfa_fcs_itnim_event event)371{372	bfa_trc(itnim->fcs, itnim->rport->pwwn);373	bfa_trc(itnim->fcs, event);374 375	switch (event) {376	case BFA_FCS_ITNIM_SM_HCB_OFFLINE:377		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);378		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);379		break;380 381	case BFA_FCS_ITNIM_SM_DELETE:382		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);383		bfa_fcs_itnim_free(itnim);384		break;385 386	default:387		bfa_sm_fault(itnim->fcs, event);388	}389}390 391/*392 * This state is set when a discovered rport is also in intiator mode.393 * This ITN is marked as no_op and is not active and will not be truned into394 * online state.395 */396static void397bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,398		 enum bfa_fcs_itnim_event event)399{400	bfa_trc(itnim->fcs, itnim->rport->pwwn);401	bfa_trc(itnim->fcs, event);402 403	switch (event) {404	case BFA_FCS_ITNIM_SM_OFFLINE:405		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);406		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);407		break;408 409	/*410	 * fcs_online is expected here for well known initiator ports411	 */412	case BFA_FCS_ITNIM_SM_FCS_ONLINE:413		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);414		break;415 416	case BFA_FCS_ITNIM_SM_RSP_ERROR:417	case BFA_FCS_ITNIM_SM_INITIATOR:418		break;419 420	case BFA_FCS_ITNIM_SM_DELETE:421		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);422		bfa_fcs_itnim_free(itnim);423		break;424 425	default:426		bfa_sm_fault(itnim->fcs, event);427	}428}429 430static void431bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,432			enum bfa_itnim_aen_event event)433{434	struct bfa_fcs_rport_s *rport = itnim->rport;435	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;436	struct bfa_aen_entry_s	*aen_entry;437 438	/* Don't post events for well known addresses */439	if (BFA_FCS_PID_IS_WKA(rport->pid))440		return;441 442	bfad_get_aen_entry(bfad, aen_entry);443	if (!aen_entry)444		return;445 446	aen_entry->aen_data.itnim.vf_id = rport->port->fabric->vf_id;447	aen_entry->aen_data.itnim.ppwwn = bfa_fcs_lport_get_pwwn(448					bfa_fcs_get_base_port(itnim->fcs));449	aen_entry->aen_data.itnim.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);450	aen_entry->aen_data.itnim.rpwwn = rport->pwwn;451 452	/* Send the AEN notification */453	bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,454				  BFA_AEN_CAT_ITNIM, event);455}456 457static void458bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)459{460	struct bfa_fcs_itnim_s *itnim = itnim_cbarg;461	struct bfa_fcs_rport_s *rport = itnim->rport;462	struct bfa_fcs_lport_s *port = rport->port;463	struct fchs_s	fchs;464	struct bfa_fcxp_s *fcxp;465	int		len;466 467	bfa_trc(itnim->fcs, itnim->rport->pwwn);468 469	fcxp = fcxp_alloced ? fcxp_alloced :470	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);471	if (!fcxp) {472		itnim->stats.fcxp_alloc_wait++;473		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,474				bfa_fcs_itnim_send_prli, itnim, BFA_TRUE);475		return;476	}477	itnim->fcxp = fcxp;478 479	len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),480			    itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);481 482	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,483		      BFA_FALSE, FC_CLASS_3, len, &fchs,484		      bfa_fcs_itnim_prli_response, (void *)itnim,485		      FC_MAX_PDUSZ, FC_ELS_TOV);486 487	itnim->stats.prli_sent++;488	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);489}490 491static void492bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,493			    bfa_status_t req_status, u32 rsp_len,494			    u32 resid_len, struct fchs_s *rsp_fchs)495{496	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;497	struct fc_els_cmd_s *els_cmd;498	struct fc_prli_s *prli_resp;499	struct fc_ls_rjt_s *ls_rjt;500	struct fc_prli_params_s *sparams;501 502	bfa_trc(itnim->fcs, req_status);503 504	/*505	 * Sanity Checks506	 */507	if (req_status != BFA_STATUS_OK) {508		itnim->stats.prli_rsp_err++;509		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);510		return;511	}512 513	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);514 515	if (els_cmd->els_code == FC_ELS_ACC) {516		prli_resp = (struct fc_prli_s *) els_cmd;517 518		if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {519			bfa_trc(itnim->fcs, rsp_len);520			/*521			 * Check if this  r-port is also in Initiator mode.522			 * If so, we need to set this ITN as a no-op.523			 */524			if (prli_resp->parampage.servparams.initiator) {525				bfa_trc(itnim->fcs, prli_resp->parampage.type);526				itnim->rport->scsi_function =527						BFA_RPORT_INITIATOR;528				itnim->stats.prli_rsp_acc++;529				itnim->stats.initiator++;530				bfa_sm_send_event(itnim,531						  BFA_FCS_ITNIM_SM_RSP_OK);532				return;533			}534 535			itnim->stats.prli_rsp_parse_err++;536			return;537		}538		itnim->rport->scsi_function = BFA_RPORT_TARGET;539 540		sparams = &prli_resp->parampage.servparams;541		itnim->seq_rec	     = sparams->retry;542		itnim->rec_support   = sparams->rec_support;543		itnim->task_retry_id = sparams->task_retry_id;544		itnim->conf_comp     = sparams->confirm;545 546		itnim->stats.prli_rsp_acc++;547		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);548	} else {549		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);550 551		bfa_trc(itnim->fcs, ls_rjt->reason_code);552		bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);553 554		itnim->stats.prli_rsp_rjt++;555		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {556			bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);557			return;558		}559		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);560	}561}562 563static void564bfa_fcs_itnim_timeout(void *arg)565{566	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;567 568	itnim->stats.timeout++;569	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);570}571 572static void573bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)574{575	if (itnim->bfa_itnim) {576		bfa_itnim_delete(itnim->bfa_itnim);577		itnim->bfa_itnim = NULL;578	}579 580	bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);581}582 583 584 585/*586 *  itnim_public FCS ITNIM public interfaces587 */588 589/*590 *	Called by rport when a new rport is created.591 *592 * @param[in] rport	-  remote port.593 */594struct bfa_fcs_itnim_s *595bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)596{597	struct bfa_fcs_lport_s *port = rport->port;598	struct bfa_fcs_itnim_s *itnim;599	struct bfad_itnim_s   *itnim_drv;600	int ret;601 602	/*603	 * call bfad to allocate the itnim604	 */605	ret = bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);606	if (ret) {607		bfa_trc(port->fcs, rport->pwwn);608		return NULL;609	}610 611	/*612	 * Initialize itnim613	 */614	itnim->rport = rport;615	itnim->fcs = rport->fcs;616	itnim->itnim_drv = itnim_drv;617 618	itnim->bfa_itnim     = NULL;619	itnim->seq_rec	     = BFA_FALSE;620	itnim->rec_support   = BFA_FALSE;621	itnim->conf_comp     = BFA_FALSE;622	itnim->task_retry_id = BFA_FALSE;623 624	/*625	 * Set State machine626	 */627	bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);628 629	return itnim;630}631 632/*633 *	Called by rport to delete  the instance of FCPIM.634 *635 * @param[in] rport	-  remote port.636 */637void638bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)639{640	bfa_trc(itnim->fcs, itnim->rport->pid);641	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);642}643 644/*645 * Notification from rport that PLOGI is complete to initiate FC-4 session.646 */647void648bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim)649{650	itnim->stats.onlines++;651 652	if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid))653		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HAL_ONLINE);654}655 656/*657 * Called by rport to handle a remote device offline.658 */659void660bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)661{662	itnim->stats.offlines++;663	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);664}665 666/*667 * Called by rport when remote port is known to be an initiator from668 * PRLI received.669 */670void671bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)672{673	bfa_trc(itnim->fcs, itnim->rport->pid);674	itnim->stats.initiator++;675	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);676}677 678/*679 * Called by rport to check if the itnim is online.680 */681bfa_status_t682bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)683{684	bfa_trc(itnim->fcs, itnim->rport->pid);685	switch (bfa_fcs_itnim_sm_to_state(itnim_sm_table, itnim->sm)) {686	case BFA_ITNIM_ONLINE:687	case BFA_ITNIM_INITIATIOR:688		return BFA_STATUS_OK;689 690	default:691		return BFA_STATUS_NO_FCPIM_NEXUS;692	}693}694 695/*696 * BFA completion callback for bfa_itnim_online().697 */698void699bfa_cb_itnim_online(void *cbarg)700{701	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;702 703	bfa_trc(itnim->fcs, itnim->rport->pwwn);704	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);705}706 707/*708 * BFA completion callback for bfa_itnim_offline().709 */710void711bfa_cb_itnim_offline(void *cb_arg)712{713	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;714 715	bfa_trc(itnim->fcs, itnim->rport->pwwn);716	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);717}718 719/*720 * Mark the beginning of PATH TOV handling. IO completion callbacks721 * are still pending.722 */723void724bfa_cb_itnim_tov_begin(void *cb_arg)725{726	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;727 728	bfa_trc(itnim->fcs, itnim->rport->pwwn);729}730 731/*732 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.733 */734void735bfa_cb_itnim_tov(void *cb_arg)736{737	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;738	struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;739 740	bfa_trc(itnim->fcs, itnim->rport->pwwn);741	itnim_drv->state = ITNIM_STATE_TIMEOUT;742}743 744/*745 *		BFA notification to FCS/driver for second level error recovery.746 *747 * Atleast one I/O request has timedout and target is unresponsive to748 * repeated abort requests. Second level error recovery should be initiated749 * by starting implicit logout and recovery procedures.750 */751void752bfa_cb_itnim_sler(void *cb_arg)753{754	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;755 756	itnim->stats.sler++;757	bfa_trc(itnim->fcs, itnim->rport->pwwn);758	bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);759}760 761struct bfa_fcs_itnim_s *762bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)763{764	struct bfa_fcs_rport_s *rport;765	rport = bfa_fcs_rport_lookup(port, rpwwn);766 767	if (!rport)768		return NULL;769 770	WARN_ON(rport->itnim == NULL);771	return rport->itnim;772}773 774bfa_status_t775bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,776		       struct bfa_itnim_attr_s *attr)777{778	struct bfa_fcs_itnim_s *itnim = NULL;779 780	itnim = bfa_fcs_itnim_lookup(port, rpwwn);781 782	if (itnim == NULL)783		return BFA_STATUS_NO_FCPIM_NEXUS;784 785	attr->state	    = bfa_fcs_itnim_sm_to_state(itnim_sm_table, itnim->sm);786	attr->retry	    = itnim->seq_rec;787	attr->rec_support   = itnim->rec_support;788	attr->conf_comp	    = itnim->conf_comp;789	attr->task_retry_id = itnim->task_retry_id;790	return BFA_STATUS_OK;791}792 793bfa_status_t794bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,795			struct bfa_itnim_stats_s *stats)796{797	struct bfa_fcs_itnim_s *itnim = NULL;798 799	WARN_ON(port == NULL);800 801	itnim = bfa_fcs_itnim_lookup(port, rpwwn);802 803	if (itnim == NULL)804		return BFA_STATUS_NO_FCPIM_NEXUS;805 806	memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));807 808	return BFA_STATUS_OK;809}810 811bfa_status_t812bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)813{814	struct bfa_fcs_itnim_s *itnim = NULL;815 816	WARN_ON(port == NULL);817 818	itnim = bfa_fcs_itnim_lookup(port, rpwwn);819 820	if (itnim == NULL)821		return BFA_STATUS_NO_FCPIM_NEXUS;822 823	memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));824	return BFA_STATUS_OK;825}826 827void828bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,829			struct fchs_s *fchs, u16 len)830{831	struct fc_els_cmd_s *els_cmd;832 833	bfa_trc(itnim->fcs, fchs->type);834 835	if (fchs->type != FC_TYPE_ELS)836		return;837 838	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);839 840	bfa_trc(itnim->fcs, els_cmd->els_code);841 842	switch (els_cmd->els_code) {843	case FC_ELS_PRLO:844		bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);845		break;846 847	default:848		WARN_ON(1);849	}850}851