xref: /illumos-gate/usr/src/uts/common/sys/ib/adapters/tavor/tavor_cmd.h (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_IB_ADAPTERS_TAVOR_CMD_H
28 #define	_SYS_IB_ADAPTERS_TAVOR_CMD_H
29 
30 /*
31  * tavor_cmd.h
32  *    Contains all of the prototypes, #defines, and structures necessary
33  *    for the Tavor Firmware Command routines.
34  *    Specifically it contains the command types, command statuses and flags,
35  *    structures used for managing Tavor mailboxes and outstanding commands,
36  *    and prototypes for most of the functions consumed by other parts of
37  *    the Tavor driver.
38  */
39 
40 #include <sys/types.h>
41 #include <sys/conf.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 
45 #include <sys/ib/mgt/sm_attr.h>
46 
47 #ifdef __cplusplus
48 extern "C" {
49 #endif
50 
51 
52 /*
53  * Defines used tavor_write_hcr() to determine the duration and number of
54  * times (at maximum) to poll while waiting for a Tavor firmware command to
55  * release the HCR resource (i.e. waiting for the command to complete)
56  */
57 #define	TAVOR_CMD_POLL_DELAY		1
58 #define	TAVOR_CMD_POLL_MAX		3000000
59 
60 /*
61  * The following defines specify the default number of mailboxes (log 2) of
62  * each type and their size and alignment restrictions.  By default the number
63  * of both "In" and "Out" mailboxes is set to eight (with each mailbox being
64  * 512 bytes in size), but both the number and sizes of each are controllable
65  * through the "tavor_log_num_inmbox", "tavor_log_num_outmbox",
66  * "tavor_log_inmbox_size" and "tavor_log_outmbox_size" configuration
67  * variables.
68  */
69 #define	TAVOR_NUM_MAILBOXES_SHIFT	8
70 #define	TAVOR_NUM_INTR_MAILBOXES_SHIFT	0
71 #define	TAVOR_MBOX_SIZE_SHIFT		0x9
72 #define	TAVOR_MBOX_SIZE			(1 << TAVOR_MBOX_SIZE_SHIFT)
73 #define	TAVOR_MBOX_ALIGN		TAVOR_MBOX_SIZE
74 
75 /*
76  * The following macro determines whether the contents of given mailbox
77  * type need to be sync'd (with ddi_dma_sync()).  This decision is based
78  * on whether the mailbox is in DDR memory (no sync) or system memory
79  * (sync required).  And it also supports the possibility that if a CQ in
80  * system memory is mapped DDI_DMA_CONSISTENT, it can be configured to not be
81  * sync'd because of the "sync override" parameter in the config profile.
82  */
83 #define	TAVOR_MBOX_IS_SYNC_REQ(state, type)				\
84 	((((((state)->ts_cfg_profile->cp_streaming_consistent) &&	\
85 	((state)->ts_cfg_profile->cp_consistent_syncoverride))) ||      \
86 	((&((state)->ts_rsrc_hdl[(type)]))->rsrc_loc == TAVOR_IN_DDR))	\
87 	? 0 : 1)
88 
89 /*
90  * These are the defines for the Tavor command type (opcodes).  They are
91  * specified by the Tavor register specification
92  */
93 #define	SYS_EN				0x1
94 #define	SYS_DIS				0x2
95 #define	QUERY_DEV_LIM			0x3
96 #define	QUERY_FW			0x4
97 #define	QUERY_DDR			0x5
98 #define	QUERY_ADAPTER			0x6
99 #define	INIT_HCA			0x7
100 #define	CLOSE_HCA			0x8
101 #define	INIT_IB				0x9
102 #define	CLOSE_IB			0xA
103 #define	QUERY_HCA			0xB
104 #define	SET_IB				0xC
105 #define	ACCESS_DDR			0x2E
106 #define	SW2HW_MPT			0xD
107 #define	QUERY_MPT			0xE
108 #define	HW2SW_MPT			0xF
109 #define	READ_MTT			0x10
110 #define	WRITE_MTT			0x11
111 #define	SYNC_TPT			0x2F
112 #define	MAP_EQ				0x12
113 #define	SW2HW_EQ			0x13
114 #define	HW2SW_EQ			0x14
115 #define	QUERY_EQ			0x15
116 #define	SW2HW_CQ			0x16
117 #define	HW2SW_CQ			0x17
118 #define	QUERY_CQ			0x18
119 #define	RESIZE_CQ			0x2C
120 #define	RST2INIT_QP			0x19
121 #define	INIT2INIT_QP			0x2D
122 #define	INIT2RTR_QP			0x1A
123 #define	RTR2RTS_QP			0x1B
124 #define	RTS2RTS_QP			0x1C
125 #define	SQERR2RTS_QP			0x1D
126 #define	TOERR_QP			0x1E
127 #define	RTS2SQD_QP			0x1F
128 #define	SQD2RTS_QP			0x20
129 #define	TORST_QP			0x21
130 #define	QUERY_QP			0x22
131 #define	CONF_SPECIAL_QP			0x23
132 #define	MAD_IFC				0x24
133 #define	READ_MGM			0x25
134 #define	WRITE_MGM			0x26
135 #define	MGID_HASH			0x27
136 #define	CONF_NTU			0x28
137 #define	QUERY_NTU			0x29
138 #define	QUERY_DEBUG_MSG			0x2A
139 #define	SET_DEBUG_MSG			0x2B
140 #define	DIAG_RPRT			0x30
141 #define	MOD_STAT_CFG			0x34
142 #define	SW2HW_SRQ			0x35
143 #define	HW2SW_SRQ			0x36
144 #define	QUERY_SRQ			0x37
145 #define	SQD2SQD_QP			0x38
146 #define	MODIFY_MPT			0x39
147 
148 /*
149  * These are the defines for the Tavor command completion statuses.  They are
150  * also specified (in part) by the Tavor register specification.  However,
151  * the TAVOR_CMD_INSUFF_RSRC, TAVOR_CMD_TIMEOUT and TAVOR_CMD_INVALID_STATUS
152  * codes were added for this driver specifically to indicate the conditions
153  * when insufficient resources are available for a command, when a command has
154  * timed out (failure in the Tavor firmware) or when some other invalid result
155  * was received.
156  */
157 #define	TAVOR_CMD_INSUFF_RSRC		0xFFFD
158 #define	TAVOR_CMD_TIMEOUT		0xFFFE
159 #define	TAVOR_CMD_INVALID_STATUS	0xFFFF
160 #define	TAVOR_CMD_SUCCESS		0x00
161 #define	TAVOR_CMD_INTERNAL_ERR		0x01
162 #define	TAVOR_CMD_BAD_OP		0x02
163 #define	TAVOR_CMD_BAD_PARAM		0x03
164 #define	TAVOR_CMD_BAD_SYS_STATE		0x04
165 #define	TAVOR_CMD_BAD_RESOURCE		0x05
166 #define	TAVOR_CMD_RESOURCE_BUSY		0x06
167 #define	TAVOR_CMD_DDR_MEM_ERR		0x07
168 #define	TAVOR_CMD_EXCEED_LIM		0x08
169 #define	TAVOR_CMD_BAD_RES_STATE		0x09
170 #define	TAVOR_CMD_BAD_INDEX		0x0A
171 #define	TAVOR_CMD_BAD_NVMEM		0x0B
172 #define	TAVOR_CMD_BAD_QP_STATE		0x10
173 #define	TAVOR_CMD_BAD_SEG_PARAM		0x20
174 #define	TAVOR_CMD_REG_BOUND		0x21
175 #define	TAVOR_CMD_BAD_PKT		0x30
176 #define	TAVOR_CMD_BAD_SIZE		0x40
177 
178 /*
179  * These defines are used in the "special QP" allocation to indicate the type
180  * of special QP (SMI, GSI, or one of the raw types).  These values are
181  * specified by the Tavor register specification
182  */
183 #define	TAVOR_CMD_QP_SMI		0
184 #define	TAVOR_CMD_QP_GSI		1
185 #define	TAVOR_CMD_QP_RAW_IPV6		2
186 #define	TAVOR_CMD_QP_RAW_ETH		3
187 
188 /*
189  * For certain Tavor QP state transition commands some optional flags are
190  * allowed.  These "opmask" flags are defined by the Tavor register
191  * specification as a bitmask.
192  */
193 #define	TAVOR_CMD_OP_ALT_PATH		(1 << 0)
194 #define	TAVOR_CMD_OP_RRE		(1 << 1)
195 #define	TAVOR_CMD_OP_RAE		(1 << 2)
196 #define	TAVOR_CMD_OP_RWE		(1 << 3)
197 #define	TAVOR_CMD_OP_PKEYINDX		(1 << 4)
198 #define	TAVOR_CMD_OP_QKEY		(1 << 5)
199 #define	TAVOR_CMD_OP_MINRNRNAK		(1 << 6)
200 #define	TAVOR_CMD_OP_PRIM_PATH		(1 << 7)
201 #define	TAVOR_CMD_OP_SRA_SET		(1 << 8)
202 #define	TAVOR_CMD_OP_RRA_SET		(1 << 9)
203 #define	TAVOR_CMD_OP_PM_STATE		(1 << 10)
204 #define	TAVOR_CMD_OP_PRIM_PORT		(1 << 11)
205 #define	TAVOR_CMD_OP_RETRYCNT		(1 << 12)
206 #define	TAVOR_CMD_OP_ALT_RNRRETRY	(1 << 13)
207 #define	TAVOR_CMD_OP_ACKTIMEOUT		(1 << 14)
208 #define	TAVOR_CMD_OP_PRIM_RNRRETRY	(1 << 15)
209 #define	TAVOR_CMD_OP_SCHEDQUEUE		(1 << 16)
210 
211 
212 /*
213  * The Tavor RTS2SQD command can take the following flag as part of its
214  * input modifier to request the Send Queue Drained event
215  */
216 #define	TAVOR_CMD_REQ_SQD_EVENT		0x80000000
217 
218 /*
219  * The Tavor TORST command can take the following flag (as part of a bitmask)
220  * in its opcode modifier to request that the transition to reset should
221  * not go through the Error state (and, hence, should not generate "flushed-
222  * in-error" completions
223  */
224 #define	TAVOR_CMD_DIRECT_TO_RESET	(1 << 1)
225 
226 /*
227  * Some Tavor commands write an OUT mailbox entry, depending on the value of
228  * the 'opmod' parameter.  These defines provide the correct opmod value to
229  * write depending on whether to write an entry or not.
230  */
231 #define	TAVOR_CMD_DO_OUTMBOX		(0)
232 #define	TAVOR_CMD_NO_OUTMBOX		(1 << 0)
233 
234 /*
235  * The Tavor SYS_EN command can take the following opcode modifier options
236  * to specify whether certain DDR checks should be performed.
237  */
238 #define	TAVOR_CMD_SYS_EN_NORMAL		0
239 #define	TAVOR_CMD_SYS_EN_DDR_MEMCHECK	2
240 #define	TAVOR_CMD_SYS_EN_DDR_PRESERVE	3
241 
242 /*
243  * The Tavor MAP_EQ command can take the following flags (and use the
244  * TAVOR_CMD_UNMAP_EQ_MASK input modifier) to indicate whether the given
245  * event queue should mapped to or unmapped from the given event type.
246  */
247 #define	TAVOR_CMD_MAP_EQ_EVT_MAP	0
248 #define	TAVOR_CMD_MAP_EQ_EVT_UNMAP	1
249 #define	TAVOR_CMD_UNMAP_EQ_MASK		0x80000000
250 
251 /*
252  * The following defines are used by the MAD_IFC command and the helper
253  * routines that get PortInfo, NodeInfo, GUIDInfo, and PKeyTable entries.
254  *
255  * The first indicates whether of not MKey checking should be enforced.
256  * This is passed in the opcode modifier field for MAD_IFC commands.
257  *
258  * The next set are used to define certain hardcoded management datagram (MAD)
259  * sizes, offsets, and header formats for each of the helper operations.
260  */
261 #define	TAVOR_CMD_MKEY_CHECK		0
262 #define	TAVOR_CMD_MKEY_DONTCHECK	1
263 
264 #define	TAVOR_CMD_MAD_IFC_SIZE		0x100
265 #define	TAVOR_CMD_MADDATA_OFFSET	0x40
266 #define	TAVOR_CMD_MADHDR0		0x01010101
267 #define	TAVOR_CMD_MADHDR1		0x00000000
268 #define	TAVOR_CMD_MADHDR2		0x00000000
269 #define	TAVOR_CMD_MADHDR3		0x00000000
270 #define	TAVOR_CMD_PORTINFO		0x00150000
271 #define	TAVOR_CMD_NODEINFO		0x00110000
272 #define	TAVOR_CMD_NODEDESC		0x00100000
273 #define	TAVOR_CMD_GUIDINFO		0x00140000
274 #define	TAVOR_CMD_PKEYTBLE		0x00160000
275 
276 /*
277  * The next few defines are used to indicate the size of the "reserved" area
278  * in the WRITE_MTT command, and the respective sizes of the SET_IB and
279  * MGID_HASH commands
280  */
281 #define	TAVOR_CMD_WRITEMTT_RSVD_SZ	0x10
282 #define	TAVOR_CMD_SETIB_SZ		0x8
283 #define	TAVOR_CMD_MGIDHASH_SZ		0x10
284 
285 /*
286  * This last define is used by tavor_cmn_ownership_cmd_post() to keep track
287  * of the direction (from hardware ownership to software, or vice versa) of
288  * the requested operation
289  */
290 #define	TAVOR_CMD_RSRC_HW2SW		0
291 #define	TAVOR_CMD_RSRC_SW2HW		1
292 
293 /*
294  * The following macros are used for handling any endianness related issues
295  * that might arise from the Tavor driver's internal use of MADs.
296  *
297  *    TAVOR_GETPORTINFO_SWAP	- All the necessary swapping to handle the
298  *				    response to a GetPortInfo MAD
299  *    TAVOR_GETNODEINFO_SWAP	- All the necessary swapping to handle the
300  *				    response to a GetNodeInfo MAD
301  *    TAVOR_GETGUIDINFO_SWAP	- All the necessary swapping to handle the
302  *				    response to a GetGUIDInfo MAD
303  *    TAVOR_GETPKEYTABLE_SWAP	- All the necessary swapping to handle the
304  *				    response to a GetPKeyTable MAD
305  */
306 #ifdef	_LITTLE_ENDIAN
307 #define	TAVOR_GETPORTINFO_SWAP(portinfo)				\
308 {									\
309 	(portinfo)->M_Key = ddi_swap64((portinfo)->M_Key);		\
310 	(portinfo)->GidPrefix = ddi_swap64((portinfo)->GidPrefix);	\
311 	(portinfo)->LID = ddi_swap16((portinfo)->LID);			\
312 	(portinfo)->MasterSMLID = ddi_swap16((portinfo)->MasterSMLID);	\
313 	(portinfo)->CapabilityMask =					\
314 	    ddi_swap32((portinfo)->CapabilityMask);			\
315 	(portinfo)->DiagCode = ddi_swap16((portinfo)->DiagCode);	\
316 	(portinfo)->M_KeyLeasePeriod =					\
317 	    ddi_swap16((portinfo)->M_KeyLeasePeriod);			\
318 	(portinfo)->M_KeyViolations =					\
319 	    ddi_swap16((portinfo)->M_KeyViolations);			\
320 	(portinfo)->P_KeyViolations =					\
321 	    ddi_swap16((portinfo)->P_KeyViolations);			\
322 	(portinfo)->Q_KeyViolations =					\
323 	    ddi_swap16((portinfo)->Q_KeyViolations);			\
324 }
325 #else
326 #define	TAVOR_GETPORTINFO_SWAP(portinfo)
327 #endif
328 
329 #ifdef	_LITTLE_ENDIAN
330 #define	TAVOR_GETNODEINFO_SWAP(nodeinfo)				\
331 {									\
332 	uint32_t	tmp;						\
333 									\
334 	tmp = ddi_swap32(((uint32_t *)nodeinfo)[9]);			\
335 	(nodeinfo)->VendorID	 = tmp & 0xFFFFFF;			\
336 	(nodeinfo)->LocalPortNum = tmp >> 24;				\
337 	(nodeinfo)->Revision	 =					\
338 	    ddi_swap32(((uint32_t *)nodeinfo)[8]);			\
339 	tmp = ddi_swap32(((uint32_t *)nodeinfo)[7]);			\
340 	(nodeinfo)->PartitionCap = tmp >> 16;				\
341 	(nodeinfo)->DeviceID	 = tmp & 0xFFFF;			\
342 	(nodeinfo)->PortGUID = ddi_swap64((((uint64_t)			\
343 	    (((uint32_t *)nodeinfo)[6]) << 32) |			\
344 	    ((uint32_t *)nodeinfo)[5]));				\
345 	(nodeinfo)->NodeGUID = ddi_swap64((((uint64_t)			\
346 	    (((uint32_t *)nodeinfo)[4]) << 32) |			\
347 	    ((uint32_t *)nodeinfo)[3]));				\
348 	(nodeinfo)->SystemImageGUID = ddi_swap64((((uint64_t)		\
349 	    (((uint32_t *)nodeinfo)[2]) << 32) |			\
350 	    ((uint32_t *)nodeinfo)[1]));				\
351 }
352 #else
353 #define	TAVOR_GETNODEINFO_SWAP(nodeinfo)				\
354 {									\
355 	uint32_t	tmp;						\
356 									\
357 	tmp = ((uint32_t *)nodeinfo)[9];				\
358 	(nodeinfo)->VendorID	 = tmp & 0xFFFFFF;			\
359 	(nodeinfo)->LocalPortNum = tmp >> 24;				\
360 	(nodeinfo)->Revision	 = ((uint32_t *)nodeinfo)[8];		\
361 	tmp = ((uint32_t *)nodeinfo)[7];				\
362 	(nodeinfo)->PartitionCap = tmp >> 16;				\
363 	(nodeinfo)->DeviceID	 = tmp & 0xFFFF;			\
364 	(nodeinfo)->PortGUID = (((uint64_t)				\
365 	    (((uint32_t *)nodeinfo)[5]) << 32) |			\
366 	    ((uint32_t *)nodeinfo)[6]);					\
367 	(nodeinfo)->NodeGUID = (((uint64_t)				\
368 	    (((uint32_t *)nodeinfo)[3]) << 32) |			\
369 	    ((uint32_t *)nodeinfo)[4]);					\
370 	(nodeinfo)->SystemImageGUID = (((uint64_t)			\
371 	    (((uint32_t *)nodeinfo)[1]) << 32) |			\
372 	    ((uint32_t *)nodeinfo)[2]);					\
373 }
374 #endif
375 
376 #ifdef	_LITTLE_ENDIAN
377 #define	TAVOR_GETGUIDINFO_SWAP(guidinfo)				\
378 {									\
379 	int	i;							\
380 									\
381 	for (i = 0; i < 8; i++) {					\
382 		(guidinfo)->GUIDBlocks[i] =				\
383 		    ddi_swap64((guidinfo)->GUIDBlocks[i]);		\
384 	}								\
385 }
386 #else
387 #define	TAVOR_GETGUIDINFO_SWAP(guidinfo)
388 #endif
389 
390 #ifdef	_LITTLE_ENDIAN
391 #define	TAVOR_GETPKEYTABLE_SWAP(pkeytable)				\
392 {									\
393 	int	i;							\
394 									\
395 	for (i = 0; i < 32; i++) {					\
396 		(pkeytable)->P_KeyTableBlocks[i] =			\
397 		    ddi_swap16((pkeytable)->P_KeyTableBlocks[i]);	\
398 	}								\
399 }
400 #else
401 #define	TAVOR_GETPKEYTABLE_SWAP(pkeytable)
402 #endif
403 
404 /*
405  * The Tavor MODIFY_MPT command can take the following opcode modifier
406  * options to specify whether to modify for ResizeSRQ() or to swap the
407  * full MPT entry.
408  */
409 #define	TAVOR_CMD_MODIFY_MPT_RESIZESRQ	3
410 #define	TAVOR_CMD_MODIFY_MPT_SWAPFULL	5
411 
412 
413 /*
414  * The tavor_mbox_t structure is used internally by the Tavor driver to track
415  * all the information necessary to manage mailboxes for the Tavor command
416  * interface.  Specifically, by containing a pointer to the buffer, the
417  * PCI mapped address, the access handle, and a back pointer to the
418  * tavor_rsrc_t structure used to track this resource, it provides enough
419  * information allocate, use, and free any type of mailbox.
420  *
421  * The mb_indx, mb_next, and mb_prev fields are used only by the mailbox
422  * alloc/free routines (see tavor_impl_mbox_alloc/free() for more details)
423  * and are not read or modified by any mailbox consumers.  They are used
424  * to implement a fast allocation mechanism.
425  */
426 typedef struct tavor_mbox_s {
427 	void			*mb_addr;
428 	uint64_t		mb_mapaddr;
429 	ddi_acc_handle_t	mb_acchdl;
430 	tavor_rsrc_t		*mb_rsrcptr;
431 	uint_t			mb_sync;
432 	uint_t			mb_indx;
433 	uint_t			mb_next;
434 	uint_t			mb_prev;
435 } tavor_mbox_t;
436 
437 /*
438  * The tavor_mboxlist_t structure is used to track all the information
439  * relevant to the pools of Tavor mailboxes.  Specifically, it has a pointer
440  * to an array of tavor_mbox_t structures, a lock and cv used for blocking
441  * on alloc when mailboxes are not available, and a head, tail, and entries
442  * free counter to keep track of which (if any) mailboxes are currently free.
443  * This is used (along with the mb_indx, mb_next, and mb_prev fields in the
444  * tavor_mbox_t) to implement the fast allocation mechanism.
445  */
446 typedef struct tavor_mboxlist_s {
447 	kmutex_t		mbl_lock;
448 	kcondvar_t		mbl_cv;
449 	tavor_mbox_t		*mbl_mbox;
450 	uint_t			mbl_list_sz;
451 	uint_t			mbl_num_alloc;
452 	uint_t			mbl_head_indx;
453 	uint_t			mbl_tail_indx;
454 	uint_t			mbl_entries_free;
455 	uint_t			mbl_waiters;
456 	uint_t			mbl_pollers;
457 	uint_t			mbl_signal;
458 } tavor_mboxlist_t;
459 _NOTE(MUTEX_PROTECTS_DATA(tavor_mboxlist_t::mbl_lock,
460     tavor_mboxlist_t::mbl_mbox
461     tavor_mboxlist_t::mbl_list_sz
462     tavor_mboxlist_t::mbl_num_alloc
463     tavor_mboxlist_t::mbl_cv
464     tavor_mboxlist_t::mbl_head_indx
465     tavor_mboxlist_t::mbl_tail_indx
466     tavor_mboxlist_t::mbl_entries_free
467     tavor_mboxlist_t::mbl_waiters
468     tavor_mboxlist_t::mbl_pollers
469     tavor_mboxlist_t::mbl_signal
470     tavor_mbox_t::mb_next
471     tavor_mbox_t::mb_prev))
472 
473 /*
474  * The tavor_mbox_info_t structure is used by mailbox allocators to specify
475  * the type of mailbox(es) being requested.  On a call to tavor_mbox_alloc()
476  * the mbi_alloc_flags may be set to TAVOR_ALLOC_INMBOX, TAVOR_ALLOC_OUTMBOX,
477  * or both.  If it is able to allocate the request type(s) of mailboxes,
478  * tavor_mbox_alloc() will fill in the "mbi_in" and/or "mbi_out" pointers
479  * to point to valid tavor_mbox_t structures from the appropriate
480  * tavor_mboxlist_t (see above).
481  * This same structure is also passed to tavor_mbox_free().  It is the
482  * responsibility of the caller to tavor_mbox_alloc() to return this exact
483  * structure (unmodified) to tavor_mbox_free().
484  *
485  * Note: If both "In" and "Out" mailboxes are requested, it is assured that
486  * no deadlock can result (from holding one mailbox while attempting to get
487  * the other).  This is assured by the fact that the "In" mailbox will always
488  * be allocated first before attempting to allocate the "Out"
489  */
490 typedef struct tavor_mbox_info_s {
491 	uint_t			mbi_alloc_flags;
492 	uint_t			mbi_sleep_context;
493 	tavor_mbox_t		*mbi_in;
494 	tavor_mbox_t		*mbi_out;
495 } tavor_mbox_info_t;
496 #define	TAVOR_ALLOC_INMBOX	(1 << 0)
497 #define	TAVOR_ALLOC_OUTMBOX	(1 << 1)
498 
499 
500 /*
501  * The tavor_cmd_t structure is used internally by the Tavor driver to track
502  * all the information necessary to manage outstanding firmware commands on
503  * the Tavor command interface.
504  *
505  * Each tavor_cmd_t structure contains a cv and lock which are used by the
506  * posting thread to block for completion (with cmd_status being overloaded
507  * to indicate the condition variable).  The cmd_outparam field is used to
508  * return additional status from those Tavor commands that specifically
509  * require it.
510  *
511  * The cmd_indx, cmd_next, and cmd_prev fields are used by the outstanding
512  * command alloc/free routines (see tavor_outstanding_cmd_alloc/free() for
513  * more details).  They are used (in much the same way as the mb_indx,
514  * mb_next, and mb_prev fields in tavor_mbox_t above) to implement a fast
515  * allocation mechanism.
516  */
517 typedef struct tavor_cmd_s {
518 	kmutex_t		cmd_comp_lock;
519 	kcondvar_t		cmd_comp_cv;
520 	uint64_t		cmd_outparm;
521 	uint_t			cmd_status;
522 	uint_t			cmd_indx;
523 	uint_t			cmd_next;
524 	uint_t			cmd_prev;
525 } tavor_cmd_t;
526 _NOTE(MUTEX_PROTECTS_DATA(tavor_cmd_t::cmd_comp_lock,
527     tavor_cmd_t::cmd_comp_cv
528     tavor_cmd_t::cmd_status))
529 
530 /*
531  * The tavor_cmdlist_t structure is used in almost exactly the same way as
532  * the tavor_mboxlist_t above, but instead to track all the information
533  * relevant to the pool of outstanding Tavor commands.  Specifically, it has
534  * a pointer to an array of tavor_cmd_t structures, a lock and cv used for
535  * blocking on alloc when outstanding command slots are not available, and a
536  * head, tail, and entries free counter to keep track of which (if any)
537  * command slots are currently free.  This is used (along with the cmd_indx,
538  * cmd_next, and cmd_prev fields in the tavor_cmd_t) to implement the fast
539  * allocation mechanism.
540  */
541 typedef struct tavor_cmdlist_s {
542 	kmutex_t		cml_lock;
543 	kcondvar_t		cml_cv;
544 	tavor_cmd_t		*cml_cmd;
545 	uint_t			cml_list_sz;
546 	uint_t			cml_num_alloc;
547 	uint_t			cml_head_indx;
548 	uint_t			cml_tail_indx;
549 	uint_t			cml_entries_free;
550 	uint_t			cml_waiters;
551 } tavor_cmdlist_t;
552 _NOTE(MUTEX_PROTECTS_DATA(tavor_cmdlist_t::cml_lock,
553     tavor_cmdlist_t::cml_cv
554     tavor_cmdlist_t::cml_cmd
555     tavor_cmdlist_t::cml_list_sz
556     tavor_cmdlist_t::cml_num_alloc
557     tavor_cmdlist_t::cml_head_indx
558     tavor_cmdlist_t::cml_tail_indx
559     tavor_cmdlist_t::cml_entries_free
560     tavor_cmdlist_t::cml_waiters
561     tavor_cmd_t::cmd_next
562     tavor_cmd_t::cmd_prev))
563 _NOTE(LOCK_ORDER(tavor_cmdlist_t::cml_lock
564     tavor_cmd_t::cmd_comp_lock))
565 
566 /*
567  * The tavor_cmd_post_t structure is used by all the Tavor Firmware Command
568  * routines to post to Tavor firmware.  The fields almost exactly mimic
569  * the fields in the Tavor HCR registers.  The notable exception is the
570  * addition of the "cp_flags" field (which can be set to TAVOR_CMD_SPIN or
571  * TAVOR_CMD_NOSPIN).  This flag really controls the value of the "e" bit
572  * in the HCR (i.e. the bit to indicate whether command should complete
573  * "in place" - in the HCR - or whether they should have their completions
574  * written to the command completion event queue.  TAVOR_CMD_SPIN means
575  * to allow commands to complete "in place" and to poll the "go" bit in
576  * the HCR to determine completion.
577  *
578  * We use TAVOR_SLEEP and TAVOR_NOSLEEP for our TAVOR_CMD_ #defines.  This is
579  * to maintain consistency with the rest of the SLEEP flags.  Additionally,
580  * because TAVOR_SLEEPFLAG_FOR_CONTEXT() in tavor_rsrc.h returns TAVOR_SLEEP or
581  * NOSLEEP we must be compatible with this macro.
582  */
583 typedef struct tavor_cmd_post_s {
584 	uint64_t		cp_inparm;
585 	uint64_t		cp_outparm;
586 	uint32_t		cp_inmod;
587 	uint16_t		cp_opcode;
588 	uint16_t		cp_opmod;
589 	uint32_t		cp_flags;
590 } tavor_cmd_post_t;
591 #define	TAVOR_CMD_SLEEP_NOSPIN		TAVOR_SLEEP
592 #define	TAVOR_CMD_NOSLEEP_SPIN		TAVOR_NOSLEEP
593 
594 
595 /*
596  * The following are the Tavor Firmware Command routines that accessible
597  * externally (i.e. throughout the rest of the Tavor driver software).
598  * These include the all the alloc/free routines, some initialization
599  * and cleanup routines, and the various specific Tavor firmware commands.
600  */
601 int tavor_cmd_post(tavor_state_t *state, tavor_cmd_post_t *cmdpost);
602 int tavor_mbox_alloc(tavor_state_t *state, tavor_mbox_info_t *mbox_info,
603     uint_t mbox_wait);
604 void tavor_mbox_free(tavor_state_t *state, tavor_mbox_info_t *mbox_info);
605 int tavor_cmd_complete_handler(tavor_state_t *state, tavor_eqhdl_t eq,
606     tavor_hw_eqe_t *eqe);
607 int tavor_inmbox_list_init(tavor_state_t *state);
608 int tavor_intr_inmbox_list_init(tavor_state_t *state);
609 int tavor_outmbox_list_init(tavor_state_t *state);
610 int tavor_intr_outmbox_list_init(tavor_state_t *state);
611 void tavor_inmbox_list_fini(tavor_state_t *state);
612 void tavor_intr_inmbox_list_fini(tavor_state_t *state);
613 void tavor_outmbox_list_fini(tavor_state_t *state);
614 void tavor_intr_outmbox_list_fini(tavor_state_t *state);
615 int tavor_outstanding_cmdlist_init(tavor_state_t *state);
616 void tavor_outstanding_cmdlist_fini(tavor_state_t *state);
617 
618 /*
619  * SYS_EN and SYS_DIS - used for startup and shutdown of Tavor device
620  */
621 int tavor_sys_en_cmd_post(tavor_state_t *state, uint_t flags,
622     uint64_t *errorcode, uint_t sleepflag);
623 int tavor_sys_dis_cmd_post(tavor_state_t *state, uint_t sleepflag);
624 
625 /*
626  * INIT_HCA and CLOSE_HCA - used for initialization and teardown of Tavor
627  * device configuration
628  */
629 int tavor_init_hca_cmd_post(tavor_state_t *state,
630     tavor_hw_initqueryhca_t *inithca, uint_t sleepflag);
631 int tavor_close_hca_cmd_post(tavor_state_t *state, uint_t sleepflag);
632 
633 /*
634  * INIT_IB, CLOSE_IB, and SET_IB - used for bring Tavor ports up and down,
635  * and to set properties of each port (e.g. PortInfo capability mask)
636  */
637 int tavor_init_ib_cmd_post(tavor_state_t *state,
638     tavor_hw_initib_t *initib, uint_t port, uint_t sleepflag);
639 int tavor_close_ib_cmd_post(tavor_state_t *state, uint_t port,
640     uint_t sleepflag);
641 int tavor_set_ib_cmd_post(tavor_state_t *state, uint32_t capmask,
642     uint_t port, uint_t reset_qkey, uint_t sleepflag);
643 
644 /*
645  * This common function is used to post the following Tavor QP state
646  * transition firmware commands:
647  * RTS2SQD, TOERR, TORST, RST2INIT, INIT2INIT, INIT2RTR, RTR2RTS, RTS2RTS,
648  * SQD2SQD, SQD2RTS, and SQERR2RTS.
649  */
650 int tavor_cmn_qp_cmd_post(tavor_state_t *state, uint_t opcode,
651     tavor_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask, uint_t sleepflag);
652 
653 /*
654  * This common function is used to post the following Tavor query firmware
655  * commands:
656  * QUERY_DEV_LIM, QUERY_FW, QUERY_DDR, QUERY_ADAPTER, QUERY_HCA, QUERY_MPT,
657  * QUERY_EQ, QUERY_CQ, and QUERY_QP.
658  */
659 int tavor_cmn_query_cmd_post(tavor_state_t *state, uint_t opcode,
660     uint_t queryindx, void *query, uint_t size, uint_t sleepflag);
661 
662 /*
663  * This common function is used to post the following Tavor resource ownership
664  * firmware commands:
665  * HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and SW2HW_CQ
666  */
667 int tavor_cmn_ownership_cmd_post(tavor_state_t *state, uint_t opcode,
668     void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag);
669 
670 /*
671  * MAD_IFC and helper functions - used for posting IB MADs to Tavor firmware.
672  * The helper functions are for the MADs most frequently used by the Tavor
673  * driver (internally).
674  */
675 int tavor_mad_ifc_cmd_post(tavor_state_t *state, uint_t port,
676     uint_t sleepflag, uint32_t *mad, uint32_t *resp);
677 int tavor_getportinfo_cmd_post(tavor_state_t *state, uint_t port,
678     uint_t sleepflag, sm_portinfo_t *portinfo);
679 int tavor_getnodeinfo_cmd_post(tavor_state_t *state, uint_t sleepflag,
680     sm_nodeinfo_t *nodeinfo);
681 int tavor_getnodedesc_cmd_post(tavor_state_t *state, uint_t sleepflag,
682     sm_nodedesc_t *nodedesc);
683 int tavor_getguidinfo_cmd_post(tavor_state_t *state, uint_t port,
684     uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo);
685 int tavor_getpkeytable_cmd_post(tavor_state_t *state, uint_t port,
686     uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable);
687 
688 /*
689  * WRITE_MTT - used for write MTT entries to the Tavor MTT table
690  */
691 int tavor_write_mtt_cmd_post(tavor_state_t *state,
692     tavor_mbox_info_t *mbox_info, uint_t num_mtt, uint_t sleepflag);
693 
694 /*
695  * SYNC_TPT - used to sync Tavor TPT caches
696  */
697 int tavor_sync_tpt_cmd_post(tavor_state_t *state, uint_t sleepflag);
698 
699 /*
700  * MAP_EQ - used for map classes of events to Tavor event queues (EQ)
701  */
702 int tavor_map_eq_cmd_post(tavor_state_t *state, uint_t map,
703     uint_t eqcindx, uint64_t eqmapmask, uint_t sleepflag);
704 
705 /*
706  * RESIZE_CQ - used for resize completion queue (CQ)
707  */
708 int tavor_resize_cq_cmd_post(tavor_state_t *state, tavor_hw_cqc_t *cqc,
709     uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag);
710 
711 /*
712  * CONF_SPECIAL_QP - used to configure a pair of queue pairs for use as
713  * special QP.  Necessary to enable full QP0 and/or QP1 operation.
714  */
715 int tavor_conf_special_qp_cmd_post(tavor_state_t *state, uint_t qpindx,
716     uint_t qptype, uint_t sleepflag);
717 
718 /*
719  * MGID_HASH, READ_MGM, and WRITE_MGM - used for manipulation of the
720  * hardware resource tables for multicast groups.
721  */
722 int tavor_mgid_hash_cmd_post(tavor_state_t *state, uint64_t mgid_h,
723     uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag);
724 int tavor_read_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg,
725     uint_t mcgindx, uint_t sleepflag);
726 int tavor_write_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg,
727     uint_t mcgindx, uint_t sleepflag);
728 
729 /*
730  * MOD_STAT_CFG - used to configure (override) settings set in NVRAM before
731  * a call to QUERY_DEV_LIM.  This is primarily used for SRQ settings in
732  * the firmware.
733  */
734 int tavor_mod_stat_cfg_cmd_post(tavor_state_t *state);
735 
736 /*
737  * MODIFY_MPT - used to change MPT attributes of a memory region.  This
738  * is primarily used for Resizing SRQs.
739  */
740 int tavor_modify_mpt_cmd_post(tavor_state_t *state, tavor_hw_mpt_t *mpt,
741     uint_t mptindx, uint_t flags, uint_t sleepflag);
742 
743 #ifdef __cplusplus
744 }
745 #endif
746 
747 #endif	/* _SYS_IB_ADAPTERS_TAVOR_CMD_H */
748