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