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 * Code to handle unsolicited received FC frames. 37 */ 38 39 /*! 40 * @defgroup unsol Unsolicited Frame Handling 41 */ 42 43 #include "ocs.h" 44 #include "ocs_els.h" 45 #include "ocs_fabric.h" 46 #include "ocs_device.h" 47 48 #define frame_printf(ocs, hdr, fmt, ...) \ 49 do { \ 50 char s_id_text[16]; \ 51 ocs_node_fcid_display(fc_be24toh((hdr)->s_id), s_id_text, sizeof(s_id_text)); \ 52 ocs_log_debug(ocs, "[%06x.%s] %02x/%04x/%04x: " fmt, fc_be24toh((hdr)->d_id), s_id_text, \ 53 (hdr)->r_ctl, ocs_be16toh((hdr)->ox_id), ocs_be16toh((hdr)->rx_id), ##__VA_ARGS__); \ 54 } while(0) 55 56 static int32_t ocs_unsol_process(ocs_t *ocs, ocs_hw_sequence_t *seq); 57 static int32_t ocs_dispatch_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq); 58 static int32_t ocs_dispatch_fcp_cmd_auto_xfer_rdy(ocs_node_t *node, ocs_hw_sequence_t *seq); 59 static int32_t ocs_dispatch_fcp_data(ocs_node_t *node, ocs_hw_sequence_t *seq); 60 static int32_t ocs_domain_dispatch_frame(void *arg, ocs_hw_sequence_t *seq); 61 static int32_t ocs_node_dispatch_frame(void *arg, ocs_hw_sequence_t *seq); 62 static int32_t ocs_fc_tmf_rejected_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg); 63 static ocs_hw_sequence_t *ocs_frame_next(ocs_list_t *pend_list, ocs_lock_t *list_lock); 64 static uint8_t ocs_node_frames_held(void *arg); 65 static uint8_t ocs_domain_frames_held(void *arg); 66 static int32_t ocs_purge_pending(ocs_t *ocs, ocs_list_t *pend_list, ocs_lock_t *list_lock); 67 static int32_t ocs_sframe_send_task_set_full_or_busy(ocs_node_t *node, ocs_hw_sequence_t *seq); 68 69 #define OCS_MAX_FRAMES_BEFORE_YEILDING 10000 70 71 /** 72 * @brief Process the RQ circular buffer and process the incoming frames. 73 * 74 * @param mythread Pointer to thread object. 75 * 76 * @return Returns 0 on success, or a non-zero value on failure. 77 */ 78 int32_t 79 ocs_unsol_rq_thread(ocs_thread_t *mythread) 80 { 81 ocs_xport_rq_thread_info_t *thread_data = mythread->arg; 82 ocs_t *ocs = thread_data->ocs; 83 ocs_hw_sequence_t *seq; 84 uint32_t yield_count = OCS_MAX_FRAMES_BEFORE_YEILDING; 85 86 ocs_log_debug(ocs, "%s running\n", mythread->name); 87 while (!ocs_thread_terminate_requested(mythread)) { 88 seq = ocs_cbuf_get(thread_data->seq_cbuf, 100000); 89 if (seq == NULL) { 90 /* Prevent soft lockups by yielding the CPU */ 91 ocs_thread_yield(&thread_data->thread); 92 yield_count = OCS_MAX_FRAMES_BEFORE_YEILDING; 93 continue; 94 } 95 /* Note: Always returns 0 */ 96 ocs_unsol_process((ocs_t*)seq->hw->os, seq); 97 98 /* We have to prevent CPU soft lockups, so just yield the CPU after x frames. */ 99 if (--yield_count == 0) { 100 ocs_thread_yield(&thread_data->thread); 101 yield_count = OCS_MAX_FRAMES_BEFORE_YEILDING; 102 } 103 } 104 ocs_log_debug(ocs, "%s exiting\n", mythread->name); 105 thread_data->thread_started = FALSE; 106 return 0; 107 } 108 109 /** 110 * @ingroup unsol 111 * @brief Callback function when aborting a port owned XRI 112 * exchanges. 113 * 114 * @return Returns 0. 115 */ 116 static int32_t 117 ocs_unsol_abort_cb (ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t len, int32_t status, uint32_t ext, void *arg) 118 { 119 ocs_t *ocs = arg; 120 ocs_assert(hio, -1); 121 ocs_assert(arg, -1); 122 ocs_log_debug(ocs, "xri=0x%x tag=0x%x\n", hio->indicator, hio->reqtag); 123 ocs_hw_io_free(&ocs->hw, hio); 124 return 0; 125 } 126 127 /** 128 * @ingroup unsol 129 * @brief Abort either a RQ Pair auto XFER RDY XRI. 130 * @return Returns None. 131 */ 132 static void 133 ocs_port_owned_abort(ocs_t *ocs, ocs_hw_io_t *hio) 134 { 135 ocs_hw_rtn_e hw_rc; 136 hw_rc = ocs_hw_io_abort(&ocs->hw, hio, FALSE, 137 ocs_unsol_abort_cb, ocs); 138 if((hw_rc == OCS_HW_RTN_IO_ABORT_IN_PROGRESS) || 139 (hw_rc == OCS_HW_RTN_IO_PORT_OWNED_ALREADY_ABORTED)) { 140 ocs_log_debug(ocs, "already aborted XRI 0x%x\n", hio->indicator); 141 } else if(hw_rc != OCS_HW_RTN_SUCCESS) { 142 ocs_log_debug(ocs, "Error aborting XRI 0x%x status %d\n", 143 hio->indicator, hw_rc); 144 } 145 } 146 147 /** 148 * @ingroup unsol 149 * @brief Handle unsolicited FC frames. 150 * 151 * <h3 class="desc">Description</h3> 152 * This function is called from the HW with unsolicited FC frames (FCP, ELS, BLS, etc.). 153 * 154 * @param arg Application-specified callback data. 155 * @param seq Header/payload sequence buffers. 156 * 157 * @return Returns 0 on success; or a negative error value on failure. 158 */ 159 160 int32_t 161 ocs_unsolicited_cb(void *arg, ocs_hw_sequence_t *seq) 162 { 163 ocs_t *ocs = arg; 164 ocs_xport_t *xport = ocs->xport; 165 int32_t rc; 166 167 CPUTRACE(""); 168 169 if (ocs->rq_threads == 0) { 170 rc = ocs_unsol_process(ocs, seq); 171 } else { 172 /* use the ox_id to dispatch this IO to a thread */ 173 fc_header_t *hdr = seq->header->dma.virt; 174 uint32_t ox_id = ocs_be16toh(hdr->ox_id); 175 uint32_t thr_index = ox_id % ocs->rq_threads; 176 177 rc = ocs_cbuf_put(xport->rq_thread_info[thr_index].seq_cbuf, seq); 178 } 179 180 if (rc) { 181 ocs_hw_sequence_free(&ocs->hw, seq); 182 } 183 184 return 0; 185 } 186 187 /** 188 * @ingroup unsol 189 * @brief Handle unsolicited FC frames. 190 * 191 * <h3 class="desc">Description</h3> 192 * This function is called either from ocs_unsolicited_cb() or ocs_unsol_rq_thread(). 193 * 194 * @param ocs Pointer to the ocs structure. 195 * @param seq Header/payload sequence buffers. 196 * 197 * @return Returns 0 on success, or a negative error value on failure. 198 */ 199 static int32_t 200 ocs_unsol_process(ocs_t *ocs, ocs_hw_sequence_t *seq) 201 { 202 ocs_xport_fcfi_t *xport_fcfi = NULL; 203 ocs_domain_t *domain; 204 uint8_t seq_fcfi = seq->fcfi; 205 206 /* HW_WORKAROUND_OVERRIDE_FCFI_IN_SRB */ 207 if (ocs->hw.workaround.override_fcfi) { 208 if (ocs->hw.first_domain_idx > -1) { 209 seq_fcfi = ocs->hw.first_domain_idx; 210 } 211 } 212 213 /* Range check seq->fcfi */ 214 if (seq_fcfi < ARRAY_SIZE(ocs->xport->fcfi)) { 215 xport_fcfi = &ocs->xport->fcfi[seq_fcfi]; 216 } 217 218 /* If the transport FCFI entry is NULL, then drop the frame */ 219 if (xport_fcfi == NULL) { 220 ocs_log_test(ocs, "FCFI %d is not valid, dropping frame\n", seq->fcfi); 221 if (seq->hio != NULL) { 222 ocs_port_owned_abort(ocs, seq->hio); 223 } 224 225 ocs_hw_sequence_free(&ocs->hw, seq); 226 return 0; 227 } 228 domain = ocs_hw_domain_get(&ocs->hw, seq_fcfi); 229 230 /* 231 * If we are holding frames or the domain is not yet registered or 232 * there's already frames on the pending list, 233 * then add the new frame to pending list 234 */ 235 if (domain == NULL || 236 xport_fcfi->hold_frames || 237 !ocs_list_empty(&xport_fcfi->pend_frames)) { 238 ocs_lock(&xport_fcfi->pend_frames_lock); 239 ocs_list_add_tail(&xport_fcfi->pend_frames, seq); 240 ocs_unlock(&xport_fcfi->pend_frames_lock); 241 242 if (domain != NULL) { 243 /* immediately process pending frames */ 244 ocs_domain_process_pending(domain); 245 } 246 } else { 247 /* 248 * We are not holding frames and pending list is empty, just process frame. 249 * A non-zero return means the frame was not handled - so cleanup 250 */ 251 if (ocs_domain_dispatch_frame(domain, seq)) { 252 if (seq->hio != NULL) { 253 ocs_port_owned_abort(ocs, seq->hio); 254 } 255 ocs_hw_sequence_free(&ocs->hw, seq); 256 } 257 } 258 return 0; 259 } 260 261 /** 262 * @ingroup unsol 263 * @brief Process pending frames queued to the given node. 264 * 265 * <h3 class="desc">Description</h3> 266 * Frames that are queued for the \c node are dispatched and returned 267 * to the RQ. 268 * 269 * @param node Node of the queued frames that are to be dispatched. 270 * 271 * @return Returns 0 on success, or a negative error value on failure. 272 */ 273 274 int32_t 275 ocs_process_node_pending(ocs_node_t *node) 276 { 277 ocs_t *ocs = node->ocs; 278 ocs_hw_sequence_t *seq = NULL; 279 uint32_t pend_frames_processed = 0; 280 281 for (;;) { 282 /* need to check for hold frames condition after each frame processed 283 * because any given frame could cause a transition to a state that 284 * holds frames 285 */ 286 if (ocs_node_frames_held(node)) { 287 break; 288 } 289 290 /* Get next frame/sequence */ 291 ocs_lock(&node->pend_frames_lock); 292 seq = ocs_list_remove_head(&node->pend_frames); 293 if (seq == NULL) { 294 pend_frames_processed = node->pend_frames_processed; 295 node->pend_frames_processed = 0; 296 ocs_unlock(&node->pend_frames_lock); 297 break; 298 } 299 node->pend_frames_processed++; 300 ocs_unlock(&node->pend_frames_lock); 301 302 /* now dispatch frame(s) to dispatch function */ 303 if (ocs_node_dispatch_frame(node, seq)) { 304 if (seq->hio != NULL) { 305 ocs_port_owned_abort(ocs, seq->hio); 306 } 307 ocs_hw_sequence_free(&ocs->hw, seq); 308 } 309 } 310 311 if (pend_frames_processed != 0) { 312 ocs_log_debug(ocs, "%u node frames held and processed\n", pend_frames_processed); 313 } 314 315 return 0; 316 } 317 318 /** 319 * @ingroup unsol 320 * @brief Process pending frames queued to the given domain. 321 * 322 * <h3 class="desc">Description</h3> 323 * Frames that are queued for the \c domain are dispatched and 324 * returned to the RQ. 325 * 326 * @param domain Domain of the queued frames that are to be 327 * dispatched. 328 * 329 * @return Returns 0 on success, or a negative error value on failure. 330 */ 331 332 int32_t 333 ocs_domain_process_pending(ocs_domain_t *domain) 334 { 335 ocs_t *ocs = domain->ocs; 336 ocs_xport_fcfi_t *xport_fcfi; 337 ocs_hw_sequence_t *seq = NULL; 338 uint32_t pend_frames_processed = 0; 339 340 ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI, -1); 341 xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator]; 342 343 for (;;) { 344 /* need to check for hold frames condition after each frame processed 345 * because any given frame could cause a transition to a state that 346 * holds frames 347 */ 348 if (ocs_domain_frames_held(domain)) { 349 break; 350 } 351 352 /* Get next frame/sequence */ 353 ocs_lock(&xport_fcfi->pend_frames_lock); 354 seq = ocs_list_remove_head(&xport_fcfi->pend_frames); 355 if (seq == NULL) { 356 pend_frames_processed = xport_fcfi->pend_frames_processed; 357 xport_fcfi->pend_frames_processed = 0; 358 ocs_unlock(&xport_fcfi->pend_frames_lock); 359 break; 360 } 361 xport_fcfi->pend_frames_processed++; 362 ocs_unlock(&xport_fcfi->pend_frames_lock); 363 364 /* now dispatch frame(s) to dispatch function */ 365 if (ocs_domain_dispatch_frame(domain, seq)) { 366 if (seq->hio != NULL) { 367 ocs_port_owned_abort(ocs, seq->hio); 368 } 369 ocs_hw_sequence_free(&ocs->hw, seq); 370 } 371 } 372 if (pend_frames_processed != 0) { 373 ocs_log_debug(ocs, "%u domain frames held and processed\n", pend_frames_processed); 374 } 375 return 0; 376 } 377 378 /** 379 * @ingroup unsol 380 * @brief Purge given pending list 381 * 382 * <h3 class="desc">Description</h3> 383 * Frames that are queued on the given pending list are 384 * discarded and returned to the RQ. 385 * 386 * @param ocs Pointer to ocs object. 387 * @param pend_list Pending list to be purged. 388 * @param list_lock Lock that protects pending list. 389 * 390 * @return Returns 0 on success, or a negative error value on failure. 391 */ 392 393 static int32_t 394 ocs_purge_pending(ocs_t *ocs, ocs_list_t *pend_list, ocs_lock_t *list_lock) 395 { 396 ocs_hw_sequence_t *frame; 397 398 for (;;) { 399 frame = ocs_frame_next(pend_list, list_lock); 400 if (frame == NULL) { 401 break; 402 } 403 404 frame_printf(ocs, (fc_header_t*) frame->header->dma.virt, "Discarding held frame\n"); 405 if (frame->hio != NULL) { 406 ocs_port_owned_abort(ocs, frame->hio); 407 } 408 ocs_hw_sequence_free(&ocs->hw, frame); 409 } 410 411 return 0; 412 } 413 414 /** 415 * @ingroup unsol 416 * @brief Purge node's pending (queued) frames. 417 * 418 * <h3 class="desc">Description</h3> 419 * Frames that are queued for the \c node are discarded and returned 420 * to the RQ. 421 * 422 * @param node Node of the queued frames that are to be discarded. 423 * 424 * @return Returns 0 on success, or a negative error value on failure. 425 */ 426 427 int32_t 428 ocs_node_purge_pending(ocs_node_t *node) 429 { 430 return ocs_purge_pending(node->ocs, &node->pend_frames, &node->pend_frames_lock); 431 } 432 433 /** 434 * @ingroup unsol 435 * @brief Purge xport's pending (queued) frames. 436 * 437 * <h3 class="desc">Description</h3> 438 * Frames that are queued for the \c xport are discarded and 439 * returned to the RQ. 440 * 441 * @param domain Pointer to domain object. 442 * 443 * @return Returns 0 on success; or a negative error value on failure. 444 */ 445 446 int32_t 447 ocs_domain_purge_pending(ocs_domain_t *domain) 448 { 449 ocs_t *ocs = domain->ocs; 450 ocs_xport_fcfi_t *xport_fcfi; 451 452 ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI, -1); 453 xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator]; 454 return ocs_purge_pending(domain->ocs, 455 &xport_fcfi->pend_frames, 456 &xport_fcfi->pend_frames_lock); 457 } 458 459 /** 460 * @ingroup unsol 461 * @brief Check if node's pending frames are held. 462 * 463 * @param arg Node for which the pending frame hold condition is 464 * checked. 465 * 466 * @return Returns 1 if node is holding pending frames, or 0 467 * if not. 468 */ 469 470 static uint8_t 471 ocs_node_frames_held(void *arg) 472 { 473 ocs_node_t *node = (ocs_node_t *)arg; 474 return node->hold_frames; 475 } 476 477 /** 478 * @ingroup unsol 479 * @brief Check if domain's pending frames are held. 480 * 481 * @param arg Domain for which the pending frame hold condition is 482 * checked. 483 * 484 * @return Returns 1 if domain is holding pending frames, or 0 485 * if not. 486 */ 487 488 static uint8_t 489 ocs_domain_frames_held(void *arg) 490 { 491 ocs_domain_t *domain = (ocs_domain_t *)arg; 492 ocs_t *ocs = domain->ocs; 493 ocs_xport_fcfi_t *xport_fcfi; 494 495 ocs_assert(domain != NULL, 1); 496 ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI, 1); 497 xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator]; 498 return xport_fcfi->hold_frames; 499 } 500 501 /** 502 * @ingroup unsol 503 * @brief Globally (at xport level) hold unsolicited frames. 504 * 505 * <h3 class="desc">Description</h3> 506 * This function places a hold on processing unsolicited FC 507 * frames queued to the xport pending list. 508 * 509 * @param domain Pointer to domain object. 510 * 511 * @return Returns None. 512 */ 513 514 void 515 ocs_domain_hold_frames(ocs_domain_t *domain) 516 { 517 ocs_t *ocs = domain->ocs; 518 ocs_xport_fcfi_t *xport_fcfi; 519 520 ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI); 521 xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator]; 522 if (!xport_fcfi->hold_frames) { 523 ocs_log_debug(domain->ocs, "hold frames set for FCFI %d\n", 524 domain->fcf_indicator); 525 xport_fcfi->hold_frames = 1; 526 } 527 } 528 529 /** 530 * @ingroup unsol 531 * @brief Clear hold on unsolicited frames. 532 * 533 * <h3 class="desc">Description</h3> 534 * This function clears the hold on processing unsolicited FC 535 * frames queued to the domain pending list. 536 * 537 * @param domain Pointer to domain object. 538 * 539 * @return Returns None. 540 */ 541 542 void 543 ocs_domain_accept_frames(ocs_domain_t *domain) 544 { 545 ocs_t *ocs = domain->ocs; 546 ocs_xport_fcfi_t *xport_fcfi; 547 548 ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI); 549 xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator]; 550 if (xport_fcfi->hold_frames == 1) { 551 ocs_log_debug(domain->ocs, "hold frames cleared for FCFI %d\n", 552 domain->fcf_indicator); 553 } 554 xport_fcfi->hold_frames = 0; 555 ocs_domain_process_pending(domain); 556 } 557 558 /** 559 * @ingroup unsol 560 * @brief Dispatch unsolicited FC frame. 561 * 562 * <h3 class="desc">Description</h3> 563 * This function processes an unsolicited FC frame queued at the 564 * domain level. 565 * 566 * @param arg Pointer to ocs object. 567 * @param seq Header/payload sequence buffers. 568 * 569 * @return Returns 0 if frame processed and RX buffers cleaned 570 * up appropriately, -1 if frame not handled. 571 */ 572 573 static __inline int32_t 574 ocs_domain_dispatch_frame(void *arg, ocs_hw_sequence_t *seq) 575 { 576 ocs_domain_t *domain = (ocs_domain_t *)arg; 577 ocs_t *ocs = domain->ocs; 578 fc_header_t *hdr; 579 uint32_t s_id; 580 uint32_t d_id; 581 ocs_node_t *node = NULL; 582 ocs_sport_t *sport = NULL; 583 584 ocs_assert(seq->header, -1); 585 ocs_assert(seq->header->dma.virt, -1); 586 ocs_assert(seq->payload->dma.virt, -1); 587 588 hdr = seq->header->dma.virt; 589 590 /* extract the s_id and d_id */ 591 s_id = fc_be24toh(hdr->s_id); 592 d_id = fc_be24toh(hdr->d_id); 593 594 sport = domain->sport; 595 if (sport == NULL) { 596 frame_printf(ocs, hdr, "phy sport for FC ID 0x%06x is NULL, dropping frame\n", d_id); 597 return -1; 598 } 599 600 if (sport->fc_id != d_id) { 601 /* Not a physical port IO lookup sport associated with the npiv port */ 602 sport = ocs_sport_find(domain, d_id); /* Look up without lock */ 603 if (sport == NULL) { 604 if (hdr->type == FC_TYPE_FCP) { 605 /* Drop frame */ 606 ocs_log_warn(ocs, "unsolicited FCP frame with invalid d_id x%x, dropping\n", 607 d_id); 608 return -1; 609 } else { 610 /* p2p will use this case */ 611 sport = domain->sport; 612 } 613 } 614 } 615 616 /* Lookup the node given the remote s_id */ 617 node = ocs_node_find(sport, s_id); 618 619 /* If not found, then create a new node */ 620 if (node == NULL) { 621 /* If this is solicited data or control based on R_CTL and there is no node context, 622 * then we can drop the frame 623 */ 624 if ((hdr->r_ctl == FC_RCTL_FC4_DATA) && ( 625 (hdr->info == FC_RCTL_INFO_SOL_DATA) || (hdr->info == FC_RCTL_INFO_SOL_CTRL))) { 626 ocs_log_debug(ocs, "solicited data/ctrl frame without node, dropping\n"); 627 return -1; 628 } 629 node = ocs_node_alloc(sport, s_id, FALSE, FALSE); 630 if (node == NULL) { 631 ocs_log_err(ocs, "ocs_node_alloc() failed\n"); 632 return -1; 633 } 634 /* don't send PLOGI on ocs_d_init entry */ 635 ocs_node_init_device(node, FALSE); 636 } 637 638 if (node->hold_frames || !ocs_list_empty((&node->pend_frames))) { 639 /* TODO: info log level 640 frame_printf(ocs, hdr, "Holding frame\n"); 641 */ 642 /* add frame to node's pending list */ 643 ocs_lock(&node->pend_frames_lock); 644 ocs_list_add_tail(&node->pend_frames, seq); 645 ocs_unlock(&node->pend_frames_lock); 646 647 return 0; 648 } 649 650 /* now dispatch frame to the node frame handler */ 651 return ocs_node_dispatch_frame(node, seq); 652 } 653 654 /** 655 * @ingroup unsol 656 * @brief Dispatch a frame. 657 * 658 * <h3 class="desc">Description</h3> 659 * A frame is dispatched from the \c node to the handler. 660 * 661 * @param arg Node that originated the frame. 662 * @param seq Header/payload sequence buffers. 663 * 664 * @return Returns 0 if frame processed and RX buffers cleaned 665 * up appropriately, -1 if frame not handled. 666 */ 667 static int32_t 668 ocs_node_dispatch_frame(void *arg, ocs_hw_sequence_t *seq) 669 { 670 671 fc_header_t *hdr = seq->header->dma.virt; 672 uint32_t port_id; 673 ocs_node_t *node = (ocs_node_t *)arg; 674 int32_t rc = -1; 675 int32_t sit_set = 0; 676 677 port_id = fc_be24toh(hdr->s_id); 678 ocs_assert(port_id == node->rnode.fc_id, -1); 679 680 if (fc_be24toh(hdr->f_ctl) & FC_FCTL_END_SEQUENCE) { 681 /*if SIT is set */ 682 if (fc_be24toh(hdr->f_ctl) & FC_FCTL_SEQUENCE_INITIATIVE) { 683 sit_set = 1; 684 } 685 switch (hdr->r_ctl) { 686 case FC_RCTL_ELS: 687 if (sit_set) { 688 rc = ocs_node_recv_els_frame(node, seq); 689 } 690 break; 691 692 case FC_RCTL_BLS: 693 if (sit_set) { 694 rc = ocs_node_recv_abts_frame(node, seq); 695 }else { 696 rc = ocs_node_recv_bls_no_sit(node, seq); 697 } 698 break; 699 700 case FC_RCTL_FC4_DATA: 701 switch(hdr->type) { 702 case FC_TYPE_FCP: 703 if (hdr->info == FC_RCTL_INFO_UNSOL_CMD) { 704 if (node->fcp_enabled) { 705 if (sit_set) { 706 rc = ocs_dispatch_fcp_cmd(node, seq); 707 }else { 708 /* send the auto xfer ready command */ 709 rc = ocs_dispatch_fcp_cmd_auto_xfer_rdy(node, seq); 710 } 711 } else { 712 rc = ocs_node_recv_fcp_cmd(node, seq); 713 } 714 } else if (hdr->info == FC_RCTL_INFO_SOL_DATA) { 715 if (sit_set) { 716 rc = ocs_dispatch_fcp_data(node, seq); 717 } 718 } 719 break; 720 case FC_TYPE_GS: 721 if (sit_set) { 722 rc = ocs_node_recv_ct_frame(node, seq); 723 } 724 break; 725 default: 726 break; 727 } 728 break; 729 } 730 } else { 731 node_printf(node, "Dropping frame hdr = %08x %08x %08x %08x %08x %08x\n", 732 ocs_htobe32(((uint32_t *)hdr)[0]), 733 ocs_htobe32(((uint32_t *)hdr)[1]), 734 ocs_htobe32(((uint32_t *)hdr)[2]), 735 ocs_htobe32(((uint32_t *)hdr)[3]), 736 ocs_htobe32(((uint32_t *)hdr)[4]), 737 ocs_htobe32(((uint32_t *)hdr)[5])); 738 } 739 return rc; 740 } 741 742 /** 743 * @ingroup unsol 744 * @brief Dispatch unsolicited FCP frames (RQ Pair). 745 * 746 * <h3 class="desc">Description</h3> 747 * Dispatch unsolicited FCP frames (called from the device node state machine). 748 * 749 * @param io Pointer to the IO context. 750 * @param task_management_flags Task management flags from the FCP_CMND frame. 751 * @param node Node that originated the frame. 752 * @param lun 32-bit LUN from FCP_CMND frame. 753 * 754 * @return Returns None. 755 */ 756 757 static void 758 ocs_dispatch_unsolicited_tmf(ocs_io_t *io, uint8_t task_management_flags, ocs_node_t *node, uint64_t lun) 759 { 760 uint32_t i; 761 struct { 762 uint32_t mask; 763 ocs_scsi_tmf_cmd_e cmd; 764 } tmflist[] = { 765 {FCP_QUERY_TASK_SET, OCS_SCSI_TMF_QUERY_TASK_SET}, 766 {FCP_ABORT_TASK_SET, OCS_SCSI_TMF_ABORT_TASK_SET}, 767 {FCP_CLEAR_TASK_SET, OCS_SCSI_TMF_CLEAR_TASK_SET}, 768 {FCP_QUERY_ASYNCHRONOUS_EVENT, OCS_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT}, 769 {FCP_LOGICAL_UNIT_RESET, OCS_SCSI_TMF_LOGICAL_UNIT_RESET}, 770 {FCP_TARGET_RESET, OCS_SCSI_TMF_TARGET_RESET}, 771 {FCP_CLEAR_ACA, OCS_SCSI_TMF_CLEAR_ACA}}; 772 773 io->exp_xfer_len = 0; /* BUG 32235 */ 774 775 for (i = 0; i < ARRAY_SIZE(tmflist); i ++) { 776 if (tmflist[i].mask & task_management_flags) { 777 io->tmf_cmd = tmflist[i].cmd; 778 ocs_scsi_recv_tmf(io, lun, tmflist[i].cmd, NULL, 0); 779 break; 780 } 781 } 782 if (i == ARRAY_SIZE(tmflist)) { 783 /* Not handled */ 784 node_printf(node, "TMF x%x rejected\n", task_management_flags); 785 ocs_scsi_send_tmf_resp(io, OCS_SCSI_TMF_FUNCTION_REJECTED, NULL, ocs_fc_tmf_rejected_cb, NULL); 786 } 787 } 788 789 static int32_t 790 ocs_validate_fcp_cmd(ocs_t *ocs, ocs_hw_sequence_t *seq) 791 { 792 size_t exp_payload_len = 0; 793 fcp_cmnd_iu_t *cmnd = seq->payload->dma.virt; 794 exp_payload_len = sizeof(fcp_cmnd_iu_t) - 16 + cmnd->additional_fcp_cdb_length; 795 796 /* 797 * If we received less than FCP_CMND_IU bytes, assume that the frame is 798 * corrupted in some way and drop it. This was seen when jamming the FCTL 799 * fill bytes field. 800 */ 801 if (seq->payload->dma.len < exp_payload_len) { 802 fc_header_t *fchdr = seq->header->dma.virt; 803 ocs_log_debug(ocs, "dropping ox_id %04x with payload length (%zd) less than expected (%zd)\n", 804 ocs_be16toh(fchdr->ox_id), seq->payload->dma.len, 805 exp_payload_len); 806 return -1; 807 } 808 return 0; 809 810 } 811 812 static void 813 ocs_populate_io_fcp_cmd(ocs_io_t *io, fcp_cmnd_iu_t *cmnd, fc_header_t *fchdr, uint8_t sit) 814 { 815 uint32_t *fcp_dl; 816 io->init_task_tag = ocs_be16toh(fchdr->ox_id); 817 /* note, tgt_task_tag, hw_tag set when HW io is allocated */ 818 fcp_dl = (uint32_t*)(&(cmnd->fcp_cdb_and_dl)); 819 fcp_dl += cmnd->additional_fcp_cdb_length; 820 io->exp_xfer_len = ocs_be32toh(*fcp_dl); 821 io->transferred = 0; 822 823 /* The upper 7 bits of CS_CTL is the frame priority thru the SAN. 824 * Our assertion here is, the priority given to a frame containing 825 * the FCP cmd should be the priority given to ALL frames contained 826 * in that IO. Thus we need to save the incoming CS_CTL here. 827 */ 828 if (fc_be24toh(fchdr->f_ctl) & FC_FCTL_PRIORITY_ENABLE) { 829 io->cs_ctl = fchdr->cs_ctl; 830 } else { 831 io->cs_ctl = 0; 832 } 833 io->seq_init = sit; 834 } 835 836 static uint32_t 837 ocs_get_flags_fcp_cmd(fcp_cmnd_iu_t *cmnd) 838 { 839 uint32_t flags = 0; 840 switch (cmnd->task_attribute) { 841 case FCP_TASK_ATTR_SIMPLE: 842 flags |= OCS_SCSI_CMD_SIMPLE; 843 break; 844 case FCP_TASK_ATTR_HEAD_OF_QUEUE: 845 flags |= OCS_SCSI_CMD_HEAD_OF_QUEUE; 846 break; 847 case FCP_TASK_ATTR_ORDERED: 848 flags |= OCS_SCSI_CMD_ORDERED; 849 break; 850 case FCP_TASK_ATTR_ACA: 851 flags |= OCS_SCSI_CMD_ACA; 852 break; 853 case FCP_TASK_ATTR_UNTAGGED: 854 flags |= OCS_SCSI_CMD_UNTAGGED; 855 break; 856 } 857 flags |= (uint32_t)cmnd->command_priority << OCS_SCSI_PRIORITY_SHIFT; 858 if (cmnd->wrdata) 859 flags |= OCS_SCSI_CMD_DIR_IN; 860 if (cmnd->rddata) 861 flags |= OCS_SCSI_CMD_DIR_OUT; 862 863 return flags; 864 } 865 866 /** 867 * @ingroup unsol 868 * @brief Dispatch unsolicited FCP_CMND frame. 869 * 870 * <h3 class="desc">Description</h3> 871 * Dispatch unsolicited FCP_CMND frame. RQ Pair mode - always 872 * used for RQ Pair mode since first burst is not supported. 873 * 874 * @param node Node that originated the frame. 875 * @param seq Header/payload sequence buffers. 876 * 877 * @return Returns 0 if frame processed and RX buffers cleaned 878 * up appropriately, -1 if frame not handled and RX buffers need 879 * to be returned. 880 */ 881 static int32_t 882 ocs_dispatch_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq) 883 { 884 ocs_t *ocs = node->ocs; 885 fc_header_t *fchdr = seq->header->dma.virt; 886 fcp_cmnd_iu_t *cmnd = NULL; 887 ocs_io_t *io = NULL; 888 fc_vm_header_t *vhdr; 889 uint8_t df_ctl; 890 uint64_t lun = UINT64_MAX; 891 int32_t rc = 0; 892 893 ocs_assert(seq->payload, -1); 894 cmnd = seq->payload->dma.virt; 895 896 /* perform FCP_CMND validation check(s) */ 897 if (ocs_validate_fcp_cmd(ocs, seq)) { 898 return -1; 899 } 900 901 lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(cmnd->fcp_lun)); 902 if (lun == UINT64_MAX) { 903 return -1; 904 } 905 906 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER); 907 if (io == NULL) { 908 uint32_t send_frame_capable; 909 910 /* If we have SEND_FRAME capability, then use it to send task set full or busy */ 911 rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable); 912 if ((rc == 0) && send_frame_capable) { 913 rc = ocs_sframe_send_task_set_full_or_busy(node, seq); 914 if (rc) { 915 ocs_log_test(ocs, "ocs_sframe_send_task_set_full_or_busy failed: %d\n", rc); 916 } 917 return rc; 918 } 919 920 ocs_log_err(ocs, "IO allocation failed ox_id %04x\n", ocs_be16toh(fchdr->ox_id)); 921 return -1; 922 } 923 io->hw_priv = seq->hw_priv; 924 925 /* Check if the CMD has vmheader. */ 926 io->app_id = 0; 927 df_ctl = fchdr->df_ctl; 928 if (df_ctl & FC_DFCTL_DEVICE_HDR_16_MASK) { 929 uint32_t vmhdr_offset = 0; 930 /* Presence of VMID. Get the vm header offset. */ 931 if (df_ctl & FC_DFCTL_ESP_HDR_MASK) { 932 vmhdr_offset += FC_DFCTL_ESP_HDR_SIZE; 933 ocs_log_err(ocs, "ESP Header present. Fix ESP Size.\n"); 934 } 935 936 if (df_ctl & FC_DFCTL_NETWORK_HDR_MASK) { 937 vmhdr_offset += FC_DFCTL_NETWORK_HDR_SIZE; 938 } 939 vhdr = (fc_vm_header_t *) ((char *)fchdr + sizeof(fc_header_t) + vmhdr_offset); 940 io->app_id = ocs_be32toh(vhdr->src_vmid); 941 } 942 943 /* RQ pair, if we got here, SIT=1 */ 944 ocs_populate_io_fcp_cmd(io, cmnd, fchdr, TRUE); 945 946 if (cmnd->task_management_flags) { 947 ocs_dispatch_unsolicited_tmf(io, cmnd->task_management_flags, node, lun); 948 } else { 949 uint32_t flags = ocs_get_flags_fcp_cmd(cmnd); 950 951 /* can return failure for things like task set full and UAs, 952 * no need to treat as a dropped frame if rc != 0 953 */ 954 ocs_scsi_recv_cmd(io, lun, cmnd->fcp_cdb, 955 sizeof(cmnd->fcp_cdb) + 956 (cmnd->additional_fcp_cdb_length * sizeof(uint32_t)), 957 flags); 958 } 959 960 /* successfully processed, now return RX buffer to the chip */ 961 ocs_hw_sequence_free(&ocs->hw, seq); 962 return 0; 963 } 964 965 /** 966 * @ingroup unsol 967 * @brief Dispatch unsolicited FCP_CMND frame (auto xfer rdy). 968 * 969 * <h3 class="desc">Description</h3> 970 * Dispatch unsolicited FCP_CMND frame that is assisted with auto xfer ready. 971 * 972 * @param node Node that originated the frame. 973 * @param seq Header/payload sequence buffers. 974 * 975 * @return Returns 0 if frame processed and RX buffers cleaned 976 * up appropriately, -1 if frame not handled and RX buffers need 977 * to be returned. 978 */ 979 static int32_t 980 ocs_dispatch_fcp_cmd_auto_xfer_rdy(ocs_node_t *node, ocs_hw_sequence_t *seq) 981 { 982 ocs_t *ocs = node->ocs; 983 fc_header_t *fchdr = seq->header->dma.virt; 984 fcp_cmnd_iu_t *cmnd = NULL; 985 ocs_io_t *io = NULL; 986 uint64_t lun = UINT64_MAX; 987 int32_t rc = 0; 988 989 ocs_assert(seq->payload, -1); 990 cmnd = seq->payload->dma.virt; 991 992 /* perform FCP_CMND validation check(s) */ 993 if (ocs_validate_fcp_cmd(ocs, seq)) { 994 return -1; 995 } 996 997 /* make sure first burst or auto xfer_rdy is enabled */ 998 if (!seq->auto_xrdy) { 999 node_printf(node, "IO is not Auto Xfr Rdy assisted, dropping FCP_CMND\n"); 1000 return -1; 1001 } 1002 1003 lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(cmnd->fcp_lun)); 1004 1005 /* TODO should there be a check here for an error? Why do any of the 1006 * below if the LUN decode failed? */ 1007 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER); 1008 if (io == NULL) { 1009 uint32_t send_frame_capable; 1010 1011 /* If we have SEND_FRAME capability, then use it to send task set full or busy */ 1012 rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable); 1013 if ((rc == 0) && send_frame_capable) { 1014 rc = ocs_sframe_send_task_set_full_or_busy(node, seq); 1015 if (rc) { 1016 ocs_log_test(ocs, "ocs_sframe_send_task_set_full_or_busy failed: %d\n", rc); 1017 } 1018 return rc; 1019 } 1020 1021 ocs_log_err(ocs, "IO allocation failed ox_id %04x\n", ocs_be16toh(fchdr->ox_id)); 1022 return -1; 1023 } 1024 io->hw_priv = seq->hw_priv; 1025 1026 /* RQ pair, if we got here, SIT=0 */ 1027 ocs_populate_io_fcp_cmd(io, cmnd, fchdr, FALSE); 1028 1029 if (cmnd->task_management_flags) { 1030 /* first burst command better not be a TMF */ 1031 ocs_log_err(ocs, "TMF flags set 0x%x\n", cmnd->task_management_flags); 1032 ocs_scsi_io_free(io); 1033 return -1; 1034 } else { 1035 uint32_t flags = ocs_get_flags_fcp_cmd(cmnd); 1036 1037 /* activate HW IO */ 1038 ocs_hw_io_activate_port_owned(&ocs->hw, seq->hio); 1039 io->hio = seq->hio; 1040 seq->hio->ul_io = io; 1041 io->tgt_task_tag = seq->hio->indicator; 1042 1043 /* Note: Data buffers are received in another call */ 1044 ocs_scsi_recv_cmd_first_burst(io, lun, cmnd->fcp_cdb, 1045 sizeof(cmnd->fcp_cdb) + 1046 (cmnd->additional_fcp_cdb_length * sizeof(uint32_t)), 1047 flags, NULL, 0); 1048 } 1049 1050 /* FCP_CMND processed, return RX buffer to the chip */ 1051 ocs_hw_sequence_free(&ocs->hw, seq); 1052 return 0; 1053 } 1054 1055 /** 1056 * @ingroup unsol 1057 * @brief Dispatch FCP data frames for auto xfer ready. 1058 * 1059 * <h3 class="desc">Description</h3> 1060 * Dispatch unsolicited FCP data frames (auto xfer ready) 1061 * containing sequence initiative transferred (SIT=1). 1062 * 1063 * @param node Node that originated the frame. 1064 * @param seq Header/payload sequence buffers. 1065 * 1066 * @return Returns 0 if frame processed and RX buffers cleaned 1067 * up appropriately, -1 if frame not handled. 1068 */ 1069 1070 static int32_t 1071 ocs_dispatch_fcp_data(ocs_node_t *node, ocs_hw_sequence_t *seq) 1072 { 1073 ocs_t *ocs = node->ocs; 1074 ocs_hw_t *hw = &ocs->hw; 1075 ocs_hw_io_t *hio = seq->hio; 1076 ocs_io_t *io; 1077 ocs_dma_t fburst[1]; 1078 1079 ocs_assert(seq->payload, -1); 1080 ocs_assert(hio, -1); 1081 1082 io = hio->ul_io; 1083 if (io == NULL) { 1084 ocs_log_err(ocs, "data received for NULL io, xri=0x%x\n", 1085 hio->indicator); 1086 return -1; 1087 } 1088 1089 /* 1090 * We only support data completions for auto xfer ready. Make sure 1091 * this is a port owned XRI. 1092 */ 1093 if (!ocs_hw_is_io_port_owned(hw, seq->hio)) { 1094 ocs_log_err(ocs, "data received for host owned XRI, xri=0x%x\n", 1095 hio->indicator); 1096 return -1; 1097 } 1098 1099 /* For error statuses, pass the error to the target back end */ 1100 if (seq->status != OCS_HW_UNSOL_SUCCESS) { 1101 ocs_log_err(ocs, "data with status 0x%x received, xri=0x%x\n", 1102 seq->status, hio->indicator); 1103 1104 /* 1105 * In this case, there is an existing, in-use HW IO that 1106 * first may need to be aborted. Then, the backend will be 1107 * notified of the error while waiting for the data. 1108 */ 1109 ocs_port_owned_abort(ocs, seq->hio); 1110 1111 /* 1112 * HW IO has already been allocated and is waiting for data. 1113 * Need to tell backend that an error has occurred. 1114 */ 1115 ocs_scsi_recv_cmd_first_burst(io, 0, NULL, 0, OCS_SCSI_FIRST_BURST_ERR, NULL, 0); 1116 return -1; 1117 } 1118 1119 /* sequence initiative has been transferred */ 1120 io->seq_init = 1; 1121 1122 /* convert the array of pointers to the correct type, to send to backend */ 1123 fburst[0] = seq->payload->dma; 1124 1125 /* the amount of first burst data was saved as "acculated sequence length" */ 1126 io->transferred = seq->payload->dma.len; 1127 1128 if (ocs_scsi_recv_cmd_first_burst(io, 0, NULL, 0, 0, 1129 fburst, io->transferred)) { 1130 ocs_log_err(ocs, "error passing first burst, xri=0x%x, oxid=0x%x\n", 1131 hio->indicator, io->init_task_tag); 1132 } 1133 1134 /* Free the header and all the accumulated payload buffers */ 1135 ocs_hw_sequence_free(&ocs->hw, seq); 1136 return 0; 1137 } 1138 1139 /** 1140 * @ingroup unsol 1141 * @brief Handle the callback for the TMF FUNCTION_REJECTED response. 1142 * 1143 * <h3 class="desc">Description</h3> 1144 * Handle the callback of a send TMF FUNCTION_REJECTED response request. 1145 * 1146 * @param io Pointer to the IO context. 1147 * @param scsi_status Status of the response. 1148 * @param flags Callback flags. 1149 * @param arg Callback argument. 1150 * 1151 * @return Returns 0 on success, or a negative error value on failure. 1152 */ 1153 1154 static int32_t 1155 ocs_fc_tmf_rejected_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg) 1156 { 1157 ocs_scsi_io_free(io); 1158 return 0; 1159 } 1160 1161 /** 1162 * @brief Return next FC frame on node->pend_frames list 1163 * 1164 * The next FC frame on the node->pend_frames list is returned, or NULL 1165 * if the list is empty. 1166 * 1167 * @param pend_list Pending list to be purged. 1168 * @param list_lock Lock that protects pending list. 1169 * 1170 * @return Returns pointer to the next FC frame, or NULL if the pending frame list 1171 * is empty. 1172 */ 1173 static ocs_hw_sequence_t * 1174 ocs_frame_next(ocs_list_t *pend_list, ocs_lock_t *list_lock) 1175 { 1176 ocs_hw_sequence_t *frame = NULL; 1177 1178 ocs_lock(list_lock); 1179 frame = ocs_list_remove_head(pend_list); 1180 ocs_unlock(list_lock); 1181 return frame; 1182 } 1183 1184 /** 1185 * @brief Process send fcp response frame callback 1186 * 1187 * The function is called when the send FCP response posting has completed. Regardless 1188 * of the outcome, the sequence is freed. 1189 * 1190 * @param arg Pointer to originator frame sequence. 1191 * @param cqe Pointer to completion queue entry. 1192 * @param status Status of operation. 1193 * 1194 * @return None. 1195 */ 1196 static void 1197 ocs_sframe_common_send_cb(void *arg, uint8_t *cqe, int32_t status) 1198 { 1199 ocs_hw_send_frame_context_t *ctx = arg; 1200 ocs_hw_t *hw = ctx->hw; 1201 1202 /* Free WQ completion callback */ 1203 ocs_hw_reqtag_free(hw, ctx->wqcb); 1204 1205 /* Free sequence */ 1206 ocs_hw_sequence_free(hw, ctx->seq); 1207 } 1208 1209 /** 1210 * @brief Send a frame, common code 1211 * 1212 * A frame is sent using SEND_FRAME, the R_CTL/F_CTL/TYPE may be specified, the payload is 1213 * sent as a single frame. 1214 * 1215 * Memory resources are allocated from RQ buffers contained in the passed in sequence data. 1216 * 1217 * @param node Pointer to node object. 1218 * @param seq Pointer to sequence object. 1219 * @param r_ctl R_CTL value to place in FC header. 1220 * @param info INFO value to place in FC header. 1221 * @param f_ctl F_CTL value to place in FC header. 1222 * @param type TYPE value to place in FC header. 1223 * @param payload Pointer to payload data 1224 * @param payload_len Length of payload in bytes. 1225 * 1226 * @return Returns 0 on success, or a negative error code value on failure. 1227 */ 1228 static int32_t 1229 ocs_sframe_common_send(ocs_node_t *node, ocs_hw_sequence_t *seq, uint8_t r_ctl, uint8_t info, uint32_t f_ctl, 1230 uint8_t type, void *payload, uint32_t payload_len) 1231 { 1232 ocs_t *ocs = node->ocs; 1233 ocs_hw_t *hw = &ocs->hw; 1234 ocs_hw_rtn_e rc = 0; 1235 fc_header_t *behdr = seq->header->dma.virt; 1236 fc_header_le_t hdr; 1237 uint32_t s_id = fc_be24toh(behdr->s_id); 1238 uint32_t d_id = fc_be24toh(behdr->d_id); 1239 uint16_t ox_id = ocs_be16toh(behdr->ox_id); 1240 uint16_t rx_id = ocs_be16toh(behdr->rx_id); 1241 ocs_hw_send_frame_context_t *ctx; 1242 1243 uint32_t heap_size = seq->payload->dma.size; 1244 uintptr_t heap_phys_base = seq->payload->dma.phys; 1245 uint8_t *heap_virt_base = seq->payload->dma.virt; 1246 uint32_t heap_offset = 0; 1247 1248 /* Build the FC header reusing the RQ header DMA buffer */ 1249 ocs_memset(&hdr, 0, sizeof(hdr)); 1250 hdr.d_id = s_id; /* send it back to whomever sent it to us */ 1251 hdr.r_ctl = r_ctl; 1252 hdr.info = info; 1253 hdr.s_id = d_id; 1254 hdr.cs_ctl = 0; 1255 hdr.f_ctl = f_ctl; 1256 hdr.type = type; 1257 hdr.seq_cnt = 0; 1258 hdr.df_ctl = 0; 1259 1260 /* 1261 * send_frame_seq_id is an atomic, we just let it increment, while storing only 1262 * the low 8 bits to hdr->seq_id 1263 */ 1264 hdr.seq_id = (uint8_t) ocs_atomic_add_return(&hw->send_frame_seq_id, 1); 1265 1266 hdr.rx_id = rx_id; 1267 hdr.ox_id = ox_id; 1268 hdr.parameter = 0; 1269 1270 /* Allocate and fill in the send frame request context */ 1271 ctx = (void*)(heap_virt_base + heap_offset); 1272 heap_offset += sizeof(*ctx); 1273 ocs_assert(heap_offset < heap_size, -1); 1274 ocs_memset(ctx, 0, sizeof(*ctx)); 1275 1276 /* Save sequence */ 1277 ctx->seq = seq; 1278 1279 /* Allocate a response payload DMA buffer from the heap */ 1280 ctx->payload.phys = heap_phys_base + heap_offset; 1281 ctx->payload.virt = heap_virt_base + heap_offset; 1282 ctx->payload.size = payload_len; 1283 ctx->payload.len = payload_len; 1284 heap_offset += payload_len; 1285 ocs_assert(heap_offset <= heap_size, -1); 1286 1287 /* Copy the payload in */ 1288 ocs_memcpy(ctx->payload.virt, payload, payload_len); 1289 1290 /* Send */ 1291 rc = ocs_hw_send_frame(&ocs->hw, (void*)&hdr, FC_SOFI3, FC_EOFT, &ctx->payload, ctx, 1292 ocs_sframe_common_send_cb, ctx); 1293 if (rc) { 1294 ocs_log_test(ocs, "ocs_hw_send_frame failed: %d\n", rc); 1295 } 1296 1297 return rc ? -1 : 0; 1298 } 1299 1300 /** 1301 * @brief Send FCP response using SEND_FRAME 1302 * 1303 * The FCP response is send using the SEND_FRAME function. 1304 * 1305 * @param node Pointer to node object. 1306 * @param seq Pointer to inbound sequence. 1307 * @param rsp Pointer to response data. 1308 * @param rsp_len Length of response data, in bytes. 1309 * 1310 * @return Returns 0 on success, or a negative error code value on failure. 1311 */ 1312 static int32_t 1313 ocs_sframe_send_fcp_rsp(ocs_node_t *node, ocs_hw_sequence_t *seq, void *rsp, uint32_t rsp_len) 1314 { 1315 return ocs_sframe_common_send(node, seq, 1316 FC_RCTL_FC4_DATA, 1317 FC_RCTL_INFO_CMD_STATUS, 1318 FC_FCTL_EXCHANGE_RESPONDER | 1319 FC_FCTL_LAST_SEQUENCE | 1320 FC_FCTL_END_SEQUENCE | 1321 FC_FCTL_SEQUENCE_INITIATIVE, 1322 FC_TYPE_FCP, 1323 rsp, rsp_len); 1324 } 1325 1326 /** 1327 * @brief Send task set full response 1328 * 1329 * Return a task set full or busy response using send frame. 1330 * 1331 * @param node Pointer to node object. 1332 * @param seq Pointer to originator frame sequence. 1333 * 1334 * @return Returns 0 on success, or a negative error code value on failure. 1335 */ 1336 static int32_t 1337 ocs_sframe_send_task_set_full_or_busy(ocs_node_t *node, ocs_hw_sequence_t *seq) 1338 { 1339 fcp_rsp_iu_t fcprsp; 1340 fcp_cmnd_iu_t *fcpcmd = seq->payload->dma.virt; 1341 uint32_t *fcp_dl_ptr; 1342 uint32_t fcp_dl; 1343 int32_t rc = 0; 1344 1345 /* extract FCP_DL from FCP command*/ 1346 fcp_dl_ptr = (uint32_t*)(&(fcpcmd->fcp_cdb_and_dl)); 1347 fcp_dl_ptr += fcpcmd->additional_fcp_cdb_length; 1348 fcp_dl = ocs_be32toh(*fcp_dl_ptr); 1349 1350 /* construct task set full or busy response */ 1351 ocs_memset(&fcprsp, 0, sizeof(fcprsp)); 1352 ocs_lock(&node->active_ios_lock); 1353 fcprsp.scsi_status = ocs_list_empty(&node->active_ios) ? SCSI_STATUS_BUSY : SCSI_STATUS_TASK_SET_FULL; 1354 ocs_unlock(&node->active_ios_lock); 1355 *((uint32_t*)&fcprsp.fcp_resid) = fcp_dl; 1356 1357 /* send it using send_frame */ 1358 rc = ocs_sframe_send_fcp_rsp(node, seq, &fcprsp, sizeof(fcprsp) - sizeof(fcprsp.data)); 1359 if (rc) { 1360 ocs_log_test(node->ocs, "ocs_sframe_send_fcp_rsp failed: %d\n", rc); 1361 } 1362 return rc; 1363 } 1364 1365 /** 1366 * @brief Send BA_ACC using sent frame 1367 * 1368 * A BA_ACC is sent using SEND_FRAME 1369 * 1370 * @param node Pointer to node object. 1371 * @param seq Pointer to originator frame sequence. 1372 * 1373 * @return Returns 0 on success, or a negative error code value on failure. 1374 */ 1375 int32_t 1376 ocs_sframe_send_bls_acc(ocs_node_t *node, ocs_hw_sequence_t *seq) 1377 { 1378 fc_header_t *behdr = seq->header->dma.virt; 1379 uint16_t ox_id = ocs_be16toh(behdr->ox_id); 1380 uint16_t rx_id = ocs_be16toh(behdr->rx_id); 1381 fc_ba_acc_payload_t acc = {0}; 1382 1383 acc.ox_id = ocs_htobe16(ox_id); 1384 acc.rx_id = ocs_htobe16(rx_id); 1385 acc.low_seq_cnt = UINT16_MAX; 1386 acc.high_seq_cnt = UINT16_MAX; 1387 1388 return ocs_sframe_common_send(node, seq, 1389 FC_RCTL_BLS, 1390 FC_RCTL_INFO_UNSOL_DATA, 1391 FC_FCTL_EXCHANGE_RESPONDER | 1392 FC_FCTL_LAST_SEQUENCE | 1393 FC_FCTL_END_SEQUENCE, 1394 FC_TYPE_BASIC_LINK, 1395 &acc, sizeof(acc)); 1396 } 1397