summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/ib/adapters/hermon/hermon_cq.h
blob: 72c47b8644bdf88dca1b9453dcb8b928dc51ee7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef	_SYS_IB_ADAPTERS_HERMON_CQ_H
#define	_SYS_IB_ADAPTERS_HERMON_CQ_H

/*
 * hermon_cq.h
 *    Contains all of the prototypes, #defines, and structures necessary
 *    for the Completion Queue Processing routines.
 *    Specifically it contains the various completion types, flags,
 *    structures used for managing Hermon completion queues, and prototypes
 *    for many of the functions consumed by other parts of the Hermon driver
 *    (including those routines directly exposed through the IBTF CI
 *    interface).
 *
 *    Most of the values defined below establish default values which,
 *    where indicated, can be controlled via their related patchable values,
 *    if 'hermon_alt_config_enable' is set.
 */

#include <sys/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>

#include <sys/ib/adapters/hermon/hermon_misc.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * The following defines the default number of Completion Queues. This
 * is controllable via the "hermon_log_num_cq" configuration variable.
 * We also have a define for the minimum size of a CQ.  CQs allocated
 * with size "less than a page" will always get back a page.
 */
#define	HERMON_NUM_CQ_SHIFT		0x12

#define	HERMON_CQ_MIN_SIZE	((PAGESIZE / 32) - 1)

/*
 * These are the defines for the Hermon CQ completion statuses.
 */
#define	HERMON_CQE_SUCCESS		0x0
#define	HERMON_CQE_LOC_LEN_ERR		0x1
#define	HERMON_CQE_LOC_OP_ERR		0x2
#define	HERMON_CQE_LOC_PROT_ERR		0x4
#define	HERMON_CQE_WR_FLUSHED_ERR	0x5
#define	HERMON_CQE_MW_BIND_ERR		0x6
#define	HERMON_CQE_BAD_RESPONSE_ERR	0x10
#define	HERMON_CQE_LOCAL_ACCESS_ERR	0x11
#define	HERMON_CQE_REM_INV_REQ_ERR	0x12
#define	HERMON_CQE_REM_ACC_ERR		0x13
#define	HERMON_CQE_REM_OP_ERR		0x14
#define	HERMON_CQE_TRANS_TO_ERR		0x15
#define	HERMON_CQE_RNRNAK_TO_ERR	0x16
#define	HERMON_CQE_EEC_REM_ABORTED_ERR	0x22

/*
 * These are the defines for the Hermon CQ entry types. They indicate what type
 * of work request is completing (for successful completions).  Note: The
 * "SND" or "RCV" in each define is used to indicate whether the completion
 * work request was from the Send work queue or the Receive work queue on
 * the associated QP.
 */
#define	HERMON_CQE_SND_NOP		0x0
#define	HERMON_CQE_SND_SEND_INV		0x1
#define	HERMON_CQE_SND_RDMAWR		0x8
#define	HERMON_CQE_SND_RDMAWR_IMM	0x9
#define	HERMON_CQE_SND_SEND		0xA
#define	HERMON_CQE_SND_SEND_IMM		0xB
#define	HERMON_CQE_SND_LSO		0xE
#define	HERMON_CQE_SND_RDMARD		0x10
#define	HERMON_CQE_SND_ATOMIC_CS	0x11
#define	HERMON_CQE_SND_ATOMIC_FA	0x12
#define	HERMON_CQE_SND_ATOMIC_CS_EX	0x14
#define	HERMON_CQE_SND_ATOMIC_FC_EX	0x15
#define	HERMON_CQE_SND_FRWR		0x19
#define	HERMON_CQE_SND_LCL_INV		0x1B
#define	HERMON_CQE_SND_CONFIG		0x1F
#define	HERMON_CQE_SND_BIND_MW		0x18

#define	HERMON_CQE_RCV_RDMAWR_IMM	0x00
#define	HERMON_CQE_RCV_SEND		0x01
#define	HERMON_CQE_RCV_SEND_IMM		0x02
#define	HERMON_CQE_RCV_SEND_INV		0x03
#define	HERMON_CQE_RCV_ERROR_CODE	0x1E
#define	HERMON_CQE_RCV_RESIZE_CODE	0x16


/* Define for maximum CQ number mask (CQ number is 24 bits) */
#define	HERMON_CQ_MAXNUMBER_MSK		0xFFFFFF

/*
 * CQ Sched Management
 *
 *	Each hermon_cq_sched struct defines a range of cq handler_id's
 *	assigned to the cq_sched instance.  Also, the "next_alloc"
 *	member is used to allocate handler_id's in a round robin fashion.
 *
 *	Valid cq handler_id's are in the range of 1 to hs_intrmsi_allocd.
 *	They are indexes into the hs_intrmsi_hdl array.
 */
#define	HERMON_CQH_MAX	32
typedef struct hermon_cq_sched_s {
	char	cqs_name[HERMON_CQH_MAX];
	uint_t	cqs_start_hid;
	uint_t	cqs_len;
	uint_t	cqs_next_alloc;
	uint_t	cqs_desired;
	uint_t	cqs_minimum;
	uint_t	cqs_refcnt;	/* could be alloc'ed more than once */
} hermon_cq_sched_t;

/*
 * new EQ mgmt - per domain (when it gets there).
 * The first hs_rsvd_eqs are reserved by the firmware.
 * The next hs_intrmsi_allocd are for CQ Completions.
 * Each of these "completion" EQs has a unique interrupt vector.
 * The EQs following that are:
 *
 *	1 for CQ Errors
 *	1 for Asyncs and Command Completions, and finally
 *	1 for All Other events.
 *
 * share the last of the interrupt vectors.
 */
#define	HERMON_CQSCHED_NEXT_HID(cq_schedp)				\
	((atomic_inc_uint_nv(&(cq_schedp)->cqs_next_alloc) %		\
	    (cq_schedp)->cqs_len) + (cq_schedp)->cqs_start_hid)

#define	HERMON_HID_TO_EQNUM(state, hid)					\
	((state)->hs_rsvd_eqs + (hid) - 1)

#define	HERMON_HID_VALID(state, hid)					\
	((uint_t)((hid) - 1) < (state)->hs_intrmsi_allocd)

#define	HERMON_EQNUM_TO_HID(state, eqnum)				\
	((eqnum) - (state)->hs_rsvd_eqs + 1)

#define	HERMON_CQ_ERREQNUM_GET(state)					\
	(state)->hs_cq_erreqnum

/*
 * The following defines are used for Hermon CQ error handling.  Note: For
 * CQEs which correspond to error events, the Hermon device requires some
 * special handling by software.  These defines are used to identify and
 * extract the necessary information from each error CQE, including status
 * code (above), doorbell count, and whether a error completion is for a
 * send or receive work request.
 */
#define	HERMON_CQE_ERR_STATUS_SHIFT	0
#define	HERMON_CQE_ERR_STATUS_MASK	0xFF
#define	HERMON_CQE_ERR_DBDCNT_MASK	0xFFFF
#define	HERMON_CQE_SEND_ERR_OPCODE	0x1E
#define	HERMON_CQE_RECV_ERR_OPCODE	0x1E

/* Defines for tracking whether a CQ is being used with special QP or not */
#define	HERMON_CQ_IS_NORMAL		0
#define	HERMON_CQ_IS_SPECIAL		1

/*
 * The hermon_sw_cq_s structure is also referred to using the "hermon_cqhdl_t"
 * typedef (see hermon_typedef.h).  It encodes all the information necessary
 * to track the various resources needed to allocate, initialize, poll, resize,
 * and (later) free a completion queue (CQ).
 *
 * Specifically, it has a consumer index and a lock to ensure single threaded
 * access to it.  It has pointers to the various resources allocated for the
 * completion queue, i.e. a CQC resource and the memory for the completion
 * queue itself. It also has a reference count and the number(s) of the EQs
 * to which it is associated (for success and for errors).
 *
 * Additionally, it has a pointer to the associated MR handle (for the mapped
 * queue memory) and a void pointer that holds the argument that should be
 * passed back to the IBTF when events are generated on the CQ.
 *
 * We also have the always necessary backpointer to the resource for the
 * CQ handle structure itself.  But we also have pointers to the "Work Request
 * ID" processing lists (both the lock and the regular list, as well as the
 * head and tail for the "reapable" list).  See hermon_wrid.c for more details.
 */

#define	HERMON_CQ_DEF_UAR_DOORBELL	0x11	/* cmd_sn = 1, req solicited */
#define	HERMON_CD_DEF_UAR_DB_SHIFT	0x38	/* decimal 56 */

struct hermon_sw_cq_s {
	kmutex_t		cq_lock;
	struct hermon_sw_cq_s 	*cq_resize_hdl; /* points to tranistory hdl */
	uint32_t		cq_consindx;
	uint32_t		cq_cqnum;
	hermon_hw_cqe_t		*cq_buf;
	hermon_mrhdl_t		cq_mrhdl;
	uint32_t		cq_bufsz;
	uint32_t		cq_log_cqsz;
	uint_t			cq_refcnt;
	uint32_t		cq_eqnum;
	uint32_t		cq_erreqnum;
	uint_t			cq_is_special;
	uint_t			cq_is_umap;
	uint32_t		cq_uarpg;
	devmap_cookie_t		cq_umap_dhp;
	hermon_rsrc_t		*cq_cqcrsrcp;
	hermon_rsrc_t		*cq_rsrcp;
	uint_t			cq_intmod_count;
	uint_t			cq_intmod_usec;

	/* DoorBell Record Information */
	ddi_acc_handle_t	cq_arm_ci_dbr_acchdl;
	hermon_dbr_t		*cq_arm_ci_vdbr;
	uint64_t		cq_arm_ci_pdbr;
	uint64_t		cq_dbr_mapoffset;	/* user mode access */

	void			*cq_hdlrarg;

	/* For Work Request ID processing */
	avl_tree_t		cq_wrid_wqhdr_avl_tree;

	struct hermon_qalloc_info_s cq_cqinfo;
};
_NOTE(READ_ONLY_DATA(hermon_sw_cq_s::cq_cqnum
    hermon_sw_cq_s::cq_erreqnum
    hermon_sw_cq_s::cq_cqcrsrcp
    hermon_sw_cq_s::cq_rsrcp
    hermon_sw_cq_s::cq_hdlrarg
    hermon_sw_cq_s::cq_is_umap
    hermon_sw_cq_s::cq_uarpg))
_NOTE(DATA_READABLE_WITHOUT_LOCK(hermon_sw_cq_s::cq_bufsz
    hermon_sw_cq_s::cq_consindx
    hermon_sw_cq_s::cq_cqinfo))
_NOTE(MUTEX_PROTECTS_DATA(hermon_sw_cq_s::cq_lock,
    hermon_sw_cq_s::cq_buf
    hermon_sw_cq_s::cq_eqnum
    hermon_sw_cq_s::cq_mrhdl
    hermon_sw_cq_s::cq_refcnt
    hermon_sw_cq_s::cq_is_special
    hermon_sw_cq_s::cq_umap_dhp))
_NOTE(SCHEME_PROTECTS_DATA("safe sharing",
    hermon_sw_cq_s::cq_intmod_count
    hermon_sw_cq_s::cq_intmod_usec
    hermon_sw_cq_s::cq_resize_hdl))

int hermon_cq_alloc(hermon_state_t *state, ibt_cq_hdl_t ibt_cqhdl,
    ibt_cq_attr_t *attr_p, uint_t *actual_size, hermon_cqhdl_t *cqhdl,
    uint_t sleepflag);
int hermon_cq_free(hermon_state_t *state, hermon_cqhdl_t *cqhdl,
    uint_t sleepflag);
int hermon_cq_resize(hermon_state_t *state, hermon_cqhdl_t cqhdl,
    uint_t req_size, uint_t *actual_size, uint_t sleepflag);
int hermon_cq_modify(hermon_state_t *state, hermon_cqhdl_t cqhdl,
    uint_t count, uint_t usec, ibt_cq_handler_id_t hid, uint_t sleepflag);
int hermon_cq_notify(hermon_state_t *state, hermon_cqhdl_t cqhdl,
    ibt_cq_notify_flags_t flags);
int hermon_cq_poll(hermon_state_t *state, hermon_cqhdl_t cqhdl, ibt_wc_t *wc_p,
    uint_t num_wc, uint_t *num_polled);
int hermon_cq_sched_alloc(hermon_state_t *state, ibt_cq_sched_attr_t *attr,
    hermon_cq_sched_t **cq_sched_pp);
int hermon_cq_sched_free(hermon_state_t *state, hermon_cq_sched_t *cq_schedp);
int hermon_cq_handler(hermon_state_t *state, hermon_eqhdl_t eq,
    hermon_hw_eqe_t *eqe);
int hermon_cq_err_handler(hermon_state_t *state, hermon_eqhdl_t eq,
    hermon_hw_eqe_t *eqe);
int hermon_cq_refcnt_inc(hermon_cqhdl_t cq, uint_t is_special);
void hermon_cq_refcnt_dec(hermon_cqhdl_t cq);
hermon_cqhdl_t hermon_cqhdl_from_cqnum(hermon_state_t *state, uint_t cqnum);
void hermon_cq_entries_flush(hermon_state_t *state, hermon_qphdl_t qp);
void hermon_cq_resize_helper(hermon_state_t *state, hermon_cqhdl_t cq);
int hermon_cq_sched_init(hermon_state_t *state);
void hermon_cq_sched_fini(hermon_state_t *state);

#ifdef __cplusplus
}
#endif

#endif	/* _SYS_IB_ADAPTERS_HERMON_CQ_H */