1 /*- 2 * Copyright (c) 2017 Broadcom. All rights reserved. 3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 /** 35 * @file 36 * Implement remote device state machine for target and initiator. 37 */ 38 39 /*! 40 @defgroup device_sm Node State Machine: Remote Device States 41 */ 42 43 #include "ocs.h" 44 #include "ocs_device.h" 45 #include "ocs_fabric.h" 46 #include "ocs_els.h" 47 48 static void *__ocs_d_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg); 49 static void *__ocs_d_wait_del_node(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg); 50 static void *__ocs_d_wait_del_ini_tgt(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg); 51 static int32_t ocs_process_abts(ocs_io_t *io, fc_header_t *hdr); 52 53 /** 54 * @ingroup device_sm 55 * @brief Send response to PRLI. 56 * 57 * <h3 class="desc">Description</h3> 58 * For device nodes, this function sends a PRLI response. 59 * 60 * @param io Pointer to a SCSI IO object. 61 * @param ox_id OX_ID of PRLI 62 * 63 * @return Returns None. 64 */ 65 66 void 67 ocs_d_send_prli_rsp(ocs_io_t *io, uint16_t ox_id) 68 { 69 ocs_t *ocs = io->ocs; 70 ocs_node_t *node = io->node; 71 72 /* If the back-end doesn't support the fc-type, we send an LS_RJT */ 73 if (ocs->fc_type != node->fc_type) { 74 node_printf(node, "PRLI rejected by target-server, fc-type not supported\n"); 75 ocs_send_ls_rjt(io, ox_id, FC_REASON_UNABLE_TO_PERFORM, 76 FC_EXPL_REQUEST_NOT_SUPPORTED, 0, NULL, NULL); 77 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 78 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 79 } 80 81 /* If the back-end doesn't want to talk to this initiator, we send an LS_RJT */ 82 if (node->sport->enable_tgt && (ocs_scsi_validate_initiator(node) == 0)) { 83 node_printf(node, "PRLI rejected by target-server\n"); 84 ocs_send_ls_rjt(io, ox_id, FC_REASON_UNABLE_TO_PERFORM, 85 FC_EXPL_NO_ADDITIONAL, 0, NULL, NULL); 86 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 87 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 88 } else { 89 /*sm: process PRLI payload, send PRLI acc */ 90 ocs_send_prli_acc(io, ox_id, ocs->fc_type, NULL, NULL); 91 92 /* Immediately go to ready state to avoid window where we're 93 * waiting for the PRLI LS_ACC to complete while holding FCP_CMNDs 94 */ 95 ocs_node_transition(node, __ocs_d_device_ready, NULL); 96 } 97 } 98 99 /** 100 * @ingroup device_sm 101 * @brief Device node state machine: Initiate node shutdown 102 * 103 * @param ctx Remote node state machine context. 104 * @param evt Event to process. 105 * @param arg Per event optional argument. 106 * 107 * @return Returns NULL. 108 */ 109 110 void * 111 __ocs_d_initiate_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 112 { 113 std_node_state_decl(); 114 115 node_sm_trace(); 116 117 switch(evt) { 118 case OCS_EVT_ENTER: { 119 int32_t rc = OCS_SCSI_CALL_COMPLETE; /* assume no wait needed */ 120 121 ocs_scsi_io_alloc_disable(node); 122 123 /* make necessary delete upcall(s) */ 124 if (node->init && !node->targ) { 125 ocs_log_debug(node->ocs, 126 "[%s] delete (initiator) WWPN %s WWNN %s\n", 127 node->display_name, node->wwpn, node->wwnn); 128 ocs_node_transition(node, __ocs_d_wait_del_node, NULL); 129 if (node->sport->enable_tgt) { 130 rc = ocs_scsi_del_initiator(node, 131 OCS_SCSI_INITIATOR_DELETED); 132 } 133 if (rc == OCS_SCSI_CALL_COMPLETE) { 134 ocs_node_post_event(node, 135 OCS_EVT_NODE_DEL_INI_COMPLETE, NULL); 136 } 137 } else if (node->targ && !node->init) { 138 ocs_log_debug(node->ocs, 139 "[%s] delete (target) WWPN %s WWNN %s\n", 140 node->display_name, node->wwpn, node->wwnn); 141 ocs_node_transition(node, __ocs_d_wait_del_node, NULL); 142 if (node->sport->enable_ini) { 143 rc = ocs_scsi_del_target(node, 144 OCS_SCSI_TARGET_DELETED); 145 } 146 if (rc == OCS_SCSI_CALL_COMPLETE) { 147 ocs_node_post_event(node, 148 OCS_EVT_NODE_DEL_TGT_COMPLETE, NULL); 149 } 150 } else if (node->init && node->targ) { 151 ocs_log_debug(node->ocs, 152 "[%s] delete (initiator+target) WWPN %s WWNN %s\n", 153 node->display_name, node->wwpn, node->wwnn); 154 ocs_node_transition(node, __ocs_d_wait_del_ini_tgt, NULL); 155 if (node->sport->enable_tgt) { 156 rc = ocs_scsi_del_initiator(node, 157 OCS_SCSI_INITIATOR_DELETED); 158 } 159 if (rc == OCS_SCSI_CALL_COMPLETE) { 160 ocs_node_post_event(node, 161 OCS_EVT_NODE_DEL_INI_COMPLETE, NULL); 162 } 163 rc = OCS_SCSI_CALL_COMPLETE; /* assume no wait needed */ 164 if (node->sport->enable_ini) { 165 rc = ocs_scsi_del_target(node, 166 OCS_SCSI_TARGET_DELETED); 167 } 168 if (rc == OCS_SCSI_CALL_COMPLETE) { 169 ocs_node_post_event(node, 170 OCS_EVT_NODE_DEL_TGT_COMPLETE, NULL); 171 } 172 } 173 174 /* we've initiated the upcalls as needed, now kick off the node 175 * detach to precipitate the aborting of outstanding exchanges 176 * associated with said node 177 * 178 * Beware: if we've made upcall(s), we've already transitioned 179 * to a new state by the time we execute this. 180 * TODO: consider doing this before the upcalls... 181 */ 182 if (node->attached) { 183 /* issue hw node free; don't care if succeeds right away 184 * or sometime later, will check node->attached later in 185 * shutdown process 186 */ 187 rc = ocs_hw_node_detach(&ocs->hw, &node->rnode); 188 if (node->rnode.free_group) { 189 ocs_remote_node_group_free(node->node_group); 190 node->node_group = NULL; 191 node->rnode.free_group = FALSE; 192 } 193 if (rc != OCS_HW_RTN_SUCCESS && 194 rc != OCS_HW_RTN_SUCCESS_SYNC) { 195 node_printf(node, 196 "Failed freeing HW node, rc=%d\n", rc); 197 } 198 } 199 200 /* if neither initiator nor target, proceed to cleanup */ 201 if (!node->init && !node->targ){ 202 /* 203 * node has either been detached or is in the process 204 * of being detached, call common node's initiate 205 * cleanup function. 206 */ 207 ocs_node_initiate_cleanup(node); 208 } 209 break; 210 } 211 case OCS_EVT_ALL_CHILD_NODES_FREE: 212 /* Ignore, this can happen if an ELS is aborted, 213 * while in a delay/retry state */ 214 break; 215 default: 216 __ocs_d_common(__func__, ctx, evt, arg); 217 return NULL; 218 } 219 return NULL; 220 } 221 222 /** 223 * @ingroup device_sm 224 * @brief Device node state machine: Common device event handler. 225 * 226 * <h3 class="desc">Description</h3> 227 * For device nodes, this event handler manages default and common events. 228 * 229 * @param funcname Function name text. 230 * @param ctx Remote node state machine context. 231 * @param evt Event to process. 232 * @param arg Per event optional argument. 233 * 234 * @return Returns NULL. 235 */ 236 237 static void * 238 __ocs_d_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 239 { 240 ocs_node_t *node = NULL; 241 ocs_t *ocs = NULL; 242 ocs_assert(ctx, NULL); 243 node = ctx->app; 244 ocs_assert(node, NULL); 245 ocs = node->ocs; 246 ocs_assert(ocs, NULL); 247 248 switch(evt) { 249 250 /* Handle shutdown events */ 251 case OCS_EVT_SHUTDOWN: 252 ocs_log_debug(ocs, "[%s] %-20s %-20s\n", node->display_name, funcname, ocs_sm_event_name(evt)); 253 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 254 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 255 break; 256 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO: 257 ocs_log_debug(ocs, "[%s] %-20s %-20s\n", node->display_name, funcname, ocs_sm_event_name(evt)); 258 node->shutdown_reason = OCS_NODE_SHUTDOWN_EXPLICIT_LOGO; 259 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 260 break; 261 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO: 262 ocs_log_debug(ocs, "[%s] %-20s %-20s\n", node->display_name, funcname, ocs_sm_event_name(evt)); 263 node->shutdown_reason = OCS_NODE_SHUTDOWN_IMPLICIT_LOGO; 264 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 265 break; 266 267 default: 268 /* call default event handler common to all nodes */ 269 __ocs_node_common(funcname, ctx, evt, arg); 270 break; 271 } 272 return NULL; 273 } 274 275 /** 276 * @ingroup device_sm 277 * @brief Device node state machine: Wait for a domain-attach completion in loop topology. 278 * 279 * <h3 class="desc">Description</h3> 280 * State waits for a domain-attached completion while in loop topology. 281 * 282 * @param ctx Remote node state machine context. 283 * @param evt Event to process. 284 * @param arg Per event optional argument. 285 * 286 * @return Returns NULL. 287 */ 288 289 void * 290 __ocs_d_wait_loop(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 291 { 292 std_node_state_decl(); 293 294 node_sm_trace(); 295 296 switch(evt) { 297 case OCS_EVT_ENTER: 298 ocs_node_hold_frames(node); 299 break; 300 301 case OCS_EVT_EXIT: 302 ocs_node_accept_frames(node); 303 break; 304 305 case OCS_EVT_DOMAIN_ATTACH_OK: { 306 /* send PLOGI automatically if initiator */ 307 ocs_node_init_device(node, TRUE); 308 break; 309 } 310 default: 311 __ocs_d_common(__func__, ctx, evt, arg); 312 return NULL; 313 } 314 315 return NULL; 316 } 317 318 319 320 321 /** 322 * @ingroup device_sm 323 * @brief state: wait for node resume event 324 * 325 * State is entered when a node is in I+T mode and sends a delete initiator/target 326 * call to the target-server/initiator-client and needs to wait for that work to complete. 327 * 328 * @param ctx Remote node state machine context. 329 * @param evt Event to process. 330 * @param arg per event optional argument 331 * 332 * @return returns NULL 333 */ 334 335 void * 336 __ocs_d_wait_del_ini_tgt(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 337 { 338 std_node_state_decl(); 339 340 node_sm_trace(); 341 342 switch(evt) { 343 case OCS_EVT_ENTER: 344 ocs_node_hold_frames(node); 345 /* Fall through */ 346 347 case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY: 348 case OCS_EVT_ALL_CHILD_NODES_FREE: 349 /* These are expected events. */ 350 break; 351 352 case OCS_EVT_NODE_DEL_INI_COMPLETE: 353 case OCS_EVT_NODE_DEL_TGT_COMPLETE: 354 ocs_node_transition(node, __ocs_d_wait_del_node, NULL); 355 break; 356 357 case OCS_EVT_EXIT: 358 ocs_node_accept_frames(node); 359 break; 360 361 case OCS_EVT_SRRS_ELS_REQ_FAIL: 362 /* Can happen as ELS IO IO's complete */ 363 ocs_assert(node->els_req_cnt, NULL); 364 node->els_req_cnt--; 365 break; 366 367 /* ignore shutdown events as we're already in shutdown path */ 368 case OCS_EVT_SHUTDOWN: 369 /* have default shutdown event take precedence */ 370 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 371 /* fall through */ 372 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO: 373 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO: 374 node_printf(node, "%s received\n", ocs_sm_event_name(evt)); 375 break; 376 case OCS_EVT_DOMAIN_ATTACH_OK: 377 /* don't care about domain_attach_ok */ 378 break; 379 default: 380 __ocs_d_common(__func__, ctx, evt, arg); 381 return NULL; 382 } 383 384 return NULL; 385 } 386 387 388 /** 389 * @ingroup device_sm 390 * @brief state: Wait for node resume event. 391 * 392 * State is entered when a node sends a delete initiator/target call to the 393 * target-server/initiator-client and needs to wait for that work to complete. 394 * 395 * @param ctx Remote node state machine context. 396 * @param evt Event to process. 397 * @param arg Per event optional argument. 398 * 399 * @return Returns NULL. 400 */ 401 402 void * 403 __ocs_d_wait_del_node(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 404 { 405 std_node_state_decl(); 406 407 node_sm_trace(); 408 409 switch(evt) { 410 case OCS_EVT_ENTER: 411 ocs_node_hold_frames(node); 412 /* Fall through */ 413 414 case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY: 415 case OCS_EVT_ALL_CHILD_NODES_FREE: 416 /* These are expected events. */ 417 break; 418 419 case OCS_EVT_NODE_DEL_INI_COMPLETE: 420 case OCS_EVT_NODE_DEL_TGT_COMPLETE: 421 /* 422 * node has either been detached or is in the process of being detached, 423 * call common node's initiate cleanup function 424 */ 425 ocs_node_initiate_cleanup(node); 426 break; 427 428 case OCS_EVT_EXIT: 429 ocs_node_accept_frames(node); 430 break; 431 432 case OCS_EVT_SRRS_ELS_REQ_FAIL: 433 /* Can happen as ELS IO IO's complete */ 434 ocs_assert(node->els_req_cnt, NULL); 435 node->els_req_cnt--; 436 break; 437 438 /* ignore shutdown events as we're already in shutdown path */ 439 case OCS_EVT_SHUTDOWN: 440 /* have default shutdown event take precedence */ 441 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 442 /* fall through */ 443 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO: 444 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO: 445 node_printf(node, "%s received\n", ocs_sm_event_name(evt)); 446 break; 447 case OCS_EVT_DOMAIN_ATTACH_OK: 448 /* don't care about domain_attach_ok */ 449 break; 450 default: 451 __ocs_d_common(__func__, ctx, evt, arg); 452 return NULL; 453 } 454 455 return NULL; 456 } 457 458 459 460 /** 461 * @brief Save the OX_ID for sending LS_ACC sometime later. 462 * 463 * <h3 class="desc">Description</h3> 464 * When deferring the response to an ELS request, the OX_ID of the request 465 * is saved using this function. 466 * 467 * @param io Pointer to a SCSI IO object. 468 * @param hdr Pointer to the FC header. 469 * @param ls Defines the type of ELS to send: LS_ACC, LS_ACC for PLOGI; 470 * or LSS_ACC for PRLI. 471 * 472 * @return None. 473 */ 474 475 void 476 ocs_send_ls_acc_after_attach(ocs_io_t *io, fc_header_t *hdr, ocs_node_send_ls_acc_e ls) 477 { 478 ocs_node_t *node = io->node; 479 uint16_t ox_id = ocs_be16toh(hdr->ox_id); 480 481 ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_NONE); 482 483 node->ls_acc_oxid = ox_id; 484 node->send_ls_acc = ls; 485 node->ls_acc_io = io; 486 node->ls_acc_did = fc_be24toh(hdr->d_id); 487 } 488 489 /** 490 * @brief Process the PRLI payload. 491 * 492 * <h3 class="desc">Description</h3> 493 * The PRLI payload is processed; the initiator/target capabilities of the 494 * remote node are extracted and saved in the node object. 495 * 496 * @param node Pointer to the node object. 497 * @param prli Pointer to the PRLI payload. 498 * 499 * @return None. 500 */ 501 502 void 503 ocs_process_prli_payload(ocs_node_t *node, fc_prli_payload_t *prli) 504 { 505 node->init = (ocs_be16toh(prli->service_params) & FC_PRLI_INITIATOR_FUNCTION) != 0; 506 node->targ = (ocs_be16toh(prli->service_params) & FC_PRLI_TARGET_FUNCTION) != 0; 507 node->fcp2device = (ocs_be16toh(prli->service_params) & FC_PRLI_RETRY) != 0; 508 node->fc_type = prli->type; 509 } 510 511 /** 512 * @brief Process the ABTS. 513 * 514 * <h3 class="desc">Description</h3> 515 * Common code to process a received ABTS. If an active IO can be found 516 * that matches the OX_ID of the ABTS request, a call is made to the 517 * backend. Otherwise, a BA_ACC is returned to the initiator. 518 * 519 * @param io Pointer to a SCSI IO object. 520 * @param hdr Pointer to the FC header. 521 * 522 * @return Returns 0 on success, or a negative error value on failure. 523 */ 524 525 static int32_t 526 ocs_process_abts(ocs_io_t *io, fc_header_t *hdr) 527 { 528 ocs_node_t *node = io->node; 529 ocs_t *ocs = node->ocs; 530 uint16_t ox_id = ocs_be16toh(hdr->ox_id); 531 uint16_t rx_id = ocs_be16toh(hdr->rx_id); 532 ocs_io_t *abortio; 533 534 abortio = ocs_io_find_tgt_io(ocs, node, ox_id, rx_id); 535 536 /* If an IO was found, attempt to take a reference on it */ 537 if (abortio != NULL && (ocs_ref_get_unless_zero(&abortio->ref) != 0)) { 538 539 /* Got a reference on the IO. Hold it until backend is notified below */ 540 node_printf(node, "Abort request: ox_id [%04x] rx_id [%04x]\n", 541 ox_id, rx_id); 542 543 /* 544 * Save the ox_id for the ABTS as the init_task_tag in our manufactured 545 * TMF IO object 546 */ 547 io->display_name = "abts"; 548 io->init_task_tag = ox_id; 549 /* don't set tgt_task_tag, don't want to confuse with XRI */ 550 551 /* 552 * Save the rx_id from the ABTS as it is needed for the BLS response, 553 * regardless of the IO context's rx_id 554 */ 555 io->abort_rx_id = rx_id; 556 557 /* Call target server command abort */ 558 io->tmf_cmd = OCS_SCSI_TMF_ABORT_TASK; 559 ocs_scsi_recv_tmf(io, abortio->tgt_io.lun, OCS_SCSI_TMF_ABORT_TASK, abortio, 0); 560 561 /* 562 * Backend will have taken an additional reference on the IO if needed; 563 * done with current reference. 564 */ 565 ocs_ref_put(&abortio->ref); /* ocs_ref_get(): same function */ 566 } else { 567 /* 568 * Either IO was not found or it has been freed between finding it 569 * and attempting to get the reference, 570 */ 571 node_printf(node, "Abort request: ox_id [%04x], IO not found (exists=%d)\n", 572 ox_id, (abortio != NULL)); 573 574 /* Send a BA_ACC */ 575 ocs_bls_send_acc_hdr(io, hdr); 576 } 577 return 0; 578 } 579 580 /** 581 * @ingroup device_sm 582 * @brief Device node state machine: Wait for the PLOGI accept to complete. 583 * 584 * @param ctx Remote node state machine context. 585 * @param evt Event to process. 586 * @param arg Per event optional argument. 587 * 588 * @return Returns NULL. 589 */ 590 591 void * 592 __ocs_d_wait_plogi_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 593 { 594 std_node_state_decl(); 595 596 node_sm_trace(); 597 598 switch(evt) { 599 case OCS_EVT_ENTER: 600 ocs_node_hold_frames(node); 601 break; 602 603 case OCS_EVT_EXIT: 604 ocs_node_accept_frames(node); 605 break; 606 607 case OCS_EVT_SRRS_ELS_CMPL_FAIL: 608 ocs_assert(node->els_cmpl_cnt, NULL); 609 node->els_cmpl_cnt--; 610 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 611 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 612 break; 613 614 case OCS_EVT_SRRS_ELS_CMPL_OK: /* PLOGI ACC completions */ 615 ocs_assert(node->els_cmpl_cnt, NULL); 616 node->els_cmpl_cnt--; 617 ocs_node_transition(node, __ocs_d_port_logged_in, NULL); 618 break; 619 620 default: 621 __ocs_d_common(__func__, ctx, evt, arg); 622 return NULL; 623 } 624 625 return NULL; 626 } 627 628 /** 629 * @ingroup device_sm 630 * @brief Device node state machine: Wait for the LOGO response. 631 * 632 * @param ctx Remote node state machine context. 633 * @param evt Event to process. 634 * @param arg Per event optional argument. 635 * 636 * @return Returns NULL. 637 */ 638 639 void * 640 __ocs_d_wait_logo_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 641 { 642 std_node_state_decl(); 643 644 node_sm_trace(); 645 646 switch(evt) { 647 case OCS_EVT_ENTER: 648 /* TODO: may want to remove this; 649 * if we'll want to know about PLOGI */ 650 ocs_node_hold_frames(node); 651 break; 652 653 case OCS_EVT_EXIT: 654 ocs_node_accept_frames(node); 655 break; 656 657 case OCS_EVT_SRRS_ELS_REQ_OK: 658 case OCS_EVT_SRRS_ELS_REQ_RJT: 659 case OCS_EVT_SRRS_ELS_REQ_FAIL: 660 /* LOGO response received, sent shutdown */ 661 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_LOGO, __ocs_d_common, __func__)) { 662 return NULL; 663 } 664 ocs_assert(node->els_req_cnt, NULL); 665 node->els_req_cnt--; 666 node_printf(node, "LOGO sent (evt=%s), shutdown node\n", ocs_sm_event_name(evt)); 667 /* sm: post explicit logout */ 668 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL); 669 break; 670 671 /* TODO: PLOGI: abort LOGO and process PLOGI? (SHUTDOWN_EXPLICIT/IMPLICIT_LOGO?) */ 672 673 default: 674 __ocs_d_common(__func__, ctx, evt, arg); 675 return NULL; 676 } 677 return NULL; 678 } 679 680 681 /** 682 * @ingroup device_sm 683 * @brief Device node state machine: Wait for the PRLO response. 684 * 685 * @param ctx Remote node state machine context. 686 * @param evt Event to process. 687 * @param arg Per event optional argument. 688 * 689 * @return Returns NULL. 690 */ 691 692 void * 693 __ocs_d_wait_prlo_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 694 { 695 std_node_state_decl(); 696 697 node_sm_trace(); 698 699 switch(evt) { 700 case OCS_EVT_ENTER: 701 ocs_node_hold_frames(node); 702 break; 703 704 case OCS_EVT_EXIT: 705 ocs_node_accept_frames(node); 706 break; 707 708 case OCS_EVT_SRRS_ELS_REQ_OK: 709 case OCS_EVT_SRRS_ELS_REQ_RJT: 710 case OCS_EVT_SRRS_ELS_REQ_FAIL: 711 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLO, __ocs_d_common, __func__)) { 712 return NULL; 713 } 714 ocs_assert(node->els_req_cnt, NULL); 715 node->els_req_cnt--; 716 node_printf(node, "PRLO sent (evt=%s)\n", ocs_sm_event_name(evt)); 717 ocs_node_transition(node, __ocs_d_port_logged_in, NULL); 718 break; 719 720 default: 721 __ocs_node_common(__func__, ctx, evt, arg); 722 return NULL; 723 } 724 return NULL; 725 } 726 727 728 /** 729 * @brief Initialize device node. 730 * 731 * Initialize device node. If a node is an initiator, then send a PLOGI and transition 732 * to __ocs_d_wait_plogi_rsp, otherwise transition to __ocs_d_init. 733 * 734 * @param node Pointer to the node object. 735 * @param send_plogi Boolean indicating to send PLOGI command or not. 736 * 737 * @return none 738 */ 739 740 void 741 ocs_node_init_device(ocs_node_t *node, int send_plogi) 742 { 743 node->send_plogi = send_plogi; 744 if ((node->ocs->nodedb_mask & OCS_NODEDB_PAUSE_NEW_NODES) && !FC_ADDR_IS_DOMAIN_CTRL(node->rnode.fc_id)) { 745 node->nodedb_state = __ocs_d_init; 746 ocs_node_transition(node, __ocs_node_paused, NULL); 747 } else { 748 ocs_node_transition(node, __ocs_d_init, NULL); 749 } 750 } 751 752 /** 753 * @ingroup device_sm 754 * @brief Device node state machine: Initial node state for an initiator or a target. 755 * 756 * <h3 class="desc">Description</h3> 757 * This state is entered when a node is instantiated, either having been 758 * discovered from a name services query, or having received a PLOGI/FLOGI. 759 * 760 * @param ctx Remote node state machine context. 761 * @param evt Event to process. 762 * @param arg Per event optional argument. 763 * - OCS_EVT_ENTER: (uint8_t *) - 1 to send a PLOGI on 764 * entry (initiator-only); 0 indicates a PLOGI is 765 * not sent on entry (initiator-only). Not applicable for a target. 766 * 767 * @return Returns NULL. 768 */ 769 770 void * 771 __ocs_d_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 772 { 773 int32_t rc; 774 ocs_node_cb_t *cbdata = arg; 775 std_node_state_decl(); 776 777 node_sm_trace(); 778 779 switch(evt) { 780 case OCS_EVT_ENTER: 781 /* check if we need to send PLOGI */ 782 if (node->send_plogi) { 783 /* only send if we have initiator capability, and domain is attached */ 784 if (node->sport->enable_ini && node->sport->domain->attached) { 785 ocs_send_plogi(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, 786 OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL); 787 ocs_node_transition(node, __ocs_d_wait_plogi_rsp, NULL); 788 } else { 789 node_printf(node, "not sending plogi sport.ini=%d, domain attached=%d\n", 790 node->sport->enable_ini, node->sport->domain->attached); 791 } 792 } 793 break; 794 case OCS_EVT_PLOGI_RCVD: { 795 /* T, or I+T */ 796 fc_header_t *hdr = cbdata->header->dma.virt; 797 uint32_t d_id = fc_be24toh(hdr->d_id); 798 799 ocs_node_save_sparms(node, cbdata->payload->dma.virt); 800 ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI); 801 802 /* domain already attached */ 803 if (node->sport->domain->attached) { 804 rc = ocs_node_attach(node); 805 ocs_node_transition(node, __ocs_d_wait_node_attach, NULL); 806 if (rc == OCS_HW_RTN_SUCCESS_SYNC) { 807 ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL); 808 } 809 break; 810 } 811 812 /* domain not attached; several possibilities: */ 813 switch (node->sport->topology) { 814 case OCS_SPORT_TOPOLOGY_P2P: 815 /* we're not attached and sport is p2p, need to attach */ 816 ocs_domain_attach(node->sport->domain, d_id); 817 ocs_node_transition(node, __ocs_d_wait_domain_attach, NULL); 818 break; 819 case OCS_SPORT_TOPOLOGY_FABRIC: 820 /* we're not attached and sport is fabric, domain attach should have 821 * already been requested as part of the fabric state machine, wait for it 822 */ 823 ocs_node_transition(node, __ocs_d_wait_domain_attach, NULL); 824 break; 825 case OCS_SPORT_TOPOLOGY_UNKNOWN: 826 /* Two possibilities: 827 * 1. received a PLOGI before our FLOGI has completed (possible since 828 * completion comes in on another CQ), thus we don't know what we're 829 * connected to yet; transition to a state to wait for the fabric 830 * node to tell us; 831 * 2. PLOGI received before link went down and we haven't performed 832 * domain attach yet. 833 * Note: we cannot distinguish between 1. and 2. so have to assume PLOGI 834 * was received after link back up. 835 */ 836 node_printf(node, "received PLOGI, with unknown topology did=0x%x\n", d_id); 837 ocs_node_transition(node, __ocs_d_wait_topology_notify, NULL); 838 break; 839 default: 840 node_printf(node, "received PLOGI, with unexpectd topology %d\n", 841 node->sport->topology); 842 ocs_assert(FALSE, NULL); 843 break; 844 } 845 break; 846 } 847 848 case OCS_EVT_FDISC_RCVD: { 849 __ocs_d_common(__func__, ctx, evt, arg); 850 break; 851 } 852 853 case OCS_EVT_FLOGI_RCVD: { 854 fc_header_t *hdr = cbdata->header->dma.virt; 855 856 /* this better be coming from an NPort */ 857 ocs_assert(ocs_rnode_is_nport(cbdata->payload->dma.virt), NULL); 858 859 /* sm: save sparams, send FLOGI acc */ 860 ocs_domain_save_sparms(node->sport->domain, cbdata->payload->dma.virt); 861 862 /* send FC LS_ACC response, override s_id */ 863 ocs_fabric_set_topology(node, OCS_SPORT_TOPOLOGY_P2P); 864 ocs_send_flogi_p2p_acc(cbdata->io, ocs_be16toh(hdr->ox_id), fc_be24toh(hdr->d_id), NULL, NULL); 865 if (ocs_p2p_setup(node->sport)) { 866 node_printf(node, "p2p setup failed, shutting down node\n"); 867 ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL); 868 } else { 869 ocs_node_transition(node, __ocs_p2p_wait_flogi_acc_cmpl, NULL); 870 } 871 872 break; 873 } 874 875 case OCS_EVT_LOGO_RCVD: { 876 fc_header_t *hdr = cbdata->header->dma.virt; 877 878 if (!node->sport->domain->attached) { 879 /* most likely a frame left over from before a link down; drop and 880 * shut node down w/ "explicit logout" so pending frames are processed */ 881 node_printf(node, "%s domain not attached, dropping\n", ocs_sm_event_name(evt)); 882 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL); 883 break; 884 } 885 ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 886 ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL); 887 break; 888 } 889 890 case OCS_EVT_PRLI_RCVD: 891 case OCS_EVT_PRLO_RCVD: 892 case OCS_EVT_PDISC_RCVD: 893 case OCS_EVT_ADISC_RCVD: 894 case OCS_EVT_RSCN_RCVD: { 895 fc_header_t *hdr = cbdata->header->dma.virt; 896 if (!node->sport->domain->attached) { 897 /* most likely a frame left over from before a link down; drop and 898 * shut node down w/ "explicit logout" so pending frames are processed */ 899 node_printf(node, "%s domain not attached, dropping\n", ocs_sm_event_name(evt)); 900 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL); 901 break; 902 } 903 node_printf(node, "%s received, sending reject\n", ocs_sm_event_name(evt)); 904 ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id), 905 FC_REASON_UNABLE_TO_PERFORM, FC_EXPL_NPORT_LOGIN_REQUIRED, 0, 906 NULL, NULL); 907 908 break; 909 } 910 911 case OCS_EVT_FCP_CMD_RCVD: { 912 /* note: problem, we're now expecting an ELS REQ completion 913 * from both the LOGO and PLOGI */ 914 if (!node->sport->domain->attached) { 915 /* most likely a frame left over from before a link down; drop and 916 * shut node down w/ "explicit logout" so pending frames are processed */ 917 node_printf(node, "%s domain not attached, dropping\n", ocs_sm_event_name(evt)); 918 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL); 919 break; 920 } 921 922 /* Send LOGO */ 923 node_printf(node, "FCP_CMND received, send LOGO\n"); 924 if (ocs_send_logo(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, 0, NULL, NULL) == NULL) { 925 /* failed to send LOGO, go ahead and cleanup node anyways */ 926 node_printf(node, "Failed to send LOGO\n"); 927 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL); 928 } else { 929 /* sent LOGO, wait for response */ 930 ocs_node_transition(node, __ocs_d_wait_logo_rsp, NULL); 931 } 932 break; 933 } 934 case OCS_EVT_DOMAIN_ATTACH_OK: 935 /* don't care about domain_attach_ok */ 936 break; 937 938 default: 939 __ocs_d_common(__func__, ctx, evt, arg); 940 return NULL; 941 } 942 943 return NULL; 944 } 945 946 /** 947 * @ingroup device_sm 948 * @brief Device node state machine: Wait on a response for a sent PLOGI. 949 * 950 * <h3 class="desc">Description</h3> 951 * State is entered when an initiator-capable node has sent 952 * a PLOGI and is waiting for a response. 953 * 954 * @param ctx Remote node state machine context. 955 * @param evt Event to process. 956 * @param arg Per event optional argument. 957 * 958 * @return Returns NULL. 959 */ 960 961 void * 962 __ocs_d_wait_plogi_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 963 { 964 int32_t rc; 965 ocs_node_cb_t *cbdata = arg; 966 std_node_state_decl(); 967 968 node_sm_trace(); 969 970 switch(evt) { 971 case OCS_EVT_PLOGI_RCVD: { 972 /* T, or I+T */ 973 /* received PLOGI with svc parms, go ahead and attach node 974 * when PLOGI that was sent ultimately completes, it'll be a no-op 975 */ 976 977 /* TODO: there is an outstanding PLOGI sent, can we set a flag 978 * to indicate that we don't want to retry it if it times out? */ 979 ocs_node_save_sparms(node, cbdata->payload->dma.virt); 980 ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI); 981 /* sm: domain->attached / ocs_node_attach */ 982 rc = ocs_node_attach(node); 983 ocs_node_transition(node, __ocs_d_wait_node_attach, NULL); 984 if (rc == OCS_HW_RTN_SUCCESS_SYNC) { 985 ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL); 986 } 987 break; 988 } 989 990 case OCS_EVT_PRLI_RCVD: 991 /* I, or I+T */ 992 /* sent PLOGI and before completion was seen, received the 993 * PRLI from the remote node (WCQEs and RCQEs come in on 994 * different queues and order of processing cannot be assumed) 995 * Save OXID so PRLI can be sent after the attach and continue 996 * to wait for PLOGI response 997 */ 998 ocs_process_prli_payload(node, cbdata->payload->dma.virt); 999 if (ocs->fc_type == node->fc_type) { 1000 ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PRLI); 1001 ocs_node_transition(node, __ocs_d_wait_plogi_rsp_recvd_prli, NULL); 1002 } else { 1003 /* TODO this need to be looked at. What do we do here ? */ 1004 } 1005 break; 1006 1007 /* TODO this need to be looked at. we could very well be logged in */ 1008 case OCS_EVT_LOGO_RCVD: /* why don't we do a shutdown here?? */ 1009 case OCS_EVT_PRLO_RCVD: 1010 case OCS_EVT_PDISC_RCVD: 1011 case OCS_EVT_FDISC_RCVD: 1012 case OCS_EVT_ADISC_RCVD: 1013 case OCS_EVT_RSCN_RCVD: 1014 case OCS_EVT_SCR_RCVD: { 1015 fc_header_t *hdr = cbdata->header->dma.virt; 1016 node_printf(node, "%s received, sending reject\n", ocs_sm_event_name(evt)); 1017 ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id), 1018 FC_REASON_UNABLE_TO_PERFORM, FC_EXPL_NPORT_LOGIN_REQUIRED, 0, 1019 NULL, NULL); 1020 1021 break; 1022 } 1023 1024 case OCS_EVT_SRRS_ELS_REQ_OK: /* PLOGI response received */ 1025 /* Completion from PLOGI sent */ 1026 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) { 1027 return NULL; 1028 } 1029 ocs_assert(node->els_req_cnt, NULL); 1030 node->els_req_cnt--; 1031 /* sm: save sparams, ocs_node_attach */ 1032 ocs_node_save_sparms(node, cbdata->els->els_rsp.virt); 1033 ocs_display_sparams(node->display_name, "plogi rcvd resp", 0, NULL, 1034 ((uint8_t*)cbdata->els->els_rsp.virt) + 4); 1035 rc = ocs_node_attach(node); 1036 ocs_node_transition(node, __ocs_d_wait_node_attach, NULL); 1037 if (rc == OCS_HW_RTN_SUCCESS_SYNC) { 1038 ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL); 1039 } 1040 break; 1041 1042 case OCS_EVT_SRRS_ELS_REQ_FAIL: /* PLOGI response received */ 1043 /* PLOGI failed, shutdown the node */ 1044 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) { 1045 return NULL; 1046 } 1047 ocs_assert(node->els_req_cnt, NULL); 1048 node->els_req_cnt--; 1049 ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL); 1050 break; 1051 1052 case OCS_EVT_SRRS_ELS_REQ_RJT: /* Our PLOGI was rejected, this is ok in some cases */ 1053 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) { 1054 return NULL; 1055 } 1056 ocs_assert(node->els_req_cnt, NULL); 1057 node->els_req_cnt--; 1058 break; 1059 1060 case OCS_EVT_FCP_CMD_RCVD: { 1061 /* not logged in yet and outstanding PLOGI so don't send LOGO, 1062 * just drop 1063 */ 1064 node_printf(node, "FCP_CMND received, drop\n"); 1065 break; 1066 } 1067 1068 default: 1069 __ocs_d_common(__func__, ctx, evt, arg); 1070 return NULL; 1071 } 1072 1073 return NULL; 1074 } 1075 1076 /** 1077 * @ingroup device_sm 1078 * @brief Device node state machine: Waiting on a response for a 1079 * sent PLOGI. 1080 * 1081 * <h3 class="desc">Description</h3> 1082 * State is entered when an initiator-capable node has sent 1083 * a PLOGI and is waiting for a response. Before receiving the 1084 * response, a PRLI was received, implying that the PLOGI was 1085 * successful. 1086 * 1087 * @param ctx Remote node state machine context. 1088 * @param evt Event to process. 1089 * @param arg Per event optional argument. 1090 * 1091 * @return Returns NULL. 1092 */ 1093 1094 void * 1095 __ocs_d_wait_plogi_rsp_recvd_prli(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1096 { 1097 int32_t rc; 1098 ocs_node_cb_t *cbdata = arg; 1099 std_node_state_decl(); 1100 1101 node_sm_trace(); 1102 1103 switch(evt) { 1104 case OCS_EVT_ENTER: 1105 /* 1106 * Since we've received a PRLI, we have a port login and will 1107 * just need to wait for the PLOGI response to do the node 1108 * attach and then we can send the LS_ACC for the PRLI. If, 1109 * during this time, we receive FCP_CMNDs (which is possible 1110 * since we've already sent a PRLI and our peer may have accepted). 1111 * At this time, we are not waiting on any other unsolicited 1112 * frames to continue with the login process. Thus, it will not 1113 * hurt to hold frames here. 1114 */ 1115 ocs_node_hold_frames(node); 1116 break; 1117 1118 case OCS_EVT_EXIT: 1119 ocs_node_accept_frames(node); 1120 break; 1121 1122 case OCS_EVT_SRRS_ELS_REQ_OK: /* PLOGI response received */ 1123 /* Completion from PLOGI sent */ 1124 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) { 1125 return NULL; 1126 } 1127 ocs_assert(node->els_req_cnt, NULL); 1128 node->els_req_cnt--; 1129 /* sm: save sparams, ocs_node_attach */ 1130 ocs_node_save_sparms(node, cbdata->els->els_rsp.virt); 1131 ocs_display_sparams(node->display_name, "plogi rcvd resp", 0, NULL, 1132 ((uint8_t*)cbdata->els->els_rsp.virt) + 4); 1133 rc = ocs_node_attach(node); 1134 ocs_node_transition(node, __ocs_d_wait_node_attach, NULL); 1135 if (rc == OCS_HW_RTN_SUCCESS_SYNC) { 1136 ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL); 1137 } 1138 break; 1139 1140 case OCS_EVT_SRRS_ELS_REQ_FAIL: /* PLOGI response received */ 1141 case OCS_EVT_SRRS_ELS_REQ_RJT: 1142 /* PLOGI failed, shutdown the node */ 1143 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) { 1144 return NULL; 1145 } 1146 ocs_assert(node->els_req_cnt, NULL); 1147 node->els_req_cnt--; 1148 ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL); 1149 break; 1150 1151 default: 1152 __ocs_d_common(__func__, ctx, evt, arg); 1153 return NULL; 1154 } 1155 1156 return NULL; 1157 } 1158 1159 /** 1160 * @ingroup device_sm 1161 * @brief Device node state machine: Wait for a domain attach. 1162 * 1163 * <h3 class="desc">Description</h3> 1164 * Waits for a domain-attach complete ok event. 1165 * 1166 * @param ctx Remote node state machine context. 1167 * @param evt Event to process. 1168 * @param arg Per event optional argument. 1169 * 1170 * @return Returns NULL. 1171 */ 1172 1173 void * 1174 __ocs_d_wait_domain_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1175 { 1176 int32_t rc; 1177 std_node_state_decl(); 1178 1179 node_sm_trace(); 1180 1181 switch(evt) { 1182 case OCS_EVT_ENTER: 1183 ocs_node_hold_frames(node); 1184 break; 1185 1186 case OCS_EVT_EXIT: 1187 ocs_node_accept_frames(node); 1188 break; 1189 1190 case OCS_EVT_DOMAIN_ATTACH_OK: 1191 ocs_assert(node->sport->domain->attached, NULL); 1192 /* sm: ocs_node_attach */ 1193 rc = ocs_node_attach(node); 1194 ocs_node_transition(node, __ocs_d_wait_node_attach, NULL); 1195 if (rc == OCS_HW_RTN_SUCCESS_SYNC) { 1196 ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL); 1197 } 1198 break; 1199 1200 default: 1201 __ocs_d_common(__func__, ctx, evt, arg); 1202 return NULL; 1203 } 1204 return NULL; 1205 } 1206 1207 /** 1208 * @ingroup device_sm 1209 * @brief Device node state machine: Wait for topology 1210 * notification 1211 * 1212 * <h3 class="desc">Description</h3> 1213 * Waits for topology notification from fabric node, then 1214 * attaches domain and node. 1215 * 1216 * @param ctx Remote node state machine context. 1217 * @param evt Event to process. 1218 * @param arg Per event optional argument. 1219 * 1220 * @return Returns NULL. 1221 */ 1222 1223 void * 1224 __ocs_d_wait_topology_notify(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1225 { 1226 int32_t rc; 1227 std_node_state_decl(); 1228 1229 node_sm_trace(); 1230 1231 switch(evt) { 1232 case OCS_EVT_ENTER: 1233 ocs_node_hold_frames(node); 1234 break; 1235 1236 case OCS_EVT_EXIT: 1237 ocs_node_accept_frames(node); 1238 break; 1239 1240 case OCS_EVT_SPORT_TOPOLOGY_NOTIFY: { 1241 ocs_sport_topology_e topology = (ocs_sport_topology_e)arg; 1242 ocs_assert(!node->sport->domain->attached, NULL); 1243 ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_PLOGI, NULL); 1244 node_printf(node, "topology notification, topology=%d\n", topology); 1245 1246 /* At the time the PLOGI was received, the topology was unknown, 1247 * so we didn't know which node would perform the domain attach: 1248 * 1. The node from which the PLOGI was sent (p2p) or 1249 * 2. The node to which the FLOGI was sent (fabric). 1250 */ 1251 if (topology == OCS_SPORT_TOPOLOGY_P2P) { 1252 /* if this is p2p, need to attach to the domain using the 1253 * d_id from the PLOGI received 1254 */ 1255 ocs_domain_attach(node->sport->domain, node->ls_acc_did); 1256 } 1257 /* else, if this is fabric, the domain attach should be performed 1258 * by the fabric node (node sending FLOGI); just wait for attach 1259 * to complete 1260 */ 1261 1262 ocs_node_transition(node, __ocs_d_wait_domain_attach, NULL); 1263 break; 1264 } 1265 case OCS_EVT_DOMAIN_ATTACH_OK: 1266 ocs_assert(node->sport->domain->attached, NULL); 1267 node_printf(node, "domain attach ok\n"); 1268 /*sm: ocs_node_attach */ 1269 rc = ocs_node_attach(node); 1270 ocs_node_transition(node, __ocs_d_wait_node_attach, NULL); 1271 if (rc == OCS_HW_RTN_SUCCESS_SYNC) { 1272 ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL); 1273 } 1274 break; 1275 1276 default: 1277 __ocs_d_common(__func__, ctx, evt, arg); 1278 return NULL; 1279 } 1280 return NULL; 1281 } 1282 1283 /** 1284 * @ingroup device_sm 1285 * @brief Device node state machine: Wait for a node attach when found by a remote node. 1286 * 1287 * @param ctx Remote node state machine context. 1288 * @param evt Event to process. 1289 * @param arg Per event optional argument. 1290 * 1291 * @return Returns NULL. 1292 */ 1293 1294 void * 1295 __ocs_d_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1296 { 1297 std_node_state_decl(); 1298 1299 node_sm_trace(); 1300 1301 switch(evt) { 1302 case OCS_EVT_ENTER: 1303 ocs_node_hold_frames(node); 1304 break; 1305 1306 case OCS_EVT_EXIT: 1307 ocs_node_accept_frames(node); 1308 break; 1309 1310 case OCS_EVT_NODE_ATTACH_OK: 1311 node->attached = TRUE; 1312 switch (node->send_ls_acc) { 1313 case OCS_NODE_SEND_LS_ACC_PLOGI: { 1314 /* sm: send_plogi_acc is set / send PLOGI acc */ 1315 /* Normal case for T, or I+T */ 1316 ocs_send_plogi_acc(node->ls_acc_io, node->ls_acc_oxid, NULL, NULL); 1317 ocs_node_transition(node, __ocs_d_wait_plogi_acc_cmpl, NULL); 1318 node->send_ls_acc = OCS_NODE_SEND_LS_ACC_NONE; 1319 node->ls_acc_io = NULL; 1320 break; 1321 } 1322 case OCS_NODE_SEND_LS_ACC_PRLI: { 1323 ocs_d_send_prli_rsp(node->ls_acc_io, node->ls_acc_oxid); 1324 node->send_ls_acc = OCS_NODE_SEND_LS_ACC_NONE; 1325 node->ls_acc_io = NULL; 1326 break; 1327 } 1328 case OCS_NODE_SEND_LS_ACC_NONE: 1329 default: 1330 /* Normal case for I */ 1331 /* sm: send_plogi_acc is not set / send PLOGI acc */ 1332 ocs_node_transition(node, __ocs_d_port_logged_in, NULL); 1333 break; 1334 } 1335 break; 1336 1337 case OCS_EVT_NODE_ATTACH_FAIL: 1338 /* node attach failed, shutdown the node */ 1339 node->attached = FALSE; 1340 node_printf(node, "node attach failed\n"); 1341 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 1342 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 1343 break; 1344 1345 /* Handle shutdown events */ 1346 case OCS_EVT_SHUTDOWN: 1347 node_printf(node, "%s received\n", ocs_sm_event_name(evt)); 1348 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 1349 ocs_node_transition(node, __ocs_d_wait_attach_evt_shutdown, NULL); 1350 break; 1351 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO: 1352 node_printf(node, "%s received\n", ocs_sm_event_name(evt)); 1353 node->shutdown_reason = OCS_NODE_SHUTDOWN_EXPLICIT_LOGO; 1354 ocs_node_transition(node, __ocs_d_wait_attach_evt_shutdown, NULL); 1355 break; 1356 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO: 1357 node_printf(node, "%s received\n", ocs_sm_event_name(evt)); 1358 node->shutdown_reason = OCS_NODE_SHUTDOWN_IMPLICIT_LOGO; 1359 ocs_node_transition(node, __ocs_d_wait_attach_evt_shutdown, NULL); 1360 break; 1361 default: 1362 __ocs_d_common(__func__, ctx, evt, arg); 1363 return NULL; 1364 } 1365 1366 return NULL; 1367 } 1368 1369 /** 1370 * @ingroup device_sm 1371 * @brief Device node state machine: Wait for a node/domain 1372 * attach then shutdown node. 1373 * 1374 * @param ctx Remote node state machine context. 1375 * @param evt Event to process. 1376 * @param arg Per event optional argument. 1377 * 1378 * @return Returns NULL. 1379 */ 1380 1381 void * 1382 __ocs_d_wait_attach_evt_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1383 { 1384 std_node_state_decl(); 1385 1386 node_sm_trace(); 1387 1388 switch(evt) { 1389 case OCS_EVT_ENTER: 1390 ocs_node_hold_frames(node); 1391 break; 1392 1393 case OCS_EVT_EXIT: 1394 ocs_node_accept_frames(node); 1395 break; 1396 1397 /* wait for any of these attach events and then shutdown */ 1398 case OCS_EVT_NODE_ATTACH_OK: 1399 node->attached = TRUE; 1400 node_printf(node, "Attach evt=%s, proceed to shutdown\n", ocs_sm_event_name(evt)); 1401 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 1402 break; 1403 1404 case OCS_EVT_NODE_ATTACH_FAIL: 1405 /* node attach failed, shutdown the node */ 1406 node->attached = FALSE; 1407 node_printf(node, "Attach evt=%s, proceed to shutdown\n", ocs_sm_event_name(evt)); 1408 ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); 1409 break; 1410 1411 /* ignore shutdown events as we're already in shutdown path */ 1412 case OCS_EVT_SHUTDOWN: 1413 /* have default shutdown event take precedence */ 1414 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; 1415 /* fall through */ 1416 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO: 1417 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO: 1418 node_printf(node, "%s received\n", ocs_sm_event_name(evt)); 1419 break; 1420 1421 default: 1422 __ocs_d_common(__func__, ctx, evt, arg); 1423 return NULL; 1424 } 1425 1426 return NULL; 1427 } 1428 1429 /** 1430 * @ingroup device_sm 1431 * @brief Device node state machine: Port is logged in. 1432 * 1433 * <h3 class="desc">Description</h3> 1434 * This state is entered when a remote port has completed port login (PLOGI). 1435 * 1436 * @param ctx Remote node state machine context. 1437 * @param evt Event to process 1438 * @param arg Per event optional argument 1439 * 1440 * @return Returns NULL. 1441 */ 1442 void * 1443 __ocs_d_port_logged_in(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1444 { 1445 ocs_node_cb_t *cbdata = arg; 1446 std_node_state_decl(); 1447 1448 node_sm_trace(); 1449 1450 /* TODO: I+T: what if PLOGI response not yet received ? */ 1451 1452 switch(evt) { 1453 case OCS_EVT_ENTER: 1454 /* Normal case for I or I+T */ 1455 if (node->sport->enable_ini && !FC_ADDR_IS_DOMAIN_CTRL(node->rnode.fc_id) 1456 && !node->sent_prli) { 1457 /* sm: if enable_ini / send PRLI */ 1458 ocs_send_prli(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL); 1459 node->sent_prli = TRUE; 1460 /* can now expect ELS_REQ_OK/FAIL/RJT */ 1461 } 1462 break; 1463 1464 case OCS_EVT_FCP_CMD_RCVD: { 1465 /* For target functionality send PRLO and drop the CMD frame. */ 1466 if (node->sport->enable_tgt) { 1467 if (ocs_send_prlo(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, 1468 OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL)) { 1469 ocs_node_transition(node, __ocs_d_wait_prlo_rsp, NULL); 1470 } 1471 } 1472 break; 1473 } 1474 1475 case OCS_EVT_PRLI_RCVD: { 1476 fc_header_t *hdr = cbdata->header->dma.virt; 1477 1478 /* Normal for T or I+T */ 1479 1480 ocs_process_prli_payload(node, cbdata->payload->dma.virt); 1481 ocs_d_send_prli_rsp(cbdata->io, ocs_be16toh(hdr->ox_id)); 1482 break; 1483 } 1484 1485 case OCS_EVT_SRRS_ELS_REQ_OK: { /* PRLI response */ 1486 /* Normal case for I or I+T */ 1487 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLI, __ocs_d_common, __func__)) { 1488 return NULL; 1489 } 1490 ocs_assert(node->els_req_cnt, NULL); 1491 node->els_req_cnt--; 1492 /* sm: process PRLI payload */ 1493 ocs_process_prli_payload(node, cbdata->els->els_rsp.virt); 1494 ocs_node_transition(node, __ocs_d_device_ready, NULL); 1495 break; 1496 } 1497 1498 case OCS_EVT_SRRS_ELS_REQ_FAIL: { /* PRLI response failed */ 1499 /* I, I+T, assume some link failure, shutdown node */ 1500 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLI, __ocs_d_common, __func__)) { 1501 return NULL; 1502 } 1503 ocs_assert(node->els_req_cnt, NULL); 1504 node->els_req_cnt--; 1505 ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL); 1506 break; 1507 } 1508 1509 case OCS_EVT_SRRS_ELS_REQ_RJT: {/* PRLI rejected by remote */ 1510 /* Normal for I, I+T (connected to an I) */ 1511 /* Node doesn't want to be a target, stay here and wait for a PRLI from the remote node 1512 * if it really wants to connect to us as target */ 1513 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLI, __ocs_d_common, __func__)) { 1514 return NULL; 1515 } 1516 ocs_assert(node->els_req_cnt, NULL); 1517 node->els_req_cnt--; 1518 break; 1519 } 1520 1521 case OCS_EVT_SRRS_ELS_CMPL_OK: { 1522 /* Normal T, I+T, target-server rejected the process login */ 1523 /* This would be received only in the case where we sent LS_RJT for the PRLI, so 1524 * do nothing. (note: as T only we could shutdown the node) 1525 */ 1526 ocs_assert(node->els_cmpl_cnt, NULL); 1527 node->els_cmpl_cnt--; 1528 break; 1529 } 1530 1531 case OCS_EVT_PLOGI_RCVD: { 1532 /* sm: save sparams, set send_plogi_acc, post implicit logout 1533 * Save plogi parameters */ 1534 ocs_node_save_sparms(node, cbdata->payload->dma.virt); 1535 ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI); 1536 1537 /* Restart node attach with new service parameters, and send ACC */ 1538 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_IMPLICIT_LOGO, NULL); 1539 break; 1540 } 1541 1542 case OCS_EVT_LOGO_RCVD: { 1543 /* I, T, I+T */ 1544 fc_header_t *hdr = cbdata->header->dma.virt; 1545 node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached); 1546 ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 1547 ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL); 1548 break; 1549 } 1550 1551 default: 1552 __ocs_d_common(__func__, ctx, evt, arg); 1553 return NULL; 1554 } 1555 1556 return NULL; 1557 } 1558 1559 /** 1560 * @ingroup device_sm 1561 * @brief Device node state machine: Wait for a LOGO accept. 1562 * 1563 * <h3 class="desc">Description</h3> 1564 * Waits for a LOGO accept completion. 1565 * 1566 * @param ctx Remote node state machine context. 1567 * @param evt Event to process 1568 * @param arg Per event optional argument 1569 * 1570 * @return Returns NULL. 1571 */ 1572 1573 void * 1574 __ocs_d_wait_logo_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1575 { 1576 std_node_state_decl(); 1577 1578 node_sm_trace(); 1579 1580 switch(evt) { 1581 case OCS_EVT_ENTER: 1582 ocs_node_hold_frames(node); 1583 break; 1584 1585 case OCS_EVT_EXIT: 1586 ocs_node_accept_frames(node); 1587 break; 1588 1589 case OCS_EVT_SRRS_ELS_CMPL_OK: 1590 case OCS_EVT_SRRS_ELS_CMPL_FAIL: 1591 /* sm: / post explicit logout */ 1592 ocs_assert(node->els_cmpl_cnt, NULL); 1593 node->els_cmpl_cnt--; 1594 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL); 1595 break; 1596 default: 1597 __ocs_d_common(__func__, ctx, evt, arg); 1598 return NULL; 1599 } 1600 1601 return NULL; 1602 } 1603 1604 /** 1605 * @ingroup device_sm 1606 * @brief Device node state machine: Device is ready. 1607 * 1608 * @param ctx Remote node state machine context. 1609 * @param evt Event to process. 1610 * @param arg Per event optional argument. 1611 * 1612 * @return Returns NULL. 1613 */ 1614 1615 void * 1616 __ocs_d_device_ready(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1617 { 1618 ocs_node_cb_t *cbdata = arg; 1619 std_node_state_decl(); 1620 1621 if (evt != OCS_EVT_FCP_CMD_RCVD) { 1622 node_sm_trace(); 1623 } 1624 1625 switch(evt) { 1626 case OCS_EVT_ENTER: 1627 node->fcp_enabled = TRUE; 1628 if (node->init) { 1629 device_printf(ocs->dev, "[%s] found (initiator) WWPN %s WWNN %s\n", node->display_name, 1630 node->wwpn, node->wwnn); 1631 if (node->sport->enable_tgt) 1632 ocs_scsi_new_initiator(node); 1633 } 1634 if (node->targ) { 1635 device_printf(ocs->dev, "[%s] found (target) WWPN %s WWNN %s\n", node->display_name, 1636 node->wwpn, node->wwnn); 1637 if (node->sport->enable_ini) 1638 ocs_scsi_new_target(node); 1639 } 1640 break; 1641 1642 case OCS_EVT_EXIT: 1643 node->fcp_enabled = FALSE; 1644 break; 1645 1646 case OCS_EVT_PLOGI_RCVD: { 1647 /* sm: save sparams, set send_plogi_acc, post implicit logout 1648 * Save plogi parameters */ 1649 ocs_node_save_sparms(node, cbdata->payload->dma.virt); 1650 ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI); 1651 1652 /* Restart node attach with new service parameters, and send ACC */ 1653 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_IMPLICIT_LOGO, NULL); 1654 break; 1655 } 1656 1657 1658 case OCS_EVT_PDISC_RCVD: { 1659 fc_header_t *hdr = cbdata->header->dma.virt; 1660 ocs_send_plogi_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 1661 break; 1662 } 1663 1664 case OCS_EVT_PRLI_RCVD: { 1665 /* T, I+T: remote initiator is slow to get started */ 1666 fc_header_t *hdr = cbdata->header->dma.virt; 1667 1668 ocs_process_prli_payload(node, cbdata->payload->dma.virt); 1669 1670 /* sm: send PRLI acc/reject */ 1671 if (ocs->fc_type == node->fc_type) 1672 ocs_send_prli_acc(cbdata->io, ocs_be16toh(hdr->ox_id), ocs->fc_type, NULL, NULL); 1673 else 1674 ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id), FC_REASON_UNABLE_TO_PERFORM, 1675 FC_EXPL_REQUEST_NOT_SUPPORTED, 0, NULL, NULL); 1676 break; 1677 } 1678 1679 case OCS_EVT_PRLO_RCVD: { 1680 fc_header_t *hdr = cbdata->header->dma.virt; 1681 fc_prlo_payload_t *prlo = cbdata->payload->dma.virt; 1682 1683 /* sm: send PRLO acc/reject */ 1684 if (ocs->fc_type == prlo->type) 1685 ocs_send_prlo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), ocs->fc_type, NULL, NULL); 1686 else 1687 ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id), FC_REASON_UNABLE_TO_PERFORM, 1688 FC_EXPL_REQUEST_NOT_SUPPORTED, 0, NULL, NULL); 1689 /*TODO: need implicit logout */ 1690 break; 1691 } 1692 1693 case OCS_EVT_LOGO_RCVD: { 1694 fc_header_t *hdr = cbdata->header->dma.virt; 1695 node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached); 1696 ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 1697 ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL); 1698 break; 1699 } 1700 1701 case OCS_EVT_ADISC_RCVD: { 1702 fc_header_t *hdr = cbdata->header->dma.virt; 1703 ocs_send_adisc_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 1704 break; 1705 } 1706 1707 case OCS_EVT_RRQ_RCVD: { 1708 fc_header_t *hdr = cbdata->header->dma.virt; 1709 /* Send LS_ACC */ 1710 ocs_send_ls_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 1711 break; 1712 } 1713 1714 case OCS_EVT_ABTS_RCVD: 1715 ocs_process_abts(cbdata->io, cbdata->header->dma.virt); 1716 break; 1717 1718 case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY: 1719 break; 1720 1721 case OCS_EVT_NODE_REFOUND: 1722 break; 1723 1724 case OCS_EVT_NODE_MISSING: 1725 if (node->sport->enable_rscn) { 1726 ocs_node_transition(node, __ocs_d_device_gone, NULL); 1727 } 1728 break; 1729 1730 case OCS_EVT_SRRS_ELS_CMPL_OK: 1731 /* T, or I+T, PRLI accept completed ok */ 1732 ocs_assert(node->els_cmpl_cnt, NULL); 1733 node->els_cmpl_cnt--; 1734 break; 1735 1736 case OCS_EVT_SRRS_ELS_CMPL_FAIL: 1737 /* T, or I+T, PRLI accept failed to complete */ 1738 ocs_assert(node->els_cmpl_cnt, NULL); 1739 node->els_cmpl_cnt--; 1740 node_printf(node, "Failed to send PRLI LS_ACC\n"); 1741 break; 1742 1743 default: 1744 __ocs_d_common(__func__, ctx, evt, arg); 1745 return NULL; 1746 } 1747 1748 return NULL; 1749 } 1750 1751 /** 1752 * @ingroup device_sm 1753 * @brief Device node state machine: Node is gone (absent from GID_PT). 1754 * 1755 * <h3 class="desc">Description</h3> 1756 * State entered when a node is detected as being gone (absent from GID_PT). 1757 * 1758 * @param ctx Remote node state machine context. 1759 * @param evt Event to process 1760 * @param arg Per event optional argument 1761 * 1762 * @return Returns NULL. 1763 */ 1764 1765 void * 1766 __ocs_d_device_gone(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1767 { 1768 int32_t rc = OCS_SCSI_CALL_COMPLETE; 1769 int32_t rc_2 = OCS_SCSI_CALL_COMPLETE; 1770 ocs_node_cb_t *cbdata = arg; 1771 std_node_state_decl(); 1772 1773 node_sm_trace(); 1774 1775 switch(evt) { 1776 case OCS_EVT_ENTER: { 1777 const char *labels[] = {"none", "initiator", "target", "initiator+target"}; 1778 1779 device_printf(ocs->dev, "[%s] missing (%s) WWPN %s WWNN %s\n", node->display_name, 1780 labels[(node->targ << 1) | (node->init)], node->wwpn, node->wwnn); 1781 1782 switch(ocs_node_get_enable(node)) { 1783 case OCS_NODE_ENABLE_T_TO_T: 1784 case OCS_NODE_ENABLE_I_TO_T: 1785 case OCS_NODE_ENABLE_IT_TO_T: 1786 rc = ocs_scsi_del_target(node, OCS_SCSI_TARGET_MISSING); 1787 break; 1788 1789 case OCS_NODE_ENABLE_T_TO_I: 1790 case OCS_NODE_ENABLE_I_TO_I: 1791 case OCS_NODE_ENABLE_IT_TO_I: 1792 rc = ocs_scsi_del_initiator(node, OCS_SCSI_INITIATOR_MISSING); 1793 break; 1794 1795 case OCS_NODE_ENABLE_T_TO_IT: 1796 rc = ocs_scsi_del_initiator(node, OCS_SCSI_INITIATOR_MISSING); 1797 break; 1798 1799 case OCS_NODE_ENABLE_I_TO_IT: 1800 rc = ocs_scsi_del_target(node, OCS_SCSI_TARGET_MISSING); 1801 break; 1802 1803 case OCS_NODE_ENABLE_IT_TO_IT: 1804 rc = ocs_scsi_del_initiator(node, OCS_SCSI_INITIATOR_MISSING); 1805 rc_2 = ocs_scsi_del_target(node, OCS_SCSI_TARGET_MISSING); 1806 break; 1807 1808 default: 1809 rc = OCS_SCSI_CALL_COMPLETE; 1810 break; 1811 1812 } 1813 1814 if ((rc == OCS_SCSI_CALL_COMPLETE) && (rc_2 == OCS_SCSI_CALL_COMPLETE)) { 1815 ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL); 1816 } 1817 1818 break; 1819 } 1820 case OCS_EVT_NODE_REFOUND: 1821 /* two approaches, reauthenticate with PLOGI/PRLI, or ADISC */ 1822 1823 /* reauthenticate with PLOGI/PRLI */ 1824 /* ocs_node_transition(node, __ocs_d_discovered, NULL); */ 1825 1826 /* reauthenticate with ADISC 1827 * sm: send ADISC */ 1828 ocs_send_adisc(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL); 1829 ocs_node_transition(node, __ocs_d_wait_adisc_rsp, NULL); 1830 break; 1831 1832 case OCS_EVT_PLOGI_RCVD: { 1833 /* sm: save sparams, set send_plogi_acc, post implicit logout 1834 * Save plogi parameters */ 1835 ocs_node_save_sparms(node, cbdata->payload->dma.virt); 1836 ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI); 1837 1838 /* Restart node attach with new service parameters, and send ACC */ 1839 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_IMPLICIT_LOGO, NULL); 1840 break; 1841 } 1842 1843 case OCS_EVT_FCP_CMD_RCVD: { 1844 /* most likely a stale frame (received prior to link down), if attempt 1845 * to send LOGO, will probably timeout and eat up 20s; thus, drop FCP_CMND 1846 */ 1847 node_printf(node, "FCP_CMND received, drop\n"); 1848 break; 1849 } 1850 case OCS_EVT_LOGO_RCVD: { 1851 /* I, T, I+T */ 1852 fc_header_t *hdr = cbdata->header->dma.virt; 1853 node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached); 1854 /* sm: send LOGO acc */ 1855 ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 1856 ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL); 1857 break; 1858 } 1859 default: 1860 __ocs_d_common(__func__, ctx, evt, arg); 1861 return NULL; 1862 } 1863 1864 return NULL; 1865 } 1866 1867 /** 1868 * @ingroup device_sm 1869 * @brief Device node state machine: Wait for the ADISC response. 1870 * 1871 * <h3 class="desc">Description</h3> 1872 * Waits for the ADISC response from the remote node. 1873 * 1874 * @param ctx Remote node state machine context. 1875 * @param evt Event to process. 1876 * @param arg Per event optional argument. 1877 * 1878 * @return Returns NULL. 1879 */ 1880 1881 void * 1882 __ocs_d_wait_adisc_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg) 1883 { 1884 ocs_node_cb_t *cbdata = arg; 1885 std_node_state_decl(); 1886 1887 node_sm_trace(); 1888 1889 switch(evt) { 1890 case OCS_EVT_SRRS_ELS_REQ_OK: 1891 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_ADISC, __ocs_d_common, __func__)) { 1892 return NULL; 1893 } 1894 ocs_assert(node->els_req_cnt, NULL); 1895 node->els_req_cnt--; 1896 ocs_node_transition(node, __ocs_d_device_ready, NULL); 1897 break; 1898 1899 case OCS_EVT_SRRS_ELS_REQ_RJT: 1900 /* received an LS_RJT, in this case, send shutdown (explicit logo) 1901 * event which will unregister the node, and start over with PLOGI 1902 */ 1903 if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_ADISC, __ocs_d_common, __func__)) { 1904 return NULL; 1905 } 1906 ocs_assert(node->els_req_cnt, NULL); 1907 node->els_req_cnt--; 1908 /*sm: post explicit logout */ 1909 ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL); 1910 break; 1911 1912 case OCS_EVT_LOGO_RCVD: { 1913 /* In this case, we have the equivalent of an LS_RJT for the ADISC, 1914 * so we need to abort the ADISC, and re-login with PLOGI 1915 */ 1916 /*sm: request abort, send LOGO acc */ 1917 fc_header_t *hdr = cbdata->header->dma.virt; 1918 node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached); 1919 ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL); 1920 ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL); 1921 break; 1922 } 1923 default: 1924 __ocs_d_common(__func__, ctx, evt, arg); 1925 return NULL; 1926 } 1927 1928 return NULL; 1929 } 1930