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_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 #define	TAVOR_CMD_BKEY_DONTCHECK	2
264 
265 #define	TAVOR_CMD_MAD_IFC_SIZE		0x100
266 #define	TAVOR_CMD_MADDATA_OFFSET	0x40
267 #define	TAVOR_CMD_MADHDR0		0x01010101
268 #define	TAVOR_CMD_MADHDR1		0x00000000
269 #define	TAVOR_CMD_MADHDR2		0x00000000
270 #define	TAVOR_CMD_MADHDR3		0x00000000
271 #define	TAVOR_CMD_PORTINFO		0x00150000
272 #define	TAVOR_CMD_NODEINFO		0x00110000
273 #define	TAVOR_CMD_NODEDESC		0x00100000
274 #define	TAVOR_CMD_GUIDINFO		0x00140000
275 #define	TAVOR_CMD_PKEYTBLE		0x00160000
276 
277 #define	TAVOR_CMD_PERF_GET		0x01040101
278 #define	TAVOR_CMD_PERF_SET		0x01040102
279 #define	TAVOR_CMD_PERFCNTRS		0x00120000
280 #define	TAVOR_CMD_PERFATTR		0x00000000
281 
282 /*
283  * The next few defines are used to indicate the size of the "reserved" area
284  * in the WRITE_MTT command, and the respective sizes of the SET_IB and
285  * MGID_HASH commands
286  */
287 #define	TAVOR_CMD_WRITEMTT_RSVD_SZ	0x10
288 #define	TAVOR_CMD_SETIB_SZ		0x8
289 #define	TAVOR_CMD_MGIDHASH_SZ		0x10
290 
291 /*
292  * This last define is used by tavor_cmn_ownership_cmd_post() to keep track
293  * of the direction (from hardware ownership to software, or vice versa) of
294  * the requested operation
295  */
296 #define	TAVOR_CMD_RSRC_HW2SW		0
297 #define	TAVOR_CMD_RSRC_SW2HW		1
298 
299 /*
300  * The following macros are used for handling any endianness related issues
301  * that might arise from the Tavor driver's internal use of MADs.
302  *
303  *    TAVOR_GETPORTINFO_SWAP	- All the necessary swapping to handle the
304  *				    response to a GetPortInfo MAD
305  *    TAVOR_GETNODEINFO_SWAP	- All the necessary swapping to handle the
306  *				    response to a GetNodeInfo MAD
307  *    TAVOR_GETGUIDINFO_SWAP	- All the necessary swapping to handle the
308  *				    response to a GetGUIDInfo MAD
309  *    TAVOR_GETPKEYTABLE_SWAP	- All the necessary swapping to handle the
310  *				    response to a GetPKeyTable MAD
311  */
312 #ifdef	_LITTLE_ENDIAN
313 #define	TAVOR_GETPORTINFO_SWAP(portinfo)				\
314 {									\
315 	(portinfo)->M_Key = ddi_swap64((portinfo)->M_Key);		\
316 	(portinfo)->GidPrefix = ddi_swap64((portinfo)->GidPrefix);	\
317 	(portinfo)->LID = ddi_swap16((portinfo)->LID);			\
318 	(portinfo)->MasterSMLID = ddi_swap16((portinfo)->MasterSMLID);	\
319 	(portinfo)->CapabilityMask =					\
320 	    ddi_swap32((portinfo)->CapabilityMask);			\
321 	(portinfo)->DiagCode = ddi_swap16((portinfo)->DiagCode);	\
322 	(portinfo)->M_KeyLeasePeriod =					\
323 	    ddi_swap16((portinfo)->M_KeyLeasePeriod);			\
324 	(portinfo)->M_KeyViolations =					\
325 	    ddi_swap16((portinfo)->M_KeyViolations);			\
326 	(portinfo)->P_KeyViolations =					\
327 	    ddi_swap16((portinfo)->P_KeyViolations);			\
328 	(portinfo)->Q_KeyViolations =					\
329 	    ddi_swap16((portinfo)->Q_KeyViolations);			\
330 }
331 #else
332 #define	TAVOR_GETPORTINFO_SWAP(portinfo)
333 #endif
334 
335 #ifdef	_LITTLE_ENDIAN
336 #define	TAVOR_GETNODEINFO_SWAP(nodeinfo)				\
337 {									\
338 	uint32_t	tmp;						\
339 									\
340 	tmp = ddi_swap32(((uint32_t *)nodeinfo)[9]);			\
341 	(nodeinfo)->VendorID	 = tmp & 0xFFFFFF;			\
342 	(nodeinfo)->LocalPortNum = tmp >> 24;				\
343 	(nodeinfo)->Revision	 =					\
344 	    ddi_swap32(((uint32_t *)nodeinfo)[8]);			\
345 	tmp = ddi_swap32(((uint32_t *)nodeinfo)[7]);			\
346 	(nodeinfo)->PartitionCap = tmp >> 16;				\
347 	(nodeinfo)->DeviceID	 = tmp & 0xFFFF;			\
348 	(nodeinfo)->PortGUID = ddi_swap64((((uint64_t)			\
349 	    (((uint32_t *)nodeinfo)[6]) << 32) |			\
350 	    ((uint32_t *)nodeinfo)[5]));				\
351 	(nodeinfo)->NodeGUID = ddi_swap64((((uint64_t)			\
352 	    (((uint32_t *)nodeinfo)[4]) << 32) |			\
353 	    ((uint32_t *)nodeinfo)[3]));				\
354 	(nodeinfo)->SystemImageGUID = ddi_swap64((((uint64_t)		\
355 	    (((uint32_t *)nodeinfo)[2]) << 32) |			\
356 	    ((uint32_t *)nodeinfo)[1]));				\
357 }
358 #else
359 #define	TAVOR_GETNODEINFO_SWAP(nodeinfo)				\
360 {									\
361 	uint32_t	tmp;						\
362 									\
363 	tmp = ((uint32_t *)nodeinfo)[9];				\
364 	(nodeinfo)->VendorID	 = tmp & 0xFFFFFF;			\
365 	(nodeinfo)->LocalPortNum = tmp >> 24;				\
366 	(nodeinfo)->Revision	 = ((uint32_t *)nodeinfo)[8];		\
367 	tmp = ((uint32_t *)nodeinfo)[7];				\
368 	(nodeinfo)->PartitionCap = tmp >> 16;				\
369 	(nodeinfo)->DeviceID	 = tmp & 0xFFFF;			\
370 	(nodeinfo)->PortGUID = (((uint64_t)				\
371 	    (((uint32_t *)nodeinfo)[5]) << 32) |			\
372 	    ((uint32_t *)nodeinfo)[6]);					\
373 	(nodeinfo)->NodeGUID = (((uint64_t)				\
374 	    (((uint32_t *)nodeinfo)[3]) << 32) |			\
375 	    ((uint32_t *)nodeinfo)[4]);					\
376 	(nodeinfo)->SystemImageGUID = (((uint64_t)			\
377 	    (((uint32_t *)nodeinfo)[1]) << 32) |			\
378 	    ((uint32_t *)nodeinfo)[2]);					\
379 }
380 #endif
381 
382 #ifdef	_LITTLE_ENDIAN
383 #define	TAVOR_GETGUIDINFO_SWAP(guidinfo)				\
384 {									\
385 	int	i;							\
386 									\
387 	for (i = 0; i < 8; i++) {					\
388 		(guidinfo)->GUIDBlocks[i] =				\
389 		    ddi_swap64((guidinfo)->GUIDBlocks[i]);		\
390 	}								\
391 }
392 #else
393 #define	TAVOR_GETGUIDINFO_SWAP(guidinfo)
394 #endif
395 
396 #ifdef	_LITTLE_ENDIAN
397 #define	TAVOR_GETPKEYTABLE_SWAP(pkeytable)				\
398 {									\
399 	int	i;							\
400 									\
401 	for (i = 0; i < 32; i++) {					\
402 		(pkeytable)->P_KeyTableBlocks[i] =			\
403 		    ddi_swap16((pkeytable)->P_KeyTableBlocks[i]);	\
404 	}								\
405 }
406 #else
407 #define	TAVOR_GETPKEYTABLE_SWAP(pkeytable)
408 #endif
409 
410 /*
411  * The Tavor MODIFY_MPT command can take the following opcode modifier
412  * options to specify whether to modify for ResizeSRQ() or to swap the
413  * full MPT entry.
414  */
415 #define	TAVOR_CMD_MODIFY_MPT_RESIZESRQ	3
416 #define	TAVOR_CMD_MODIFY_MPT_SWAPFULL	5
417 
418 
419 /*
420  * The tavor_mbox_t structure is used internally by the Tavor driver to track
421  * all the information necessary to manage mailboxes for the Tavor command
422  * interface.  Specifically, by containing a pointer to the buffer, the
423  * PCI mapped address, the access handle, and a back pointer to the
424  * tavor_rsrc_t structure used to track this resource, it provides enough
425  * information allocate, use, and free any type of mailbox.
426  *
427  * The mb_indx, mb_next, and mb_prev fields are used only by the mailbox
428  * alloc/free routines (see tavor_impl_mbox_alloc/free() for more details)
429  * and are not read or modified by any mailbox consumers.  They are used
430  * to implement a fast allocation mechanism.
431  */
432 typedef struct tavor_mbox_s {
433 	void			*mb_addr;
434 	uint64_t		mb_mapaddr;
435 	ddi_acc_handle_t	mb_acchdl;
436 	tavor_rsrc_t		*mb_rsrcptr;
437 	uint_t			mb_sync;
438 	uint_t			mb_indx;
439 	uint_t			mb_next;
440 	uint_t			mb_prev;
441 } tavor_mbox_t;
442 
443 /*
444  * The tavor_mboxlist_t structure is used to track all the information
445  * relevant to the pools of Tavor mailboxes.  Specifically, it has a pointer
446  * to an array of tavor_mbox_t structures, a lock and cv used for blocking
447  * on alloc when mailboxes are not available, and a head, tail, and entries
448  * free counter to keep track of which (if any) mailboxes are currently free.
449  * This is used (along with the mb_indx, mb_next, and mb_prev fields in the
450  * tavor_mbox_t) to implement the fast allocation mechanism.
451  */
452 typedef struct tavor_mboxlist_s {
453 	kmutex_t		mbl_lock;
454 	kcondvar_t		mbl_cv;
455 	tavor_mbox_t		*mbl_mbox;
456 	uint_t			mbl_list_sz;
457 	uint_t			mbl_num_alloc;
458 	uint_t			mbl_head_indx;
459 	uint_t			mbl_tail_indx;
460 	uint_t			mbl_entries_free;
461 	uint_t			mbl_waiters;
462 	uint_t			mbl_pollers;
463 	uint_t			mbl_signal;
464 } tavor_mboxlist_t;
465 _NOTE(MUTEX_PROTECTS_DATA(tavor_mboxlist_t::mbl_lock,
466     tavor_mboxlist_t::mbl_mbox
467     tavor_mboxlist_t::mbl_list_sz
468     tavor_mboxlist_t::mbl_num_alloc
469     tavor_mboxlist_t::mbl_cv
470     tavor_mboxlist_t::mbl_head_indx
471     tavor_mboxlist_t::mbl_tail_indx
472     tavor_mboxlist_t::mbl_entries_free
473     tavor_mboxlist_t::mbl_waiters
474     tavor_mboxlist_t::mbl_pollers
475     tavor_mboxlist_t::mbl_signal
476     tavor_mbox_t::mb_next
477     tavor_mbox_t::mb_prev))
478 
479 /*
480  * The tavor_mbox_info_t structure is used by mailbox allocators to specify
481  * the type of mailbox(es) being requested.  On a call to tavor_mbox_alloc()
482  * the mbi_alloc_flags may be set to TAVOR_ALLOC_INMBOX, TAVOR_ALLOC_OUTMBOX,
483  * or both.  If it is able to allocate the request type(s) of mailboxes,
484  * tavor_mbox_alloc() will fill in the "mbi_in" and/or "mbi_out" pointers
485  * to point to valid tavor_mbox_t structures from the appropriate
486  * tavor_mboxlist_t (see above).
487  * This same structure is also passed to tavor_mbox_free().  It is the
488  * responsibility of the caller to tavor_mbox_alloc() to return this exact
489  * structure (unmodified) to tavor_mbox_free().
490  *
491  * Note: If both "In" and "Out" mailboxes are requested, it is assured that
492  * no deadlock can result (from holding one mailbox while attempting to get
493  * the other).  This is assured by the fact that the "In" mailbox will always
494  * be allocated first before attempting to allocate the "Out"
495  */
496 typedef struct tavor_mbox_info_s {
497 	uint_t			mbi_alloc_flags;
498 	uint_t			mbi_sleep_context;
499 	tavor_mbox_t		*mbi_in;
500 	tavor_mbox_t		*mbi_out;
501 } tavor_mbox_info_t;
502 #define	TAVOR_ALLOC_INMBOX	(1 << 0)
503 #define	TAVOR_ALLOC_OUTMBOX	(1 << 1)
504 
505 
506 /*
507  * The tavor_cmd_t structure is used internally by the Tavor driver to track
508  * all the information necessary to manage outstanding firmware commands on
509  * the Tavor command interface.
510  *
511  * Each tavor_cmd_t structure contains a cv and lock which are used by the
512  * posting thread to block for completion (with cmd_status being overloaded
513  * to indicate the condition variable).  The cmd_outparam field is used to
514  * return additional status from those Tavor commands that specifically
515  * require it.
516  *
517  * The cmd_indx, cmd_next, and cmd_prev fields are used by the outstanding
518  * command alloc/free routines (see tavor_outstanding_cmd_alloc/free() for
519  * more details).  They are used (in much the same way as the mb_indx,
520  * mb_next, and mb_prev fields in tavor_mbox_t above) to implement a fast
521  * allocation mechanism.
522  */
523 typedef struct tavor_cmd_s {
524 	kmutex_t		cmd_comp_lock;
525 	kcondvar_t		cmd_comp_cv;
526 	uint64_t		cmd_outparm;
527 	uint_t			cmd_status;
528 	uint_t			cmd_indx;
529 	uint_t			cmd_next;
530 	uint_t			cmd_prev;
531 } tavor_cmd_t;
532 _NOTE(MUTEX_PROTECTS_DATA(tavor_cmd_t::cmd_comp_lock,
533     tavor_cmd_t::cmd_comp_cv
534     tavor_cmd_t::cmd_status))
535 
536 /*
537  * The tavor_cmdlist_t structure is used in almost exactly the same way as
538  * the tavor_mboxlist_t above, but instead to track all the information
539  * relevant to the pool of outstanding Tavor commands.  Specifically, it has
540  * a pointer to an array of tavor_cmd_t structures, a lock and cv used for
541  * blocking on alloc when outstanding command slots are not available, and a
542  * head, tail, and entries free counter to keep track of which (if any)
543  * command slots are currently free.  This is used (along with the cmd_indx,
544  * cmd_next, and cmd_prev fields in the tavor_cmd_t) to implement the fast
545  * allocation mechanism.
546  */
547 typedef struct tavor_cmdlist_s {
548 	kmutex_t		cml_lock;
549 	kcondvar_t		cml_cv;
550 	tavor_cmd_t		*cml_cmd;
551 	uint_t			cml_list_sz;
552 	uint_t			cml_num_alloc;
553 	uint_t			cml_head_indx;
554 	uint_t			cml_tail_indx;
555 	uint_t			cml_entries_free;
556 	uint_t			cml_waiters;
557 } tavor_cmdlist_t;
558 _NOTE(MUTEX_PROTECTS_DATA(tavor_cmdlist_t::cml_lock,
559     tavor_cmdlist_t::cml_cv
560     tavor_cmdlist_t::cml_cmd
561     tavor_cmdlist_t::cml_list_sz
562     tavor_cmdlist_t::cml_num_alloc
563     tavor_cmdlist_t::cml_head_indx
564     tavor_cmdlist_t::cml_tail_indx
565     tavor_cmdlist_t::cml_entries_free
566     tavor_cmdlist_t::cml_waiters
567     tavor_cmd_t::cmd_next
568     tavor_cmd_t::cmd_prev))
569 _NOTE(LOCK_ORDER(tavor_cmdlist_t::cml_lock
570     tavor_cmd_t::cmd_comp_lock))
571 
572 /*
573  * The tavor_cmd_post_t structure is used by all the Tavor Firmware Command
574  * routines to post to Tavor firmware.  The fields almost exactly mimic
575  * the fields in the Tavor HCR registers.  The notable exception is the
576  * addition of the "cp_flags" field (which can be set to TAVOR_CMD_SPIN or
577  * TAVOR_CMD_NOSPIN).  This flag really controls the value of the "e" bit
578  * in the HCR (i.e. the bit to indicate whether command should complete
579  * "in place" - in the HCR - or whether they should have their completions
580  * written to the command completion event queue.  TAVOR_CMD_SPIN means
581  * to allow commands to complete "in place" and to poll the "go" bit in
582  * the HCR to determine completion.
583  *
584  * We use TAVOR_SLEEP and TAVOR_NOSLEEP for our TAVOR_CMD_ #defines.  This is
585  * to maintain consistency with the rest of the SLEEP flags.  Additionally,
586  * because TAVOR_SLEEPFLAG_FOR_CONTEXT() in tavor_rsrc.h returns TAVOR_SLEEP or
587  * NOSLEEP we must be compatible with this macro.
588  */
589 typedef struct tavor_cmd_post_s {
590 	uint64_t		cp_inparm;
591 	uint64_t		cp_outparm;
592 	uint32_t		cp_inmod;
593 	uint16_t		cp_opcode;
594 	uint16_t		cp_opmod;
595 	uint32_t		cp_flags;
596 } tavor_cmd_post_t;
597 #define	TAVOR_CMD_SLEEP_NOSPIN		TAVOR_SLEEP
598 #define	TAVOR_CMD_NOSLEEP_SPIN		TAVOR_NOSLEEP
599 
600 
601 /*
602  * The following are the Tavor Firmware Command routines that accessible
603  * externally (i.e. throughout the rest of the Tavor driver software).
604  * These include the all the alloc/free routines, some initialization
605  * and cleanup routines, and the various specific Tavor firmware commands.
606  */
607 int tavor_cmd_post(tavor_state_t *state, tavor_cmd_post_t *cmdpost);
608 int tavor_mbox_alloc(tavor_state_t *state, tavor_mbox_info_t *mbox_info,
609     uint_t mbox_wait);
610 void tavor_mbox_free(tavor_state_t *state, tavor_mbox_info_t *mbox_info);
611 int tavor_cmd_complete_handler(tavor_state_t *state, tavor_eqhdl_t eq,
612     tavor_hw_eqe_t *eqe);
613 int tavor_inmbox_list_init(tavor_state_t *state);
614 int tavor_intr_inmbox_list_init(tavor_state_t *state);
615 int tavor_outmbox_list_init(tavor_state_t *state);
616 int tavor_intr_outmbox_list_init(tavor_state_t *state);
617 void tavor_inmbox_list_fini(tavor_state_t *state);
618 void tavor_intr_inmbox_list_fini(tavor_state_t *state);
619 void tavor_outmbox_list_fini(tavor_state_t *state);
620 void tavor_intr_outmbox_list_fini(tavor_state_t *state);
621 int tavor_outstanding_cmdlist_init(tavor_state_t *state);
622 void tavor_outstanding_cmdlist_fini(tavor_state_t *state);
623 
624 /*
625  * SYS_EN and SYS_DIS - used for startup and shutdown of Tavor device
626  */
627 int tavor_sys_en_cmd_post(tavor_state_t *state, uint_t flags,
628     uint64_t *errorcode, uint_t sleepflag);
629 int tavor_sys_dis_cmd_post(tavor_state_t *state, uint_t sleepflag);
630 
631 /*
632  * INIT_HCA and CLOSE_HCA - used for initialization and teardown of Tavor
633  * device configuration
634  */
635 int tavor_init_hca_cmd_post(tavor_state_t *state,
636     tavor_hw_initqueryhca_t *inithca, uint_t sleepflag);
637 int tavor_close_hca_cmd_post(tavor_state_t *state, uint_t sleepflag);
638 
639 /*
640  * INIT_IB, CLOSE_IB, and SET_IB - used for bring Tavor ports up and down,
641  * and to set properties of each port (e.g. PortInfo capability mask)
642  */
643 int tavor_init_ib_cmd_post(tavor_state_t *state,
644     tavor_hw_initib_t *initib, uint_t port, uint_t sleepflag);
645 int tavor_close_ib_cmd_post(tavor_state_t *state, uint_t port,
646     uint_t sleepflag);
647 int tavor_set_ib_cmd_post(tavor_state_t *state, uint32_t capmask,
648     uint_t port, uint_t reset_qkey, uint_t sleepflag);
649 
650 /*
651  * This common function is used to post the following Tavor QP state
652  * transition firmware commands:
653  * RTS2SQD, TOERR, TORST, RST2INIT, INIT2INIT, INIT2RTR, RTR2RTS, RTS2RTS,
654  * SQD2SQD, SQD2RTS, and SQERR2RTS.
655  */
656 int tavor_cmn_qp_cmd_post(tavor_state_t *state, uint_t opcode,
657     tavor_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask, uint_t sleepflag);
658 
659 /*
660  * This common function is used to post the following Tavor query firmware
661  * commands:
662  * QUERY_DEV_LIM, QUERY_FW, QUERY_DDR, QUERY_ADAPTER, QUERY_HCA, QUERY_MPT,
663  * QUERY_EQ, QUERY_CQ, and QUERY_QP.
664  */
665 int tavor_cmn_query_cmd_post(tavor_state_t *state, uint_t opcode,
666     uint_t queryindx, void *query, uint_t size, uint_t sleepflag);
667 
668 /*
669  * This common function is used to post the following Tavor resource ownership
670  * firmware commands:
671  * HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and SW2HW_CQ
672  */
673 int tavor_cmn_ownership_cmd_post(tavor_state_t *state, uint_t opcode,
674     void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag);
675 
676 /*
677  * MAD_IFC and helper functions - used for posting IB MADs to Tavor firmware.
678  * The helper functions are for the MADs most frequently used by the Tavor
679  * driver (internally).
680  */
681 int tavor_mad_ifc_cmd_post(tavor_state_t *state, uint_t port,
682     uint_t sleepflag, uint32_t *mad, uint32_t *resp);
683 int tavor_getportinfo_cmd_post(tavor_state_t *state, uint_t port,
684     uint_t sleepflag, sm_portinfo_t *portinfo);
685 int tavor_getnodeinfo_cmd_post(tavor_state_t *state, uint_t sleepflag,
686     sm_nodeinfo_t *nodeinfo);
687 int tavor_getnodedesc_cmd_post(tavor_state_t *state, uint_t sleepflag,
688     sm_nodedesc_t *nodedesc);
689 int tavor_getguidinfo_cmd_post(tavor_state_t *state, uint_t port,
690     uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo);
691 int tavor_getpkeytable_cmd_post(tavor_state_t *state, uint_t port,
692     uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable);
693 int tavor_getperfcntr_cmd_post(tavor_state_t *state, uint_t port,
694     uint_t sleepflag, tavor_hw_sm_perfcntr_t *perfinfo, int reset);
695 
696 /*
697  * WRITE_MTT - used for write MTT entries to the Tavor MTT table
698  */
699 int tavor_write_mtt_cmd_post(tavor_state_t *state,
700     tavor_mbox_info_t *mbox_info, uint_t num_mtt, uint_t sleepflag);
701 
702 /*
703  * SYNC_TPT - used to sync Tavor TPT caches
704  */
705 int tavor_sync_tpt_cmd_post(tavor_state_t *state, uint_t sleepflag);
706 
707 /*
708  * MAP_EQ - used for map classes of events to Tavor event queues (EQ)
709  */
710 int tavor_map_eq_cmd_post(tavor_state_t *state, uint_t map,
711     uint_t eqcindx, uint64_t eqmapmask, uint_t sleepflag);
712 
713 /*
714  * RESIZE_CQ - used for resize completion queue (CQ)
715  */
716 int tavor_resize_cq_cmd_post(tavor_state_t *state, tavor_hw_cqc_t *cqc,
717     uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag);
718 
719 /*
720  * CONF_SPECIAL_QP - used to configure a pair of queue pairs for use as
721  * special QP.  Necessary to enable full QP0 and/or QP1 operation.
722  */
723 int tavor_conf_special_qp_cmd_post(tavor_state_t *state, uint_t qpindx,
724     uint_t qptype, uint_t sleepflag);
725 
726 /*
727  * MGID_HASH, READ_MGM, and WRITE_MGM - used for manipulation of the
728  * hardware resource tables for multicast groups.
729  */
730 int tavor_mgid_hash_cmd_post(tavor_state_t *state, uint64_t mgid_h,
731     uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag);
732 int tavor_read_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg,
733     uint_t mcgindx, uint_t sleepflag);
734 int tavor_write_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg,
735     uint_t mcgindx, uint_t sleepflag);
736 
737 /*
738  * MOD_STAT_CFG - used to configure (override) settings set in NVRAM before
739  * a call to QUERY_DEV_LIM.  This is primarily used for SRQ settings in
740  * the firmware.
741  */
742 int tavor_mod_stat_cfg_cmd_post(tavor_state_t *state);
743 
744 /*
745  * MODIFY_MPT - used to change MPT attributes of a memory region.  This
746  * is primarily used for Resizing SRQs.
747  */
748 int tavor_modify_mpt_cmd_post(tavor_state_t *state, tavor_hw_mpt_t *mpt,
749     uint_t mptindx, uint_t flags, uint_t sleepflag);
750 
751 #ifdef __cplusplus
752 }
753 #endif
754 
755 #endif	/* _SYS_IB_ADAPTERS_TAVOR_CMD_H */
756