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
45typedef 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 */
58typedef struct hw_eq_s hw_eq_t;
59typedef struct hw_cq_s hw_cq_t;
60typedef struct hw_mq_s hw_mq_t;
61typedef struct hw_wq_s hw_wq_t;
62typedef struct hw_rq_s hw_rq_t;
63typedef struct hw_rq_grp_s hw_rq_grp_t;
64
65/* HW asserts/verify
66 *
67 */
68
69extern void _ocs_hw_assert(const char *cond, const char *filename, int linenum);
70extern 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 */
136enum {
137	OCS_CMD_POLL,	/**< command executes synchronously and busy-waits for completion */
138	OCS_CMD_NOWAIT,	/**< command executes asynchronously. Uses callback */
139};
140
141typedef 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
154typedef enum {
155	OCS_HW_RESET_FUNCTION,
156	OCS_HW_RESET_FIRMWARE,
157	OCS_HW_RESET_MAX
158} ocs_hw_reset_e;
159
160typedef 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
233enum {
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
241enum {
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
252typedef 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 */
263typedef 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 */
272typedef 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 */
280enum {
281	OCS_HW_DIF_MODE_INLINE,
282	OCS_HW_DIF_MODE_SEPARATE,
283};
284
285/**
286 * @brief Defines the type of RQ buffer
287 */
288typedef 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 */
298typedef struct {
299	uint16_t rqindex;
300	ocs_dma_t dma;
301} ocs_hw_rq_buffer_t;
302
303/**
304 * @brief T10 DIF operations.
305 */
306typedef 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 */
326typedef 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 */
339typedef 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
358enum {
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 */
371typedef 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;
396typedef 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
416typedef 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 */
445typedef 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
454typedef 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 */
464typedef 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
466typedef 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 */
531typedef 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 */
540typedef 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 */
557struct 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
623typedef 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 */
632typedef 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
644typedef 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
653typedef 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
662typedef 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 */
674typedef 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 */
684typedef 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 */
692typedef 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
716typedef 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
734typedef 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 */
746typedef 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
777typedef 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 */
797typedef 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 */
805typedef 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
812typedef 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
821typedef 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 */
831typedef 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
842typedef 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 */
850typedef 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
856typedef 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 */
886struct 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
1084typedef 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
1092typedef 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
1098struct 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
1113struct 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
1128typedef struct {
1129	ocs_list_link_t link;		/*<< must be first */
1130	sli4_qtype_e type;		/*<< must be second */
1131} hw_q_t;
1132
1133struct 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
1148struct 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
1194struct 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
1227typedef struct ocs_hw_global_s {
1228	const char	*queue_topology_string;			/**< queue topology string */
1229} ocs_hw_global_t;
1230extern ocs_hw_global_t hw_global;
1231
1232extern hw_eq_t *hw_new_eq(ocs_hw_t *hw, uint32_t entry_count);
1233extern hw_cq_t *hw_new_cq(hw_eq_t *eq, uint32_t entry_count);
1234extern uint32_t hw_new_cq_set(hw_eq_t *eqs[], hw_cq_t *cqs[], uint32_t num_cqs, uint32_t entry_count);
1235extern hw_mq_t *hw_new_mq(hw_cq_t *cq, uint32_t entry_count);
1236extern hw_wq_t *hw_new_wq(hw_cq_t *cq, uint32_t entry_count, uint32_t class, uint32_t ulp);
1237extern hw_rq_t *hw_new_rq(hw_cq_t *cq, uint32_t entry_count, uint32_t ulp);
1238extern 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);
1239extern void hw_del_eq(hw_eq_t *eq);
1240extern void hw_del_cq(hw_cq_t *cq);
1241extern void hw_del_mq(hw_mq_t *mq);
1242extern void hw_del_wq(hw_wq_t *wq);
1243extern void hw_del_rq(hw_rq_t *rq);
1244extern void hw_queue_dump(ocs_hw_t *hw);
1245extern void hw_queue_teardown(ocs_hw_t *hw);
1246extern int32_t hw_route_rqe(ocs_hw_t *hw, ocs_hw_sequence_t *seq);
1247extern int32_t ocs_hw_queue_hash_find(ocs_queue_hash_t *, uint16_t);
1248extern ocs_hw_rtn_e ocs_hw_setup(ocs_hw_t *, ocs_os_handle_t, sli4_port_type_e);
1249extern ocs_hw_rtn_e ocs_hw_init(ocs_hw_t *);
1250extern ocs_hw_rtn_e ocs_hw_teardown(ocs_hw_t *);
1251extern ocs_hw_rtn_e ocs_hw_reset(ocs_hw_t *, ocs_hw_reset_e);
1252extern int32_t ocs_hw_get_num_eq(ocs_hw_t *);
1253extern ocs_hw_rtn_e ocs_hw_get(ocs_hw_t *, ocs_hw_property_e, uint32_t *);
1254extern void *ocs_hw_get_ptr(ocs_hw_t *, ocs_hw_property_e);
1255extern ocs_hw_rtn_e ocs_hw_set(ocs_hw_t *, ocs_hw_property_e, uint32_t);
1256extern ocs_hw_rtn_e ocs_hw_set_ptr(ocs_hw_t *, ocs_hw_property_e, void*);
1257extern int32_t ocs_hw_event_check(ocs_hw_t *, uint32_t);
1258extern int32_t ocs_hw_process(ocs_hw_t *, uint32_t, uint32_t);
1259extern ocs_hw_rtn_e ocs_hw_command(ocs_hw_t *, uint8_t *, uint32_t, void *, void *);
1260extern ocs_hw_rtn_e ocs_hw_callback(ocs_hw_t *, ocs_hw_callback_e, void *, void *);
1261extern ocs_hw_rtn_e ocs_hw_port_alloc(ocs_hw_t *, ocs_sli_port_t *, ocs_domain_t *, uint8_t *);
1262extern ocs_hw_rtn_e ocs_hw_port_attach(ocs_hw_t *, ocs_sli_port_t *, uint32_t);
1263typedef void (*ocs_hw_port_control_cb_t)(int32_t status, uintptr_t value, void *arg);
1264extern ocs_hw_rtn_e ocs_hw_port_control(ocs_hw_t *, ocs_hw_port_e, uintptr_t, ocs_hw_port_control_cb_t, void *);
1265extern ocs_hw_rtn_e ocs_hw_port_free(ocs_hw_t *, ocs_sli_port_t *);
1266extern ocs_hw_rtn_e ocs_hw_domain_alloc(ocs_hw_t *, ocs_domain_t *, uint32_t, uint32_t);
1267extern ocs_hw_rtn_e ocs_hw_domain_attach(ocs_hw_t *, ocs_domain_t *, uint32_t);
1268extern ocs_hw_rtn_e ocs_hw_domain_free(ocs_hw_t *, ocs_domain_t *);
1269extern ocs_hw_rtn_e ocs_hw_domain_force_free(ocs_hw_t *, ocs_domain_t *);
1270extern ocs_domain_t * ocs_hw_domain_get(ocs_hw_t *, uint16_t);
1271extern ocs_hw_rtn_e ocs_hw_node_alloc(ocs_hw_t *, ocs_remote_node_t *, uint32_t, ocs_sli_port_t *);
1272extern ocs_hw_rtn_e ocs_hw_node_free_all(ocs_hw_t *);
1273extern ocs_hw_rtn_e ocs_hw_node_attach(ocs_hw_t *, ocs_remote_node_t *, ocs_dma_t *);
1274extern ocs_hw_rtn_e ocs_hw_node_detach(ocs_hw_t *, ocs_remote_node_t *);
1275extern ocs_hw_rtn_e ocs_hw_node_free_resources(ocs_hw_t *, ocs_remote_node_t *);
1276extern ocs_hw_rtn_e ocs_hw_node_group_alloc(ocs_hw_t *, ocs_remote_node_group_t *);
1277extern ocs_hw_rtn_e ocs_hw_node_group_attach(ocs_hw_t *, ocs_remote_node_group_t *, ocs_remote_node_t *);
1278extern ocs_hw_rtn_e ocs_hw_node_group_free(ocs_hw_t *, ocs_remote_node_group_t *);
1279extern ocs_hw_io_t *ocs_hw_io_alloc(ocs_hw_t *);
1280extern ocs_hw_io_t *ocs_hw_io_activate_port_owned(ocs_hw_t *, ocs_hw_io_t *);
1281extern int32_t ocs_hw_io_free(ocs_hw_t *, ocs_hw_io_t *);
1282extern uint8_t ocs_hw_io_inuse(ocs_hw_t *hw, ocs_hw_io_t *io);
1283typedef 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);
1284extern 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 *);
1285extern 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 *);
1286extern 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);
1289extern ocs_hw_rtn_e ocs_hw_io_register_sgl(ocs_hw_t *, ocs_hw_io_t *, ocs_dma_t *, uint32_t);
1290extern ocs_hw_rtn_e ocs_hw_io_init_sges(ocs_hw_t *hw, ocs_hw_io_t *io, ocs_hw_io_type_e type);
1291extern 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);
1292extern ocs_hw_rtn_e ocs_hw_io_add_sge(ocs_hw_t *, ocs_hw_io_t *, uintptr_t, uint32_t);
1293extern ocs_hw_rtn_e ocs_hw_io_add_dif_sge(ocs_hw_t *hw, ocs_hw_io_t *io, uintptr_t addr);
1294extern ocs_hw_rtn_e ocs_hw_io_abort(ocs_hw_t *, ocs_hw_io_t *, uint32_t, void *, void *);
1295extern int32_t ocs_hw_io_get_xid(ocs_hw_t *, ocs_hw_io_t *);
1296extern uint32_t ocs_hw_io_get_count(ocs_hw_t *, ocs_hw_io_count_type_e);
1297extern uint32_t ocs_hw_get_rqes_produced_count(ocs_hw_t *hw);
1298
1299typedef void (*ocs_hw_fw_cb_t)(int32_t status, uint32_t bytes_written, uint32_t change_status, void *arg);
1300extern 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 */
1303typedef void (*ocs_hw_sfp_cb_t)(void *, int32_t, uint32_t, uint32_t *, void *);
1304extern 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 */
1307typedef 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);
1315extern ocs_hw_rtn_e ocs_hw_get_temperature(ocs_hw_t *, ocs_hw_temp_cb_t, void*);
1316
1317/* Function for retrieving link statistics */
1318typedef 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);
1322extern 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 */
1328typedef 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);
1332extern 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
1334extern ocs_hw_rtn_e ocs_hw_raise_ue(ocs_hw_t *, uint8_t);
1335typedef void (*ocs_hw_dump_get_cb_t)(int32_t status, uint32_t bytes_read, uint8_t eof, void *arg);
1336extern 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 *);
1337extern ocs_hw_rtn_e ocs_hw_set_dump_location(ocs_hw_t *, uint32_t, ocs_dma_t *, uint8_t);
1338
1339typedef void (*ocs_get_port_protocol_cb_t)(int32_t status, ocs_hw_port_protocol_e port_protocol, void *arg);
1340extern 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);
1341typedef void (*ocs_set_port_protocol_cb_t)(int32_t status,  void *arg);
1342extern 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
1346typedef void (*ocs_get_profile_list_cb_t)(int32_t status,  ocs_hw_profile_list_t*, void *arg);
1347extern ocs_hw_rtn_e ocs_hw_get_profile_list(ocs_hw_t *hw, ocs_get_profile_list_cb_t mgmt_cb, void *arg);
1348typedef void (*ocs_get_active_profile_cb_t)(int32_t status,  uint32_t active_profile, void *arg);
1349extern ocs_hw_rtn_e ocs_hw_get_active_profile(ocs_hw_t *hw, ocs_get_active_profile_cb_t mgmt_cb, void *arg);
1350typedef void (*ocs_set_active_profile_cb_t)(int32_t status, void *arg);
1351extern 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);
1353typedef 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);
1355extern ocs_hw_rtn_e ocs_hw_get_nvparms(ocs_hw_t *hw, ocs_get_nvparms_cb_t mgmt_cb, void *arg);
1356typedef void (*ocs_set_nvparms_cb_t)(int32_t status, void *arg);
1357extern 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);
1359extern int32_t ocs_hw_eq_process(ocs_hw_t *hw, hw_eq_t *eq, uint32_t max_isr_time_msec);
1360extern void ocs_hw_cq_process(ocs_hw_t *hw, hw_cq_t *cq);
1361extern void ocs_hw_wq_process(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe, int32_t status, uint16_t rid);
1362extern void ocs_hw_xabt_process(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe, uint16_t rid);
1363extern int32_t hw_wq_write(hw_wq_t *wq, ocs_hw_wqe_t *wqe);
1364
1365typedef void (*ocs_hw_dump_clear_cb_t)(int32_t status, void *arg);
1366extern ocs_hw_rtn_e ocs_hw_dump_clear(ocs_hw_t *, ocs_hw_dump_clear_cb_t, void *);
1367
1368extern uint8_t ocs_hw_is_io_port_owned(ocs_hw_t *hw, ocs_hw_io_t *io);
1369
1370extern uint8_t ocs_hw_is_xri_port_owned(ocs_hw_t *hw, uint32_t xri);
1371extern ocs_hw_io_t * ocs_hw_io_lookup(ocs_hw_t *hw, uint32_t indicator);
1372extern uint32_t ocs_hw_xri_move_to_port_owned(ocs_hw_t *hw, uint32_t num_xri);
1373extern ocs_hw_rtn_e ocs_hw_xri_move_to_host_owned(ocs_hw_t *hw, uint8_t num_xri);
1374extern int32_t ocs_hw_reque_xri(ocs_hw_t *hw, ocs_hw_io_t *io);
1375ocs_hw_rtn_e ocs_hw_set_persistent_topology(ocs_hw_t *hw, uint32_t topology, uint32_t opts);
1376extern uint32_t ocs_hw_get_config_persistent_topology(ocs_hw_t *hw);
1377
1378typedef 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
1395struct 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
1404ocs_hw_rtn_e
1405ocs_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 */
1410extern int32_t ocs_hw_rqpair_process_rq(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe);
1411extern ocs_hw_rtn_e ocs_hw_rqpair_sequence_free(ocs_hw_t *hw, ocs_hw_sequence_t *seq);
1412extern int32_t ocs_hw_rqpair_process_auto_xfr_rdy_cmd(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe);
1413extern int32_t ocs_hw_rqpair_process_auto_xfr_rdy_data(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe);
1414extern ocs_hw_rtn_e ocs_hw_rqpair_init(ocs_hw_t *hw);
1415extern ocs_hw_rtn_e ocs_hw_rqpair_auto_xfer_rdy_buffer_alloc(ocs_hw_t *hw, uint32_t num_buffers);
1416extern uint8_t ocs_hw_rqpair_auto_xfer_rdy_buffer_post(ocs_hw_t *hw, ocs_hw_io_t *io, int reuse_buf);
1417extern ocs_hw_rtn_e ocs_hw_rqpair_auto_xfer_rdy_move_to_port(ocs_hw_t *hw, ocs_hw_io_t *io);
1418extern void ocs_hw_rqpair_auto_xfer_rdy_move_to_host(ocs_hw_t *hw, ocs_hw_io_t *io);
1419extern void ocs_hw_rqpair_teardown(ocs_hw_t *hw);
1420
1421extern ocs_hw_rtn_e ocs_hw_rx_allocate(ocs_hw_t *hw);
1422extern ocs_hw_rtn_e ocs_hw_rx_post(ocs_hw_t *hw);
1423extern void ocs_hw_rx_free(ocs_hw_t *hw);
1424
1425extern void ocs_hw_unsol_process_bounce(void *arg);
1426
1427typedef int32_t (*ocs_hw_async_cb_t)(ocs_hw_t *hw, int32_t status, uint8_t *mqe, void *arg);
1428extern int32_t ocs_hw_async_call(ocs_hw_t *hw, ocs_hw_async_cb_t callback, void *arg);
1429
1430static inline void
1431ocs_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
1438static inline ocs_hw_rtn_e
1439ocs_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 */
1446extern ocs_hw_rtn_e ocs_hw_reqtag_init(ocs_hw_t *hw);
1447extern 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);
1449extern void ocs_hw_reqtag_free(ocs_hw_t *hw, hw_wq_callback_t *wqcb);
1450extern hw_wq_callback_t *ocs_hw_reqtag_get_instance(ocs_hw_t *hw, uint32_t instance_index);
1451extern void ocs_hw_reqtag_reset(ocs_hw_t *hw);
1452
1453extern uint32_t ocs_hw_dif_blocksize(ocs_hw_dif_info_t *dif_info);
1454extern int32_t ocs_hw_dif_mem_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem);
1455extern int32_t ocs_hw_dif_wire_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem);
1456extern 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
1477extern 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