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