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 * OCS Linux SCSI API base driver implementation. 37 */ 38 39 /** 40 * @defgroup scsi_api_base SCSI Base Target/Initiator 41 */ 42 43 #include "ocs.h" 44 #include "ocs_els.h" 45 #include "ocs_scsi.h" 46 #include "ocs_vpd.h" 47 #include "ocs_utils.h" 48 #include "ocs_device.h" 49 50 #define SCSI_IOFMT "[%04x][i:%0*x t:%0*x h:%04x]" 51 #define SCSI_ITT_SIZE(ocs) ((ocs->ocs_xport == OCS_XPORT_FC) ? 4 : 8) 52 53 #define SCSI_IOFMT_ARGS(io) io->instance_index, SCSI_ITT_SIZE(io->ocs), io->init_task_tag, SCSI_ITT_SIZE(io->ocs), io->tgt_task_tag, io->hw_tag 54 55 #define enable_tsend_auto_resp(ocs) ((ocs->ctrlmask & OCS_CTRLMASK_XPORT_DISABLE_AUTORSP_TSEND) == 0) 56 #define enable_treceive_auto_resp(ocs) ((ocs->ctrlmask & OCS_CTRLMASK_XPORT_DISABLE_AUTORSP_TRECEIVE) == 0) 57 58 #define scsi_io_printf(io, fmt, ...) ocs_log_info(io->ocs, "[%s]" SCSI_IOFMT fmt, \ 59 io->node->display_name, SCSI_IOFMT_ARGS(io), ##__VA_ARGS__) 60 61 #define scsi_io_trace(io, fmt, ...) \ 62 do { \ 63 if (OCS_LOG_ENABLE_SCSI_TRACE(io->ocs)) \ 64 scsi_io_printf(io, fmt, ##__VA_ARGS__); \ 65 } while (0) 66 67 #define scsi_log(ocs, fmt, ...) \ 68 do { \ 69 if (OCS_LOG_ENABLE_SCSI_TRACE(ocs)) \ 70 ocs_log_info(ocs, fmt, ##__VA_ARGS__); \ 71 } while (0) 72 73 static int32_t ocs_target_send_bls_resp(ocs_io_t *io, ocs_scsi_io_cb_t cb, void *arg); 74 static int32_t ocs_scsi_abort_io_cb(struct ocs_hw_io_s *hio, ocs_remote_node_t *rnode, uint32_t len, int32_t status, 75 uint32_t ext, void *arg); 76 77 static void ocs_scsi_io_free_ovfl(ocs_io_t *io); 78 static uint32_t ocs_scsi_count_sgls(ocs_hw_dif_info_t *hw_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count); 79 static int ocs_scsi_dif_guard_is_crc(uint8_t direction, ocs_hw_dif_info_t *dif_info); 80 static ocs_scsi_io_status_e ocs_scsi_dif_check_unknown(ocs_io_t *io, uint32_t length, uint32_t check_length, int is_crc); 81 static uint32_t ocs_scsi_dif_check_guard(ocs_hw_dif_info_t *dif_info, ocs_scsi_vaddr_len_t addrlen[], 82 uint32_t addrlen_count, ocs_dif_t *dif, int is_crc); 83 static uint32_t ocs_scsi_dif_check_app_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint16_t exp_app_tag, ocs_dif_t *dif); 84 static uint32_t ocs_scsi_dif_check_ref_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint32_t exp_ref_tag, ocs_dif_t *dif); 85 static int32_t ocs_scsi_convert_dif_info(ocs_t *ocs, ocs_scsi_dif_info_t *scsi_dif_info, 86 ocs_hw_dif_info_t *hw_dif_info); 87 static int32_t ocs_scsi_io_dispatch_hw_io(ocs_io_t *io, ocs_hw_io_t *hio); 88 static int32_t ocs_scsi_io_dispatch_no_hw_io(ocs_io_t *io); 89 static void _ocs_scsi_io_free(void *arg); 90 91 /** 92 * @ingroup scsi_api_base 93 * @brief Returns a big-endian 32-bit value given a pointer. 94 * 95 * @param p Pointer to the 32-bit big-endian location. 96 * 97 * @return Returns the byte-swapped 32-bit value. 98 */ 99 100 static inline uint32_t 101 ocs_fc_getbe32(void *p) 102 { 103 return ocs_be32toh(*((uint32_t*)p)); 104 } 105 106 /** 107 * @ingroup scsi_api_base 108 * @brief Enable IO allocation. 109 * 110 * @par Description 111 * The SCSI and Transport IO allocation functions are enabled. If the allocation functions 112 * are not enabled, then calls to ocs_scsi_io_alloc() (and ocs_els_io_alloc() for FC) will 113 * fail. 114 * 115 * @param node Pointer to node object. 116 * 117 * @return None. 118 */ 119 void 120 ocs_scsi_io_alloc_enable(ocs_node_t *node) 121 { 122 ocs_assert(node != NULL); 123 ocs_lock(&node->active_ios_lock); 124 node->io_alloc_enabled = TRUE; 125 ocs_unlock(&node->active_ios_lock); 126 } 127 128 /** 129 * @ingroup scsi_api_base 130 * @brief Disable IO allocation 131 * 132 * @par Description 133 * The SCSI and Transport IO allocation functions are disabled. If the allocation functions 134 * are not enabled, then calls to ocs_scsi_io_alloc() (and ocs_els_io_alloc() for FC) will 135 * fail. 136 * 137 * @param node Pointer to node object 138 * 139 * @return None. 140 */ 141 void 142 ocs_scsi_io_alloc_disable(ocs_node_t *node) 143 { 144 ocs_assert(node != NULL); 145 ocs_lock(&node->active_ios_lock); 146 node->io_alloc_enabled = FALSE; 147 ocs_unlock(&node->active_ios_lock); 148 } 149 150 /** 151 * @ingroup scsi_api_base 152 * @brief Allocate a SCSI IO context. 153 * 154 * @par Description 155 * A SCSI IO context is allocated and associated with a @c node. This function 156 * is called by an initiator-client when issuing SCSI commands to remote 157 * target devices. On completion, ocs_scsi_io_free() is called. 158 * @n @n 159 * The returned ocs_io_t structure has an element of type ocs_scsi_ini_io_t named 160 * "ini_io" that is declared and used by an initiator-client for private information. 161 * 162 * @param node Pointer to the associated node structure. 163 * @param role Role for IO (originator/responder). 164 * 165 * @return Returns the pointer to the IO context, or NULL. 166 * 167 */ 168 169 ocs_io_t * 170 ocs_scsi_io_alloc(ocs_node_t *node, ocs_scsi_io_role_e role) 171 { 172 ocs_t *ocs; 173 ocs_xport_t *xport; 174 ocs_io_t *io; 175 176 ocs_assert(node, NULL); 177 ocs_assert(node->ocs, NULL); 178 179 ocs = node->ocs; 180 ocs_assert(ocs->xport, NULL); 181 xport = ocs->xport; 182 183 ocs_lock(&node->active_ios_lock); 184 185 if (!node->io_alloc_enabled) { 186 ocs_unlock(&node->active_ios_lock); 187 return NULL; 188 } 189 190 io = ocs_io_alloc(ocs); 191 if (io == NULL) { 192 ocs_atomic_add_return(&xport->io_alloc_failed_count, 1); 193 ocs_unlock(&node->active_ios_lock); 194 return NULL; 195 } 196 197 /* initialize refcount */ 198 ocs_ref_init(&io->ref, _ocs_scsi_io_free, io); 199 200 if (io->hio != NULL) { 201 ocs_log_err(node->ocs, "assertion failed: io->hio is not NULL\n"); 202 ocs_io_free(ocs, io); 203 ocs_unlock(&node->active_ios_lock); 204 return NULL; 205 } 206 207 /* set generic fields */ 208 io->ocs = ocs; 209 io->node = node; 210 211 /* set type and name */ 212 io->io_type = OCS_IO_TYPE_IO; 213 io->display_name = "scsi_io"; 214 215 switch (role) { 216 case OCS_SCSI_IO_ROLE_ORIGINATOR: 217 io->cmd_ini = TRUE; 218 io->cmd_tgt = FALSE; 219 break; 220 case OCS_SCSI_IO_ROLE_RESPONDER: 221 io->cmd_ini = FALSE; 222 io->cmd_tgt = TRUE; 223 break; 224 } 225 226 /* Add to node's active_ios list */ 227 ocs_list_add_tail(&node->active_ios, io); 228 229 ocs_unlock(&node->active_ios_lock); 230 231 return io; 232 } 233 234 /** 235 * @ingroup scsi_api_base 236 * @brief Free a SCSI IO context (internal). 237 * 238 * @par Description 239 * The IO context previously allocated using ocs_scsi_io_alloc() 240 * is freed. This is called from within the transport layer, 241 * when the reference count goes to zero. 242 * 243 * @param arg Pointer to the IO context. 244 * 245 * @return None. 246 */ 247 static void 248 _ocs_scsi_io_free(void *arg) 249 { 250 ocs_io_t *io = (ocs_io_t *)arg; 251 ocs_t *ocs = io->ocs; 252 ocs_node_t *node = io->node; 253 int send_empty_event; 254 255 ocs_assert(io != NULL); 256 257 scsi_io_trace(io, "freeing io 0x%p %s\n", io, io->display_name); 258 259 ocs_assert(ocs_io_busy(io)); 260 261 ocs_lock(&node->active_ios_lock); 262 ocs_list_remove(&node->active_ios, io); 263 send_empty_event = (!node->io_alloc_enabled) && ocs_list_empty(&node->active_ios); 264 ocs_unlock(&node->active_ios_lock); 265 266 if (send_empty_event) { 267 ocs_node_post_event(node, OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY, NULL); 268 } 269 270 io->node = NULL; 271 ocs_io_free(ocs, io); 272 273 } 274 275 /** 276 * @ingroup scsi_api_base 277 * @brief Free a SCSI IO context. 278 * 279 * @par Description 280 * The IO context previously allocated using ocs_scsi_io_alloc() is freed. 281 * 282 * @param io Pointer to the IO context. 283 * 284 * @return None. 285 */ 286 void 287 ocs_scsi_io_free(ocs_io_t *io) 288 { 289 scsi_io_trace(io, "freeing io 0x%p %s\n", io, io->display_name); 290 ocs_assert(ocs_ref_read_count(&io->ref) > 0); 291 ocs_ref_put(&io->ref); /* ocs_ref_get(): ocs_scsi_io_alloc() */ 292 } 293 294 static int32_t 295 ocs_scsi_send_io(ocs_hw_io_type_e type, ocs_node_t *node, ocs_io_t *io, uint64_t lun, 296 ocs_scsi_tmf_cmd_e tmf, uint8_t *cdb, uint32_t cdb_len, 297 ocs_scsi_dif_info_t *dif_info, 298 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst, 299 ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags); 300 301 /** 302 * @brief Target response completion callback. 303 * 304 * @par Description 305 * Function is called upon the completion of a target IO request. 306 * 307 * @param hio Pointer to the HW IO structure. 308 * @param rnode Remote node associated with the IO that is completing. 309 * @param length Length of the response payload. 310 * @param status Completion status. 311 * @param ext_status Extended completion status. 312 * @param app Application-specific data (generally a pointer to the IO context). 313 * 314 * @return None. 315 */ 316 317 static void 318 ocs_target_io_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, 319 int32_t status, uint32_t ext_status, void *app) 320 { 321 ocs_io_t *io = app; 322 ocs_t *ocs; 323 ocs_scsi_io_status_e scsi_status = OCS_SCSI_STATUS_GOOD; 324 uint16_t additional_length; 325 uint8_t edir; 326 uint8_t tdpv; 327 ocs_hw_dif_info_t *dif_info = &io->hw_dif; 328 int is_crc; 329 330 ocs_assert(io); 331 332 scsi_io_trace(io, "status x%x ext_status x%x\n", status, ext_status); 333 334 ocs = io->ocs; 335 ocs_assert(ocs); 336 337 ocs_scsi_io_free_ovfl(io); 338 339 io->transferred += length; 340 341 /* Call target server completion */ 342 if (io->scsi_tgt_cb) { 343 ocs_scsi_io_cb_t cb = io->scsi_tgt_cb; 344 uint32_t flags = 0; 345 346 /* Clear the callback before invoking the callback */ 347 io->scsi_tgt_cb = NULL; 348 349 /* if status was good, and auto-good-response was set, then callback 350 * target-server with IO_CMPL_RSP_SENT, otherwise send IO_CMPL 351 */ 352 if ((status == 0) && (io->auto_resp)) 353 flags |= OCS_SCSI_IO_CMPL_RSP_SENT; 354 else 355 flags |= OCS_SCSI_IO_CMPL; 356 357 switch (status) { 358 case SLI4_FC_WCQE_STATUS_SUCCESS: 359 scsi_status = OCS_SCSI_STATUS_GOOD; 360 break; 361 case SLI4_FC_WCQE_STATUS_DI_ERROR: 362 if (ext_status & SLI4_FC_DI_ERROR_GE) { 363 scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR; 364 } else if (ext_status & SLI4_FC_DI_ERROR_AE) { 365 scsi_status = OCS_SCSI_STATUS_DIF_APP_TAG_ERROR; 366 } else if (ext_status & SLI4_FC_DI_ERROR_RE) { 367 scsi_status = OCS_SCSI_STATUS_DIF_REF_TAG_ERROR; 368 } else { 369 additional_length = ((ext_status >> 16) & 0xFFFF); 370 371 /* Capture the EDIR and TDPV bits as 0 or 1 for easier printing. */ 372 edir = !!(ext_status & SLI4_FC_DI_ERROR_EDIR); 373 tdpv = !!(ext_status & SLI4_FC_DI_ERROR_TDPV); 374 375 is_crc = ocs_scsi_dif_guard_is_crc(edir, dif_info); 376 377 if (edir == 0) { 378 /* For reads, we have everything in memory. Start checking from beginning. */ 379 scsi_status = ocs_scsi_dif_check_unknown(io, 0, io->wire_len, is_crc); 380 } else { 381 /* For writes, use the additional length to determine where to look for the error. 382 * The additional_length field is set to 0 if it is not supported. 383 * The additional length field is valid if: 384 * . additional_length is not zero 385 * . Total Data Placed is valid 386 * . Error Direction is RX (1) 387 * . Operation is a pass thru (CRC or CKSUM on IN, and CRC or CHKSUM on OUT) (all pass-thru cases except raw) 388 */ 389 if ((additional_length != 0) && (tdpv != 0) && 390 (dif_info->dif == SLI4_DIF_PASS_THROUGH) && (dif_info->dif_oper != OCS_HW_SGE_DIF_OP_IN_RAW_OUT_RAW) ) { 391 scsi_status = ocs_scsi_dif_check_unknown(io, length, additional_length, is_crc); 392 } else { 393 /* If we can't do additional checking, then fall-back to guard error */ 394 scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR; 395 } 396 } 397 } 398 break; 399 case SLI4_FC_WCQE_STATUS_LOCAL_REJECT: 400 switch (ext_status) { 401 case SLI4_FC_LOCAL_REJECT_INVALID_RELOFFSET: 402 case SLI4_FC_LOCAL_REJECT_ABORT_REQUESTED: 403 scsi_status = OCS_SCSI_STATUS_ABORTED; 404 break; 405 case SLI4_FC_LOCAL_REJECT_INVALID_RPI: 406 scsi_status = OCS_SCSI_STATUS_NEXUS_LOST; 407 break; 408 case SLI4_FC_LOCAL_REJECT_NO_XRI: 409 scsi_status = OCS_SCSI_STATUS_NO_IO; 410 break; 411 default: 412 /* TODO: we have seen 0x0d (TX_DMA_FAILED error) */ 413 scsi_status = OCS_SCSI_STATUS_ERROR; 414 break; 415 } 416 break; 417 418 case SLI4_FC_WCQE_STATUS_TARGET_WQE_TIMEOUT: 419 /* target IO timed out */ 420 scsi_status = OCS_SCSI_STATUS_TIMEDOUT_AND_ABORTED; 421 break; 422 423 case SLI4_FC_WCQE_STATUS_SHUTDOWN: 424 /* Target IO cancelled by HW */ 425 scsi_status = OCS_SCSI_STATUS_SHUTDOWN; 426 break; 427 428 default: 429 scsi_status = OCS_SCSI_STATUS_ERROR; 430 break; 431 } 432 433 cb(io, scsi_status, flags, io->scsi_tgt_cb_arg); 434 } 435 ocs_scsi_check_pending(ocs); 436 } 437 438 /** 439 * @brief Determine if an IO is using CRC for DIF guard format. 440 * 441 * @param direction IO direction: 1 for write, 0 for read. 442 * @param dif_info Pointer to HW DIF info data. 443 * 444 * @return Returns TRUE if using CRC, FALSE if not. 445 */ 446 static int 447 ocs_scsi_dif_guard_is_crc(uint8_t direction, ocs_hw_dif_info_t *dif_info) 448 { 449 int is_crc; 450 451 if (direction) { 452 /* For writes, check if operation is "OUT_CRC" or not */ 453 switch(dif_info->dif_oper) { 454 case OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC: 455 case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC: 456 case OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CRC: 457 is_crc = TRUE; 458 break; 459 default: 460 is_crc = FALSE; 461 break; 462 } 463 } else { 464 /* For reads, check if operation is "IN_CRC" or not */ 465 switch(dif_info->dif_oper) { 466 case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF: 467 case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC: 468 case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CHKSUM: 469 is_crc = TRUE; 470 break; 471 default: 472 is_crc = FALSE; 473 break; 474 } 475 } 476 477 return is_crc; 478 } 479 480 /** 481 * @brief Check a block and DIF data, computing the appropriate SCSI status 482 * 483 * @par Description 484 * This function is used to check blocks and DIF when given an unknown DIF 485 * status using the following logic: 486 * 487 * Given the address of the last good block, and a length of bytes that includes 488 * the block with the DIF error, find the bad block. If a block is found with an 489 * app_tag or ref_tag error, then return the appropriate error. No block is expected 490 * to have a block guard error since hardware "fixes" the crc. So if no block in the 491 * range of blocks has an error, then it is presumed to be a BLOCK GUARD error. 492 * 493 * @param io Pointer to the IO object. 494 * @param length Length of bytes covering the good blocks. 495 * @param check_length Length of bytes that covers the bad block. 496 * @param is_crc True if guard is using CRC format. 497 * 498 * @return Returns SCSI status. 499 */ 500 501 static ocs_scsi_io_status_e 502 ocs_scsi_dif_check_unknown(ocs_io_t *io, uint32_t length, uint32_t check_length, int is_crc) 503 { 504 uint32_t i; 505 ocs_t *ocs = io->ocs; 506 ocs_hw_dif_info_t *dif_info = &io->hw_dif; 507 ocs_scsi_io_status_e scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR; 508 uint32_t blocksize; /* data block size */ 509 uint64_t first_check_block; /* first block following total data placed */ 510 uint64_t last_check_block; /* last block to check */ 511 uint32_t check_count; /* count of blocks to check */ 512 ocs_scsi_vaddr_len_t addrlen[4]; /* address-length pairs returned from target */ 513 int32_t addrlen_count; /* count of address-length pairs */ 514 ocs_dif_t *dif; /* pointer to DIF block returned from target */ 515 ocs_scsi_dif_info_t scsi_dif_info = io->scsi_dif_info; 516 517 blocksize = ocs_hw_dif_mem_blocksize(&io->hw_dif, TRUE); 518 first_check_block = length / blocksize; 519 last_check_block = ((length + check_length) / blocksize); 520 check_count = last_check_block - first_check_block; 521 522 ocs_log_debug(ocs, "blocksize %d first check_block %" PRId64 " last_check_block %" PRId64 " check_count %d\n", 523 blocksize, first_check_block, last_check_block, check_count); 524 525 for (i = first_check_block; i < last_check_block; i++) { 526 addrlen_count = ocs_scsi_get_block_vaddr(io, (scsi_dif_info.lba + i), addrlen, ARRAY_SIZE(addrlen), (void**) &dif); 527 if (addrlen_count < 0) { 528 ocs_log_test(ocs, "ocs_scsi_get_block_vaddr() failed: %d\n", addrlen_count); 529 scsi_status = OCS_SCSI_STATUS_DIF_UNKNOWN_ERROR; 530 break; 531 } 532 533 if (! ocs_scsi_dif_check_guard(dif_info, addrlen, addrlen_count, dif, is_crc)) { 534 ocs_log_debug(ocs, "block guard check error, lba %" PRId64 "\n", scsi_dif_info.lba + i); 535 scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR; 536 break; 537 } 538 if (! ocs_scsi_dif_check_app_tag(ocs, dif_info, scsi_dif_info.app_tag, dif)) { 539 ocs_log_debug(ocs, "app tag check error, lba %" PRId64 "\n", scsi_dif_info.lba + i); 540 scsi_status = OCS_SCSI_STATUS_DIF_APP_TAG_ERROR; 541 break; 542 } 543 if (! ocs_scsi_dif_check_ref_tag(ocs, dif_info, (scsi_dif_info.ref_tag + i), dif)) { 544 ocs_log_debug(ocs, "ref tag check error, lba %" PRId64 "\n", scsi_dif_info.lba + i); 545 scsi_status = OCS_SCSI_STATUS_DIF_REF_TAG_ERROR; 546 break; 547 } 548 } 549 return scsi_status; 550 } 551 552 /** 553 * @brief Check the block guard of block data 554 * 555 * @par Description 556 * Using the dif_info for the transfer, check the block guard value. 557 * 558 * @param dif_info Pointer to HW DIF info data. 559 * @param addrlen Array of address length pairs. 560 * @param addrlen_count Number of entries in the addrlen[] array. 561 * @param dif Pointer to the DIF data block being checked. 562 * @param is_crc True if guard is using CRC format. 563 * 564 * @return Returns TRUE if block guard check is ok. 565 */ 566 static uint32_t 567 ocs_scsi_dif_check_guard(ocs_hw_dif_info_t *dif_info, ocs_scsi_vaddr_len_t addrlen[], uint32_t addrlen_count, 568 ocs_dif_t *dif, int is_crc) 569 { 570 uint16_t crc = dif_info->dif_seed; 571 uint32_t i; 572 uint16_t checksum; 573 574 if ((dif == NULL) || !dif_info->check_guard) { 575 return TRUE; 576 } 577 578 if (is_crc) { 579 for (i = 0; i < addrlen_count; i++) { 580 crc = ocs_scsi_dif_calc_crc(addrlen[i].vaddr, addrlen[i].length, crc); 581 } 582 return (crc == ocs_be16toh(dif->crc)); 583 } else { 584 checksum = ocs_scsi_dif_calc_checksum(addrlen, addrlen_count); 585 586 return (checksum == dif->crc); 587 } 588 } 589 590 /** 591 * @brief Check the app tag of dif data 592 * 593 * @par Description 594 * Using the dif_info for the transfer, check the app tag. 595 * 596 * @param ocs Pointer to the ocs structure for logging. 597 * @param dif_info Pointer to HW DIF info data. 598 * @param exp_app_tag The value the app tag is expected to be. 599 * @param dif Pointer to the DIF data block being checked. 600 * 601 * @return Returns TRUE if app tag check is ok. 602 */ 603 static uint32_t 604 ocs_scsi_dif_check_app_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint16_t exp_app_tag, ocs_dif_t *dif) 605 { 606 if ((dif == NULL) || !dif_info->check_app_tag) { 607 return TRUE; 608 } 609 610 ocs_log_debug(ocs, "expected app tag 0x%x, actual 0x%x\n", 611 exp_app_tag, ocs_be16toh(dif->app_tag)); 612 613 return (exp_app_tag == ocs_be16toh(dif->app_tag)); 614 } 615 616 /** 617 * @brief Check the ref tag of dif data 618 * 619 * @par Description 620 * Using the dif_info for the transfer, check the app tag. 621 * 622 * @param ocs Pointer to the ocs structure for logging. 623 * @param dif_info Pointer to HW DIF info data. 624 * @param exp_ref_tag The value the ref tag is expected to be. 625 * @param dif Pointer to the DIF data block being checked. 626 * 627 * @return Returns TRUE if ref tag check is ok. 628 */ 629 static uint32_t 630 ocs_scsi_dif_check_ref_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint32_t exp_ref_tag, ocs_dif_t *dif) 631 { 632 if ((dif == NULL) || !dif_info->check_ref_tag) { 633 return TRUE; 634 } 635 636 if (exp_ref_tag != ocs_be32toh(dif->ref_tag)) { 637 ocs_log_debug(ocs, "expected ref tag 0x%x, actual 0x%x\n", 638 exp_ref_tag, ocs_be32toh(dif->ref_tag)); 639 return FALSE; 640 } else { 641 return TRUE; 642 } 643 } 644 645 /** 646 * @brief Return count of SGE's required for request 647 * 648 * @par Description 649 * An accurate count of SGEs is computed and returned. 650 * 651 * @param hw_dif Pointer to HW dif information. 652 * @param sgl Pointer to SGL from back end. 653 * @param sgl_count Count of SGEs in SGL. 654 * 655 * @return Count of SGEs. 656 */ 657 static uint32_t 658 ocs_scsi_count_sgls(ocs_hw_dif_info_t *hw_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count) 659 { 660 uint32_t count = 0; 661 uint32_t i; 662 663 /* Convert DIF Information */ 664 if (hw_dif->dif_oper != OCS_HW_DIF_OPER_DISABLED) { 665 /* If we're not DIF separate, then emit a seed SGE */ 666 if (!hw_dif->dif_separate) { 667 count++; 668 } 669 670 for (i = 0; i < sgl_count; i++) { 671 /* If DIF is enabled, and DIF is separate, then append a SEED then DIF SGE */ 672 if (hw_dif->dif_separate) { 673 count += 2; 674 } 675 676 count++; 677 } 678 } else { 679 count = sgl_count; 680 } 681 return count; 682 } 683 684 static int32_t 685 ocs_scsi_build_sgls(ocs_hw_t *hw, ocs_hw_io_t *hio, ocs_hw_dif_info_t *hw_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, ocs_hw_io_type_e type) 686 { 687 int32_t rc; 688 uint32_t i; 689 ocs_t *ocs = hw->os; 690 uint32_t blocksize = 0; 691 uint32_t blockcount; 692 693 ocs_assert(hio, -1); 694 695 /* Initialize HW SGL */ 696 rc = ocs_hw_io_init_sges(hw, hio, type); 697 if (rc) { 698 ocs_log_err(ocs, "ocs_hw_io_init_sges failed: %d\n", rc); 699 return -1; 700 } 701 702 /* Convert DIF Information */ 703 if (hw_dif->dif_oper != OCS_HW_DIF_OPER_DISABLED) { 704 /* If we're not DIF separate, then emit a seed SGE */ 705 if (!hw_dif->dif_separate) { 706 rc = ocs_hw_io_add_seed_sge(hw, hio, hw_dif); 707 if (rc) { 708 return rc; 709 } 710 } 711 712 /* if we are doing DIF separate, then figure out the block size so that we 713 * can update the ref tag in the DIF seed SGE. Also verify that the 714 * the sgl lengths are all multiples of the blocksize 715 */ 716 if (hw_dif->dif_separate) { 717 switch(hw_dif->blk_size) { 718 case OCS_HW_DIF_BK_SIZE_512: blocksize = 512; break; 719 case OCS_HW_DIF_BK_SIZE_1024: blocksize = 1024; break; 720 case OCS_HW_DIF_BK_SIZE_2048: blocksize = 2048; break; 721 case OCS_HW_DIF_BK_SIZE_4096: blocksize = 4096; break; 722 case OCS_HW_DIF_BK_SIZE_520: blocksize = 520; break; 723 case OCS_HW_DIF_BK_SIZE_4104: blocksize = 4104; break; 724 default: 725 ocs_log_test(hw->os, "Inavlid hw_dif blocksize %d\n", hw_dif->blk_size); 726 return -1; 727 } 728 for (i = 0; i < sgl_count; i++) { 729 if ((sgl[i].len % blocksize) != 0) { 730 ocs_log_test(hw->os, "sgl[%d] len of %ld is not multiple of blocksize\n", 731 i, sgl[i].len); 732 return -1; 733 } 734 } 735 } 736 737 for (i = 0; i < sgl_count; i++) { 738 ocs_assert(sgl[i].addr, -1); 739 ocs_assert(sgl[i].len, -1); 740 741 /* If DIF is enabled, and DIF is separate, then append a SEED then DIF SGE */ 742 if (hw_dif->dif_separate) { 743 rc = ocs_hw_io_add_seed_sge(hw, hio, hw_dif); 744 if (rc) { 745 return rc; 746 } 747 rc = ocs_hw_io_add_dif_sge(hw, hio, sgl[i].dif_addr); 748 if (rc) { 749 return rc; 750 } 751 /* Update the ref_tag for the next DIF seed SGE */ 752 blockcount = sgl[i].len / blocksize; 753 if (hw_dif->dif_oper == OCS_HW_DIF_OPER_INSERT) { 754 hw_dif->ref_tag_repl += blockcount; 755 } else { 756 hw_dif->ref_tag_cmp += blockcount; 757 } 758 } 759 760 /* Add data SGE */ 761 rc = ocs_hw_io_add_sge(hw, hio, sgl[i].addr, sgl[i].len); 762 if (rc) { 763 ocs_log_err(ocs, "ocs_hw_io_add_sge failed: count=%d rc=%d\n", 764 sgl_count, rc); 765 return rc; 766 } 767 } 768 } else { 769 for (i = 0; i < sgl_count; i++) { 770 ocs_assert(sgl[i].addr, -1); 771 ocs_assert(sgl[i].len, -1); 772 773 /* Add data SGE */ 774 rc = ocs_hw_io_add_sge(hw, hio, sgl[i].addr, sgl[i].len); 775 if (rc) { 776 ocs_log_err(ocs, "ocs_hw_io_add_sge failed: count=%d rc=%d\n", 777 sgl_count, rc); 778 return rc; 779 } 780 } 781 } 782 return 0; 783 } 784 785 /** 786 * @ingroup scsi_api_base 787 * @brief Convert SCSI API T10 DIF information into the FC HW format. 788 * 789 * @param ocs Pointer to the ocs structure for logging. 790 * @param scsi_dif_info Pointer to the SCSI API T10 DIF fields. 791 * @param hw_dif_info Pointer to the FC HW API T10 DIF fields. 792 * 793 * @return Returns 0 on success, or a negative error code value on failure. 794 */ 795 796 static int32_t 797 ocs_scsi_convert_dif_info(ocs_t *ocs, ocs_scsi_dif_info_t *scsi_dif_info, ocs_hw_dif_info_t *hw_dif_info) 798 { 799 uint32_t dif_seed; 800 ocs_memset(hw_dif_info, 0, sizeof(ocs_hw_dif_info_t)); 801 802 if (scsi_dif_info == NULL) { 803 hw_dif_info->dif_oper = OCS_HW_DIF_OPER_DISABLED; 804 hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_NA; 805 return 0; 806 } 807 808 /* Convert the DIF operation */ 809 switch(scsi_dif_info->dif_oper) { 810 case OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CRC: 811 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC; 812 hw_dif_info->dif = SLI4_DIF_INSERT; 813 break; 814 case OCS_SCSI_DIF_OPER_IN_CRC_OUT_NODIF: 815 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF; 816 hw_dif_info->dif = SLI4_DIF_STRIP; 817 break; 818 case OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CHKSUM: 819 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CHKSUM; 820 hw_dif_info->dif = SLI4_DIF_INSERT; 821 break; 822 case OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_NODIF: 823 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_NODIF; 824 hw_dif_info->dif = SLI4_DIF_STRIP; 825 break; 826 case OCS_SCSI_DIF_OPER_IN_CRC_OUT_CRC: 827 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC; 828 hw_dif_info->dif = SLI4_DIF_PASS_THROUGH; 829 break; 830 case OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CHKSUM: 831 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CHKSUM; 832 hw_dif_info->dif = SLI4_DIF_PASS_THROUGH; 833 break; 834 case OCS_SCSI_DIF_OPER_IN_CRC_OUT_CHKSUM: 835 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CHKSUM; 836 hw_dif_info->dif = SLI4_DIF_PASS_THROUGH; 837 break; 838 case OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CRC: 839 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CRC; 840 hw_dif_info->dif = SLI4_DIF_PASS_THROUGH; 841 break; 842 case OCS_SCSI_DIF_OPER_IN_RAW_OUT_RAW: 843 hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_RAW_OUT_RAW; 844 hw_dif_info->dif = SLI4_DIF_PASS_THROUGH; 845 break; 846 default: 847 ocs_log_test(ocs, "unhandled SCSI DIF operation %d\n", 848 scsi_dif_info->dif_oper); 849 return -1; 850 } 851 852 switch(scsi_dif_info->blk_size) { 853 case OCS_SCSI_DIF_BK_SIZE_512: 854 hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_512; 855 break; 856 case OCS_SCSI_DIF_BK_SIZE_1024: 857 hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_1024; 858 break; 859 case OCS_SCSI_DIF_BK_SIZE_2048: 860 hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_2048; 861 break; 862 case OCS_SCSI_DIF_BK_SIZE_4096: 863 hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_4096; 864 break; 865 case OCS_SCSI_DIF_BK_SIZE_520: 866 hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_520; 867 break; 868 case OCS_SCSI_DIF_BK_SIZE_4104: 869 hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_4104; 870 break; 871 default: 872 ocs_log_test(ocs, "unhandled SCSI DIF block size %d\n", 873 scsi_dif_info->blk_size); 874 return -1; 875 } 876 877 /* If the operation is an INSERT the tags provided are the ones that should be 878 * inserted, otherwise they're the ones to be checked against. */ 879 if (hw_dif_info->dif == SLI4_DIF_INSERT ) { 880 hw_dif_info->ref_tag_repl = scsi_dif_info->ref_tag; 881 hw_dif_info->app_tag_repl = scsi_dif_info->app_tag; 882 } else { 883 hw_dif_info->ref_tag_cmp = scsi_dif_info->ref_tag; 884 hw_dif_info->app_tag_cmp = scsi_dif_info->app_tag; 885 } 886 887 hw_dif_info->check_ref_tag = scsi_dif_info->check_ref_tag; 888 hw_dif_info->check_app_tag = scsi_dif_info->check_app_tag; 889 hw_dif_info->check_guard = scsi_dif_info->check_guard; 890 hw_dif_info->auto_incr_ref_tag = 1; 891 hw_dif_info->dif_separate = scsi_dif_info->dif_separate; 892 hw_dif_info->disable_app_ffff = scsi_dif_info->disable_app_ffff; 893 hw_dif_info->disable_app_ref_ffff = scsi_dif_info->disable_app_ref_ffff; 894 895 ocs_hw_get(&ocs->hw, OCS_HW_DIF_SEED, &dif_seed); 896 hw_dif_info->dif_seed = dif_seed; 897 898 return 0; 899 } 900 901 /** 902 * @ingroup scsi_api_base 903 * @brief This function logs the SGLs for an IO. 904 * 905 * @param io Pointer to the IO context. 906 */ 907 static void ocs_log_sgl(ocs_io_t *io) 908 { 909 ocs_hw_io_t *hio = io->hio; 910 sli4_sge_t *data = NULL; 911 uint32_t *dword = NULL; 912 uint32_t i; 913 uint32_t n_sge; 914 915 scsi_io_trace(io, "def_sgl at 0x%x 0x%08x\n", 916 ocs_addr32_hi(hio->def_sgl.phys), 917 ocs_addr32_lo(hio->def_sgl.phys)); 918 n_sge = (hio->sgl == &hio->def_sgl ? hio->n_sge : hio->def_sgl_count); 919 for (i = 0, data = hio->def_sgl.virt; i < n_sge; i++, data++) { 920 dword = (uint32_t*)data; 921 922 scsi_io_trace(io, "SGL %2d 0x%08x 0x%08x 0x%08x 0x%08x\n", 923 i, dword[0], dword[1], dword[2], dword[3]); 924 925 if (dword[2] & (1U << 31)) { 926 break; 927 } 928 } 929 930 if (hio->ovfl_sgl != NULL && 931 hio->sgl == hio->ovfl_sgl) { 932 scsi_io_trace(io, "Overflow at 0x%x 0x%08x\n", 933 ocs_addr32_hi(hio->ovfl_sgl->phys), 934 ocs_addr32_lo(hio->ovfl_sgl->phys)); 935 for (i = 0, data = hio->ovfl_sgl->virt; i < hio->n_sge; i++, data++) { 936 dword = (uint32_t*)data; 937 938 scsi_io_trace(io, "SGL %2d 0x%08x 0x%08x 0x%08x 0x%08x\n", 939 i, dword[0], dword[1], dword[2], dword[3]); 940 if (dword[2] & (1U << 31)) { 941 break; 942 } 943 } 944 } 945 946 } 947 948 /** 949 * @brief Check pending error asynchronous callback function. 950 * 951 * @par Description 952 * Invoke the HW callback function for a given IO. This function is called 953 * from the NOP mailbox completion context. 954 * 955 * @param hw Pointer to HW object. 956 * @param status Completion status. 957 * @param mqe Mailbox completion queue entry. 958 * @param arg General purpose argument. 959 * 960 * @return Returns 0. 961 */ 962 static int32_t 963 ocs_scsi_check_pending_async_cb(ocs_hw_t *hw, int32_t status, uint8_t *mqe, void *arg) 964 { 965 ocs_io_t *io = arg; 966 967 if (io != NULL) { 968 if (io->hw_cb != NULL) { 969 ocs_hw_done_t cb = io->hw_cb; 970 971 io->hw_cb = NULL; 972 cb(io->hio, NULL, 0, SLI4_FC_WCQE_STATUS_DISPATCH_ERROR, 0, io); 973 } 974 } 975 return 0; 976 } 977 978 /** 979 * @brief Check for pending IOs to dispatch. 980 * 981 * @par Description 982 * If there are IOs on the pending list, and a HW IO is available, then 983 * dispatch the IOs. 984 * 985 * @param ocs Pointer to the OCS structure. 986 * 987 * @return None. 988 */ 989 990 void 991 ocs_scsi_check_pending(ocs_t *ocs) 992 { 993 ocs_xport_t *xport = ocs->xport; 994 ocs_io_t *io; 995 ocs_hw_io_t *hio; 996 int32_t status; 997 int count = 0; 998 int dispatch; 999 1000 /* Guard against recursion */ 1001 if (ocs_atomic_add_return(&xport->io_pending_recursing, 1)) { 1002 /* This function is already running. Decrement and return. */ 1003 ocs_atomic_sub_return(&xport->io_pending_recursing, 1); 1004 return; 1005 } 1006 1007 do { 1008 ocs_lock(&xport->io_pending_lock); 1009 status = 0; 1010 hio = NULL; 1011 io = ocs_list_remove_head(&xport->io_pending_list); 1012 if (io != NULL) { 1013 if (io->io_type == OCS_IO_TYPE_ABORT) { 1014 hio = NULL; 1015 } else { 1016 hio = ocs_hw_io_alloc(&ocs->hw); 1017 if (hio == NULL) { 1018 /* 1019 * No HW IO available. 1020 * Put IO back on the front of pending list 1021 */ 1022 ocs_list_add_head(&xport->io_pending_list, io); 1023 io = NULL; 1024 } else { 1025 hio->eq = io->hw_priv; 1026 } 1027 } 1028 } 1029 /* Must drop the lock before dispatching the IO */ 1030 ocs_unlock(&xport->io_pending_lock); 1031 1032 if (io != NULL) { 1033 count++; 1034 1035 /* 1036 * We pulled an IO off the pending list, 1037 * and either got an HW IO or don't need one 1038 */ 1039 ocs_atomic_sub_return(&xport->io_pending_count, 1); 1040 if (hio == NULL) { 1041 status = ocs_scsi_io_dispatch_no_hw_io(io); 1042 } else { 1043 status = ocs_scsi_io_dispatch_hw_io(io, hio); 1044 } 1045 if (status) { 1046 /* 1047 * Invoke the HW callback, but do so in the separate execution context, 1048 * provided by the NOP mailbox completion processing context by using 1049 * ocs_hw_async_call() 1050 */ 1051 if (ocs_hw_async_call(&ocs->hw, ocs_scsi_check_pending_async_cb, io)) { 1052 ocs_log_test(ocs, "call to ocs_hw_async_call() failed\n"); 1053 } 1054 } 1055 } 1056 } while (io != NULL); 1057 1058 /* 1059 * If nothing was removed from the list, 1060 * we might be in a case where we need to abort an 1061 * active IO and the abort is on the pending list. 1062 * Look for an abort we can dispatch. 1063 */ 1064 if (count == 0 ) { 1065 dispatch = 0; 1066 1067 ocs_lock(&xport->io_pending_lock); 1068 ocs_list_foreach(&xport->io_pending_list, io) { 1069 if (io->io_type == OCS_IO_TYPE_ABORT) { 1070 if (io->io_to_abort->hio != NULL) { 1071 /* This IO has a HW IO, so it is active. Dispatch the abort. */ 1072 dispatch = 1; 1073 } else { 1074 /* Leave this abort on the pending list and keep looking */ 1075 dispatch = 0; 1076 } 1077 } 1078 if (dispatch) { 1079 ocs_list_remove(&xport->io_pending_list, io); 1080 ocs_atomic_sub_return(&xport->io_pending_count, 1); 1081 break; 1082 } 1083 } 1084 ocs_unlock(&xport->io_pending_lock); 1085 1086 if (dispatch) { 1087 status = ocs_scsi_io_dispatch_no_hw_io(io); 1088 if (status) { 1089 if (ocs_hw_async_call(&ocs->hw, ocs_scsi_check_pending_async_cb, io)) { 1090 ocs_log_test(ocs, "call to ocs_hw_async_call() failed\n"); 1091 } 1092 } 1093 } 1094 } 1095 1096 ocs_atomic_sub_return(&xport->io_pending_recursing, 1); 1097 return; 1098 } 1099 1100 /** 1101 * @brief Attempt to dispatch a non-abort IO 1102 * 1103 * @par Description 1104 * An IO is dispatched: 1105 * - if the pending list is not empty, add IO to pending list 1106 * and call a function to process the pending list. 1107 * - if pending list is empty, try to allocate a HW IO. If none 1108 * is available, place this IO at the tail of the pending IO 1109 * list. 1110 * - if HW IO is available, attach this IO to the HW IO and 1111 * submit it. 1112 * 1113 * @param io Pointer to IO structure. 1114 * @param cb Callback function. 1115 * 1116 * @return Returns 0 on success, a negative error code value on failure. 1117 */ 1118 1119 int32_t 1120 ocs_scsi_io_dispatch(ocs_io_t *io, void *cb) 1121 { 1122 ocs_hw_io_t *hio; 1123 ocs_t *ocs = io->ocs; 1124 ocs_xport_t *xport = ocs->xport; 1125 1126 ocs_assert(io->cmd_tgt || io->cmd_ini, -1); 1127 ocs_assert((io->io_type != OCS_IO_TYPE_ABORT), -1); 1128 io->hw_cb = cb; 1129 1130 /* 1131 * if this IO already has a HW IO, then this is either not the first phase of 1132 * the IO. Send it to the HW. 1133 */ 1134 if (io->hio != NULL) { 1135 return ocs_scsi_io_dispatch_hw_io(io, io->hio); 1136 } 1137 1138 /* 1139 * We don't already have a HW IO associated with the IO. First check 1140 * the pending list. If not empty, add IO to the tail and process the 1141 * pending list. 1142 */ 1143 ocs_lock(&xport->io_pending_lock); 1144 if (!ocs_list_empty(&xport->io_pending_list)) { 1145 /* 1146 * If this is a low latency request, the put at the front of the IO pending 1147 * queue, otherwise put it at the end of the queue. 1148 */ 1149 if (io->low_latency) { 1150 ocs_list_add_head(&xport->io_pending_list, io); 1151 } else { 1152 ocs_list_add_tail(&xport->io_pending_list, io); 1153 } 1154 ocs_unlock(&xport->io_pending_lock); 1155 ocs_atomic_add_return(&xport->io_pending_count, 1); 1156 ocs_atomic_add_return(&xport->io_total_pending, 1); 1157 1158 /* process pending list */ 1159 ocs_scsi_check_pending(ocs); 1160 return 0; 1161 } 1162 ocs_unlock(&xport->io_pending_lock); 1163 1164 /* 1165 * We don't have a HW IO associated with the IO and there's nothing 1166 * on the pending list. Attempt to allocate a HW IO and dispatch it. 1167 */ 1168 hio = ocs_hw_io_alloc(&io->ocs->hw); 1169 if (hio == NULL) { 1170 /* Couldn't get a HW IO. Save this IO on the pending list */ 1171 ocs_lock(&xport->io_pending_lock); 1172 ocs_list_add_tail(&xport->io_pending_list, io); 1173 ocs_unlock(&xport->io_pending_lock); 1174 1175 ocs_atomic_add_return(&xport->io_total_pending, 1); 1176 ocs_atomic_add_return(&xport->io_pending_count, 1); 1177 return 0; 1178 } 1179 1180 /* We successfully allocated a HW IO; dispatch to HW */ 1181 return ocs_scsi_io_dispatch_hw_io(io, hio); 1182 } 1183 1184 /** 1185 * @brief Attempt to dispatch an Abort IO. 1186 * 1187 * @par Description 1188 * An Abort IO is dispatched: 1189 * - if the pending list is not empty, add IO to pending list 1190 * and call a function to process the pending list. 1191 * - if pending list is empty, send abort to the HW. 1192 * 1193 * @param io Pointer to IO structure. 1194 * @param cb Callback function. 1195 * 1196 * @return Returns 0 on success, a negative error code value on failure. 1197 */ 1198 1199 int32_t 1200 ocs_scsi_io_dispatch_abort(ocs_io_t *io, void *cb) 1201 { 1202 ocs_t *ocs = io->ocs; 1203 ocs_xport_t *xport = ocs->xport; 1204 1205 ocs_assert((io->io_type == OCS_IO_TYPE_ABORT), -1); 1206 io->hw_cb = cb; 1207 1208 /* 1209 * For aborts, we don't need a HW IO, but we still want to pass through 1210 * the pending list to preserve ordering. Thus, if the pending list is 1211 * not empty, add this abort to the pending list and process the pending list. 1212 */ 1213 ocs_lock(&xport->io_pending_lock); 1214 if (!ocs_list_empty(&xport->io_pending_list)) { 1215 ocs_list_add_tail(&xport->io_pending_list, io); 1216 ocs_unlock(&xport->io_pending_lock); 1217 ocs_atomic_add_return(&xport->io_pending_count, 1); 1218 ocs_atomic_add_return(&xport->io_total_pending, 1); 1219 1220 /* process pending list */ 1221 ocs_scsi_check_pending(ocs); 1222 return 0; 1223 } 1224 ocs_unlock(&xport->io_pending_lock); 1225 1226 /* nothing on pending list, dispatch abort */ 1227 return ocs_scsi_io_dispatch_no_hw_io(io); 1228 1229 } 1230 1231 /** 1232 * @brief Dispatch IO 1233 * 1234 * @par Description 1235 * An IO and its associated HW IO is dispatched to the HW. 1236 * 1237 * @param io Pointer to IO structure. 1238 * @param hio Pointer to HW IO structure from which IO will be 1239 * dispatched. 1240 * 1241 * @return Returns 0 on success, a negative error code value on failure. 1242 */ 1243 1244 static int32_t 1245 ocs_scsi_io_dispatch_hw_io(ocs_io_t *io, ocs_hw_io_t *hio) 1246 { 1247 int32_t rc; 1248 ocs_t *ocs = io->ocs; 1249 1250 /* Got a HW IO; update ini/tgt_task_tag with HW IO info and dispatch */ 1251 io->hio = hio; 1252 if (io->cmd_tgt) { 1253 io->tgt_task_tag = hio->indicator; 1254 } else if (io->cmd_ini) { 1255 io->init_task_tag = hio->indicator; 1256 } 1257 io->hw_tag = hio->reqtag; 1258 1259 hio->eq = io->hw_priv; 1260 1261 /* Copy WQ steering */ 1262 switch(io->wq_steering) { 1263 case OCS_SCSI_WQ_STEERING_CLASS >> OCS_SCSI_WQ_STEERING_SHIFT: 1264 hio->wq_steering = OCS_HW_WQ_STEERING_CLASS; 1265 break; 1266 case OCS_SCSI_WQ_STEERING_REQUEST >> OCS_SCSI_WQ_STEERING_SHIFT: 1267 hio->wq_steering = OCS_HW_WQ_STEERING_REQUEST; 1268 break; 1269 case OCS_SCSI_WQ_STEERING_CPU >> OCS_SCSI_WQ_STEERING_SHIFT: 1270 hio->wq_steering = OCS_HW_WQ_STEERING_CPU; 1271 break; 1272 } 1273 1274 switch (io->io_type) { 1275 case OCS_IO_TYPE_IO: { 1276 uint32_t max_sgl; 1277 uint32_t total_count; 1278 uint32_t host_allocated; 1279 1280 ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &max_sgl); 1281 ocs_hw_get(&ocs->hw, OCS_HW_SGL_CHAINING_HOST_ALLOCATED, &host_allocated); 1282 1283 /* 1284 * If the requested SGL is larger than the default size, then we can allocate 1285 * an overflow SGL. 1286 */ 1287 total_count = ocs_scsi_count_sgls(&io->hw_dif, io->sgl, io->sgl_count); 1288 1289 /* 1290 * Lancer requires us to allocate the chained memory area, but 1291 * Skyhawk must use the SGL list associated with another XRI. 1292 */ 1293 if (host_allocated && total_count > max_sgl) { 1294 /* Compute count needed, the number extra plus 1 for the link sge */ 1295 uint32_t count = total_count - max_sgl + 1; 1296 rc = ocs_dma_alloc(ocs, &io->ovfl_sgl, count*sizeof(sli4_sge_t), 64); 1297 if (rc) { 1298 ocs_log_err(ocs, "ocs_dma_alloc overflow sgl failed\n"); 1299 break; 1300 } 1301 rc = ocs_hw_io_register_sgl(&ocs->hw, io->hio, &io->ovfl_sgl, count); 1302 if (rc) { 1303 ocs_scsi_io_free_ovfl(io); 1304 ocs_log_err(ocs, "ocs_hw_io_register_sgl() failed\n"); 1305 break; 1306 } 1307 /* EVT: update chained_io_count */ 1308 io->node->chained_io_count++; 1309 } 1310 1311 rc = ocs_scsi_build_sgls(&ocs->hw, io->hio, &io->hw_dif, io->sgl, io->sgl_count, io->hio_type); 1312 if (rc) { 1313 ocs_scsi_io_free_ovfl(io); 1314 break; 1315 } 1316 1317 if (OCS_LOG_ENABLE_SCSI_TRACE(ocs)) { 1318 ocs_log_sgl(io); 1319 } 1320 1321 if (io->app_id) { 1322 io->iparam.fcp_tgt.app_id = io->app_id; 1323 } 1324 1325 rc = ocs_hw_io_send(&io->ocs->hw, io->hio_type, io->hio, io->wire_len, &io->iparam, &io->node->rnode, 1326 io->hw_cb, io); 1327 break; 1328 } 1329 case OCS_IO_TYPE_ELS: 1330 case OCS_IO_TYPE_CT: { 1331 rc = ocs_hw_srrs_send(&ocs->hw, io->hio_type, io->hio, 1332 &io->els_req, io->wire_len, 1333 &io->els_rsp, &io->node->rnode, &io->iparam, 1334 io->hw_cb, io); 1335 break; 1336 } 1337 case OCS_IO_TYPE_CT_RESP: { 1338 rc = ocs_hw_srrs_send(&ocs->hw, io->hio_type, io->hio, 1339 &io->els_rsp, io->wire_len, 1340 NULL, &io->node->rnode, &io->iparam, 1341 io->hw_cb, io); 1342 break; 1343 } 1344 case OCS_IO_TYPE_BLS_RESP: { 1345 /* no need to update tgt_task_tag for BLS response since the RX_ID 1346 * will be specified by the payload, not the XRI */ 1347 rc = ocs_hw_srrs_send(&ocs->hw, io->hio_type, io->hio, 1348 NULL, 0, NULL, &io->node->rnode, &io->iparam, io->hw_cb, io); 1349 break; 1350 } 1351 default: 1352 scsi_io_printf(io, "Unknown IO type=%d\n", io->io_type); 1353 rc = -1; 1354 break; 1355 } 1356 return rc; 1357 } 1358 1359 /** 1360 * @brief Dispatch IO 1361 * 1362 * @par Description 1363 * An IO that does require a HW IO is dispatched to the HW. 1364 * 1365 * @param io Pointer to IO structure. 1366 * 1367 * @return Returns 0 on success, or a negative error code value on failure. 1368 */ 1369 1370 static int32_t 1371 ocs_scsi_io_dispatch_no_hw_io(ocs_io_t *io) 1372 { 1373 int32_t rc; 1374 1375 switch (io->io_type) { 1376 case OCS_IO_TYPE_ABORT: { 1377 ocs_hw_io_t *hio_to_abort = NULL; 1378 ocs_assert(io->io_to_abort, -1); 1379 hio_to_abort = io->io_to_abort->hio; 1380 1381 if (hio_to_abort == NULL) { 1382 /* 1383 * If "IO to abort" does not have an associated HW IO, immediately 1384 * make callback with success. The command must have been sent to 1385 * the backend, but the data phase has not yet started, so we don't 1386 * have a HW IO. 1387 * 1388 * Note: since the backend shims should be taking a reference 1389 * on io_to_abort, it should not be possible to have been completed 1390 * and freed by the backend before the abort got here. 1391 */ 1392 scsi_io_printf(io, "IO: " SCSI_IOFMT " not active\n", 1393 SCSI_IOFMT_ARGS(io->io_to_abort)); 1394 ((ocs_hw_done_t)io->hw_cb)(io->hio, NULL, 0, SLI4_FC_WCQE_STATUS_SUCCESS, 0, io); 1395 rc = 0; 1396 } else { 1397 /* HW IO is valid, abort it */ 1398 scsi_io_printf(io, "aborting " SCSI_IOFMT "\n", SCSI_IOFMT_ARGS(io->io_to_abort)); 1399 rc = ocs_hw_io_abort(&io->ocs->hw, hio_to_abort, io->send_abts, 1400 io->hw_cb, io); 1401 if (rc) { 1402 int status = SLI4_FC_WCQE_STATUS_SUCCESS; 1403 if ((rc != OCS_HW_RTN_IO_NOT_ACTIVE) && 1404 (rc != OCS_HW_RTN_IO_ABORT_IN_PROGRESS)) { 1405 status = -1; 1406 scsi_io_printf(io, "Failed to abort IO: " SCSI_IOFMT " status=%d\n", 1407 SCSI_IOFMT_ARGS(io->io_to_abort), rc); 1408 } 1409 ((ocs_hw_done_t)io->hw_cb)(io->hio, NULL, 0, status, 0, io); 1410 rc = 0; 1411 } 1412 } 1413 1414 break; 1415 } 1416 default: 1417 scsi_io_printf(io, "Unknown IO type=%d\n", io->io_type); 1418 rc = -1; 1419 break; 1420 } 1421 return rc; 1422 } 1423 1424 /** 1425 * @ingroup scsi_api_base 1426 * @brief Send read/write data. 1427 * 1428 * @par Description 1429 * This call is made by a target-server to initiate a SCSI read or write data phase, transferring 1430 * data between the target to the remote initiator. The payload is specified by the 1431 * scatter-gather list @c sgl of length @c sgl_count. The @c wire_len argument 1432 * specifies the payload length (independent of the scatter-gather list cumulative length). 1433 * @n @n 1434 * The @c flags argument has one bit, OCS_SCSI_LAST_DATAPHASE, which is a hint to the base 1435 * driver that it may use auto SCSI response features if the hardware supports it. 1436 * @n @n 1437 * Upon completion, the callback function @b cb is called with flags indicating that the 1438 * IO has completed (OCS_SCSI_IO_COMPL) and another data phase or response may be sent; 1439 * that the IO has completed and no response needs to be sent (OCS_SCSI_IO_COMPL_NO_RSP); 1440 * or that the IO was aborted (OCS_SCSI_IO_ABORTED). 1441 * 1442 * @param io Pointer to the IO context. 1443 * @param flags Flags controlling the sending of data. 1444 * @param dif_info Pointer to T10 DIF fields, or NULL if no DIF. 1445 * @param sgl Pointer to the payload scatter-gather list. 1446 * @param sgl_count Count of the scatter-gather list elements. 1447 * @param xwire_len Length of the payload on wire, in bytes. 1448 * @param type HW IO type. 1449 * @param enable_ar Enable auto-response if true. 1450 * @param cb Completion callback. 1451 * @param arg Application-supplied callback data. 1452 * 1453 * @return Returns 0 on success, or a negative error code value on failure. 1454 */ 1455 1456 static inline int32_t 1457 ocs_scsi_xfer_data(ocs_io_t *io, uint32_t flags, 1458 ocs_scsi_dif_info_t *dif_info, 1459 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t xwire_len, 1460 ocs_hw_io_type_e type, int enable_ar, 1461 ocs_scsi_io_cb_t cb, void *arg) 1462 { 1463 int32_t rc; 1464 ocs_t *ocs; 1465 uint32_t disable_ar_tgt_dif = FALSE; 1466 size_t residual = 0; 1467 1468 if ((dif_info != NULL) && (dif_info->dif_oper == OCS_SCSI_DIF_OPER_DISABLED)) { 1469 dif_info = NULL; 1470 } 1471 1472 ocs_assert(io, -1); 1473 1474 if (dif_info != NULL) { 1475 ocs_hw_get(&io->ocs->hw, OCS_HW_DISABLE_AR_TGT_DIF, &disable_ar_tgt_dif); 1476 if (disable_ar_tgt_dif) { 1477 enable_ar = FALSE; 1478 } 1479 } 1480 1481 io->sgl_count = sgl_count; 1482 1483 /* If needed, copy SGL */ 1484 if (sgl && (sgl != io->sgl)) { 1485 ocs_assert(sgl_count <= io->sgl_allocated, -1); 1486 ocs_memcpy(io->sgl, sgl, sgl_count*sizeof(*io->sgl)); 1487 } 1488 1489 ocs = io->ocs; 1490 ocs_assert(ocs, -1); 1491 ocs_assert(io->node, -1); 1492 1493 scsi_io_trace(io, "%s wire_len %d\n", (type == OCS_HW_IO_TARGET_READ) ? "send" : "recv", xwire_len); 1494 1495 ocs_assert(sgl, -1); 1496 ocs_assert(sgl_count > 0, -1); 1497 ocs_assert(io->exp_xfer_len > io->transferred, -1); 1498 1499 io->hio_type = type; 1500 1501 io->scsi_tgt_cb = cb; 1502 io->scsi_tgt_cb_arg = arg; 1503 1504 rc = ocs_scsi_convert_dif_info(ocs, dif_info, &io->hw_dif); 1505 if (rc) { 1506 return rc; 1507 } 1508 1509 /* If DIF is used, then save lba for error recovery */ 1510 if (dif_info) { 1511 io->scsi_dif_info = *dif_info; 1512 } 1513 1514 io->wire_len = MIN(xwire_len, io->exp_xfer_len - io->transferred); 1515 residual = (xwire_len - io->wire_len); 1516 1517 ocs_memset(&io->iparam, 0, sizeof(io->iparam)); 1518 io->iparam.fcp_tgt.ox_id = io->init_task_tag; 1519 io->iparam.fcp_tgt.offset = io->transferred; 1520 io->iparam.fcp_tgt.dif_oper = io->hw_dif.dif; 1521 io->iparam.fcp_tgt.blk_size = io->hw_dif.blk_size; 1522 io->iparam.fcp_tgt.cs_ctl = io->cs_ctl; 1523 io->iparam.fcp_tgt.timeout = io->timeout; 1524 1525 /* if this is the last data phase and there is no residual, enable 1526 * auto-good-response 1527 */ 1528 if (enable_ar && (flags & OCS_SCSI_LAST_DATAPHASE) && 1529 (residual == 0) && ((io->transferred + io->wire_len) == io->exp_xfer_len) && (!(flags & OCS_SCSI_NO_AUTO_RESPONSE))) { 1530 io->iparam.fcp_tgt.flags |= SLI4_IO_AUTO_GOOD_RESPONSE; 1531 io->auto_resp = TRUE; 1532 } else { 1533 io->auto_resp = FALSE; 1534 } 1535 1536 /* save this transfer length */ 1537 io->xfer_req = io->wire_len; 1538 1539 /* Adjust the transferred count to account for overrun 1540 * when the residual is calculated in ocs_scsi_send_resp 1541 */ 1542 io->transferred += residual; 1543 1544 /* Adjust the SGL size if there is overrun */ 1545 1546 if (residual) { 1547 ocs_scsi_sgl_t *sgl_ptr = &io->sgl[sgl_count-1]; 1548 1549 while (residual) { 1550 size_t len = sgl_ptr->len; 1551 if ( len > residual) { 1552 sgl_ptr->len = len - residual; 1553 residual = 0; 1554 } else { 1555 sgl_ptr->len = 0; 1556 residual -= len; 1557 io->sgl_count--; 1558 } 1559 sgl_ptr--; 1560 } 1561 } 1562 1563 /* Set latency and WQ steering */ 1564 io->low_latency = (flags & OCS_SCSI_LOW_LATENCY) != 0; 1565 io->wq_steering = (flags & OCS_SCSI_WQ_STEERING_MASK) >> OCS_SCSI_WQ_STEERING_SHIFT; 1566 io->wq_class = (flags & OCS_SCSI_WQ_CLASS_MASK) >> OCS_SCSI_WQ_CLASS_SHIFT; 1567 1568 return ocs_scsi_io_dispatch(io, ocs_target_io_cb); 1569 } 1570 1571 int32_t 1572 ocs_scsi_send_rd_data(ocs_io_t *io, uint32_t flags, 1573 ocs_scsi_dif_info_t *dif_info, 1574 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t len, 1575 ocs_scsi_io_cb_t cb, void *arg) 1576 { 1577 return ocs_scsi_xfer_data(io, flags, dif_info, sgl, sgl_count, len, OCS_HW_IO_TARGET_READ, 1578 enable_tsend_auto_resp(io->ocs), cb, arg); 1579 } 1580 1581 int32_t 1582 ocs_scsi_recv_wr_data(ocs_io_t *io, uint32_t flags, 1583 ocs_scsi_dif_info_t *dif_info, 1584 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t len, 1585 ocs_scsi_io_cb_t cb, void *arg) 1586 { 1587 return ocs_scsi_xfer_data(io, flags, dif_info, sgl, sgl_count, len, OCS_HW_IO_TARGET_WRITE, 1588 enable_treceive_auto_resp(io->ocs), cb, arg); 1589 } 1590 1591 /** 1592 * @ingroup scsi_api_base 1593 * @brief Free overflow SGL. 1594 * 1595 * @par Description 1596 * Free the overflow SGL if it is present. 1597 * 1598 * @param io Pointer to IO object. 1599 * 1600 * @return None. 1601 */ 1602 static void 1603 ocs_scsi_io_free_ovfl(ocs_io_t *io) { 1604 if (io->ovfl_sgl.size) { 1605 ocs_dma_free(io->ocs, &io->ovfl_sgl); 1606 } 1607 } 1608 1609 /** 1610 * @ingroup scsi_api_base 1611 * @brief Send response data. 1612 * 1613 * @par Description 1614 * This function is used by a target-server to send the SCSI response data to a remote 1615 * initiator node. The target-server populates the @c ocs_scsi_cmd_resp_t 1616 * argument with scsi status, status qualifier, sense data, and response data, as 1617 * needed. 1618 * @n @n 1619 * Upon completion, the callback function @c cb is invoked. The target-server will generally 1620 * clean up its IO context resources and call ocs_scsi_io_complete(). 1621 * 1622 * @param io Pointer to the IO context. 1623 * @param flags Flags to control sending of the SCSI response. 1624 * @param rsp Pointer to the response data populated by the caller. 1625 * @param cb Completion callback. 1626 * @param arg Application-specified completion callback argument. 1627 1628 * @return Returns 0 on success, or a negative error code value on failure. 1629 */ 1630 int32_t 1631 ocs_scsi_send_resp(ocs_io_t *io, uint32_t flags, ocs_scsi_cmd_resp_t *rsp, ocs_scsi_io_cb_t cb, void *arg) 1632 { 1633 ocs_t *ocs; 1634 int32_t residual; 1635 int auto_resp = TRUE; /* Always try auto resp */ 1636 uint8_t scsi_status = 0; 1637 uint16_t scsi_status_qualifier = 0; 1638 uint8_t *sense_data = NULL; 1639 uint32_t sense_data_length = 0; 1640 1641 ocs_assert(io, -1); 1642 1643 ocs = io->ocs; 1644 ocs_assert(ocs, -1); 1645 1646 ocs_assert(io->node, -1); 1647 1648 ocs_scsi_convert_dif_info(ocs, NULL, &io->hw_dif); 1649 1650 if (rsp) { 1651 scsi_status = rsp->scsi_status; 1652 scsi_status_qualifier = rsp->scsi_status_qualifier; 1653 sense_data = rsp->sense_data; 1654 sense_data_length = rsp->sense_data_length; 1655 residual = rsp->residual; 1656 } else { 1657 residual = io->exp_xfer_len - io->transferred; 1658 } 1659 1660 io->wire_len = 0; 1661 io->hio_type = OCS_HW_IO_TARGET_RSP; 1662 1663 io->scsi_tgt_cb = cb; 1664 io->scsi_tgt_cb_arg = arg; 1665 1666 ocs_memset(&io->iparam, 0, sizeof(io->iparam)); 1667 io->iparam.fcp_tgt.ox_id = io->init_task_tag; 1668 io->iparam.fcp_tgt.offset = 0; 1669 io->iparam.fcp_tgt.cs_ctl = io->cs_ctl; 1670 io->iparam.fcp_tgt.timeout = io->timeout; 1671 1672 /* Set low latency queueing request */ 1673 io->low_latency = (flags & OCS_SCSI_LOW_LATENCY) != 0; 1674 io->wq_steering = (flags & OCS_SCSI_WQ_STEERING_MASK) >> OCS_SCSI_WQ_STEERING_SHIFT; 1675 io->wq_class = (flags & OCS_SCSI_WQ_CLASS_MASK) >> OCS_SCSI_WQ_CLASS_SHIFT; 1676 1677 if ((scsi_status != 0) || residual || sense_data_length) { 1678 fcp_rsp_iu_t *fcprsp = io->rspbuf.virt; 1679 1680 if (!fcprsp) { 1681 ocs_log_err(ocs, "NULL response buffer\n"); 1682 return -1; 1683 } 1684 1685 auto_resp = FALSE; 1686 1687 ocs_memset(fcprsp, 0, sizeof(*fcprsp)); 1688 1689 io->wire_len += (sizeof(*fcprsp) - sizeof(fcprsp->data)); 1690 1691 fcprsp->scsi_status = scsi_status; 1692 *((uint16_t*)fcprsp->status_qualifier) = ocs_htobe16(scsi_status_qualifier); 1693 1694 /* set residual status if necessary */ 1695 if (residual != 0) { 1696 /* FCP: if data transferred is less than the amount expected, then this is an 1697 * underflow. If data transferred would have been greater than the amount expected 1698 * then this is an overflow 1699 */ 1700 if (residual > 0) { 1701 fcprsp->flags |= FCP_RESID_UNDER; 1702 *((uint32_t *)fcprsp->fcp_resid) = ocs_htobe32(residual); 1703 } else { 1704 fcprsp->flags |= FCP_RESID_OVER; 1705 *((uint32_t *)fcprsp->fcp_resid) = ocs_htobe32(-residual); 1706 } 1707 } 1708 1709 if (sense_data && sense_data_length) { 1710 ocs_assert(sense_data_length <= sizeof(fcprsp->data), -1); 1711 fcprsp->flags |= FCP_SNS_LEN_VALID; 1712 ocs_memcpy(fcprsp->data, sense_data, sense_data_length); 1713 *((uint32_t*)fcprsp->fcp_sns_len) = ocs_htobe32(sense_data_length); 1714 io->wire_len += sense_data_length; 1715 } 1716 1717 io->sgl[0].addr = io->rspbuf.phys; 1718 io->sgl[0].dif_addr = 0; 1719 io->sgl[0].len = io->wire_len; 1720 io->sgl_count = 1; 1721 } 1722 1723 if (auto_resp) { 1724 io->iparam.fcp_tgt.flags |= SLI4_IO_AUTO_GOOD_RESPONSE; 1725 } 1726 1727 return ocs_scsi_io_dispatch(io, ocs_target_io_cb); 1728 } 1729 1730 /** 1731 * @ingroup scsi_api_base 1732 * @brief Send TMF response data. 1733 * 1734 * @par Description 1735 * This function is used by a target-server to send SCSI TMF response data to a remote 1736 * initiator node. 1737 * Upon completion, the callback function @c cb is invoked. The target-server will generally 1738 * clean up its IO context resources and call ocs_scsi_io_complete(). 1739 * 1740 * @param io Pointer to the IO context. 1741 * @param rspcode TMF response code. 1742 * @param addl_rsp_info Additional TMF response information (may be NULL for zero data). 1743 * @param cb Completion callback. 1744 * @param arg Application-specified completion callback argument. 1745 * 1746 * @return Returns 0 on success, or a negative error code value on failure. 1747 */ 1748 int32_t 1749 ocs_scsi_send_tmf_resp(ocs_io_t *io, ocs_scsi_tmf_resp_e rspcode, uint8_t addl_rsp_info[3], 1750 ocs_scsi_io_cb_t cb, void *arg) 1751 { 1752 int32_t rc = -1; 1753 ocs_t *ocs = NULL; 1754 fcp_rsp_iu_t *fcprsp = NULL; 1755 fcp_rsp_info_t *rspinfo = NULL; 1756 uint8_t fcp_rspcode; 1757 1758 ocs_assert(io, -1); 1759 ocs_assert(io->ocs, -1); 1760 ocs_assert(io->node, -1); 1761 1762 ocs = io->ocs; 1763 1764 io->wire_len = 0; 1765 ocs_scsi_convert_dif_info(ocs, NULL, &io->hw_dif); 1766 1767 switch(rspcode) { 1768 case OCS_SCSI_TMF_FUNCTION_COMPLETE: 1769 fcp_rspcode = FCP_TMF_COMPLETE; 1770 break; 1771 case OCS_SCSI_TMF_FUNCTION_SUCCEEDED: 1772 case OCS_SCSI_TMF_FUNCTION_IO_NOT_FOUND: 1773 fcp_rspcode = FCP_TMF_SUCCEEDED; 1774 break; 1775 case OCS_SCSI_TMF_FUNCTION_REJECTED: 1776 fcp_rspcode = FCP_TMF_REJECTED; 1777 break; 1778 case OCS_SCSI_TMF_INCORRECT_LOGICAL_UNIT_NUMBER: 1779 fcp_rspcode = FCP_TMF_INCORRECT_LUN; 1780 break; 1781 case OCS_SCSI_TMF_SERVICE_DELIVERY: 1782 fcp_rspcode = FCP_TMF_FAILED; 1783 break; 1784 default: 1785 fcp_rspcode = FCP_TMF_REJECTED; 1786 break; 1787 } 1788 1789 io->hio_type = OCS_HW_IO_TARGET_RSP; 1790 1791 io->scsi_tgt_cb = cb; 1792 io->scsi_tgt_cb_arg = arg; 1793 1794 if (io->tmf_cmd == OCS_SCSI_TMF_ABORT_TASK) { 1795 rc = ocs_target_send_bls_resp(io, cb, arg); 1796 return rc; 1797 } 1798 1799 /* populate the FCP TMF response */ 1800 fcprsp = io->rspbuf.virt; 1801 ocs_memset(fcprsp, 0, sizeof(*fcprsp)); 1802 1803 fcprsp->flags |= FCP_RSP_LEN_VALID; 1804 1805 rspinfo = (fcp_rsp_info_t*) fcprsp->data; 1806 if (addl_rsp_info != NULL) { 1807 ocs_memcpy(rspinfo->addl_rsp_info, addl_rsp_info, sizeof(rspinfo->addl_rsp_info)); 1808 } 1809 rspinfo->rsp_code = fcp_rspcode; 1810 1811 io->wire_len = sizeof(*fcprsp) - sizeof(fcprsp->data) + sizeof(*rspinfo); 1812 1813 *((uint32_t*)fcprsp->fcp_rsp_len) = ocs_htobe32(sizeof(*rspinfo)); 1814 1815 io->sgl[0].addr = io->rspbuf.phys; 1816 io->sgl[0].dif_addr = 0; 1817 io->sgl[0].len = io->wire_len; 1818 io->sgl_count = 1; 1819 1820 ocs_memset(&io->iparam, 0, sizeof(io->iparam)); 1821 io->iparam.fcp_tgt.ox_id = io->init_task_tag; 1822 io->iparam.fcp_tgt.offset = 0; 1823 io->iparam.fcp_tgt.cs_ctl = io->cs_ctl; 1824 io->iparam.fcp_tgt.timeout = io->timeout; 1825 1826 rc = ocs_scsi_io_dispatch(io, ocs_target_io_cb); 1827 1828 return rc; 1829 } 1830 1831 /** 1832 * @brief Process target abort callback. 1833 * 1834 * @par Description 1835 * Accepts HW abort requests. 1836 * 1837 * @param hio HW IO context. 1838 * @param rnode Remote node. 1839 * @param length Length of response data. 1840 * @param status Completion status. 1841 * @param ext_status Extended completion status. 1842 * @param app Application-specified callback data. 1843 * 1844 * @return Returns 0 on success, or a negative error code value on failure. 1845 */ 1846 1847 static int32_t 1848 ocs_target_abort_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app) 1849 { 1850 ocs_io_t *io = app; 1851 ocs_t *ocs; 1852 ocs_scsi_io_status_e scsi_status; 1853 1854 ocs_assert(io, -1); 1855 ocs_assert(io->ocs, -1); 1856 1857 ocs = io->ocs; 1858 1859 if (io->abort_cb) { 1860 ocs_scsi_io_cb_t abort_cb = io->abort_cb; 1861 void *abort_cb_arg = io->abort_cb_arg; 1862 1863 io->abort_cb = NULL; 1864 io->abort_cb_arg = NULL; 1865 1866 switch (status) { 1867 case SLI4_FC_WCQE_STATUS_SUCCESS: 1868 scsi_status = OCS_SCSI_STATUS_GOOD; 1869 break; 1870 case SLI4_FC_WCQE_STATUS_LOCAL_REJECT: 1871 switch (ext_status) { 1872 case SLI4_FC_LOCAL_REJECT_NO_XRI: 1873 scsi_status = OCS_SCSI_STATUS_NO_IO; 1874 break; 1875 case SLI4_FC_LOCAL_REJECT_ABORT_IN_PROGRESS: 1876 scsi_status = OCS_SCSI_STATUS_ABORT_IN_PROGRESS; 1877 break; 1878 default: 1879 /* TODO: we have seen 0x15 (abort in progress) */ 1880 scsi_status = OCS_SCSI_STATUS_ERROR; 1881 break; 1882 } 1883 break; 1884 case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE: 1885 scsi_status = OCS_SCSI_STATUS_CHECK_RESPONSE; 1886 break; 1887 default: 1888 scsi_status = OCS_SCSI_STATUS_ERROR; 1889 break; 1890 } 1891 /* invoke callback */ 1892 abort_cb(io->io_to_abort, scsi_status, 0, abort_cb_arg); 1893 } 1894 1895 ocs_assert(io != io->io_to_abort, -1); 1896 1897 /* done with IO to abort */ 1898 ocs_ref_put(&io->io_to_abort->ref); /* ocs_ref_get(): ocs_scsi_tgt_abort_io() */ 1899 1900 ocs_io_free(ocs, io); 1901 1902 ocs_scsi_check_pending(ocs); 1903 return 0; 1904 } 1905 1906 /** 1907 * @ingroup scsi_api_base 1908 * @brief Abort a target IO. 1909 * 1910 * @par Description 1911 * This routine is called from a SCSI target-server. It initiates an abort of a 1912 * previously-issued target data phase or response request. 1913 * 1914 * @param io IO context. 1915 * @param cb SCSI target server callback. 1916 * @param arg SCSI target server supplied callback argument. 1917 * 1918 * @return Returns 0 on success, or a non-zero value on failure. 1919 */ 1920 int32_t 1921 ocs_scsi_tgt_abort_io(ocs_io_t *io, ocs_scsi_io_cb_t cb, void *arg) 1922 { 1923 ocs_t *ocs; 1924 ocs_xport_t *xport; 1925 int32_t rc; 1926 1927 ocs_io_t *abort_io = NULL; 1928 ocs_assert(io, -1); 1929 ocs_assert(io->node, -1); 1930 ocs_assert(io->ocs, -1); 1931 1932 ocs = io->ocs; 1933 xport = ocs->xport; 1934 1935 /* take a reference on IO being aborted */ 1936 if ((ocs_ref_get_unless_zero(&io->ref) == 0)) { 1937 /* command no longer active */ 1938 scsi_io_printf(io, "command no longer active\n"); 1939 return -1; 1940 } 1941 1942 /* 1943 * allocate a new IO to send the abort request. Use ocs_io_alloc() directly, as 1944 * we need an IO object that will not fail allocation due to allocations being 1945 * disabled (in ocs_scsi_io_alloc()) 1946 */ 1947 abort_io = ocs_io_alloc(ocs); 1948 if (abort_io == NULL) { 1949 ocs_atomic_add_return(&xport->io_alloc_failed_count, 1); 1950 ocs_ref_put(&io->ref); /* ocs_ref_get(): same function */ 1951 return -1; 1952 } 1953 1954 /* Save the target server callback and argument */ 1955 ocs_assert(abort_io->hio == NULL, -1); 1956 1957 /* set generic fields */ 1958 abort_io->cmd_tgt = TRUE; 1959 abort_io->node = io->node; 1960 1961 /* set type and abort-specific fields */ 1962 abort_io->io_type = OCS_IO_TYPE_ABORT; 1963 abort_io->display_name = "tgt_abort"; 1964 abort_io->io_to_abort = io; 1965 abort_io->send_abts = FALSE; 1966 abort_io->abort_cb = cb; 1967 abort_io->abort_cb_arg = arg; 1968 1969 /* now dispatch IO */ 1970 rc = ocs_scsi_io_dispatch_abort(abort_io, ocs_target_abort_cb); 1971 if (rc) { 1972 ocs_ref_put(&io->ref); /* ocs_ref_get(): same function */ 1973 } 1974 return rc; 1975 } 1976 1977 /** 1978 * @brief Process target BLS response callback. 1979 * 1980 * @par Description 1981 * Accepts HW abort requests. 1982 * 1983 * @param hio HW IO context. 1984 * @param rnode Remote node. 1985 * @param length Length of response data. 1986 * @param status Completion status. 1987 * @param ext_status Extended completion status. 1988 * @param app Application-specified callback data. 1989 * 1990 * @return Returns 0 on success, or a negative error code value on failure. 1991 */ 1992 1993 static int32_t 1994 ocs_target_bls_resp_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app) 1995 { 1996 ocs_io_t *io = app; 1997 ocs_t *ocs; 1998 ocs_scsi_io_status_e bls_status; 1999 2000 ocs_assert(io, -1); 2001 ocs_assert(io->ocs, -1); 2002 2003 ocs = io->ocs; 2004 2005 /* BLS isn't really a "SCSI" concept, but use SCSI status */ 2006 if (status) { 2007 io_error_log(io, "s=%#x x=%#x\n", status, ext_status); 2008 bls_status = OCS_SCSI_STATUS_ERROR; 2009 } else { 2010 bls_status = OCS_SCSI_STATUS_GOOD; 2011 } 2012 2013 if (io->bls_cb) { 2014 ocs_scsi_io_cb_t bls_cb = io->bls_cb; 2015 void *bls_cb_arg = io->bls_cb_arg; 2016 2017 io->bls_cb = NULL; 2018 io->bls_cb_arg = NULL; 2019 2020 /* invoke callback */ 2021 bls_cb(io, bls_status, 0, bls_cb_arg); 2022 } 2023 2024 ocs_scsi_check_pending(ocs); 2025 return 0; 2026 } 2027 2028 /** 2029 * @brief Complete abort request. 2030 * 2031 * @par Description 2032 * An abort request is completed by posting a BA_ACC for the IO that requested the abort. 2033 * 2034 * @param io Pointer to the IO context. 2035 * @param cb Callback function to invoke upon completion. 2036 * @param arg Application-specified completion callback argument. 2037 * 2038 * @return Returns 0 on success, or a negative error code value on failure. 2039 */ 2040 2041 static int32_t 2042 ocs_target_send_bls_resp(ocs_io_t *io, ocs_scsi_io_cb_t cb, void *arg) 2043 { 2044 int32_t rc; 2045 fc_ba_acc_payload_t *acc; 2046 2047 ocs_assert(io, -1); 2048 2049 /* fill out IO structure with everything needed to send BA_ACC */ 2050 ocs_memset(&io->iparam, 0, sizeof(io->iparam)); 2051 io->iparam.bls.ox_id = io->init_task_tag; 2052 io->iparam.bls.rx_id = io->abort_rx_id; 2053 2054 acc = (void *)io->iparam.bls.payload; 2055 2056 ocs_memset(io->iparam.bls.payload, 0, sizeof(io->iparam.bls.payload)); 2057 acc->ox_id = io->iparam.bls.ox_id; 2058 acc->rx_id = io->iparam.bls.rx_id; 2059 acc->high_seq_cnt = UINT16_MAX; 2060 2061 /* generic io fields have already been populated */ 2062 2063 /* set type and BLS-specific fields */ 2064 io->io_type = OCS_IO_TYPE_BLS_RESP; 2065 io->display_name = "bls_rsp"; 2066 io->hio_type = OCS_HW_BLS_ACC; 2067 io->bls_cb = cb; 2068 io->bls_cb_arg = arg; 2069 2070 /* dispatch IO */ 2071 rc = ocs_scsi_io_dispatch(io, ocs_target_bls_resp_cb); 2072 return rc; 2073 } 2074 2075 /** 2076 * @ingroup scsi_api_base 2077 * @brief Notify the base driver that the IO is complete. 2078 * 2079 * @par Description 2080 * This function is called by a target-server to notify the base driver that an IO 2081 * has completed, allowing for the base driver to free resources. 2082 * @n 2083 * @n @b Note: This function is not called by initiator-clients. 2084 * 2085 * @param io Pointer to IO context. 2086 * 2087 * @return None. 2088 */ 2089 void 2090 ocs_scsi_io_complete(ocs_io_t *io) 2091 { 2092 ocs_assert(io); 2093 2094 if (!ocs_io_busy(io)) { 2095 ocs_log_test(io->ocs, "Got completion for non-busy io with tag 0x%x\n", io->tag); 2096 return; 2097 } 2098 2099 scsi_io_trace(io, "freeing io 0x%p %s\n", io, io->display_name); 2100 ocs_assert(ocs_ref_read_count(&io->ref) > 0); 2101 ocs_ref_put(&io->ref); /* ocs_ref_get(): ocs_scsi_io_alloc() */ 2102 } 2103 2104 /** 2105 * @brief Handle initiator IO completion. 2106 * 2107 * @par Description 2108 * This callback is made upon completion of an initiator operation (initiator read/write command). 2109 * 2110 * @param hio HW IO context. 2111 * @param rnode Remote node. 2112 * @param length Length of completion data. 2113 * @param status Completion status. 2114 * @param ext_status Extended completion status. 2115 * @param app Application-specified callback data. 2116 * 2117 * @return None. 2118 */ 2119 2120 static void 2121 ocs_initiator_io_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, 2122 int32_t status, uint32_t ext_status, void *app) 2123 { 2124 ocs_io_t *io = app; 2125 ocs_t *ocs; 2126 ocs_scsi_io_status_e scsi_status; 2127 2128 ocs_assert(io); 2129 ocs_assert(io->scsi_ini_cb); 2130 2131 scsi_io_trace(io, "status x%x ext_status x%x\n", status, ext_status); 2132 2133 ocs = io->ocs; 2134 ocs_assert(ocs); 2135 2136 ocs_scsi_io_free_ovfl(io); 2137 2138 /* Call target server completion */ 2139 if (io->scsi_ini_cb) { 2140 fcp_rsp_iu_t *fcprsp = io->rspbuf.virt; 2141 ocs_scsi_cmd_resp_t rsp; 2142 ocs_scsi_rsp_io_cb_t cb = io->scsi_ini_cb; 2143 uint32_t flags = 0; 2144 uint8_t *pd = fcprsp->data; 2145 2146 /* Clear the callback before invoking the callback */ 2147 io->scsi_ini_cb = NULL; 2148 2149 ocs_memset(&rsp, 0, sizeof(rsp)); 2150 2151 /* Unless status is FCP_RSP_FAILURE, fcprsp is not filled in */ 2152 switch (status) { 2153 case SLI4_FC_WCQE_STATUS_SUCCESS: 2154 scsi_status = OCS_SCSI_STATUS_GOOD; 2155 break; 2156 case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE: 2157 scsi_status = OCS_SCSI_STATUS_CHECK_RESPONSE; 2158 rsp.scsi_status = fcprsp->scsi_status; 2159 rsp.scsi_status_qualifier = ocs_be16toh(*((uint16_t*)fcprsp->status_qualifier)); 2160 2161 if (fcprsp->flags & FCP_RSP_LEN_VALID) { 2162 rsp.response_data = pd; 2163 rsp.response_data_length = ocs_fc_getbe32(fcprsp->fcp_rsp_len); 2164 pd += rsp.response_data_length; 2165 } 2166 if (fcprsp->flags & FCP_SNS_LEN_VALID) { 2167 uint32_t sns_len = ocs_fc_getbe32(fcprsp->fcp_sns_len); 2168 rsp.sense_data = pd; 2169 rsp.sense_data_length = sns_len; 2170 pd += sns_len; 2171 } 2172 /* Set residual */ 2173 if (fcprsp->flags & FCP_RESID_OVER) { 2174 rsp.residual = -ocs_fc_getbe32(fcprsp->fcp_resid); 2175 rsp.response_wire_length = length; 2176 } else if (fcprsp->flags & FCP_RESID_UNDER) { 2177 rsp.residual = ocs_fc_getbe32(fcprsp->fcp_resid); 2178 rsp.response_wire_length = length; 2179 } 2180 2181 /* 2182 * Note: The FCP_RSP_FAILURE can be returned for initiator IOs when the total data 2183 * placed does not match the requested length even if the status is good. If 2184 * the status is all zeroes, then we have to assume that a frame(s) were 2185 * dropped and change the status to LOCAL_REJECT/OUT_OF_ORDER_DATA 2186 */ 2187 if (length != io->wire_len) { 2188 uint32_t rsp_len = ext_status; 2189 uint8_t *rsp_bytes = io->rspbuf.virt; 2190 uint32_t i; 2191 uint8_t all_zeroes = (rsp_len > 0); 2192 /* Check if the rsp is zero */ 2193 for (i = 0; i < rsp_len; i++) { 2194 if (rsp_bytes[i] != 0) { 2195 all_zeroes = FALSE; 2196 break; 2197 } 2198 } 2199 if (all_zeroes) { 2200 scsi_status = OCS_SCSI_STATUS_ERROR; 2201 ocs_log_test(io->ocs, "[%s]" SCSI_IOFMT "local reject=0x%02x\n", 2202 io->node->display_name, SCSI_IOFMT_ARGS(io), 2203 SLI4_FC_LOCAL_REJECT_OUT_OF_ORDER_DATA); 2204 } 2205 } 2206 break; 2207 case SLI4_FC_WCQE_STATUS_LOCAL_REJECT: 2208 if (ext_status == SLI4_FC_LOCAL_REJECT_SEQUENCE_TIMEOUT) { 2209 scsi_status = OCS_SCSI_STATUS_COMMAND_TIMEOUT; 2210 } else { 2211 scsi_status = OCS_SCSI_STATUS_ERROR; 2212 } 2213 break; 2214 case SLI4_FC_WCQE_STATUS_DI_ERROR: 2215 if (ext_status & 0x01) { 2216 scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR; 2217 } else if (ext_status & 0x02) { 2218 scsi_status = OCS_SCSI_STATUS_DIF_APP_TAG_ERROR; 2219 } else if (ext_status & 0x04) { 2220 scsi_status = OCS_SCSI_STATUS_DIF_REF_TAG_ERROR; 2221 } else { 2222 scsi_status = OCS_SCSI_STATUS_DIF_UNKNOWN_ERROR; 2223 } 2224 break; 2225 default: 2226 scsi_status = OCS_SCSI_STATUS_ERROR; 2227 break; 2228 } 2229 2230 cb(io, scsi_status, &rsp, flags, io->scsi_ini_cb_arg); 2231 } 2232 ocs_scsi_check_pending(ocs); 2233 } 2234 2235 /** 2236 * @ingroup scsi_api_base 2237 * @brief Initiate initiator read IO. 2238 * 2239 * @par Description 2240 * This call is made by an initiator-client to send a SCSI read command. The payload 2241 * for the command is given by a scatter-gather list @c sgl for @c sgl_count 2242 * entries. 2243 * @n @n 2244 * Upon completion, the callback @b cb is invoked and passed request status. 2245 * If the command completed successfully, the callback is given SCSI response data. 2246 * 2247 * @param node Pointer to the node. 2248 * @param io Pointer to the IO context. 2249 * @param lun LUN value. 2250 * @param cdb Pointer to the CDB. 2251 * @param cdb_len Length of the CDB. 2252 * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF. 2253 * @param sgl Pointer to the scatter-gather list. 2254 * @param sgl_count Count of the scatter-gather list elements. 2255 * @param wire_len Length of the payload. 2256 * @param cb Completion callback. 2257 * @param arg Application-specified completion callback argument. 2258 * 2259 * @return Returns 0 on success, or a negative error code value on failure. 2260 */ 2261 int32_t 2262 ocs_scsi_send_rd_io(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len, 2263 ocs_scsi_dif_info_t *dif_info, 2264 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, 2265 ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags) 2266 { 2267 int32_t rc; 2268 2269 rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_READ, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count, 2270 wire_len, 0, cb, arg, flags); 2271 2272 return rc; 2273 } 2274 2275 /** 2276 * @ingroup scsi_api_base 2277 * @brief Initiate initiator write IO. 2278 * 2279 * @par Description 2280 * This call is made by an initiator-client to send a SCSI write command. The payload 2281 * for the command is given by a scatter-gather list @c sgl for @c sgl_count 2282 * entries. 2283 * @n @n 2284 * Upon completion, the callback @c cb is invoked and passed request status. If the command 2285 * completed successfully, the callback is given SCSI response data. 2286 * 2287 * @param node Pointer to the node. 2288 * @param io Pointer to IO context. 2289 * @param lun LUN value. 2290 * @param cdb Pointer to the CDB. 2291 * @param cdb_len Length of the CDB. 2292 * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF. 2293 * @param sgl Pointer to the scatter-gather list. 2294 * @param sgl_count Count of the scatter-gather list elements. 2295 * @param wire_len Length of the payload. 2296 * @param cb Completion callback. 2297 * @param arg Application-specified completion callback argument. 2298 * 2299 * @return Returns 0 on success, or a negative error code value on failure. 2300 */ 2301 int32_t ocs_scsi_send_wr_io(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len, 2302 ocs_scsi_dif_info_t *dif_info, 2303 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, 2304 ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags) 2305 { 2306 int32_t rc; 2307 2308 rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_WRITE, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count, 2309 wire_len, 0, cb, arg, flags); 2310 2311 return rc; 2312 } 2313 2314 /** 2315 * @ingroup scsi_api_base 2316 * @brief Initiate initiator write IO. 2317 * 2318 * @par Description 2319 * This call is made by an initiator-client to send a SCSI write command. The payload 2320 * for the command is given by a scatter-gather list @c sgl for @c sgl_count 2321 * entries. 2322 * @n @n 2323 * Upon completion, the callback @c cb is invoked and passed request status. If the command 2324 * completed successfully, the callback is given SCSI response data. 2325 * 2326 * @param node Pointer to the node. 2327 * @param io Pointer to IO context. 2328 * @param lun LUN value. 2329 * @param cdb Pointer to the CDB. 2330 * @param cdb_len Length of the CDB. 2331 * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF. 2332 * @param sgl Pointer to the scatter-gather list. 2333 * @param sgl_count Count of the scatter-gather list elements. 2334 * @param wire_len Length of the payload. 2335 * @param first_burst Number of first burst bytes to send. 2336 * @param cb Completion callback. 2337 * @param arg Application-specified completion callback argument. 2338 * 2339 * @return Returns 0 on success, or a negative error code value on failure. 2340 */ 2341 int32_t 2342 ocs_scsi_send_wr_io_first_burst(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len, 2343 ocs_scsi_dif_info_t *dif_info, 2344 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst, 2345 ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags) 2346 { 2347 int32_t rc; 2348 2349 rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_WRITE, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count, 2350 wire_len, 0, cb, arg, flags); 2351 2352 return rc; 2353 } 2354 2355 /** 2356 * @ingroup scsi_api_base 2357 * @brief Initiate initiator SCSI command with no data. 2358 * 2359 * @par Description 2360 * This call is made by an initiator-client to send a SCSI command with no data. 2361 * @n @n 2362 * Upon completion, the callback @c cb is invoked and passed request status. If the command 2363 * completed successfully, the callback is given SCSI response data. 2364 * 2365 * @param node Pointer to the node. 2366 * @param io Pointer to the IO context. 2367 * @param lun LUN value. 2368 * @param cdb Pointer to the CDB. 2369 * @param cdb_len Length of the CDB. 2370 * @param cb Completion callback. 2371 * @param arg Application-specified completion callback argument. 2372 * 2373 * @return Returns 0 on success, or a negative error code value on failure. 2374 */ 2375 int32_t ocs_scsi_send_nodata_io(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len, 2376 ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags) 2377 { 2378 int32_t rc; 2379 2380 rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_NODATA, node, io, lun, 0, cdb, cdb_len, NULL, NULL, 0, 0, 0, cb, arg, flags); 2381 2382 return rc; 2383 } 2384 /** 2385 * @ingroup scsi_api_base 2386 * @brief Initiate initiator task management operation. 2387 * 2388 * @par Description 2389 * This command is used to send a SCSI task management function command. If the command 2390 * requires it (QUERY_TASK_SET for example), a payload may be associated with the command. 2391 * If no payload is required, then @c sgl_count may be zero and @c sgl is ignored. 2392 * @n @n 2393 * Upon completion @c cb is invoked with status and SCSI response data. 2394 * 2395 * @param node Pointer to the node. 2396 * @param io Pointer to the IO context. 2397 * @param io_to_abort Pointer to the IO context to abort in the 2398 * case of OCS_SCSI_TMF_ABORT_TASK. Note: this can point to the 2399 * same the same ocs_io_t as @c io, provided that @c io does not 2400 * have any outstanding work requests. 2401 * @param lun LUN value. 2402 * @param tmf Task management command. 2403 * @param sgl Pointer to the scatter-gather list. 2404 * @param sgl_count Count of the scatter-gather list elements. 2405 * @param len Length of the payload. 2406 * @param cb Completion callback. 2407 * @param arg Application-specified completion callback argument. 2408 * 2409 * @return Returns 0 on success, or a negative error code value on failure. 2410 */ 2411 int32_t 2412 ocs_scsi_send_tmf(ocs_node_t *node, ocs_io_t *io, ocs_io_t *io_to_abort, uint64_t lun, ocs_scsi_tmf_cmd_e tmf, 2413 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t len, ocs_scsi_rsp_io_cb_t cb, void *arg) 2414 { 2415 int32_t rc; 2416 ocs_assert(io, -1); 2417 2418 if (tmf == OCS_SCSI_TMF_ABORT_TASK) { 2419 ocs_assert(io_to_abort, -1); 2420 2421 /* take a reference on IO being aborted */ 2422 if ((ocs_ref_get_unless_zero(&io_to_abort->ref) == 0)) { 2423 /* command no longer active */ 2424 scsi_io_printf(io, "command no longer active\n"); 2425 return -1; 2426 } 2427 /* generic io fields have already been populated */ 2428 2429 /* abort-specific fields */ 2430 io->io_type = OCS_IO_TYPE_ABORT; 2431 io->display_name = "abort_task"; 2432 io->io_to_abort = io_to_abort; 2433 io->send_abts = TRUE; 2434 io->scsi_ini_cb = cb; 2435 io->scsi_ini_cb_arg = arg; 2436 2437 /* now dispatch IO */ 2438 rc = ocs_scsi_io_dispatch_abort(io, ocs_scsi_abort_io_cb); 2439 if (rc) { 2440 scsi_io_printf(io, "Failed to dispatch abort\n"); 2441 ocs_ref_put(&io->ref); /* ocs_ref_get(): same function */ 2442 } 2443 } else { 2444 io->display_name = "tmf"; 2445 rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_READ, node, io, lun, tmf, NULL, 0, NULL, 2446 sgl, sgl_count, len, 0, cb, arg, 0); 2447 } 2448 2449 return rc; 2450 } 2451 2452 /** 2453 * @ingroup scsi_api_base 2454 * @brief Send an FCP IO. 2455 * 2456 * @par Description 2457 * An FCP read/write IO command, with optional task management flags, is sent to @c node. 2458 * 2459 * @param type HW IO type to send. 2460 * @param node Pointer to the node destination of the IO. 2461 * @param io Pointer to the IO context. 2462 * @param lun LUN value. 2463 * @param tmf Task management command. 2464 * @param cdb Pointer to the SCSI CDB. 2465 * @param cdb_len Length of the CDB, in bytes. 2466 * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF. 2467 * @param sgl Pointer to the scatter-gather list. 2468 * @param sgl_count Number of SGL entries in SGL. 2469 * @param wire_len Payload length, in bytes, of data on wire. 2470 * @param first_burst Number of first burst bytes to send. 2471 * @param cb Completion callback. 2472 * @param arg Application-specified completion callback argument. 2473 * 2474 * @return Returns 0 on success, or a negative error code value on failure. 2475 */ 2476 2477 /* tc: could elminiate LUN, as it's part of the IO structure */ 2478 2479 static int32_t ocs_scsi_send_io(ocs_hw_io_type_e type, ocs_node_t *node, ocs_io_t *io, uint64_t lun, 2480 ocs_scsi_tmf_cmd_e tmf, uint8_t *cdb, uint32_t cdb_len, 2481 ocs_scsi_dif_info_t *dif_info, 2482 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst, 2483 ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags) 2484 { 2485 int32_t rc; 2486 ocs_t *ocs; 2487 fcp_cmnd_iu_t *cmnd; 2488 uint32_t cmnd_bytes = 0; 2489 uint32_t *fcp_dl; 2490 uint8_t tmf_flags = 0; 2491 2492 ocs_assert(io->node, -1); 2493 ocs_assert(io->node == node, -1); 2494 ocs_assert(io, -1); 2495 ocs = io->ocs; 2496 ocs_assert(cb, -1); 2497 2498 io->sgl_count = sgl_count; 2499 2500 /* Copy SGL if needed */ 2501 if (sgl != io->sgl) { 2502 ocs_assert(sgl_count <= io->sgl_allocated, -1); 2503 ocs_memcpy(io->sgl, sgl, sizeof(*io->sgl) * sgl_count); 2504 } 2505 2506 /* save initiator and target task tags for debugging */ 2507 io->tgt_task_tag = 0xffff; 2508 2509 io->wire_len = wire_len; 2510 io->hio_type = type; 2511 2512 if (OCS_LOG_ENABLE_SCSI_TRACE(ocs)) { 2513 char buf[80]; 2514 ocs_textbuf_t txtbuf; 2515 uint32_t i; 2516 2517 ocs_textbuf_init(ocs, &txtbuf, buf, sizeof(buf)); 2518 2519 ocs_textbuf_printf(&txtbuf, "cdb%d: ", cdb_len); 2520 for (i = 0; i < cdb_len; i ++) { 2521 ocs_textbuf_printf(&txtbuf, "%02X%s", cdb[i], (i == (cdb_len-1)) ? "" : " "); 2522 } 2523 scsi_io_printf(io, "%s len %d, %s\n", (io->hio_type == OCS_HW_IO_INITIATOR_READ) ? "read" : 2524 (io->hio_type == OCS_HW_IO_INITIATOR_WRITE) ? "write" : "", io->wire_len, 2525 ocs_textbuf_get_buffer(&txtbuf)); 2526 } 2527 2528 ocs_assert(io->cmdbuf.virt, -1); 2529 2530 cmnd = io->cmdbuf.virt; 2531 2532 ocs_assert(sizeof(*cmnd) <= io->cmdbuf.size, -1); 2533 2534 ocs_memset(cmnd, 0, sizeof(*cmnd)); 2535 2536 /* Default FCP_CMND IU doesn't include additional CDB bytes but does include FCP_DL */ 2537 cmnd_bytes = sizeof(fcp_cmnd_iu_t) - sizeof(cmnd->fcp_cdb_and_dl) + sizeof(uint32_t); 2538 2539 fcp_dl = (uint32_t*)(&(cmnd->fcp_cdb_and_dl)); 2540 2541 if (cdb) { 2542 if (cdb_len <= 16) { 2543 ocs_memcpy(cmnd->fcp_cdb, cdb, cdb_len); 2544 } else { 2545 uint32_t addl_cdb_bytes; 2546 2547 ocs_memcpy(cmnd->fcp_cdb, cdb, 16); 2548 addl_cdb_bytes = cdb_len - 16; 2549 ocs_memcpy(cmnd->fcp_cdb_and_dl, &(cdb[16]), addl_cdb_bytes); 2550 /* additional_fcp_cdb_length is in words, not bytes */ 2551 cmnd->additional_fcp_cdb_length = (addl_cdb_bytes + 3) / 4; 2552 fcp_dl += cmnd->additional_fcp_cdb_length; 2553 2554 /* Round up additional CDB bytes */ 2555 cmnd_bytes += (addl_cdb_bytes + 3) & ~0x3; 2556 } 2557 } 2558 2559 be64enc(cmnd->fcp_lun, CAM_EXTLUN_BYTE_SWIZZLE(lun)); 2560 2561 if (node->fcp2device) { 2562 if(ocs_get_crn(node, &cmnd->command_reference_number, 2563 lun)) { 2564 return -1; 2565 } 2566 } 2567 if (flags & OCS_SCSI_CMD_HEAD_OF_QUEUE) 2568 cmnd->task_attribute = FCP_TASK_ATTR_HEAD_OF_QUEUE; 2569 else if (flags & OCS_SCSI_CMD_ORDERED) 2570 cmnd->task_attribute = FCP_TASK_ATTR_ORDERED; 2571 else if (flags & OCS_SCSI_CMD_UNTAGGED) 2572 cmnd->task_attribute = FCP_TASK_ATTR_UNTAGGED; 2573 else if (flags & OCS_SCSI_CMD_ACA) 2574 cmnd->task_attribute = FCP_TASK_ATTR_ACA; 2575 else 2576 cmnd->task_attribute = FCP_TASK_ATTR_SIMPLE; 2577 cmnd->command_priority = (flags & OCS_SCSI_PRIORITY_MASK) >> 2578 OCS_SCSI_PRIORITY_SHIFT; 2579 2580 switch (tmf) { 2581 case OCS_SCSI_TMF_QUERY_TASK_SET: 2582 tmf_flags = FCP_QUERY_TASK_SET; 2583 break; 2584 case OCS_SCSI_TMF_ABORT_TASK_SET: 2585 tmf_flags = FCP_ABORT_TASK_SET; 2586 break; 2587 case OCS_SCSI_TMF_CLEAR_TASK_SET: 2588 tmf_flags = FCP_CLEAR_TASK_SET; 2589 break; 2590 case OCS_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT: 2591 tmf_flags = FCP_QUERY_ASYNCHRONOUS_EVENT; 2592 break; 2593 case OCS_SCSI_TMF_LOGICAL_UNIT_RESET: 2594 tmf_flags = FCP_LOGICAL_UNIT_RESET; 2595 break; 2596 case OCS_SCSI_TMF_CLEAR_ACA: 2597 tmf_flags = FCP_CLEAR_ACA; 2598 break; 2599 case OCS_SCSI_TMF_TARGET_RESET: 2600 tmf_flags = FCP_TARGET_RESET; 2601 break; 2602 default: 2603 tmf_flags = 0; 2604 } 2605 cmnd->task_management_flags = tmf_flags; 2606 2607 *fcp_dl = ocs_htobe32(io->wire_len); 2608 2609 switch (io->hio_type) { 2610 case OCS_HW_IO_INITIATOR_READ: 2611 cmnd->rddata = 1; 2612 break; 2613 case OCS_HW_IO_INITIATOR_WRITE: 2614 cmnd->wrdata = 1; 2615 break; 2616 case OCS_HW_IO_INITIATOR_NODATA: 2617 /* sets neither */ 2618 break; 2619 default: 2620 ocs_log_test(ocs, "bad IO type %d\n", io->hio_type); 2621 return -1; 2622 } 2623 2624 rc = ocs_scsi_convert_dif_info(ocs, dif_info, &io->hw_dif); 2625 if (rc) { 2626 return rc; 2627 } 2628 2629 io->scsi_ini_cb = cb; 2630 io->scsi_ini_cb_arg = arg; 2631 2632 /* set command and response buffers in the iparam */ 2633 io->iparam.fcp_ini.cmnd = &io->cmdbuf; 2634 io->iparam.fcp_ini.cmnd_size = cmnd_bytes; 2635 io->iparam.fcp_ini.rsp = &io->rspbuf; 2636 io->iparam.fcp_ini.flags = 0; 2637 io->iparam.fcp_ini.dif_oper = io->hw_dif.dif; 2638 io->iparam.fcp_ini.blk_size = io->hw_dif.blk_size; 2639 io->iparam.fcp_ini.timeout = io->timeout; 2640 io->iparam.fcp_ini.first_burst = first_burst; 2641 2642 return ocs_scsi_io_dispatch(io, ocs_initiator_io_cb); 2643 } 2644 2645 /** 2646 * @ingroup scsi_api_base 2647 * @brief Callback for an aborted IO. 2648 * 2649 * @par Description 2650 * Callback function invoked upon completion of an IO abort request. 2651 * 2652 * @param hio HW IO context. 2653 * @param rnode Remote node. 2654 * @param len Response length. 2655 * @param status Completion status. 2656 * @param ext_status Extended completion status. 2657 * @param arg Application-specific callback, usually IO context. 2658 2659 * @return Returns 0 on success, or a negative error code value on failure. 2660 */ 2661 2662 static int32_t 2663 ocs_scsi_abort_io_cb(struct ocs_hw_io_s *hio, ocs_remote_node_t *rnode, uint32_t len, int32_t status, 2664 uint32_t ext_status, void *arg) 2665 { 2666 ocs_io_t *io = arg; 2667 ocs_t *ocs; 2668 ocs_scsi_io_status_e scsi_status = OCS_SCSI_STATUS_GOOD; 2669 2670 ocs_assert(io, -1); 2671 ocs_assert(ocs_io_busy(io), -1); 2672 ocs_assert(io->ocs, -1); 2673 ocs_assert(io->io_to_abort, -1); 2674 ocs = io->ocs; 2675 2676 ocs_log_debug(ocs, "status %d ext %d\n", status, ext_status); 2677 2678 /* done with IO to abort */ 2679 ocs_ref_put(&io->io_to_abort->ref); /* ocs_ref_get(): ocs_scsi_send_tmf() */ 2680 2681 ocs_scsi_io_free_ovfl(io); 2682 2683 switch (status) { 2684 case SLI4_FC_WCQE_STATUS_SUCCESS: 2685 scsi_status = OCS_SCSI_STATUS_GOOD; 2686 break; 2687 case SLI4_FC_WCQE_STATUS_LOCAL_REJECT: 2688 if (ext_status == SLI4_FC_LOCAL_REJECT_ABORT_REQUESTED) { 2689 scsi_status = OCS_SCSI_STATUS_ABORTED; 2690 } else if (ext_status == SLI4_FC_LOCAL_REJECT_NO_XRI) { 2691 scsi_status = OCS_SCSI_STATUS_NO_IO; 2692 } else if (ext_status == SLI4_FC_LOCAL_REJECT_ABORT_IN_PROGRESS) { 2693 scsi_status = OCS_SCSI_STATUS_ABORT_IN_PROGRESS; 2694 } else { 2695 ocs_log_test(ocs, "Unhandled local reject 0x%x/0x%x\n", status, ext_status); 2696 scsi_status = OCS_SCSI_STATUS_ERROR; 2697 } 2698 break; 2699 default: 2700 scsi_status = OCS_SCSI_STATUS_ERROR; 2701 break; 2702 } 2703 2704 if (io->scsi_ini_cb) { 2705 (*io->scsi_ini_cb)(io, scsi_status, NULL, 0, io->scsi_ini_cb_arg); 2706 } else { 2707 ocs_scsi_io_free(io); 2708 } 2709 2710 ocs_scsi_check_pending(ocs); 2711 return 0; 2712 } 2713 2714 /** 2715 * @ingroup scsi_api_base 2716 * @brief Return SCSI API integer valued property. 2717 * 2718 * @par Description 2719 * This function is called by a target-server or initiator-client to 2720 * retrieve an integer valued property. 2721 * 2722 * @param ocs Pointer to the ocs. 2723 * @param prop Property value to return. 2724 * 2725 * @return Returns a value, or 0 if invalid property was requested. 2726 */ 2727 uint32_t 2728 ocs_scsi_get_property(ocs_t *ocs, ocs_scsi_property_e prop) 2729 { 2730 ocs_xport_t *xport = ocs->xport; 2731 uint32_t val; 2732 2733 switch (prop) { 2734 case OCS_SCSI_MAX_SGE: 2735 if (0 == ocs_hw_get(&ocs->hw, OCS_HW_MAX_SGE, &val)) { 2736 return val; 2737 } 2738 break; 2739 case OCS_SCSI_MAX_SGL: 2740 if (ocs->ctrlmask & OCS_CTRLMASK_TEST_CHAINED_SGLS) { 2741 /* 2742 * If chain SGL test-mode is enabled, the number of HW SGEs 2743 * has been limited; report back original max. 2744 */ 2745 return (OCS_FC_MAX_SGL); 2746 } 2747 if (0 == ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &val)) { 2748 return val; 2749 } 2750 break; 2751 case OCS_SCSI_MAX_IOS: 2752 return ocs_io_pool_allocated(xport->io_pool); 2753 case OCS_SCSI_DIF_CAPABLE: 2754 if (0 == ocs_hw_get(&ocs->hw, OCS_HW_DIF_CAPABLE, &val)) { 2755 return val; 2756 } 2757 break; 2758 case OCS_SCSI_MAX_FIRST_BURST: 2759 return 0; 2760 case OCS_SCSI_DIF_MULTI_SEPARATE: 2761 if (ocs_hw_get(&ocs->hw, OCS_HW_DIF_MULTI_SEPARATE, &val) == 0) { 2762 return val; 2763 } 2764 break; 2765 case OCS_SCSI_ENABLE_TASK_SET_FULL: 2766 /* Return FALSE if we are send frame capable */ 2767 if (ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &val) == 0) { 2768 return ! val; 2769 } 2770 break; 2771 default: 2772 break; 2773 } 2774 2775 ocs_log_debug(ocs, "invalid property request %d\n", prop); 2776 return 0; 2777 } 2778 2779 /** 2780 * @ingroup scsi_api_base 2781 * @brief Return a property pointer. 2782 * 2783 * @par Description 2784 * This function is called by a target-server or initiator-client to 2785 * retrieve a pointer to the requested property. 2786 * 2787 * @param ocs Pointer to the ocs. 2788 * @param prop Property value to return. 2789 * 2790 * @return Returns pointer to the requested property, or NULL otherwise. 2791 */ 2792 void *ocs_scsi_get_property_ptr(ocs_t *ocs, ocs_scsi_property_e prop) 2793 { 2794 void *rc = NULL; 2795 2796 switch (prop) { 2797 case OCS_SCSI_WWNN: 2798 rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_NODE); 2799 break; 2800 case OCS_SCSI_WWPN: 2801 rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_PORT); 2802 break; 2803 case OCS_SCSI_PORTNUM: 2804 rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_PORTNUM); 2805 break; 2806 case OCS_SCSI_BIOS_VERSION_STRING: 2807 rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_BIOS_VERSION_STRING); 2808 break; 2809 case OCS_SCSI_SERIALNUMBER: 2810 { 2811 uint8_t *pvpd; 2812 uint32_t vpd_len; 2813 2814 if (ocs_hw_get(&ocs->hw, OCS_HW_VPD_LEN, &vpd_len)) { 2815 ocs_log_test(ocs, "Can't get VPD length\n"); 2816 rc = "\012sn-unknown"; 2817 break; 2818 } 2819 2820 pvpd = ocs_hw_get_ptr(&ocs->hw, OCS_HW_VPD); 2821 if (pvpd) { 2822 rc = ocs_find_vpd(pvpd, vpd_len, "SN"); 2823 } 2824 2825 if (rc == NULL || 2826 ocs_strlen(rc) == 0) { 2827 /* Note: VPD is missing, using wwnn for serial number */ 2828 scsi_log(ocs, "Note: VPD is missing, using wwnn for serial number\n"); 2829 /* Use the last 32 bits of the WWN */ 2830 if ((ocs == NULL) || (ocs->domain == NULL) || (ocs->domain->sport == NULL)) { 2831 rc = "\011(Unknown)"; 2832 } else { 2833 rc = &ocs->domain->sport->wwnn_str[8]; 2834 } 2835 } 2836 break; 2837 } 2838 case OCS_SCSI_PARTNUMBER: 2839 { 2840 uint8_t *pvpd; 2841 uint32_t vpd_len; 2842 2843 if (ocs_hw_get(&ocs->hw, OCS_HW_VPD_LEN, &vpd_len)) { 2844 ocs_log_test(ocs, "Can't get VPD length\n"); 2845 rc = "\012pn-unknown"; 2846 break; 2847 } 2848 pvpd = ocs_hw_get_ptr(&ocs->hw, OCS_HW_VPD); 2849 if (pvpd) { 2850 rc = ocs_find_vpd(pvpd, vpd_len, "PN"); 2851 if (rc == NULL) { 2852 rc = "\012pn-unknown"; 2853 } 2854 } else { 2855 rc = "\012pn-unknown"; 2856 } 2857 break; 2858 } 2859 default: 2860 break; 2861 } 2862 2863 if (rc == NULL) { 2864 ocs_log_debug(ocs, "invalid property request %d\n", prop); 2865 } 2866 return rc; 2867 } 2868 2869 /** 2870 * @ingroup scsi_api_base 2871 * @brief Notify that delete initiator is complete. 2872 * 2873 * @par Description 2874 * Sent by the target-server to notify the base driver that the work started from 2875 * ocs_scsi_del_initiator() is now complete and that it is safe for the node to 2876 * release the rest of its resources. 2877 * 2878 * @param node Pointer to the node. 2879 * 2880 * @return None. 2881 */ 2882 void 2883 ocs_scsi_del_initiator_complete(ocs_node_t *node) 2884 { 2885 /* Notify the node to resume */ 2886 ocs_node_post_event(node, OCS_EVT_NODE_DEL_INI_COMPLETE, NULL); 2887 } 2888 2889 /** 2890 * @ingroup scsi_api_base 2891 * @brief Notify that delete target is complete. 2892 * 2893 * @par Description 2894 * Sent by the initiator-client to notify the base driver that the work started from 2895 * ocs_scsi_del_target() is now complete and that it is safe for the node to 2896 * release the rest of its resources. 2897 * 2898 * @param node Pointer to the node. 2899 * 2900 * @return None. 2901 */ 2902 void 2903 ocs_scsi_del_target_complete(ocs_node_t *node) 2904 { 2905 /* Notify the node to resume */ 2906 ocs_node_post_event(node, OCS_EVT_NODE_DEL_TGT_COMPLETE, NULL); 2907 } 2908 2909 /** 2910 * @brief Update transferred count 2911 * 2912 * @par Description 2913 * Updates io->transferred, as required when using first burst, when the amount 2914 * of first burst data processed differs from the amount of first burst 2915 * data received. 2916 * 2917 * @param io Pointer to the io object. 2918 * @param transferred Number of bytes transferred out of first burst buffers. 2919 * 2920 * @return None. 2921 */ 2922 void 2923 ocs_scsi_update_first_burst_transferred(ocs_io_t *io, uint32_t transferred) 2924 { 2925 io->transferred = transferred; 2926 } 2927 2928 /** 2929 * @brief Register bounce callback for multi-threading. 2930 * 2931 * @par Description 2932 * Register the back end bounce function. 2933 * 2934 * @param ocs Pointer to device object. 2935 * @param fctn Function pointer of bounce function. 2936 * 2937 * @return None. 2938 */ 2939 void 2940 ocs_scsi_register_bounce(ocs_t *ocs, void(*fctn)(void(*fctn)(void *arg), void *arg, uint32_t s_id, uint32_t d_id, 2941 uint32_t ox_id)) 2942 { 2943 ocs_hw_rtn_e rc; 2944 2945 rc = ocs_hw_callback(&ocs->hw, OCS_HW_CB_BOUNCE, fctn, NULL); 2946 if (rc) { 2947 ocs_log_test(ocs, "ocs_hw_callback(OCS_HW_CB_BOUNCE) failed: %d\n", rc); 2948 } 2949 } 2950