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