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