xref: /freebsd/sys/dev/ocs_fc/ocs_hw.h (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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