cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bfa_fcs_fcpim.c (21708B)


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