xref: /illumos-gate/usr/src/uts/common/sys/ib/adapters/hermon/hermon_cq.h (revision 9525b14bcdeb5b5f6f95ab27c2f48f18bd2ec829)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_IB_ADAPTERS_HERMON_CQ_H
28 #define	_SYS_IB_ADAPTERS_HERMON_CQ_H
29 
30 /*
31  * hermon_cq.h
32  *    Contains all of the prototypes, #defines, and structures necessary
33  *    for the Completion Queue Processing routines.
34  *    Specifically it contains the various completion types, flags,
35  *    structures used for managing Hermon completion queues, and prototypes
36  *    for many of the functions consumed by other parts of the Hermon driver
37  *    (including those routines directly exposed through the IBTF CI
38  *    interface).
39  *
40  *    Most of the values defined below establish default values which,
41  *    where indicated, can be controlled via their related patchable values,
42  *    if 'hermon_alt_config_enable' is set.
43  */
44 
45 #include <sys/types.h>
46 #include <sys/conf.h>
47 #include <sys/ddi.h>
48 #include <sys/sunddi.h>
49 
50 #include <sys/ib/adapters/hermon/hermon_misc.h>
51 
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55 
56 /*
57  * The following defines the default number of Completion Queues. This
58  * is controllable via the "hermon_log_num_cq" configuration variable.
59  * We also have a define for the minimum size of a CQ.  CQs allocated
60  * with size 0, 1, 2, or 3 will always get back a CQ of size 4.
61  */
62 #define	HERMON_NUM_CQ_SHIFT		0x10
63 /*
64  *	#define	HERMON_CQ_MIN_SIZE	0x3
65  */
66 
67 /*
68  *	#define	HERMON_CQ_MIN_SIZE	0xFF	 testing, try min 1 page
69  */
70 
71 /* page div 32 (cqe size) minus 1, for min size */
72 #define	HERMON_CQ_MIN_SIZE	((PAGESIZE / 32) - 1)
73 
74 /*
75  * These are the defines for the Hermon CQ completion statuses.
76  */
77 #define	HERMON_CQE_SUCCESS		0x0
78 #define	HERMON_CQE_LOC_LEN_ERR		0x1
79 #define	HERMON_CQE_LOC_OP_ERR		0x2
80 #define	HERMON_CQE_LOC_PROT_ERR		0x4
81 #define	HERMON_CQE_WR_FLUSHED_ERR	0x5
82 #define	HERMON_CQE_MW_BIND_ERR		0x6
83 #define	HERMON_CQE_BAD_RESPONSE_ERR	0x10
84 #define	HERMON_CQE_LOCAL_ACCESS_ERR	0x11
85 #define	HERMON_CQE_REM_INV_REQ_ERR	0x12
86 #define	HERMON_CQE_REM_ACC_ERR		0x13
87 #define	HERMON_CQE_REM_OP_ERR		0x14
88 #define	HERMON_CQE_TRANS_TO_ERR		0x15
89 #define	HERMON_CQE_RNRNAK_TO_ERR	0x16
90 #define	HERMON_CQE_EEC_REM_ABORTED_ERR	0x22
91 
92 /*
93  * These are the defines for the Hermon CQ entry types. They indicate what type
94  * of work request is completing (for successful completions).  Note: The
95  * "SND" or "RCV" in each define is used to indicate whether the completion
96  * work request was from the Send work queue or the Receive work queue on
97  * the associated QP.
98  */
99 #define	HERMON_CQE_SND_NOP		0x0
100 #define	HERMON_CQE_SND_SND_INV		0x1
101 #define	HERMON_CQE_SND_RDMAWR		0x8
102 #define	HERMON_CQE_SND_RDMAWR_IMM	0x9
103 #define	HERMON_CQE_SND_SEND		0xA
104 #define	HERMON_CQE_SND_SEND_IMM		0xB
105 #define	HERMON_CQE_SND_LSO		0xE
106 #define	HERMON_CQE_SND_RDMARD		0x10
107 #define	HERMON_CQE_SND_ATOMIC_CS	0x11
108 #define	HERMON_CQE_SND_ATOMIC_FA	0x12
109 #define	HERMON_CQE_SND_ATOMIC_CS_EX	0x14
110 #define	HERMON_CQE_SND_ATOMIC_FC_EX	0x15
111 #define	HERMON_CQE_SND_FRWR		0x19
112 #define	HERMON_CQE_SND_LCL_INV		0x1B
113 #define	HERMON_CQE_SND_CONFIG		0x1F
114 #define	HERMON_CQE_SND_BIND_MW		0x18
115 
116 #define	HERMON_CQE_RCV_RDMAWR_IMM	0x00
117 #define	HERMON_CQE_RCV_SEND		0x01
118 #define	HERMON_CQE_RCV_SEND_IMM		0x02
119 #define	HERMON_CQE_RCV_SND_INV		0x03
120 #define	HERMON_CQE_RCV_ERROR_CODE	0x1E
121 #define	HERMON_CQE_RCV_RESIZE_CODE	0x16
122 
123 
124 /* Define for maximum CQ number mask (CQ number is 24 bits) */
125 #define	HERMON_CQ_MAXNUMBER_MSK		0xFFFFFF
126 
127 
128 /*
129  * new EQ mgmt - per domain (when it gets there).
130  * The first N are for CQ Completions.  Following that are:
131  *
132  *	1 for CQ Errors
133  *	1 for Asyncs and Command Completions, and finally
134  *	1 for All Other events.
135  *
136  * hs_intrmsi_allocd is the N in the above.
137  */
138 
139 #define	HERMON_CQ_EQNUM_GET(state)					\
140 	(state->hs_devlim.num_rsvd_eq +					\
141 	    (atomic_inc_uint_nv(&state->hs_eq_dist) %			\
142 	    state->hs_intrmsi_allocd))
143 
144 #define	HERMON_CQ_ERREQNUM_GET(state)					\
145 	(state->hs_devlim.num_rsvd_eq + state->hs_intrmsi_allocd)
146 /*
147  * The following defines are used for Hermon CQ error handling.  Note: For
148  * CQEs which correspond to error events, the Hermon device requires some
149  * special handling by software.  These defines are used to identify and
150  * extract the necessary information from each error CQE, including status
151  * code (above), doorbell count, and whether a error completion is for a
152  * send or receive work request.
153  */
154 
155 
156 #define	HERMON_CQE_ERR_STATUS_SHIFT	0
157 #define	HERMON_CQE_ERR_STATUS_MASK	0xFF
158 #define	HERMON_CQE_ERR_DBDCNT_MASK	0xFFFF
159 #define	HERMON_CQE_SEND_ERR_OPCODE	0x1E
160 #define	HERMON_CQE_RECV_ERR_OPCODE	0x1E
161 
162 /* Defines for tracking whether a CQ is being used with special QP or not */
163 #define	HERMON_CQ_IS_NORMAL		0
164 #define	HERMON_CQ_IS_SPECIAL		1
165 
166 /*
167  * The hermon_sw_cq_s structure is also referred to using the "hermon_cqhdl_t"
168  * typedef (see hermon_typedef.h).  It encodes all the information necessary
169  * to track the various resources needed to allocate, initialize, poll, resize,
170  * and (later) free a completion queue (CQ).
171  *
172  * Specifically, it has a consumer index and a lock to ensure single threaded
173  * access to it.  It has pointers to the various resources allocated for the
174  * completion queue, i.e. a CQC resource and the memory for the completion
175  * queue itself. It also has a reference count and the number(s) of the EQs
176  * to which it is associated (for success and for errors).
177  *
178  * Additionally, it has a pointer to the associated MR handle (for the mapped
179  * queue memory) and a void pointer that holds the argument that should be
180  * passed back to the IBTF when events are generated on the CQ.
181  *
182  * We also have the always necessary backpointer to the resource for the
183  * CQ handle structure itself.  But we also have pointers to the "Work Request
184  * ID" processing lists (both the lock and the regular list, as well as the
185  * head and tail for the "reapable" list).  See hermon_wrid.c for more details.
186  */
187 
188 #define	HERMON_CQ_DEF_UAR_DOORBELL	0x11	/* cmd_sn = 1, req solicited */
189 #define	HERMON_CD_DEF_UAR_DB_SHIFT	0x38	/* decimal 56 */
190 
191 struct hermon_sw_cq_s {
192 	kmutex_t		cq_lock;
193 	struct hermon_sw_cq_s 	*cq_resize_hdl; /* points to tranistory hdl */
194 	uint32_t		cq_consindx;
195 	uint32_t		cq_cqnum;
196 	hermon_hw_cqe_t		*cq_buf;
197 	hermon_mrhdl_t		cq_mrhdl;
198 	uint32_t		cq_bufsz;
199 	uint32_t		cq_log_cqsz;
200 	uint_t			cq_refcnt;
201 	uint32_t		cq_eqnum;
202 	uint32_t		cq_erreqnum;
203 	uint_t			cq_is_special;
204 	uint_t			cq_is_umap;
205 	uint32_t		cq_uarpg;
206 	devmap_cookie_t		cq_umap_dhp;
207 	hermon_rsrc_t		*cq_cqcrsrcp;
208 	hermon_rsrc_t		*cq_rsrcp;
209 	uint_t			cq_intmod_count;
210 	uint_t			cq_intmod_usec;
211 
212 	/* DoorBell Record Information */
213 	ddi_acc_handle_t	cq_arm_ci_dbr_acchdl;
214 	hermon_dbr_t		*cq_arm_ci_vdbr;
215 	uint64_t		cq_arm_ci_pdbr;
216 	uint64_t		cq_dbr_mapoffset;	/* user mode access */
217 
218 	void			*cq_hdlrarg;
219 
220 	/* For Work Request ID processing */
221 	avl_tree_t		cq_wrid_wqhdr_avl_tree;
222 
223 	struct hermon_qalloc_info_s cq_cqinfo;
224 };
225 _NOTE(READ_ONLY_DATA(hermon_sw_cq_s::cq_cqnum
226     hermon_sw_cq_s::cq_eqnum
227     hermon_sw_cq_s::cq_erreqnum
228     hermon_sw_cq_s::cq_cqcrsrcp
229     hermon_sw_cq_s::cq_rsrcp
230     hermon_sw_cq_s::cq_hdlrarg
231     hermon_sw_cq_s::cq_is_umap
232     hermon_sw_cq_s::cq_uarpg))
233 _NOTE(DATA_READABLE_WITHOUT_LOCK(hermon_sw_cq_s::cq_bufsz
234     hermon_sw_cq_s::cq_consindx
235     hermon_sw_cq_s::cq_cqinfo))
236 _NOTE(MUTEX_PROTECTS_DATA(hermon_sw_cq_s::cq_lock,
237     hermon_sw_cq_s::cq_buf
238     hermon_sw_cq_s::cq_mrhdl
239     hermon_sw_cq_s::cq_refcnt
240     hermon_sw_cq_s::cq_is_special
241     hermon_sw_cq_s::cq_umap_dhp))
242 _NOTE(SCHEME_PROTECTS_DATA("safe sharing",
243     hermon_sw_cq_s::cq_intmod_count
244     hermon_sw_cq_s::cq_intmod_usec
245     hermon_sw_cq_s::cq_resize_hdl))
246 
247 int hermon_cq_alloc(hermon_state_t *state, ibt_cq_hdl_t ibt_cqhdl,
248     ibt_cq_attr_t *attr_p, uint_t *actual_size, hermon_cqhdl_t *cqhdl,
249     uint_t sleepflag);
250 int hermon_cq_free(hermon_state_t *state, hermon_cqhdl_t *cqhdl,
251     uint_t sleepflag);
252 int hermon_cq_resize(hermon_state_t *state, hermon_cqhdl_t cqhdl,
253     uint_t req_size, uint_t *actual_size, uint_t sleepflag);
254 int hermon_cq_modify(hermon_state_t *state, hermon_cqhdl_t cqhdl,
255     uint_t count, uint_t usec, ibt_cq_handler_id_t hid, uint_t sleepflag);
256 int hermon_cq_notify(hermon_state_t *state, hermon_cqhdl_t cqhdl,
257     ibt_cq_notify_flags_t flags);
258 int hermon_cq_poll(hermon_state_t *state, hermon_cqhdl_t cqhdl, ibt_wc_t *wc_p,
259     uint_t num_wc, uint_t *num_polled);
260 int hermon_cq_handler(hermon_state_t *state, hermon_eqhdl_t eq,
261     hermon_hw_eqe_t *eqe);
262 int hermon_cq_err_handler(hermon_state_t *state, hermon_eqhdl_t eq,
263     hermon_hw_eqe_t *eqe);
264 int hermon_cq_refcnt_inc(hermon_cqhdl_t cq, uint_t is_special);
265 void hermon_cq_refcnt_dec(hermon_cqhdl_t cq);
266 hermon_cqhdl_t hermon_cqhdl_from_cqnum(hermon_state_t *state, uint_t cqnum);
267 void hermon_cq_entries_flush(hermon_state_t *state, hermon_qphdl_t qp);
268 void hermon_cq_resize_helper(hermon_state_t *state, hermon_cqhdl_t cq);
269 
270 #ifdef __cplusplus
271 }
272 #endif
273 
274 #endif	/* _SYS_IB_ADAPTERS_HERMON_CQ_H */
275