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