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 * Defines the Hardware Abstraction Layer (HW) interface functions. 37 */ 38 39 #ifndef _OCS_HW_H 40 #define _OCS_HW_H 41 42 #include "sli4.h" 43 #include "ocs_hw.h" 44 #include "ocs_stats.h" 45 #include "ocs_utils.h" 46 47 typedef struct ocs_hw_io_s ocs_hw_io_t; 48 49 #if defined(OCS_INCLUDE_DEBUG) 50 #else 51 #define ocs_queue_history_wq(...) 52 #define ocs_queue_history_cqe(...) 53 #define ocs_queue_history_init(...) 54 #define ocs_queue_history_free(...) 55 #endif 56 57 /** 58 * @brief HW queue forward declarations 59 */ 60 typedef struct hw_eq_s hw_eq_t; 61 typedef struct hw_cq_s hw_cq_t; 62 typedef struct hw_mq_s hw_mq_t; 63 typedef struct hw_wq_s hw_wq_t; 64 typedef struct hw_rq_s hw_rq_t; 65 typedef struct hw_rq_grp_s hw_rq_grp_t; 66 67 /* HW asserts/verify 68 * 69 */ 70 71 extern void _ocs_hw_assert(const char *cond, const char *filename, int linenum); 72 extern void _ocs_hw_verify(const char *cond, const char *filename, int linenum); 73 74 #if defined(HW_NDEBUG) 75 #define ocs_hw_assert(cond) 76 #define ocs_hw_verify(cond, ...) 77 #else 78 #define ocs_hw_assert(cond) \ 79 do { \ 80 if ((!(cond))) { \ 81 _ocs_hw_assert(#cond, __FILE__, __LINE__); \ 82 } \ 83 } while (0) 84 85 #define ocs_hw_verify(cond, ...) \ 86 do { \ 87 if ((!(cond))) { \ 88 _ocs_hw_verify(#cond, __FILE__, __LINE__); \ 89 return __VA_ARGS__; \ 90 } \ 91 } while (0) 92 #endif 93 #define ocs_hw_verify_arg(cond) ocs_hw_verify(cond, OCS_HW_RTN_INVALID_ARG) 94 95 /* 96 * HW completion loop control parameters. 97 * 98 * The HW completion loop must terminate periodically to keep the OS happy. The 99 * loop terminates when a predefined time has elapsed, but to keep the overhead of 100 * computing time down, the time is only checked after a number of loop iterations 101 * has completed. 102 * 103 * OCS_HW_TIMECHECK_ITERATIONS number of loop iterations between time checks 104 * 105 */ 106 107 #define OCS_HW_TIMECHECK_ITERATIONS 100 108 #define OCS_HW_MAX_NUM_MQ 1 109 #define OCS_HW_MAX_NUM_RQ 32 110 #define OCS_HW_MAX_NUM_EQ 16 111 #define OCS_HW_MAX_NUM_WQ 32 112 113 #define OCE_HW_MAX_NUM_MRQ_PAIRS 16 114 115 #define OCS_HW_MAX_WQ_CLASS 4 116 #define OCS_HW_MAX_WQ_CPU 128 117 118 /* 119 * A CQ will be assinged to each WQ (CQ must have 2X entries of the WQ for abort 120 * processing), plus a separate one for each RQ PAIR and one for MQ 121 */ 122 #define OCS_HW_MAX_NUM_CQ ((OCS_HW_MAX_NUM_WQ*2) + 1 + (OCE_HW_MAX_NUM_MRQ_PAIRS * 2)) 123 124 /* 125 * Q hash - size is the maximum of all the queue sizes, rounded up to the next 126 * power of 2 127 */ 128 #define OCS_HW_Q_HASH_SIZE B32_NEXT_POWER_OF_2(OCS_MAX(OCS_HW_MAX_NUM_MQ, OCS_MAX(OCS_HW_MAX_NUM_RQ, \ 129 OCS_MAX(OCS_HW_MAX_NUM_EQ, OCS_MAX(OCS_HW_MAX_NUM_WQ, \ 130 OCS_HW_MAX_NUM_CQ))))) 131 132 #define OCS_HW_RQ_HEADER_SIZE 128 133 #define OCS_HW_RQ_HEADER_INDEX 0 134 135 /** 136 * @brief Options for ocs_hw_command(). 137 */ 138 enum { 139 OCS_CMD_POLL, /**< command executes synchronously and busy-waits for completion */ 140 OCS_CMD_NOWAIT, /**< command executes asynchronously. Uses callback */ 141 }; 142 143 typedef enum { 144 OCS_HW_RTN_SUCCESS = 0, 145 OCS_HW_RTN_SUCCESS_SYNC = 1, 146 OCS_HW_RTN_ERROR = -1, 147 OCS_HW_RTN_NO_RESOURCES = -2, 148 OCS_HW_RTN_NO_MEMORY = -3, 149 OCS_HW_RTN_IO_NOT_ACTIVE = -4, 150 OCS_HW_RTN_IO_ABORT_IN_PROGRESS = -5, 151 OCS_HW_RTN_IO_PORT_OWNED_ALREADY_ABORTED = -6, 152 OCS_HW_RTN_INVALID_ARG = -7, 153 } ocs_hw_rtn_e; 154 #define OCS_HW_RTN_IS_ERROR(e) ((e) < 0) 155 156 typedef enum { 157 OCS_HW_RESET_FUNCTION, 158 OCS_HW_RESET_FIRMWARE, 159 OCS_HW_RESET_MAX 160 } ocs_hw_reset_e; 161 162 typedef enum { 163 OCS_HW_N_IO, 164 OCS_HW_N_SGL, 165 OCS_HW_MAX_IO, 166 OCS_HW_MAX_SGE, 167 OCS_HW_MAX_SGL, 168 OCS_HW_MAX_NODES, 169 OCS_HW_MAX_RQ_ENTRIES, 170 OCS_HW_TOPOLOGY, /**< auto, nport, loop */ 171 OCS_HW_WWN_NODE, 172 OCS_HW_WWN_PORT, 173 OCS_HW_FW_REV, 174 OCS_HW_FW_REV2, 175 OCS_HW_IPL, 176 OCS_HW_VPD, 177 OCS_HW_VPD_LEN, 178 OCS_HW_MODE, /**< initiator, target, both */ 179 OCS_HW_LINK_SPEED, 180 OCS_HW_IF_TYPE, 181 OCS_HW_SLI_REV, 182 OCS_HW_SLI_FAMILY, 183 OCS_HW_RQ_PROCESS_LIMIT, 184 OCS_HW_RQ_DEFAULT_BUFFER_SIZE, 185 OCS_HW_AUTO_XFER_RDY_CAPABLE, 186 OCS_HW_AUTO_XFER_RDY_XRI_CNT, 187 OCS_HW_AUTO_XFER_RDY_SIZE, 188 OCS_HW_AUTO_XFER_RDY_BLK_SIZE, 189 OCS_HW_AUTO_XFER_RDY_T10_ENABLE, 190 OCS_HW_AUTO_XFER_RDY_P_TYPE, 191 OCS_HW_AUTO_XFER_RDY_REF_TAG_IS_LBA, 192 OCS_HW_AUTO_XFER_RDY_APP_TAG_VALID, 193 OCS_HW_AUTO_XFER_RDY_APP_TAG_VALUE, 194 OCS_HW_DIF_CAPABLE, 195 OCS_HW_DIF_SEED, 196 OCS_HW_DIF_MODE, 197 OCS_HW_DIF_MULTI_SEPARATE, 198 OCS_HW_DUMP_MAX_SIZE, 199 OCS_HW_DUMP_READY, 200 OCS_HW_DUMP_PRESENT, 201 OCS_HW_RESET_REQUIRED, 202 OCS_HW_FW_ERROR, 203 OCS_HW_FW_READY, 204 OCS_HW_HIGH_LOGIN_MODE, 205 OCS_HW_PREREGISTER_SGL, 206 OCS_HW_HW_REV1, 207 OCS_HW_HW_REV2, 208 OCS_HW_HW_REV3, 209 OCS_HW_LINKCFG, 210 OCS_HW_ETH_LICENSE, 211 OCS_HW_LINK_MODULE_TYPE, 212 OCS_HW_NUM_CHUTES, 213 OCS_HW_WAR_VERSION, 214 OCS_HW_DISABLE_AR_TGT_DIF, 215 OCS_HW_EMULATE_I_ONLY_AAB, /**< emulate IAAB=0 for initiator-commands only */ 216 OCS_HW_EMULATE_TARGET_WQE_TIMEOUT, /**< enable driver timeouts for target WQEs */ 217 OCS_HW_LINK_CONFIG_SPEED, 218 OCS_HW_CONFIG_TOPOLOGY, 219 OCS_HW_BOUNCE, 220 OCS_HW_PORTNUM, 221 OCS_HW_BIOS_VERSION_STRING, 222 OCS_HW_RQ_SELECT_POLICY, 223 OCS_HW_SGL_CHAINING_CAPABLE, 224 OCS_HW_SGL_CHAINING_ALLOWED, 225 OCS_HW_SGL_CHAINING_HOST_ALLOCATED, 226 OCS_HW_SEND_FRAME_CAPABLE, 227 OCS_HW_RQ_SELECTION_POLICY, 228 OCS_HW_RR_QUANTA, 229 OCS_HW_FILTER_DEF, 230 OCS_HW_MAX_VPORTS, 231 OCS_ESOC, 232 OCS_HW_FW_TIMED_OUT, 233 } ocs_hw_property_e; 234 235 enum { 236 OCS_HW_TOPOLOGY_AUTO, 237 OCS_HW_TOPOLOGY_NPORT, 238 OCS_HW_TOPOLOGY_LOOP, 239 OCS_HW_TOPOLOGY_NONE, 240 OCS_HW_TOPOLOGY_MAX 241 }; 242 243 enum { 244 OCS_HW_MODE_INITIATOR, 245 OCS_HW_MODE_TARGET, 246 OCS_HW_MODE_BOTH, 247 OCS_HW_MODE_MAX 248 }; 249 250 /** 251 * @brief Port protocols 252 */ 253 254 typedef enum { 255 OCS_HW_PORT_PROTOCOL_ISCSI, 256 OCS_HW_PORT_PROTOCOL_FCOE, 257 OCS_HW_PORT_PROTOCOL_FC, 258 OCS_HW_PORT_PROTOCOL_OTHER, 259 } ocs_hw_port_protocol_e; 260 261 #define OCS_HW_MAX_PROFILES 40 262 /** 263 * @brief A Profile Descriptor 264 */ 265 typedef struct { 266 uint32_t profile_index; 267 uint32_t profile_id; 268 char profile_description[512]; 269 } ocs_hw_profile_descriptor_t; 270 271 /** 272 * @brief A Profile List 273 */ 274 typedef struct { 275 uint32_t num_descriptors; 276 ocs_hw_profile_descriptor_t descriptors[OCS_HW_MAX_PROFILES]; 277 } ocs_hw_profile_list_t; 278 279 /** 280 * @brief Defines DIF operation modes 281 */ 282 enum { 283 OCS_HW_DIF_MODE_INLINE, 284 OCS_HW_DIF_MODE_SEPARATE, 285 }; 286 287 /** 288 * @brief Defines the type of RQ buffer 289 */ 290 typedef enum { 291 OCS_HW_RQ_BUFFER_TYPE_HDR, 292 OCS_HW_RQ_BUFFER_TYPE_PAYLOAD, 293 OCS_HW_RQ_BUFFER_TYPE_MAX, 294 } ocs_hw_rq_buffer_type_e; 295 296 /** 297 * @brief Defines a wrapper for the RQ payload buffers so that we can place it 298 * back on the proper queue. 299 */ 300 typedef struct { 301 uint16_t rqindex; 302 ocs_dma_t dma; 303 } ocs_hw_rq_buffer_t; 304 305 /** 306 * @brief T10 DIF operations. 307 */ 308 typedef enum { 309 OCS_HW_DIF_OPER_DISABLED, 310 OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC, 311 OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF, 312 OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CHKSUM, 313 OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_NODIF, 314 OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC, 315 OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CHKSUM, 316 OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CHKSUM, 317 OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CRC, 318 OCS_HW_SGE_DIF_OP_IN_RAW_OUT_RAW, 319 } ocs_hw_dif_oper_e; 320 321 #define OCS_HW_DIF_OPER_PASS_THRU OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC 322 #define OCS_HW_DIF_OPER_STRIP OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF 323 #define OCS_HW_DIF_OPER_INSERT OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC 324 325 /** 326 * @brief T10 DIF block sizes. 327 */ 328 typedef enum { 329 OCS_HW_DIF_BK_SIZE_512, 330 OCS_HW_DIF_BK_SIZE_1024, 331 OCS_HW_DIF_BK_SIZE_2048, 332 OCS_HW_DIF_BK_SIZE_4096, 333 OCS_HW_DIF_BK_SIZE_520, 334 OCS_HW_DIF_BK_SIZE_4104, 335 OCS_HW_DIF_BK_SIZE_NA = 0 336 } ocs_hw_dif_blk_size_e; 337 338 /** 339 * @brief Link configurations. 340 */ 341 typedef enum { 342 OCS_HW_LINKCFG_4X10G = 0, 343 OCS_HW_LINKCFG_1X40G, 344 OCS_HW_LINKCFG_2X16G, 345 OCS_HW_LINKCFG_4X8G, 346 OCS_HW_LINKCFG_4X1G, 347 OCS_HW_LINKCFG_2X10G, 348 OCS_HW_LINKCFG_2X10G_2X8G, 349 350 /* must be last */ 351 OCS_HW_LINKCFG_NA, 352 } ocs_hw_linkcfg_e; 353 354 /** 355 * @brief link module types 356 * 357 * (note: these just happen to match SLI4 values) 358 */ 359 360 enum { 361 OCS_HW_LINK_MODULE_TYPE_1GB = 0x0004, 362 OCS_HW_LINK_MODULE_TYPE_2GB = 0x0008, 363 OCS_HW_LINK_MODULE_TYPE_4GB = 0x0040, 364 OCS_HW_LINK_MODULE_TYPE_8GB = 0x0080, 365 OCS_HW_LINK_MODULE_TYPE_10GB = 0x0100, 366 OCS_HW_LINK_MODULE_TYPE_16GB = 0x0200, 367 OCS_HW_LINK_MODULE_TYPE_32GB = 0x0400, 368 }; 369 370 /** 371 * @brief T10 DIF information passed to the transport. 372 */ 373 typedef struct ocs_hw_dif_info_s { 374 ocs_hw_dif_oper_e dif_oper; 375 ocs_hw_dif_blk_size_e blk_size; 376 uint32_t ref_tag_cmp; 377 uint32_t ref_tag_repl; 378 uint32_t app_tag_cmp:16, 379 app_tag_repl:16; 380 uint32_t check_ref_tag:1, 381 check_app_tag:1, 382 check_guard:1, 383 auto_incr_ref_tag:1, 384 repl_app_tag:1, 385 repl_ref_tag:1, 386 dif:2, 387 dif_separate:1, 388 389 /* If the APP TAG is 0xFFFF, disable checking the REF TAG and CRC fields */ 390 disable_app_ffff:1, 391 392 /* if the APP TAG is 0xFFFF and REF TAG is 0xFFFF_FFFF, disable checking the received CRC field. */ 393 disable_app_ref_ffff:1, 394 395 :21; 396 uint16_t dif_seed; 397 } ocs_hw_dif_info_t; 398 typedef enum { 399 OCS_HW_ELS_REQ, /**< ELS request */ 400 OCS_HW_ELS_RSP, /**< ELS response */ 401 OCS_HW_ELS_RSP_SID, /**< ELS response, override the S_ID */ 402 OCS_HW_FC_CT, /**< FC Common Transport */ 403 OCS_HW_FC_CT_RSP, /**< FC Common Transport Response */ 404 OCS_HW_BLS_ACC, /**< BLS accept (BA_ACC) */ 405 OCS_HW_BLS_ACC_SID, /**< BLS accept (BA_ACC), override the S_ID */ 406 OCS_HW_BLS_RJT, /**< BLS reject (BA_RJT) */ 407 OCS_HW_BCAST, /**< Class 3 broadcast sequence */ 408 OCS_HW_IO_TARGET_READ, 409 OCS_HW_IO_TARGET_WRITE, 410 OCS_HW_IO_TARGET_RSP, 411 OCS_HW_IO_INITIATOR_READ, 412 OCS_HW_IO_INITIATOR_WRITE, 413 OCS_HW_IO_INITIATOR_NODATA, 414 OCS_HW_IO_DNRX_REQUEUE, 415 OCS_HW_IO_MAX, 416 } ocs_hw_io_type_e; 417 418 typedef enum { 419 OCS_HW_IO_STATE_FREE, 420 OCS_HW_IO_STATE_INUSE, 421 OCS_HW_IO_STATE_WAIT_FREE, 422 OCS_HW_IO_STATE_WAIT_SEC_HIO, 423 } ocs_hw_io_state_e; 424 425 /* Descriptive strings for the HW IO request types (note: these must always 426 * match up with the ocs_hw_io_type_e declaration) */ 427 #define OCS_HW_IO_TYPE_STRINGS \ 428 "ELS request", \ 429 "ELS response", \ 430 "ELS response(set SID)", \ 431 "FC CT request", \ 432 "BLS accept", \ 433 "BLS accept(set SID)", \ 434 "BLS reject", \ 435 "target read", \ 436 "target write", \ 437 "target response", \ 438 "initiator read", \ 439 "initiator write", \ 440 "initiator nodata", 441 442 /** 443 * @brief HW command context. 444 * 445 * Stores the state for the asynchronous commands sent to the hardware. 446 */ 447 typedef struct ocs_command_ctx_s { 448 ocs_list_t link; 449 /**< Callback function */ 450 int32_t (*cb)(struct ocs_hw_s *, int32_t, uint8_t *, void *); 451 void *arg; /**< Argument for callback */ 452 uint8_t *buf; /**< buffer holding command / results */ 453 void *ctx; /**< upper layer context */ 454 } ocs_command_ctx_t; 455 456 typedef struct ocs_hw_sgl_s { 457 uintptr_t addr; 458 size_t len; 459 } ocs_hw_sgl_t; 460 461 /** 462 * @brief HW callback type 463 * 464 * Typedef for HW "done" callback. 465 */ 466 typedef int32_t (*ocs_hw_done_t)(struct ocs_hw_io_s *, ocs_remote_node_t *, uint32_t len, int32_t status, uint32_t ext, void *ul_arg); 467 468 typedef union ocs_hw_io_param_u { 469 struct { 470 uint16_t ox_id; 471 uint16_t rx_id; 472 uint8_t payload[12]; /**< big enough for ABTS BA_ACC */ 473 } bls; 474 struct { 475 uint32_t s_id; 476 uint16_t ox_id; 477 uint16_t rx_id; 478 uint8_t payload[12]; /**< big enough for ABTS BA_ACC */ 479 } bls_sid; 480 struct { 481 uint8_t r_ctl; 482 uint8_t type; 483 uint8_t df_ctl; 484 uint8_t timeout; 485 } bcast; 486 struct { 487 uint16_t ox_id; 488 uint8_t timeout; 489 } els; 490 struct { 491 uint32_t s_id; 492 uint16_t ox_id; 493 uint8_t timeout; 494 } els_sid; 495 struct { 496 uint8_t r_ctl; 497 uint8_t type; 498 uint8_t df_ctl; 499 uint8_t timeout; 500 } fc_ct; 501 struct { 502 uint8_t r_ctl; 503 uint8_t type; 504 uint8_t df_ctl; 505 uint8_t timeout; 506 uint16_t ox_id; 507 } fc_ct_rsp; 508 struct { 509 uint32_t offset; 510 uint16_t ox_id; 511 uint16_t flags; 512 uint8_t cs_ctl; 513 ocs_hw_dif_oper_e dif_oper; 514 ocs_hw_dif_blk_size_e blk_size; 515 uint8_t timeout; 516 uint32_t app_id; 517 } fcp_tgt; 518 struct { 519 ocs_dma_t *cmnd; 520 ocs_dma_t *rsp; 521 ocs_hw_dif_oper_e dif_oper; 522 ocs_hw_dif_blk_size_e blk_size; 523 uint32_t cmnd_size; 524 uint16_t flags; 525 uint8_t timeout; 526 uint32_t first_burst; 527 } fcp_ini; 528 } ocs_hw_io_param_t; 529 530 /** 531 * @brief WQ steering mode 532 */ 533 typedef enum { 534 OCS_HW_WQ_STEERING_CLASS, 535 OCS_HW_WQ_STEERING_REQUEST, 536 OCS_HW_WQ_STEERING_CPU, 537 } ocs_hw_wq_steering_e; 538 539 /** 540 * @brief HW wqe object 541 */ 542 typedef struct { 543 uint32_t abort_wqe_submit_needed:1, /**< set if abort wqe needs to be submitted */ 544 send_abts:1, /**< set to 1 to have hardware to automatically send ABTS */ 545 auto_xfer_rdy_dnrx:1, /**< TRUE if DNRX was set on this IO */ 546 :29; 547 uint32_t id; 548 uint32_t abort_reqtag; 549 ocs_list_link_t link; 550 uint8_t *wqebuf; /**< work queue entry buffer */ 551 } ocs_hw_wqe_t; 552 553 /** 554 * @brief HW IO object. 555 * 556 * Stores the per-IO information necessary for both the lower (SLI) and upper 557 * layers (ocs). 558 */ 559 struct ocs_hw_io_s { 560 /* Owned by HW */ 561 ocs_list_link_t link; /**< used for busy, wait_free, free lists */ 562 ocs_list_link_t wqe_link; /**< used for timed_wqe list */ 563 ocs_list_link_t dnrx_link; /**< used for io posted dnrx list */ 564 ocs_hw_io_state_e state; /**< state of IO: free, busy, wait_free */ 565 ocs_hw_wqe_t wqe; /**< Work queue object, with link for pending */ 566 ocs_lock_t axr_lock; /**< Lock to synchronize TRSP and AXT Data/Cmd Cqes */ 567 ocs_hw_t *hw; /**< pointer back to hardware context */ 568 ocs_remote_node_t *rnode; 569 struct ocs_hw_auto_xfer_rdy_buffer_s *axr_buf; 570 ocs_dma_t xfer_rdy; 571 uint16_t type; 572 uint32_t port_owned_abort_count; /**< IO abort count */ 573 hw_wq_t *wq; /**< WQ assigned to the exchange */ 574 uint32_t xbusy; /**< Exchange is active in FW */ 575 ocs_hw_done_t done; /**< Function called on IO completion */ 576 void *arg; /**< argument passed to "IO done" callback */ 577 ocs_hw_done_t abort_done; /**< Function called on abort completion */ 578 void *abort_arg; /**< argument passed to "abort done" callback */ 579 ocs_ref_t ref; /**< refcount object */ 580 size_t length; /**< needed for bug O127585: length of IO */ 581 uint8_t tgt_wqe_timeout; /**< timeout value for target WQEs */ 582 uint64_t submit_ticks; /**< timestamp when current WQE was submitted */ 583 584 uint32_t status_saved:1, /**< if TRUE, latched status should be returned */ 585 abort_in_progress:1, /**< if TRUE, abort is in progress */ 586 quarantine:1, /**< set if IO to be quarantined */ 587 quarantine_first_phase:1, /**< set if first phase of IO */ 588 is_port_owned:1, /**< set if POST_XRI was used to send XRI to th chip */ 589 auto_xfer_rdy_dnrx:1, /**< TRUE if DNRX was set on this IO */ 590 :26; 591 uint32_t saved_status; /**< latched status */ 592 uint32_t saved_len; /**< latched length */ 593 uint32_t saved_ext; /**< latched extended status */ 594 595 hw_eq_t *eq; /**< EQ that this HIO came up on */ 596 ocs_hw_wq_steering_e wq_steering; /**< WQ steering mode request */ 597 uint8_t wq_class; /**< WQ class if steering mode is Class */ 598 599 /* Owned by SLI layer */ 600 uint16_t reqtag; /**< request tag for this HW IO */ 601 uint32_t abort_reqtag; /**< request tag for an abort of this HW IO (note: this is a 32 bit value 602 to allow us to use UINT32_MAX as an uninitialized value) */ 603 uint32_t indicator; /**< XRI */ 604 ocs_dma_t def_sgl; /**< default scatter gather list */ 605 uint32_t def_sgl_count; /**< count of SGEs in default SGL */ 606 ocs_dma_t *sgl; /**< pointer to current active SGL */ 607 uint32_t sgl_count; /**< count of SGEs in io->sgl */ 608 uint32_t first_data_sge; /**< index of first data SGE */ 609 ocs_dma_t *ovfl_sgl; /**< overflow SGL */ 610 uint32_t ovfl_sgl_count; /**< count of SGEs in default SGL */ 611 sli4_lsp_sge_t *ovfl_lsp; /**< pointer to overflow segment length */ 612 ocs_hw_io_t *ovfl_io; /**< Used for SGL chaining on skyhawk */ 613 uint32_t n_sge; /**< number of active SGEs */ 614 uint32_t sge_offset; 615 616 /* BZ 161832 Workaround: */ 617 struct ocs_hw_io_s *sec_hio; /**< Secondary HW IO context */ 618 ocs_hw_io_param_t sec_iparam; /**< Secondary HW IO context saved iparam */ 619 uint32_t sec_len; /**< Secondary HW IO context saved len */ 620 621 /* Owned by upper layer */ 622 void *ul_io; /**< where upper layer can store reference to its IO */ 623 }; 624 625 typedef enum { 626 OCS_HW_PORT_INIT, 627 OCS_HW_PORT_SHUTDOWN, 628 OCS_HW_PORT_SET_LINK_CONFIG, 629 } ocs_hw_port_e; 630 631 /** 632 * @brief Fabric/Domain events 633 */ 634 typedef enum { 635 OCS_HW_DOMAIN_ALLOC_OK, /**< domain successfully allocated */ 636 OCS_HW_DOMAIN_ALLOC_FAIL, /**< domain allocation failed */ 637 OCS_HW_DOMAIN_ATTACH_OK, /**< successfully attached to domain */ 638 OCS_HW_DOMAIN_ATTACH_FAIL, /**< domain attach failed */ 639 OCS_HW_DOMAIN_FREE_OK, /**< successfully freed domain */ 640 OCS_HW_DOMAIN_FREE_FAIL, /**< domain free failed */ 641 OCS_HW_DOMAIN_LOST, /**< previously discovered domain no longer available */ 642 OCS_HW_DOMAIN_FOUND, /**< new domain discovered */ 643 OCS_HW_DOMAIN_CHANGED, /**< previously discovered domain properties have changed */ 644 } ocs_hw_domain_event_e; 645 646 typedef enum { 647 OCS_HW_PORT_ALLOC_OK, /**< port successfully allocated */ 648 OCS_HW_PORT_ALLOC_FAIL, /**< port allocation failed */ 649 OCS_HW_PORT_ATTACH_OK, /**< successfully attached to port */ 650 OCS_HW_PORT_ATTACH_FAIL, /**< port attach failed */ 651 OCS_HW_PORT_FREE_OK, /**< successfully freed port */ 652 OCS_HW_PORT_FREE_FAIL, /**< port free failed */ 653 } ocs_hw_port_event_e; 654 655 typedef enum { 656 OCS_HW_NODE_ATTACH_OK, 657 OCS_HW_NODE_ATTACH_FAIL, 658 OCS_HW_NODE_FREE_OK, 659 OCS_HW_NODE_FREE_FAIL, 660 OCS_HW_NODE_FREE_ALL_OK, 661 OCS_HW_NODE_FREE_ALL_FAIL, 662 } ocs_hw_remote_node_event_e; 663 664 typedef enum { 665 OCS_HW_CB_DOMAIN, 666 OCS_HW_CB_PORT, 667 OCS_HW_CB_REMOTE_NODE, 668 OCS_HW_CB_UNSOLICITED, 669 OCS_HW_CB_BOUNCE, 670 OCS_HW_CB_MAX, /**< must be last */ 671 } ocs_hw_callback_e; 672 673 /** 674 * @brief HW unsolicited callback status 675 */ 676 typedef enum { 677 OCS_HW_UNSOL_SUCCESS, 678 OCS_HW_UNSOL_ERROR, 679 OCS_HW_UNSOL_ABTS_RCVD, 680 OCS_HW_UNSOL_MAX, /**< must be last */ 681 } ocs_hw_unsol_status_e; 682 683 /** 684 * @brief Node group rpi reference 685 */ 686 typedef struct { 687 ocs_atomic_t rpi_count; 688 ocs_atomic_t rpi_attached; 689 } ocs_hw_rpi_ref_t; 690 691 /** 692 * @brief HW link stat types 693 */ 694 typedef enum { 695 OCS_HW_LINK_STAT_LINK_FAILURE_COUNT, 696 OCS_HW_LINK_STAT_LOSS_OF_SYNC_COUNT, 697 OCS_HW_LINK_STAT_LOSS_OF_SIGNAL_COUNT, 698 OCS_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT, 699 OCS_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT, 700 OCS_HW_LINK_STAT_CRC_COUNT, 701 OCS_HW_LINK_STAT_PRIMITIVE_SEQ_TIMEOUT_COUNT, 702 OCS_HW_LINK_STAT_ELASTIC_BUFFER_OVERRUN_COUNT, 703 OCS_HW_LINK_STAT_ARB_TIMEOUT_COUNT, 704 OCS_HW_LINK_STAT_ADVERTISED_RCV_B2B_CREDIT, 705 OCS_HW_LINK_STAT_CURR_RCV_B2B_CREDIT, 706 OCS_HW_LINK_STAT_ADVERTISED_XMIT_B2B_CREDIT, 707 OCS_HW_LINK_STAT_CURR_XMIT_B2B_CREDIT, 708 OCS_HW_LINK_STAT_RCV_EOFA_COUNT, 709 OCS_HW_LINK_STAT_RCV_EOFDTI_COUNT, 710 OCS_HW_LINK_STAT_RCV_EOFNI_COUNT, 711 OCS_HW_LINK_STAT_RCV_SOFF_COUNT, 712 OCS_HW_LINK_STAT_RCV_DROPPED_NO_AER_COUNT, 713 OCS_HW_LINK_STAT_RCV_DROPPED_NO_RPI_COUNT, 714 OCS_HW_LINK_STAT_RCV_DROPPED_NO_XRI_COUNT, 715 OCS_HW_LINK_STAT_MAX, /**< must be last */ 716 } ocs_hw_link_stat_e; 717 718 typedef enum { 719 OCS_HW_HOST_STAT_TX_KBYTE_COUNT, 720 OCS_HW_HOST_STAT_RX_KBYTE_COUNT, 721 OCS_HW_HOST_STAT_TX_FRAME_COUNT, 722 OCS_HW_HOST_STAT_RX_FRAME_COUNT, 723 OCS_HW_HOST_STAT_TX_SEQ_COUNT, 724 OCS_HW_HOST_STAT_RX_SEQ_COUNT, 725 OCS_HW_HOST_STAT_TOTAL_EXCH_ORIG, 726 OCS_HW_HOST_STAT_TOTAL_EXCH_RESP, 727 OCS_HW_HOSY_STAT_RX_P_BSY_COUNT, 728 OCS_HW_HOST_STAT_RX_F_BSY_COUNT, 729 OCS_HW_HOST_STAT_DROP_FRM_DUE_TO_NO_RQ_BUF_COUNT, 730 OCS_HW_HOST_STAT_EMPTY_RQ_TIMEOUT_COUNT, 731 OCS_HW_HOST_STAT_DROP_FRM_DUE_TO_NO_XRI_COUNT, 732 OCS_HW_HOST_STAT_EMPTY_XRI_POOL_COUNT, 733 OCS_HW_HOST_STAT_MAX /* MUST BE LAST */ 734 } ocs_hw_host_stat_e; 735 736 typedef enum { 737 OCS_HW_STATE_UNINITIALIZED, /* power-on, no allocations, no initializations */ 738 OCS_HW_STATE_QUEUES_ALLOCATED, /* chip is reset, allocations are complete (queues not registered) */ 739 OCS_HW_STATE_ACTIVE, /* chip is up an running */ 740 OCS_HW_STATE_RESET_IN_PROGRESS, /* chip is being reset */ 741 OCS_HW_STATE_TEARDOWN_IN_PROGRESS, /* teardown has been started */ 742 } ocs_hw_state_e; 743 744 /** 745 * @brief Defines a general FC sequence object, consisting of a header, payload buffers 746 * and a HW IO in the case of port owned XRI 747 */ 748 typedef struct { 749 ocs_hw_t *hw; /**< HW that owns this sequence */ 750 /* sequence information */ 751 uint8_t fcfi; /**< FCFI associated with sequence */ 752 uint8_t auto_xrdy; /**< If auto XFER_RDY was generated */ 753 uint8_t out_of_xris; /**< If IO would have been assisted if XRIs were available */ 754 ocs_hw_rq_buffer_t *header; 755 ocs_hw_rq_buffer_t *payload; /**< received frame payload buffer */ 756 757 /* other "state" information from the SRB (sequence coalescing) */ 758 ocs_hw_unsol_status_e status; 759 uint32_t xri; /**< XRI associated with sequence; sequence coalescing only */ 760 ocs_hw_io_t *hio; /**< HW IO */ 761 762 ocs_list_link_t link; 763 void *hw_priv; /**< HW private context */ 764 } ocs_hw_sequence_t; 765 766 /** 767 * @brief Structure to track optimized write buffers posted to chip owned XRIs. 768 * 769 * Note: The rqindex will be set the following "fake" indexes. This will be used 770 * when the buffer is returned via ocs_seq_free() to make the buffer available 771 * for re-use on another XRI. 772 * 773 * The dma->alloc pointer on the dummy header will be used to get back to this structure when the buffer is freed. 774 * 775 * More of these object may be allocated on the fly if more XRIs are pushed to the chip. 776 */ 777 #define OCS_HW_RQ_INDEX_DUMMY_HDR 0xFF00 778 #define OCS_HW_RQ_INDEX_DUMMY_DATA 0xFF01 779 typedef struct ocs_hw_auto_xfer_rdy_buffer_s { 780 fc_header_t hdr; /**< used to build a dummy data header for unsolicited processing */ 781 ocs_hw_rq_buffer_t header; /**< Points to the dummy data header */ 782 ocs_hw_rq_buffer_t payload; /**< received frame payload buffer */ 783 ocs_hw_sequence_t seq; /**< sequence for passing the buffers */ 784 uint8_t data_cqe; 785 uint8_t cmd_cqe; 786 787 /* fields saved from the command header that are needed when the data arrives */ 788 uint8_t fcfi; 789 790 /* To handle outof order completions save AXR cmd and data cqes */ 791 uint8_t call_axr_cmd; 792 uint8_t call_axr_data; 793 ocs_hw_sequence_t *cmd_seq; 794 } ocs_hw_auto_xfer_rdy_buffer_t; 795 796 /** 797 * @brief Node group rpi reference 798 */ 799 typedef struct { 800 uint8_t overflow; 801 uint32_t counter; 802 } ocs_hw_link_stat_counts_t; 803 804 /** 805 * @brief HW object describing fc host stats 806 */ 807 typedef struct { 808 uint32_t counter; 809 } ocs_hw_host_stat_counts_t; 810 811 #define TID_HASH_BITS 8 812 #define TID_HASH_LEN (1U << TID_HASH_BITS) 813 814 typedef struct ocs_hw_iopt_s { 815 char name[32]; 816 uint32_t instance_index; 817 ocs_thread_t iopt_thread; 818 ocs_cbuf_t *iopt_free_queue; /* multiple reader, multiple writer */ 819 ocs_cbuf_t *iopt_work_queue; 820 ocs_array_t *iopt_cmd_array; 821 } ocs_hw_iopt_t; 822 823 typedef enum { 824 HW_CQ_HANDLER_LOCAL, 825 HW_CQ_HANDLER_THREAD, 826 } hw_cq_handler_e; 827 828 #include "ocs_hw_queues.h" 829 830 /** 831 * @brief Stucture used for the hash lookup of queue IDs 832 */ 833 typedef struct { 834 uint32_t id:16, 835 in_use:1, 836 index:15; 837 } ocs_queue_hash_t; 838 839 /** 840 * @brief Define the fields required to implement the skyhawk DIF quarantine. 841 */ 842 #define OCS_HW_QUARANTINE_QUEUE_DEPTH 4 843 844 typedef struct { 845 uint32_t quarantine_index; 846 ocs_hw_io_t *quarantine_ios[OCS_HW_QUARANTINE_QUEUE_DEPTH]; 847 } ocs_quarantine_info_t; 848 849 /** 850 * @brief Define the WQ callback object 851 */ 852 typedef struct { 853 uint16_t instance_index; /**< use for request tag */ 854 void (*callback)(void *arg, uint8_t *cqe, int32_t status); 855 void *arg; 856 } hw_wq_callback_t; 857 858 typedef struct { 859 uint64_t fwrev; 860 861 /* Control Declarations here ...*/ 862 863 uint8_t retain_tsend_io_length; 864 865 /* Use unregistered RPI */ 866 uint8_t use_unregistered_rpi; 867 uint32_t unregistered_rid; 868 uint32_t unregistered_index; 869 870 uint8_t disable_ar_tgt_dif; /* Disable auto response if target DIF */ 871 uint8_t disable_dump_loc; 872 uint8_t use_dif_quarantine; 873 uint8_t use_dif_sec_xri; 874 875 uint8_t override_fcfi; 876 877 uint8_t fw_version_too_low; 878 879 uint8_t sglc_misreported; 880 881 uint8_t ignore_send_frame; 882 883 } ocs_hw_workaround_t; 884 885 /** 886 * @brief HW object 887 */ 888 struct ocs_hw_s { 889 ocs_os_handle_t os; 890 sli4_t sli; 891 uint16_t ulp_start; 892 uint16_t ulp_max; 893 uint32_t dump_size; 894 ocs_hw_state_e state; 895 uint8_t hw_setup_called; 896 uint8_t sliport_healthcheck; 897 uint16_t watchdog_timeout; 898 ocs_lock_t watchdog_lock; 899 900 /** HW configuration, subject to ocs_hw_set() */ 901 struct { 902 uint32_t n_eq; /**< number of event queues */ 903 uint32_t n_cq; /**< number of completion queues */ 904 uint32_t n_mq; /**< number of mailbox queues */ 905 uint32_t n_rq; /**< number of receive queues */ 906 uint32_t n_wq; /**< number of work queues */ 907 uint32_t n_io; /**< total number of IO objects */ 908 uint32_t n_sgl;/**< length of SGL */ 909 uint32_t speed; /** requested link speed in Mbps */ 910 uint32_t topology; /** requested link topology */ 911 uint32_t rq_default_buffer_size; /** size of the buffers for first burst */ 912 uint32_t auto_xfer_rdy_xri_cnt; /** Initial XRIs to post to chip at initialization */ 913 uint32_t auto_xfer_rdy_size; /** max size IO to use with this feature */ 914 uint8_t auto_xfer_rdy_blk_size_chip; /** block size to use with this feature */ 915 uint8_t esoc; 916 uint16_t dif_seed; /** The seed for the DIF CRC calculation */ 917 uint16_t auto_xfer_rdy_app_tag_value; 918 uint8_t dif_mode; /**< DIF mode to use */ 919 uint8_t i_only_aab; /** Enable initiator-only auto-abort */ 920 uint8_t emulate_tgt_wqe_timeout; /** Enable driver target wqe timeouts */ 921 uint32_t bounce:1; 922 const char *queue_topology; /**< Queue topology string */ 923 uint8_t auto_xfer_rdy_t10_enable; /** Enable t10 PI for auto xfer ready */ 924 uint8_t auto_xfer_rdy_p_type; /** p_type for auto xfer ready */ 925 uint8_t auto_xfer_rdy_ref_tag_is_lba; 926 uint8_t auto_xfer_rdy_app_tag_valid; 927 uint8_t rq_selection_policy; /** MRQ RQ selection policy */ 928 uint8_t rr_quanta; /** RQ quanta if rq_selection_policy == 2 */ 929 uint32_t filter_def[SLI4_CMD_REG_FCFI_NUM_RQ_CFG]; 930 } config; 931 932 /* calculated queue sizes for each type */ 933 uint32_t num_qentries[SLI_QTYPE_MAX]; 934 935 /* Storage for SLI queue objects */ 936 sli4_queue_t wq[OCS_HW_MAX_NUM_WQ]; 937 sli4_queue_t rq[OCS_HW_MAX_NUM_RQ]; 938 uint16_t hw_rq_lookup[OCS_HW_MAX_NUM_RQ]; 939 sli4_queue_t mq[OCS_HW_MAX_NUM_MQ]; 940 sli4_queue_t cq[OCS_HW_MAX_NUM_CQ]; 941 sli4_queue_t eq[OCS_HW_MAX_NUM_EQ]; 942 943 /* HW queue */ 944 uint32_t eq_count; 945 uint32_t cq_count; 946 uint32_t mq_count; 947 uint32_t wq_count; 948 uint32_t rq_count; /**< count of SLI RQs */ 949 ocs_list_t eq_list; 950 951 ocs_queue_hash_t cq_hash[OCS_HW_Q_HASH_SIZE]; 952 ocs_queue_hash_t rq_hash[OCS_HW_Q_HASH_SIZE]; 953 ocs_queue_hash_t wq_hash[OCS_HW_Q_HASH_SIZE]; 954 955 /* Storage for HW queue objects */ 956 hw_wq_t *hw_wq[OCS_HW_MAX_NUM_WQ]; 957 hw_rq_t *hw_rq[OCS_HW_MAX_NUM_RQ]; 958 hw_mq_t *hw_mq[OCS_HW_MAX_NUM_MQ]; 959 hw_cq_t *hw_cq[OCS_HW_MAX_NUM_CQ]; 960 hw_eq_t *hw_eq[OCS_HW_MAX_NUM_EQ]; 961 uint32_t hw_rq_count; /**< count of hw_rq[] entries */ 962 uint32_t hw_mrq_count; /**< count of multirq RQs */ 963 964 ocs_varray_t *wq_class_array[OCS_HW_MAX_WQ_CLASS]; /**< pool per class WQs */ 965 ocs_varray_t *wq_cpu_array[OCS_HW_MAX_WQ_CPU]; /**< pool per CPU WQs */ 966 967 /* Sequence objects used in incoming frame processing */ 968 ocs_array_t *seq_pool; 969 970 /* Auto XFER RDY Buffers - protect with io_lock */ 971 uint32_t auto_xfer_rdy_enabled:1, /**< TRUE if auto xfer rdy is enabled */ 972 :31; 973 ocs_pool_t *auto_xfer_rdy_buf_pool; /**< pool of ocs_hw_auto_xfer_rdy_buffer_t objects */ 974 975 /** Maintain an ordered, linked list of outstanding HW commands. */ 976 ocs_lock_t cmd_lock; 977 ocs_list_t cmd_head; 978 ocs_list_t cmd_pending; 979 uint32_t cmd_head_count; 980 981 sli4_link_event_t link; 982 ocs_hw_linkcfg_e linkcfg; /**< link configuration setting */ 983 uint32_t eth_license; /**< Ethernet license; to enable FCoE on Lancer */ 984 985 struct { 986 /** 987 * Function + argument used to notify upper layer of domain events. 988 * 989 * The final argument to the callback is a generic data pointer: 990 * - ocs_domain_record_t on OCS_HW_DOMAIN_FOUND 991 * - ocs_domain_t on OCS_HW_DOMAIN_ALLOC_FAIL, OCS_HW_DOMAIN_ALLOC_OK, 992 * OCS_HW_DOMAIN_FREE_FAIL, OCS_HW_DOMAIN_FREE_OK, 993 * OCS_HW_DOMAIN_ATTACH_FAIL, OCS_HW_DOMAIN_ATTACH_OK, and 994 * OCS_HW_DOMAIN_LOST. 995 */ 996 int32_t (*domain)(void *, ocs_hw_domain_event_e, void *); 997 /** 998 * Function + argument used to notify upper layers of port events. 999 * 1000 * The final argument to the callback is a pointer to the effected 1001 * SLI port for all events. 1002 */ 1003 int32_t (*port)(void *, ocs_hw_port_event_e, void *); 1004 /** Function + argument used to announce arrival of unsolicited frames */ 1005 int32_t (*unsolicited)(void *, ocs_hw_sequence_t *); 1006 int32_t (*rnode)(void *, ocs_hw_remote_node_event_e, void *); 1007 int32_t (*bounce)(void (*)(void *arg), void *arg, uint32_t s_id, uint32_t d_id, uint32_t ox_id); 1008 } callback; 1009 struct { 1010 void *domain; 1011 void *port; 1012 void *unsolicited; 1013 void *rnode; 1014 void *bounce; 1015 } args; 1016 1017 /* OCS domain objects index by FCFI */ 1018 int32_t first_domain_idx; /* Workaround for srb->fcfi == 0 */ 1019 ocs_domain_t *domains[SLI4_MAX_FCFI]; 1020 1021 /* Table of FCFI values index by FCF_index */ 1022 uint16_t fcf_index_fcfi[SLI4_MAX_FCF_INDEX]; 1023 1024 uint16_t fcf_indicator; 1025 1026 ocs_hw_io_t **io; /**< pointer array of IO objects */ 1027 uint8_t *wqe_buffs; /**< array of WQE buffs mapped to IO objects */ 1028 1029 ocs_lock_t io_lock; /**< IO lock to synchronize list access */ 1030 ocs_lock_t io_abort_lock; /**< IO lock to synchronize IO aborting */ 1031 ocs_list_t io_inuse; /**< List of IO objects in use */ 1032 ocs_list_t io_timed_wqe; /**< List of IO objects with a timed target WQE */ 1033 ocs_list_t io_wait_free; /**< List of IO objects waiting to be freed */ 1034 ocs_list_t io_free; /**< List of IO objects available for allocation */ 1035 ocs_list_t io_port_owned; /**< List of IO objects posted for chip use */ 1036 ocs_list_t io_port_dnrx; /**< List of IO objects needing auto xfer rdy buffers */ 1037 1038 ocs_dma_t loop_map; 1039 1040 ocs_dma_t xfer_rdy; 1041 1042 ocs_dma_t dump_sges; 1043 1044 ocs_dma_t rnode_mem; 1045 1046 ocs_dma_t domain_dmem; /*domain dma mem for service params */ 1047 ocs_dma_t fcf_dmem; /*dma men for fcf */ 1048 1049 ocs_hw_rpi_ref_t *rpi_ref; 1050 1051 char *hw_war_version; 1052 ocs_hw_workaround_t workaround; 1053 1054 ocs_atomic_t io_alloc_failed_count; 1055 1056 #if defined(OCS_DEBUG_QUEUE_HISTORY) 1057 ocs_hw_q_hist_t q_hist; 1058 #endif 1059 1060 ocs_list_t sec_hio_wait_list; /**< BZ 161832 Workaround: Secondary HW IO context wait list */ 1061 uint32_t sec_hio_wait_count; /**< BZ 161832 Workaround: Count of IOs that were put on the 1062 * Secondary HW IO wait list 1063 */ 1064 1065 #define HW_MAX_TCMD_THREADS 16 1066 ocs_hw_qtop_t *qtop; /**< pointer to queue topology */ 1067 1068 uint32_t tcmd_wq_submit[OCS_HW_MAX_NUM_WQ]; /**< stat: wq sumbit count */ 1069 uint32_t tcmd_wq_complete[OCS_HW_MAX_NUM_WQ]; /**< stat: wq complete count */ 1070 1071 ocs_timer_t wqe_timer; /**< Timer to periodically check for WQE timeouts */ 1072 ocs_timer_t watchdog_timer; /**< Timer for heartbeat */ 1073 bool expiration_logged; 1074 uint32_t in_active_wqe_timer:1, /**< TRUE if currently in active wqe timer handler */ 1075 active_wqe_timer_shutdown:1, /** TRUE if wqe timer is to be shutdown */ 1076 :30; 1077 1078 ocs_list_t iopc_list; /**< list of IO processing contexts */ 1079 ocs_lock_t iopc_list_lock; /**< lock for iopc_list */ 1080 1081 ocs_pool_t *wq_reqtag_pool; /**< pool of hw_wq_callback_t objects */ 1082 1083 ocs_atomic_t send_frame_seq_id; /**< send frame sequence ID */ 1084 }; 1085 1086 typedef enum { 1087 OCS_HW_IO_INUSE_COUNT, 1088 OCS_HW_IO_FREE_COUNT, 1089 OCS_HW_IO_WAIT_FREE_COUNT, 1090 OCS_HW_IO_PORT_OWNED_COUNT, 1091 OCS_HW_IO_N_TOTAL_IO_COUNT, 1092 } ocs_hw_io_count_type_e; 1093 1094 typedef void (*tcmd_cq_handler)(ocs_hw_t *hw, uint32_t cq_idx, void *cq_handler_arg); 1095 1096 /* 1097 * HW queue data structures 1098 */ 1099 1100 struct hw_eq_s { 1101 ocs_list_link_t link; /**< must be first */ 1102 sli4_qtype_e type; /**< must be second */ 1103 uint32_t instance; 1104 uint32_t entry_count; 1105 uint32_t entry_size; 1106 ocs_hw_t *hw; 1107 sli4_queue_t *queue; 1108 ocs_list_t cq_list; 1109 #if OCS_STAT_ENABLE 1110 uint32_t use_count; 1111 #endif 1112 ocs_varray_t *wq_array; /*<< array of WQs */ 1113 }; 1114 1115 struct hw_cq_s { 1116 ocs_list_link_t link; /*<< must be first */ 1117 sli4_qtype_e type; /**< must be second */ 1118 uint32_t instance; /*<< CQ instance (cq_idx) */ 1119 uint32_t entry_count; /*<< Number of entries */ 1120 uint32_t entry_size; /*<< entry size */ 1121 hw_eq_t *eq; /*<< parent EQ */ 1122 sli4_queue_t *queue; /**< pointer to SLI4 queue */ 1123 ocs_list_t q_list; /**< list of children queues */ 1124 1125 #if OCS_STAT_ENABLE 1126 uint32_t use_count; 1127 #endif 1128 }; 1129 1130 typedef struct { 1131 ocs_list_link_t link; /*<< must be first */ 1132 sli4_qtype_e type; /*<< must be second */ 1133 } hw_q_t; 1134 1135 struct hw_mq_s { 1136 ocs_list_link_t link; /*<< must be first */ 1137 sli4_qtype_e type; /*<< must be second */ 1138 uint32_t instance; 1139 1140 uint32_t entry_count; 1141 uint32_t entry_size; 1142 hw_cq_t *cq; 1143 sli4_queue_t *queue; 1144 1145 #if OCS_STAT_ENABLE 1146 uint32_t use_count; 1147 #endif 1148 }; 1149 1150 struct hw_wq_s { 1151 ocs_list_link_t link; /*<< must be first */ 1152 sli4_qtype_e type; /*<< must be second */ 1153 uint32_t instance; 1154 ocs_hw_t *hw; 1155 1156 uint32_t entry_count; 1157 uint32_t entry_size; 1158 hw_cq_t *cq; 1159 sli4_queue_t *queue; 1160 uint32_t class; 1161 uint8_t ulp; 1162 1163 /* WQ consumed */ 1164 uint32_t wqec_set_count; /*<< how often IOs are submitted with wqce set */ 1165 uint32_t wqec_count; /*<< current wqce counter */ 1166 uint32_t free_count; /*<< free count */ 1167 uint32_t total_submit_count; /*<< total submit count */ 1168 ocs_list_t pending_list; /*<< list of IOs pending for this WQ */ 1169 1170 /* 1171 * ---Skyhawk only --- 1172 * BZ 160124 - Driver must quarantine XRIs for target writes and 1173 * initiator read when using DIF separates. Throw them on a 1174 * queue until another 4 similar requests are completed to ensure they 1175 * are flushed from the internal chip cache before being re-used. 1176 * The must be a separate queue per CQ because the actual chip completion 1177 * order cannot be determined. Since each WQ has a separate CQ, use the wq 1178 * associated with the IO. 1179 * 1180 * Note: Protected by queue->lock 1181 */ 1182 ocs_quarantine_info_t quarantine_info; 1183 1184 /* 1185 * HW IO allocated for use with Send Frame 1186 */ 1187 ocs_hw_io_t *send_frame_io; 1188 1189 /* Stats */ 1190 #if OCS_STAT_ENABLE 1191 uint32_t use_count; /*<< use count */ 1192 uint32_t wq_pending_count; /*<< count of HW IOs that were queued on the WQ pending list */ 1193 #endif 1194 }; 1195 1196 struct hw_rq_s { 1197 ocs_list_link_t link; /*<< must be first */ 1198 sli4_qtype_e type; /*<< must be second */ 1199 uint32_t instance; 1200 1201 uint32_t entry_count; 1202 uint32_t hdr_entry_size; 1203 uint32_t first_burst_entry_size; 1204 uint32_t data_entry_size; 1205 uint8_t ulp; 1206 bool is_mrq; 1207 uint32_t base_mrq_id; 1208 1209 hw_cq_t *cq; 1210 1211 uint8_t filter_mask; /* Filter mask value */ 1212 sli4_queue_t *hdr; 1213 sli4_queue_t *first_burst; 1214 sli4_queue_t *data; 1215 1216 ocs_hw_rq_buffer_t *hdr_buf; 1217 ocs_hw_rq_buffer_t *fb_buf; 1218 ocs_hw_rq_buffer_t *payload_buf; 1219 1220 ocs_hw_sequence_t **rq_tracker; /* RQ tracker for this RQ */ 1221 #if OCS_STAT_ENABLE 1222 uint32_t use_count; 1223 uint32_t hdr_use_count; 1224 uint32_t fb_use_count; 1225 uint32_t payload_use_count; 1226 #endif 1227 }; 1228 1229 typedef struct ocs_hw_global_s { 1230 const char *queue_topology_string; /**< queue topology string */ 1231 } ocs_hw_global_t; 1232 extern ocs_hw_global_t hw_global; 1233 1234 extern hw_eq_t *hw_new_eq(ocs_hw_t *hw, uint32_t entry_count); 1235 extern hw_cq_t *hw_new_cq(hw_eq_t *eq, uint32_t entry_count); 1236 extern uint32_t hw_new_cq_set(hw_eq_t *eqs[], hw_cq_t *cqs[], uint32_t num_cqs, uint32_t entry_count); 1237 extern hw_mq_t *hw_new_mq(hw_cq_t *cq, uint32_t entry_count); 1238 extern hw_wq_t *hw_new_wq(hw_cq_t *cq, uint32_t entry_count, uint32_t class, uint32_t ulp); 1239 extern hw_rq_t *hw_new_rq(hw_cq_t *cq, uint32_t entry_count, uint32_t ulp); 1240 extern uint32_t hw_new_rq_set(hw_cq_t *cqs[], hw_rq_t *rqs[], uint32_t num_rq_pairs, uint32_t entry_count, uint32_t ulp); 1241 extern void hw_del_eq(hw_eq_t *eq); 1242 extern void hw_del_cq(hw_cq_t *cq); 1243 extern void hw_del_mq(hw_mq_t *mq); 1244 extern void hw_del_wq(hw_wq_t *wq); 1245 extern void hw_del_rq(hw_rq_t *rq); 1246 extern void hw_queue_dump(ocs_hw_t *hw); 1247 extern void hw_queue_teardown(ocs_hw_t *hw); 1248 extern int32_t hw_route_rqe(ocs_hw_t *hw, ocs_hw_sequence_t *seq); 1249 extern int32_t ocs_hw_queue_hash_find(ocs_queue_hash_t *, uint16_t); 1250 extern ocs_hw_rtn_e ocs_hw_setup(ocs_hw_t *, ocs_os_handle_t, sli4_port_type_e); 1251 extern ocs_hw_rtn_e ocs_hw_init(ocs_hw_t *); 1252 extern ocs_hw_rtn_e ocs_hw_teardown(ocs_hw_t *); 1253 extern ocs_hw_rtn_e ocs_hw_reset(ocs_hw_t *, ocs_hw_reset_e); 1254 extern int32_t ocs_hw_get_num_eq(ocs_hw_t *); 1255 extern ocs_hw_rtn_e ocs_hw_get(ocs_hw_t *, ocs_hw_property_e, uint32_t *); 1256 extern void *ocs_hw_get_ptr(ocs_hw_t *, ocs_hw_property_e); 1257 extern ocs_hw_rtn_e ocs_hw_set(ocs_hw_t *, ocs_hw_property_e, uint32_t); 1258 extern ocs_hw_rtn_e ocs_hw_set_ptr(ocs_hw_t *, ocs_hw_property_e, void*); 1259 extern int32_t ocs_hw_event_check(ocs_hw_t *, uint32_t); 1260 extern int32_t ocs_hw_process(ocs_hw_t *, uint32_t, uint32_t); 1261 extern ocs_hw_rtn_e ocs_hw_command(ocs_hw_t *, uint8_t *, uint32_t, void *, void *); 1262 extern ocs_hw_rtn_e ocs_hw_callback(ocs_hw_t *, ocs_hw_callback_e, void *, void *); 1263 extern ocs_hw_rtn_e ocs_hw_port_alloc(ocs_hw_t *, ocs_sli_port_t *, ocs_domain_t *, uint8_t *); 1264 extern ocs_hw_rtn_e ocs_hw_port_attach(ocs_hw_t *, ocs_sli_port_t *, uint32_t); 1265 typedef void (*ocs_hw_port_control_cb_t)(int32_t status, uintptr_t value, void *arg); 1266 extern ocs_hw_rtn_e ocs_hw_port_control(ocs_hw_t *, ocs_hw_port_e, uintptr_t, ocs_hw_port_control_cb_t, void *); 1267 extern ocs_hw_rtn_e ocs_hw_port_free(ocs_hw_t *, ocs_sli_port_t *); 1268 extern ocs_hw_rtn_e ocs_hw_domain_alloc(ocs_hw_t *, ocs_domain_t *, uint32_t, uint32_t); 1269 extern ocs_hw_rtn_e ocs_hw_domain_attach(ocs_hw_t *, ocs_domain_t *, uint32_t); 1270 extern ocs_hw_rtn_e ocs_hw_domain_free(ocs_hw_t *, ocs_domain_t *); 1271 extern ocs_hw_rtn_e ocs_hw_domain_force_free(ocs_hw_t *, ocs_domain_t *); 1272 extern ocs_domain_t * ocs_hw_domain_get(ocs_hw_t *, uint16_t); 1273 extern ocs_hw_rtn_e ocs_hw_node_alloc(ocs_hw_t *, ocs_remote_node_t *, uint32_t, ocs_sli_port_t *); 1274 extern ocs_hw_rtn_e ocs_hw_node_free_all(ocs_hw_t *); 1275 extern ocs_hw_rtn_e ocs_hw_node_attach(ocs_hw_t *, ocs_remote_node_t *, ocs_dma_t *); 1276 extern ocs_hw_rtn_e ocs_hw_node_detach(ocs_hw_t *, ocs_remote_node_t *); 1277 extern ocs_hw_rtn_e ocs_hw_node_free_resources(ocs_hw_t *, ocs_remote_node_t *); 1278 extern ocs_hw_rtn_e ocs_hw_node_group_alloc(ocs_hw_t *, ocs_remote_node_group_t *); 1279 extern ocs_hw_rtn_e ocs_hw_node_group_attach(ocs_hw_t *, ocs_remote_node_group_t *, ocs_remote_node_t *); 1280 extern ocs_hw_rtn_e ocs_hw_node_group_free(ocs_hw_t *, ocs_remote_node_group_t *); 1281 extern ocs_hw_io_t *ocs_hw_io_alloc(ocs_hw_t *); 1282 extern ocs_hw_io_t *ocs_hw_io_activate_port_owned(ocs_hw_t *, ocs_hw_io_t *); 1283 extern int32_t ocs_hw_io_free(ocs_hw_t *, ocs_hw_io_t *); 1284 extern uint8_t ocs_hw_io_inuse(ocs_hw_t *hw, ocs_hw_io_t *io); 1285 typedef int32_t (*ocs_hw_srrs_cb_t)(ocs_hw_io_t *io, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg); 1286 extern ocs_hw_rtn_e ocs_hw_srrs_send(ocs_hw_t *, ocs_hw_io_type_e, ocs_hw_io_t *, ocs_dma_t *, uint32_t, ocs_dma_t *, ocs_remote_node_t *, ocs_hw_io_param_t *, ocs_hw_srrs_cb_t, void *); 1287 extern ocs_hw_rtn_e ocs_hw_io_send(ocs_hw_t *, ocs_hw_io_type_e, ocs_hw_io_t *, uint32_t, ocs_hw_io_param_t *, ocs_remote_node_t *, void *, void *); 1288 extern ocs_hw_rtn_e _ocs_hw_io_send(ocs_hw_t *hw, ocs_hw_io_type_e type, ocs_hw_io_t *io, 1289 uint32_t len, ocs_hw_io_param_t *iparam, ocs_remote_node_t *rnode, 1290 void *cb, void *arg); 1291 extern ocs_hw_rtn_e ocs_hw_io_register_sgl(ocs_hw_t *, ocs_hw_io_t *, ocs_dma_t *, uint32_t); 1292 extern ocs_hw_rtn_e ocs_hw_io_init_sges(ocs_hw_t *hw, ocs_hw_io_t *io, ocs_hw_io_type_e type); 1293 extern ocs_hw_rtn_e ocs_hw_io_add_seed_sge(ocs_hw_t *hw, ocs_hw_io_t *io, ocs_hw_dif_info_t *dif_info); 1294 extern ocs_hw_rtn_e ocs_hw_io_add_sge(ocs_hw_t *, ocs_hw_io_t *, uintptr_t, uint32_t); 1295 extern ocs_hw_rtn_e ocs_hw_io_add_dif_sge(ocs_hw_t *hw, ocs_hw_io_t *io, uintptr_t addr); 1296 extern ocs_hw_rtn_e ocs_hw_io_abort(ocs_hw_t *, ocs_hw_io_t *, uint32_t, void *, void *); 1297 extern int32_t ocs_hw_io_get_xid(ocs_hw_t *, ocs_hw_io_t *); 1298 extern uint32_t ocs_hw_io_get_count(ocs_hw_t *, ocs_hw_io_count_type_e); 1299 extern uint32_t ocs_hw_get_rqes_produced_count(ocs_hw_t *hw); 1300 1301 typedef void (*ocs_hw_fw_cb_t)(int32_t status, uint32_t bytes_written, uint32_t change_status, void *arg); 1302 extern ocs_hw_rtn_e ocs_hw_firmware_write(ocs_hw_t *, ocs_dma_t *, uint32_t, uint32_t, int, ocs_hw_fw_cb_t, void*); 1303 1304 /* Function for retrieving SFP data */ 1305 typedef void (*ocs_hw_sfp_cb_t)(void *, int32_t, uint32_t, uint32_t *, void *); 1306 extern ocs_hw_rtn_e ocs_hw_get_sfp(ocs_hw_t *, uint16_t, ocs_hw_sfp_cb_t, void *); 1307 1308 /* Function for retrieving temperature data */ 1309 typedef void (*ocs_hw_temp_cb_t)(int32_t status, 1310 uint32_t curr_temp, 1311 uint32_t crit_temp_thrshld, 1312 uint32_t warn_temp_thrshld, 1313 uint32_t norm_temp_thrshld, 1314 uint32_t fan_off_thrshld, 1315 uint32_t fan_on_thrshld, 1316 void *arg); 1317 extern ocs_hw_rtn_e ocs_hw_get_temperature(ocs_hw_t *, ocs_hw_temp_cb_t, void*); 1318 1319 /* Function for retrieving link statistics */ 1320 typedef void (*ocs_hw_link_stat_cb_t)(int32_t status, 1321 uint32_t num_counters, 1322 ocs_hw_link_stat_counts_t *counters, 1323 void *arg); 1324 extern ocs_hw_rtn_e ocs_hw_get_link_stats(ocs_hw_t *, 1325 uint8_t req_ext_counters, 1326 uint8_t clear_overflow_flags, 1327 uint8_t clear_all_counters, 1328 ocs_hw_link_stat_cb_t, void*); 1329 /* Function for retrieving host statistics */ 1330 typedef void (*ocs_hw_host_stat_cb_t)(int32_t status, 1331 uint32_t num_counters, 1332 ocs_hw_host_stat_counts_t *counters, 1333 void *arg); 1334 extern ocs_hw_rtn_e ocs_hw_get_host_stats(ocs_hw_t *hw, uint8_t cc, ocs_hw_host_stat_cb_t, void *arg); 1335 1336 extern ocs_hw_rtn_e ocs_hw_raise_ue(ocs_hw_t *, uint8_t); 1337 typedef void (*ocs_hw_dump_get_cb_t)(int32_t status, uint32_t bytes_read, uint8_t eof, void *arg); 1338 extern ocs_hw_rtn_e ocs_hw_dump_get(ocs_hw_t *, ocs_dma_t *, uint32_t, uint32_t, ocs_hw_dump_get_cb_t, void *); 1339 extern ocs_hw_rtn_e ocs_hw_set_dump_location(ocs_hw_t *, uint32_t, ocs_dma_t *, uint8_t); 1340 1341 typedef void (*ocs_get_port_protocol_cb_t)(int32_t status, ocs_hw_port_protocol_e port_protocol, void *arg); 1342 extern ocs_hw_rtn_e ocs_hw_get_port_protocol(ocs_hw_t *hw, uint32_t pci_func, ocs_get_port_protocol_cb_t mgmt_cb, void* ul_arg); 1343 typedef void (*ocs_set_port_protocol_cb_t)(int32_t status, void *arg); 1344 extern ocs_hw_rtn_e ocs_hw_set_port_protocol(ocs_hw_t *hw, ocs_hw_port_protocol_e profile, 1345 uint32_t pci_func, ocs_set_port_protocol_cb_t mgmt_cb, 1346 void* ul_arg); 1347 1348 typedef void (*ocs_get_profile_list_cb_t)(int32_t status, ocs_hw_profile_list_t*, void *arg); 1349 extern ocs_hw_rtn_e ocs_hw_get_profile_list(ocs_hw_t *hw, ocs_get_profile_list_cb_t mgmt_cb, void *arg); 1350 typedef void (*ocs_get_active_profile_cb_t)(int32_t status, uint32_t active_profile, void *arg); 1351 extern ocs_hw_rtn_e ocs_hw_get_active_profile(ocs_hw_t *hw, ocs_get_active_profile_cb_t mgmt_cb, void *arg); 1352 typedef void (*ocs_set_active_profile_cb_t)(int32_t status, void *arg); 1353 extern ocs_hw_rtn_e ocs_hw_set_active_profile(ocs_hw_t *hw, ocs_set_active_profile_cb_t mgmt_cb, 1354 uint32_t profile_id, void *arg); 1355 typedef void (*ocs_get_nvparms_cb_t)(int32_t status, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa, 1356 uint32_t preferred_d_id, void *arg); 1357 extern ocs_hw_rtn_e ocs_hw_get_nvparms(ocs_hw_t *hw, ocs_get_nvparms_cb_t mgmt_cb, void *arg); 1358 typedef void (*ocs_set_nvparms_cb_t)(int32_t status, void *arg); 1359 extern ocs_hw_rtn_e ocs_hw_set_nvparms(ocs_hw_t *hw, ocs_set_nvparms_cb_t mgmt_cb, uint8_t *wwpn, 1360 uint8_t *wwnn, uint8_t hard_alpa, uint32_t preferred_d_id, void *arg); 1361 extern int32_t ocs_hw_eq_process(ocs_hw_t *hw, hw_eq_t *eq, uint32_t max_isr_time_msec); 1362 extern void ocs_hw_cq_process(ocs_hw_t *hw, hw_cq_t *cq); 1363 extern void ocs_hw_wq_process(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe, int32_t status, uint16_t rid); 1364 extern void ocs_hw_xabt_process(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe, uint16_t rid); 1365 extern int32_t hw_wq_write(hw_wq_t *wq, ocs_hw_wqe_t *wqe); 1366 1367 typedef void (*ocs_hw_dump_clear_cb_t)(int32_t status, void *arg); 1368 extern ocs_hw_rtn_e ocs_hw_dump_clear(ocs_hw_t *, ocs_hw_dump_clear_cb_t, void *); 1369 1370 extern uint8_t ocs_hw_is_io_port_owned(ocs_hw_t *hw, ocs_hw_io_t *io); 1371 1372 extern uint8_t ocs_hw_is_xri_port_owned(ocs_hw_t *hw, uint32_t xri); 1373 extern ocs_hw_io_t * ocs_hw_io_lookup(ocs_hw_t *hw, uint32_t indicator); 1374 extern uint32_t ocs_hw_xri_move_to_port_owned(ocs_hw_t *hw, uint32_t num_xri); 1375 extern ocs_hw_rtn_e ocs_hw_xri_move_to_host_owned(ocs_hw_t *hw, uint8_t num_xri); 1376 extern int32_t ocs_hw_reque_xri(ocs_hw_t *hw, ocs_hw_io_t *io); 1377 ocs_hw_rtn_e ocs_hw_set_persistent_topology(ocs_hw_t *hw, uint32_t topology, uint32_t opts); 1378 extern uint32_t ocs_hw_get_config_persistent_topology(ocs_hw_t *hw); 1379 1380 typedef struct { 1381 /* structure elements used by HW */ 1382 ocs_hw_t *hw; /**> pointer to HW */ 1383 hw_wq_callback_t *wqcb; /**> WQ callback object, request tag */ 1384 ocs_hw_wqe_t wqe; /**> WQE buffer object (may be queued on WQ pending list) */ 1385 void (*callback)(int32_t status, void *arg); /**> final callback function */ 1386 void *arg; /**> final callback argument */ 1387 1388 /* General purpose elements */ 1389 ocs_hw_sequence_t *seq; 1390 ocs_dma_t payload; /**> a payload DMA buffer */ 1391 } ocs_hw_send_frame_context_t; 1392 1393 #define OCS_HW_OBJECT_G5 0xfeaa0001 1394 #define OCS_HW_OBJECT_G6 0xfeaa0003 1395 #define OCS_FILE_TYPE_GROUP 0xf7 1396 #define OCS_FILE_ID_GROUP 0xa2 1397 struct ocs_hw_grp_hdr { 1398 uint32_t size; 1399 uint32_t magic_number; 1400 uint32_t word2; 1401 uint8_t rev_name[128]; 1402 uint8_t date[12]; 1403 uint8_t revision[32]; 1404 }; 1405 1406 ocs_hw_rtn_e 1407 ocs_hw_send_frame(ocs_hw_t *hw, fc_header_le_t *hdr, uint8_t sof, uint8_t eof, ocs_dma_t *payload, 1408 ocs_hw_send_frame_context_t *ctx, 1409 void (*callback)(void *arg, uint8_t *cqe, int32_t status), void *arg); 1410 1411 /* RQ completion handlers for RQ pair mode */ 1412 extern int32_t ocs_hw_rqpair_process_rq(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe); 1413 extern ocs_hw_rtn_e ocs_hw_rqpair_sequence_free(ocs_hw_t *hw, ocs_hw_sequence_t *seq); 1414 extern int32_t ocs_hw_rqpair_process_auto_xfr_rdy_cmd(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe); 1415 extern int32_t ocs_hw_rqpair_process_auto_xfr_rdy_data(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe); 1416 extern ocs_hw_rtn_e ocs_hw_rqpair_init(ocs_hw_t *hw); 1417 extern ocs_hw_rtn_e ocs_hw_rqpair_auto_xfer_rdy_buffer_alloc(ocs_hw_t *hw, uint32_t num_buffers); 1418 extern uint8_t ocs_hw_rqpair_auto_xfer_rdy_buffer_post(ocs_hw_t *hw, ocs_hw_io_t *io, int reuse_buf); 1419 extern ocs_hw_rtn_e ocs_hw_rqpair_auto_xfer_rdy_move_to_port(ocs_hw_t *hw, ocs_hw_io_t *io); 1420 extern void ocs_hw_rqpair_auto_xfer_rdy_move_to_host(ocs_hw_t *hw, ocs_hw_io_t *io); 1421 extern void ocs_hw_rqpair_teardown(ocs_hw_t *hw); 1422 1423 extern ocs_hw_rtn_e ocs_hw_rx_allocate(ocs_hw_t *hw); 1424 extern ocs_hw_rtn_e ocs_hw_rx_post(ocs_hw_t *hw); 1425 extern void ocs_hw_rx_free(ocs_hw_t *hw); 1426 1427 extern void ocs_hw_unsol_process_bounce(void *arg); 1428 1429 typedef int32_t (*ocs_hw_async_cb_t)(ocs_hw_t *hw, int32_t status, uint8_t *mqe, void *arg); 1430 extern int32_t ocs_hw_async_call(ocs_hw_t *hw, ocs_hw_async_cb_t callback, void *arg); 1431 1432 static inline void 1433 ocs_hw_sequence_copy(ocs_hw_sequence_t *dst, ocs_hw_sequence_t *src) 1434 { 1435 /* Copy the src to dst, then zero out the linked list link */ 1436 *dst = *src; 1437 ocs_memset(&dst->link, 0, sizeof(dst->link)); 1438 } 1439 1440 static inline ocs_hw_rtn_e 1441 ocs_hw_sequence_free(ocs_hw_t *hw, ocs_hw_sequence_t *seq) 1442 { 1443 /* Only RQ pair mode is supported */ 1444 return ocs_hw_rqpair_sequence_free(hw, seq); 1445 } 1446 1447 /* HW WQ request tag API */ 1448 extern ocs_hw_rtn_e ocs_hw_reqtag_init(ocs_hw_t *hw); 1449 extern hw_wq_callback_t *ocs_hw_reqtag_alloc(ocs_hw_t *hw, 1450 void (*callback)(void *arg, uint8_t *cqe, int32_t status), void *arg); 1451 extern void ocs_hw_reqtag_free(ocs_hw_t *hw, hw_wq_callback_t *wqcb); 1452 extern hw_wq_callback_t *ocs_hw_reqtag_get_instance(ocs_hw_t *hw, uint32_t instance_index); 1453 extern void ocs_hw_reqtag_reset(ocs_hw_t *hw); 1454 1455 extern uint32_t ocs_hw_dif_blocksize(ocs_hw_dif_info_t *dif_info); 1456 extern int32_t ocs_hw_dif_mem_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem); 1457 extern int32_t ocs_hw_dif_wire_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem); 1458 extern uint32_t ocs_hw_get_def_wwn(ocs_t *ocs, uint32_t chan, uint64_t *wwpn, uint64_t *wwnn); 1459 1460 /* Uncomment to enable CPUTRACE */ 1461 //#define ENABLE_CPUTRACE 1462 #ifdef ENABLE_CPUTRACE 1463 #define CPUTRACE(t) ocs_printf("trace: %-20s %2s %-16s cpu %2d\n", __func__, t, \ 1464 ({ocs_thread_t *self = ocs_thread_self(); self != NULL ? self->name : "unknown";}), ocs_thread_getcpu()); 1465 #else 1466 #define CPUTRACE(...) 1467 #endif 1468 1469 /* Two levels of macro needed due to expansion */ 1470 #define HW_FWREV(a,b,c,d) (((uint64_t)(a) << 48) | ((uint64_t)(b) << 32) | ((uint64_t)(c) << 16) | ((uint64_t)(d))) 1471 #define HW_FWREV_1(x) HW_FWREV(x) 1472 1473 #define OCS_FW_VER_STR2(a,b,c,d) #a "." #b "." #c "." #d 1474 #define OCS_FW_VER_STR(x) OCS_FW_VER_STR2(x) 1475 1476 #define OCS_MIN_FW_VER_LANCER 10,4,255,0 1477 #define OCS_MIN_FW_VER_SKYHAWK 10,4,255,0 1478 1479 extern void ocs_hw_workaround_setup(struct ocs_hw_s *hw); 1480 1481 /** 1482 * @brief Defines the number of the RQ buffers for each RQ 1483 */ 1484 1485 #ifndef OCS_HW_RQ_NUM_HDR 1486 #define OCS_HW_RQ_NUM_HDR 1024 1487 #endif 1488 1489 #ifndef OCS_HW_RQ_NUM_PAYLOAD 1490 #define OCS_HW_RQ_NUM_PAYLOAD 1024 1491 #endif 1492 1493 /** 1494 * @brief Defines the size of the RQ buffers used for each RQ 1495 */ 1496 #ifndef OCS_HW_RQ_SIZE_HDR 1497 #define OCS_HW_RQ_SIZE_HDR 128 1498 #endif 1499 1500 #ifndef OCS_HW_RQ_SIZE_PAYLOAD 1501 #define OCS_HW_RQ_SIZE_PAYLOAD 1024 1502 #endif 1503 1504 /* 1505 * @brief Define the maximum number of multi-receive queues 1506 */ 1507 #ifndef OCS_HW_MAX_MRQS 1508 #define OCS_HW_MAX_MRQS 8 1509 #endif 1510 1511 /* 1512 * @brief Define count of when to set the WQEC bit in a submitted 1513 * WQE, causing a consummed/released completion to be posted. 1514 */ 1515 #ifndef OCS_HW_WQEC_SET_COUNT 1516 #define OCS_HW_WQEC_SET_COUNT 32 1517 #endif 1518 1519 /* 1520 * @brief Send frame timeout in seconds 1521 */ 1522 #ifndef OCS_HW_SEND_FRAME_TIMEOUT 1523 #define OCS_HW_SEND_FRAME_TIMEOUT 10 1524 #endif 1525 1526 /* 1527 * @brief FDT Transfer Hint value, reads greater than this value 1528 * will be segmented to implement fairness. A value of zero disables 1529 * the feature. 1530 */ 1531 #ifndef OCS_HW_FDT_XFER_HINT 1532 #define OCS_HW_FDT_XFER_HINT 8192 1533 #endif 1534 1535 #endif /* !_OCS_HW_H */ 1536