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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#ifndef	_SYS_IB_ADAPTERS_HERMON_QP_H
27#define	_SYS_IB_ADAPTERS_HERMON_QP_H
28
29/*
30 * hermon_qp.h
31 *    Contains all of the prototypes, #defines, and structures necessary
32 *    for all of the Queue Pair Processing routines.
33 *    Specifically it contains the various flags, structures used for managing
34 *    Hermon queue pairs, and prototypes for many of the functions consumed by
35 *    other parts of the Hermon driver (including those routines directly
36 *    exposed through the IBTF CI interface).
37 *
38 *    Most of the values defined below establish default values which,
39 *    where indicated, can be controlled via their related patchable values,
40 *    if 'hermon_alt_config_enable' is set.
41 */
42
43#include <sys/types.h>
44#include <sys/conf.h>
45#include <sys/ddi.h>
46#include <sys/sunddi.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52/*
53 * The following defines the default number of Queue Pairs. This value is
54 * controlled via the "hermon_log_num_qp" configuration variables.
55 * We also have a define for the minimum size of a QP.  QPs allocated
56 * with size 0, 1, 2, or 3 will always get back a QP of size 4.
57 *
58 * Note: Increasing #QPs from 64K to 256K for reserved ranges for FCoIB.
59 */
60#define	HERMON_NUM_QP_SHIFT		0x12
61#define	HERMON_NUM_QPS			(1 << HERMON_NUM_QP_SHIFT) /* 256K */
62#define	HERMON_QP_MIN_SIZE		0xf
63
64/*
65 * The following defines the default number of Hermon RDMA Remote read
66 * database (RDB) entries per QP.  This value is controllable through the
67 * "hermon_log_num_rdb_per_qp" configuration variable.
68 */
69#define	HERMON_LOG_NUM_RDB_PER_QP	0x4
70
71/*
72 * This defines the maximum number of SGLs per WQE.  This value is
73 * controllable through the "hermon_wqe_max_sgl" configuration variable
74 * (but should not be set larger than this value).
75 */
76#define	HERMON_NUM_SGL_PER_WQE		0x10
77
78/*
79 * Maximum QP number mask (QP number is 24 bits).
80 * We reserve the most significant bit to indicate an "XRC" QP
81 * as recommended by the PRM.  All XRC QPs will have this bit set.
82 */
83#define	HERMON_QP_MAXNUMBER_MSK		0x7FFFFF
84#define	HERMON_QP_XRC_MSK		0x800000
85
86/*
87 * This define and the following macro are used to find a schedule queue for
88 * a new QP based on its queue pair number.  Note:  This is a rather simple
89 * method that we use today.  We simply choose from the schedule queue based
90 * on the 4 least significant bits of the QP number.
91 */
92
93/*
94 * The following defines are used to indicate whether a QP is special or
95 * not (and what type it is).  They are used in the "qp_is_special" field
96 * below in qp_state.  If "qp_is_special" == 0 then an ordinary data qp.
97 */
98
99/*
100 * The sl is selected based on the qpnum as it was for Tavor/Arbel, except for
101 * QP0, which is defined as being 0xF
102 */
103
104#define	HERMON_QP_SMI			0x1
105#define	HERMON_QP_GSI			0x2
106
107#define	HERMON_DEF_SCHED_POLICY		0x03
108#define	HERMON_DEF_SCHED_SELECTION	0x0F
109
110#define	HERMON_QP_SCHEDQ_GET(port, sl, issmi)   \
111	(HERMON_DEF_SCHED_POLICY 		\
112	| (issmi == HERMON_QP_SMI ? (HERMON_DEF_SCHED_SELECTION << 2) : \
113	((issmi == HERMON_QP_GSI ? 0 : (sl & 0XF)) << 2)) \
114	| ((port & 0x01) << 6) \
115	| ((issmi == HERMON_QP_SMI ? 0 : 1) << 7))
116
117
118/*
119 * This define determines the frequency with which the AckReq bit will be
120 * set in outgoing RC packets.  By default it is set to five (5) or 2^5 = 32.
121 * So AckReq will be set once every 32 packets sent.  This value is
122 * controllable through the "hermon_qp_ackreq_freq" configuration variable.
123 */
124#define	HERMON_QP_ACKREQ_FREQ		0x5
125
126/*
127 * Define the maximum message size (log 2).  Note: This value corresponds
128 * to the maximum allowable message sized as defined by the IBA spec.
129 */
130#define	HERMON_QP_LOG_MAX_MSGSZ		0x1F
131
132/*
133 * This macro is used to determine if the hermon QP type (qp_serv) is the
134 * same as the caller passed in IBT type (qp_trans).  This is used in QP modify
135 * to ensure the types match.
136 */
137#define	HERMON_QP_TYPE_VALID(qp_trans, qp_serv)				\
138	((qp_trans == IBT_RC_SRV && qp_serv == HERMON_QP_RC) ||		\
139	(qp_trans == IBT_UD_SRV && (qp_serv == HERMON_QP_UD ||		\
140	qp_serv == HERMON_QP_RFCI || qp_serv == HERMON_QP_FCMND ||	\
141	qp_serv == HERMON_QP_FEXCH)) ||					\
142	(qp_trans == IBT_UC_SRV && qp_serv == HERMON_QP_UC))
143
144/*
145 * The following enumerated type is used to capture all the various types
146 * of Hermon work queue types. It is specifically used as an argument to the
147 * to the hermon_qp_sgl_to_logwqesz() routine to determine the amount of
148 * overhead (in WQE header size) consumed by each of the types. This
149 * information is used to round the WQE size to the next largest power-of-2
150 * (and to determine the number of SGLs that are supported for the given WQE
151 * type).  There is also a define below used to specify the minimum size for a
152 * WQE.  The minimum size is set to 64 bytes (a single cacheline).
153 */
154
155typedef enum {
156	HERMON_QP_WQ_TYPE_SENDQ_UD,
157	HERMON_QP_WQ_TYPE_SENDQ_CONN,
158	HERMON_QP_WQ_TYPE_RECVQ,
159	HERMON_QP_WQ_TYPE_SENDMLX_QP0,
160	HERMON_QP_WQ_TYPE_SENDMLX_QP1
161} hermon_qp_wq_type_t;
162#define	HERMON_QP_WQE_MLX_SND_HDRS	0x40
163#define	HERMON_QP_WQE_MLX_RCV_HDRS	0x00
164#define	HERMON_QP_WQE_MLX_SRQ_HDRS	0x10
165#define	HERMON_QP_WQE_MLX_QP0_HDRS	0x40
166#define	HERMON_QP_WQE_MLX_QP1_HDRS	0x70
167#define	HERMON_QP_WQE_LOG_MINIMUM	0x6
168
169
170/*
171 * The hermon_qp_range_t is used to manage a qp_range for RSS and FEXCH.
172 * It has a reference count.  When the reference count goes to 0,
173 * the qpc resource can be freed.
174 */
175typedef struct hermon_qp_range_s {
176	kmutex_t	hqpr_lock;
177	hermon_rsrc_t	*hqpr_qpcrsrc;
178	uint_t		hqpr_refcnt;
179} hermon_qp_range_t;
180
181/*
182 * The hermon_qp_info_t structure is used internally by the Hermon driver to
183 * pass information to and from the hermon_qp_alloc() and
184 * hermon_special_qp_alloc() routines.  It contains placeholders for all of the
185 * potential inputs and outputs that either routine can take.
186 */
187typedef struct hermon_qp_info_s {
188	ibt_qp_alloc_attr_t	*qpi_attrp;
189	uint_t			qpi_type;
190	uint_t			qpi_port;
191	ibtl_qp_hdl_t		qpi_ibt_qphdl;
192	ibt_chan_sizes_t	*qpi_queueszp;
193	ib_qpn_t		*qpi_qpn;
194	hermon_qphdl_t		qpi_qphdl;
195} hermon_qp_info_t;
196
197/*
198 * The QPN entry which is stored in the AVL tree
199 */
200typedef struct hermon_qpn_entry_s {
201	avl_node_t		qpn_avlnode;
202	uint_t			qpn_refcnt;
203	uint_t			qpn_counter;
204	uint_t			qpn_indx;
205	hermon_rsrc_t		*qpn_qpc;
206} hermon_qpn_entry_t;
207#define	HERMON_QPN_NOFLAG		0x0
208#define	HERMON_QPN_RELEASE		0x1
209#define	HERMON_QPN_FREE_ONLY		0x2
210
211#define	HERMON_QP_OH_SIZE		0x0800
212/*
213 * 2KB, fixed per Mnox PRM 0.35c & conversation w/Mnox technical Sep 5, 2007
214 */
215
216/*
217 * The hermon_sw_qp_s structure is also referred to using the "hermon_qphdl_t"
218 * typedef (see hermon_typedef.h).  It encodes all the information necessary
219 * to track the various resources needed to allocate, query, modify, and
220 * (later) free both normal QP and special QP.
221 *
222 * Specifically, it has a lock to ensure single threaded access to the QP.
223 * It has QP state, type, and number, pointers to the PD, MR, and CQ handles
224 * associated with the QP, and pointers to the buffer where the work queues
225 * come from.
226 *
227 * It has two pointers (one per work queue) to the workQ headers for the WRID
228 * list, as well as pointers to the last WQE on each chain (used when
229 * connecting a new chain of WQEs to a previously executing chain - see
230 * hermon_wr.c).  It's also got the real WQE size, real number of SGL per WQE,
231 * and the size of each of the work queues (in number of WQEs).
232 *
233 * Additionally, it has pointers to the resources associated with the QP,
234 * including the obligatory backpointer to the resource for the QP handle
235 * itself.  But it also has some flags, like "qp_forward_sqd_event" and
236 * "qp_sqd_still_draining" (which are used to indicate whether a Send Queue
237 * Drained Event should be forwarded to the IBTF) or "qp_is_special",
238 * "qp_portnum", and "qp_pkeyindx" (which are used by special QP to store
239 * necessary information about the type of the QP, which port it's connected
240 * to, and what its current PKey index is set to).
241 */
242struct hermon_sw_qp_s {
243	kmutex_t		qp_lock;
244	uint_t			qp_state;
245	uint32_t		qp_qpnum;
246	hermon_pdhdl_t		qp_pdhdl;
247	uint_t			qp_serv_type;
248	ibt_qp_type_t		qp_type;
249	uint_t			qp_sl;		/* service level */
250	hermon_mrhdl_t		qp_mrhdl;
251	uint_t			qp_sq_sigtype;
252	uint_t			qp_is_special;
253	ibt_qp_alloc_flags_t	qp_alloc_flags;
254	uint32_t		qp_uarpg;
255	devmap_cookie_t		qp_umap_dhp;
256	uint_t			qp_portnum;	/* port 0/1 for HCA */
257	uint_t			qp_portnum_alt;	/* port 0/1 for HCA */
258	uint_t			qp_pkeyindx;
259	uint_t			qp_no_prefetch;
260				/* prefetch == 0, none == 1, for headroom */
261	uint_t			qp_rlky;	/* using reserved lkey */
262
263	/* Send Work Queue */
264	kmutex_t		qp_sq_lock;
265	hermon_cqhdl_t		qp_sq_cqhdl;
266	hermon_workq_avl_t	qp_sq_wqavl;
267	hermon_workq_hdr_t	*qp_sq_wqhdr;
268	uint32_t		*qp_sq_buf;
269	uint32_t		qp_sq_bufsz;
270	uint32_t		qp_sq_logqsz;	/* used to check owner valid */
271	uint32_t		qp_sq_log_wqesz;
272	uint32_t		qp_sq_headroom; /* #bytes needed for headroom */
273	uint32_t		qp_sq_hdrmwqes;	/* # wqes needed for headroom */
274	uint32_t		qp_sq_baseaddr;
275	uint32_t		qp_sq_sgl;
276	uint_t			qp_uses_lso;
277	uint32_t		qp_ring;
278	uint_t			qp_state_for_post_send; /* copy of qp_state */
279
280	/* Receive Work Queue - not used when SRQ is used */
281	hermon_cqhdl_t		qp_rq_cqhdl;
282	hermon_workq_avl_t	qp_rq_wqavl;	/* needed for srq */
283	hermon_workq_hdr_t	*qp_rq_wqhdr;
284	uint32_t		*qp_rq_buf;
285	uint32_t		qp_rq_bufsz;
286	uint32_t		qp_rq_logqsz;	/* used to check owner valid */
287	uint32_t		qp_rq_log_wqesz;
288	uint32_t		qp_rq_wqecntr;
289	uint32_t		qp_rq_baseaddr;
290	uint32_t		qp_rq_sgl;
291
292	/* DoorBell Record information */
293	ddi_acc_handle_t	qp_rq_dbr_acchdl;
294	hermon_dbr_t		*qp_rq_vdbr;
295	uint64_t		qp_rq_pdbr;
296	uint64_t		qp_rdbr_mapoffset;	/* user mode access */
297
298	uint64_t		qp_desc_off;
299
300	hermon_rsrc_t		*qp_qpcrsrcp;
301	hermon_rsrc_t		*qp_rsrcp;
302	void			*qp_hdlrarg;
303	uint_t			qp_forward_sqd_event;
304	uint_t			qp_sqd_still_draining;
305
306	/* Shared Receive Queue */
307	hermon_srqhdl_t		qp_srqhdl;
308
309	/* Refcnt of QP belongs to an MCG */
310	uint_t			qp_mcg_refcnt;
311
312	/* save the mtu from init2rtr for future use */
313	uint_t			qp_save_mtu;
314	hermon_qpn_entry_t	*qp_qpn_hdl;
315
316	struct hermon_qalloc_info_s qp_wqinfo;
317
318	ibt_fc_attr_t		qp_fc_attr;
319
320	struct hermon_qp_range_s *qp_rangep;
321
322	/* Beware: 8-byte alignment needed here */
323
324	struct hermon_hw_qpc_s qpc;
325};
326_NOTE(READ_ONLY_DATA(hermon_sw_qp_s::qp_qpnum
327    hermon_sw_qp_s::qp_sq_buf
328    hermon_sw_qp_s::qp_sq_log_wqesz
329    hermon_sw_qp_s::qp_sq_bufsz
330    hermon_sw_qp_s::qp_sq_sgl
331    hermon_sw_qp_s::qp_rq_buf
332    hermon_sw_qp_s::qp_rq_log_wqesz
333    hermon_sw_qp_s::qp_rq_bufsz
334    hermon_sw_qp_s::qp_rq_sgl
335    hermon_sw_qp_s::qp_desc_off
336    hermon_sw_qp_s::qp_mrhdl
337    hermon_sw_qp_s::qp_wqinfo
338    hermon_sw_qp_s::qp_qpcrsrcp
339    hermon_sw_qp_s::qp_rsrcp
340    hermon_sw_qp_s::qp_hdlrarg
341    hermon_sw_qp_s::qp_pdhdl
342    hermon_sw_qp_s::qp_sq_cqhdl
343    hermon_sw_qp_s::qp_rq_cqhdl
344    hermon_sw_qp_s::qp_sq_sigtype
345    hermon_sw_qp_s::qp_serv_type
346    hermon_sw_qp_s::qp_is_special
347    hermon_sw_qp_s::qp_alloc_flags
348    hermon_sw_qp_s::qp_uarpg
349    hermon_sw_qp_s::qp_sq_wqhdr
350    hermon_sw_qp_s::qp_rq_wqhdr
351    hermon_sw_qp_s::qp_qpn_hdl))
352_NOTE(MUTEX_PROTECTS_DATA(hermon_sw_qp_s::qp_lock,
353    hermon_sw_qp_s::qp_state
354    hermon_sw_qp_s::qpc
355    hermon_sw_qp_s::qp_forward_sqd_event
356    hermon_sw_qp_s::qp_sqd_still_draining
357    hermon_sw_qp_s::qp_mcg_refcnt
358    hermon_sw_qp_s::qp_save_mtu
359    hermon_sw_qp_s::qp_umap_dhp))
360_NOTE(SCHEME_PROTECTS_DATA("safe sharing",
361    hermon_sw_qp_s::qp_pkeyindx
362    hermon_sw_qp_s::qp_portnum))
363
364#define	HERMON_SET_QP_POST_SEND_STATE(qp, state)			\
365	mutex_enter(&qp->qp_sq_lock);					\
366	qp->qp_state_for_post_send = state;				\
367	mutex_exit(&qp->qp_sq_lock)
368
369/* Defined in hermon_qp.c */
370int hermon_qp_alloc(hermon_state_t *state, hermon_qp_info_t *qpinfo,
371    uint_t sleepflag);
372int hermon_special_qp_alloc(hermon_state_t *state, hermon_qp_info_t *qpinfo,
373    uint_t sleepflag);
374int hermon_qp_alloc_range(hermon_state_t *state, uint_t log2,
375    hermon_qp_info_t *qpinfo, ibtl_qp_hdl_t *ibtl_qp_p, ibc_cq_hdl_t *send_cq_p,
376    ibc_cq_hdl_t *recv_cq_p, hermon_qphdl_t *qp_p, uint_t sleepflag);
377int hermon_qp_free(hermon_state_t *state, hermon_qphdl_t *qphdl,
378    ibc_free_qp_flags_t free_qp_flags, ibc_qpn_hdl_t *qpnh, uint_t sleepflag);
379int hermon_qp_query(hermon_state_t *state, hermon_qphdl_t qphdl,
380    ibt_qp_query_attr_t *attr_p);
381hermon_qphdl_t hermon_qphdl_from_qpnum(hermon_state_t *state, uint_t qpnum);
382void hermon_qp_release_qpn(hermon_state_t *state, hermon_qpn_entry_t *entry,
383    int flags);
384void hermon_qpn_avl_init(hermon_state_t *state);
385void hermon_qpn_avl_fini(hermon_state_t *state);
386
387/* Defined in hermon_qpmod.c */
388int hermon_qp_modify(hermon_state_t *state, hermon_qphdl_t qp,
389    ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p,
390    ibt_queue_sizes_t *actual_sz);
391int hermon_qp_to_reset(hermon_state_t *state, hermon_qphdl_t qp);
392
393#ifdef __cplusplus
394}
395#endif
396
397#endif	/* _SYS_IB_ADAPTERS_HERMON_QP_H */
398