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_CMD_H
27 #define	_SYS_IB_ADAPTERS_HERMON_CMD_H
28 
29 /*
30  * hermon_cmd.h
31  *    Contains all of the prototypes, #defines, and structures necessary
32  *    for the Hermon Firmware Command routines.
33  *    Specifically it contains the command types, command statuses and flags,
34  *    structures used for managing Hermon mailboxes and outstanding commands,
35  *    and prototypes for most of the functions consumed by other parts of
36  *    the Hermon driver.
37  */
38 
39 #include <sys/types.h>
40 #include <sys/conf.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 
44 #include <sys/ib/mgt/sm_attr.h>
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 
51 /*
52  * Defines used hermon_write_hcr() to determine the duration and number of
53  * times (at maximum) to poll while waiting for a Hermon firmware command to
54  * release the HCR resource (i.e. waiting for the command to complete)
55  */
56 #define	HERMON_CMD_POLL_DELAY		1
57 #define	HERMON_CMD_POLL_MAX		3000000
58 
59 /*
60  * The following defines specify the default number of mailboxes (log 2) of
61  * each type and their size and alignment restrictions.  By default the number
62  * of both "In" and "Out" mailboxes is set to 1024 (with each mailbox being
63  * 4KB in size), but both the number and sizes of each are controllable
64  * through the "hermon_log_num_inmbox", "hermon_log_num_outmbox",
65  * "hermon_log_inmbox_size" and "hermon_log_outmbox_size" configuration
66  * variables. Also, we have a define that is used to allocate interrupt
67  * mailboxes (1 in, 1 out).
68  */
69 #define	HERMON_NUM_MAILBOXES_SHIFT	0xA
70 #define	HERMON_NUM_INTR_MAILBOXES_SHIFT	0
71 #define	HERMON_MBOX_SIZE_SHIFT		0xC
72 #define	HERMON_MBOX_SIZE			(1 << HERMON_MBOX_SIZE_SHIFT)
73 #define	HERMON_MBOX_ALIGN		HERMON_MBOX_SIZE
74 
75 /*
76  * These are the defines for the Hermon command type (opcodes).  They are
77  * specified by the Hermon PRM
78  */
79 
80 /* Init Commands */
81 #define	QUERY_DEV_LIM			0x3
82 #define	QUERY_DEV_CAP			0x3
83 #define	QUERY_FW			0x4
84 #define	QUERY_ADAPTER			0x6
85 #define	INIT_HCA			0x7
86 #define	CLOSE_HCA			0x8
87 #define	INIT_IB				0x9
88 #define	INIT_PORT			0x9
89 #define	CLOSE_IB			0xA
90 #define	CLOSE_PORT			0xA
91 #define	QUERY_HCA			0xB
92 #define	SET_IB				0xC
93 #define	SET_PORT			0xC
94 /* added late in tavor for SRQ support */
95 #define	MOD_STAT_CFG			0x34
96 /* added late in Hermon (PRM 0.35) */
97 #define	QUERY_PORT			0x43
98 
99 
100 /* TPT Commands */
101 #define	SW2HW_MPT			0xD
102 #define	QUERY_MPT			0xE
103 #define	HW2SW_MPT			0xF
104 #define	READ_MTT			0x10
105 #define	WRITE_MTT			0x11
106 #define	SYNC_TPT			0x2F
107 #define	MODIFY_MPT			0x39
108 
109 /* EQ Commands */
110 #define	MAP_EQ				0x12
111 #define	SW2HW_EQ			0x13
112 #define	HW2SW_EQ			0x14
113 #define	QUERY_EQ			0x15
114 
115 /* CQ Commands */
116 #define	SW2HW_CQ			0x16
117 #define	HW2SW_CQ			0x17
118 #define	QUERY_CQ			0x18
119 #define	MODIFY_CQ			0x2C
120 
121 /* Modify CQ Command - opcode modifiers */
122 #define	RESIZE_CQ			0x0
123 #define	MODIFY_MODERATION_CQ		0x1
124 #define	MODIFY_EQN			0x2
125 
126 /* QP Commands */
127 #define	RST2INIT_QP			0x19
128 #define	INIT2INIT_QP			0x2D
129 #define	INIT2RTR_QP			0x1A
130 #define	RTR2RTS_QP			0x1B
131 #define	RTS2RTS_QP			0x1C
132 #define	SQERR2RTS_QP			0x1D
133 #define	TOERR_QP			0x1E
134 #define	RTS2SQD_QP			0x1F
135 #define	SQD2SQD_QP			0x38
136 #define	SQD2RTS_QP			0x20
137 #define	TORST_QP			0x21
138 #define	QUERY_QP			0x22
139 #define	SUSPEND_QP			0x32	/* new w/ hermon driver */
140 #define	UNSUSPEND_QP			0x33	/* new w/ hermon driver */
141 
142 /* SPECIAL QPs Commands */
143 #define	CONF_SPECIAL_QP			0x23
144 #define	MAD_IFC				0x24
145 
146 /* added late in tavor for SRQ support */
147 /* SRQ Commands */
148 #define	SW2HW_SRQ			0x35
149 #define	HW2SW_SRQ			0x36
150 #define	QUERY_SRQ			0x37
151 /* new in hermon, replaces part of modify MPT */
152 #define	RESIZE_SRQ			0X44
153 /* new in hermon, set limit water mark */
154 #define	ARM_RQ				0X40
155 /* new in hermon (PRM 0.36) configure interrupt moderation */
156 #define	CONFIG_INT_MOD			0X45
157 #define	HW_HEALTH_CHECK			0X50
158 
159 /* Multicast Group Commands */
160 #define	READ_MGM			0x25
161 #define	READ_MCG			0x25
162 #define	WRITE_MGM			0x26
163 #define	WRITE_MCG			0x26
164 #define	MGID_HASH			0x27
165 
166 /* Debug/Diagnostic Commands */
167 #define	QUERY_DEBUG_MSG			0x2A
168 #define	SET_DEBUG_MSG			0x2B
169 #define	DIAG_RPRT			0x30
170 #define	CMD_NOP				0x31
171 
172 #define	SET_VLAN_FLTR			0x47
173 #define	SET_MCAST_FLTR			0x48
174 
175 #define	CONFIG_FC			0x4A
176 #define	QUERY_FC			0x4B
177 #define	HEART_BEAT_RQ			0x4C
178 
179 #define	SENSE_PORT			0x4D
180 
181 /* ICM and related commands - w/out LAM commands from Arbel */
182 #define	RUN_FW				0xFF6
183 #define	UNMAP_ICM			0xFF9
184 #define	MAP_ICM				0xFFA
185 #define	UNMAP_ICM_AUX			0xFFB
186 #define	MAP_ICM_AUX			0xFFC
187 #define	SET_ICM_SIZE			0xFFD
188 #define	UNMAP_FA			0xFFE
189 #define	MAP_FA				0xFFF
190 
191 /*
192  * Commands mentioned but not defined in PRM v35
193  *	REL_ICM_AUX
194  *	INIT_VM
195  */
196 
197 /*
198  * These are the defines for the Hermon command completion statuses.  They are
199  * also specified (in part) by the Hermon PRM.  However,
200  * the HERMON_CMD_INSUFF_RSRC, HERMON_CMD_TIMEOUT and HERMON_CMD_INVALID_STATUS
201  * codes were added for this driver specifically to indicate the conditions
202  * when insufficient resources are available for a command, when a command has
203  * timed out (failure in the Hermon firmware) or when some other invalid result
204  * was received.
205  */
206 #define	HERMON_CMD_TIMEOUT_TOGGLE	0xFFFC 	/* -4 */
207 #define	HERMON_CMD_INSUFF_RSRC		0xFFFD	/* -3 */
208 #define	HERMON_CMD_TIMEOUT_GOBIT	0xFFFE 	/* -2 */
209 #define	HERMON_CMD_INVALID_STATUS	0xFFFF  /* -1 */
210 #define	HERMON_CMD_SUCCESS		0x00
211 #define	HERMON_CMD_INTERNAL_ERR		0x01
212 #define	HERMON_CMD_BAD_OP		0x02
213 #define	HERMON_CMD_BAD_PARAM		0x03
214 #define	HERMON_CMD_BAD_SYS_STATE		0x04
215 #define	HERMON_CMD_BAD_RESOURCE		0x05
216 #define	HERMON_CMD_RESOURCE_BUSY		0x06
217 #define	HERMON_CMD_EXCEED_LIM		0x08
218 #define	HERMON_CMD_BAD_RES_STATE		0x09
219 #define	HERMON_CMD_BAD_INDEX		0x0A
220 #define	HERMON_CMD_BAD_NVMEM		0x0B
221 #define	HERMON_CMD_ICM_ERROR		0x0C
222 #define	HERMON_CMD_BAD_QP_STATE		0x10
223 #define	HERMON_CMD_BAD_SEG_PARAM		0x20
224 #define	HERMON_CMD_REG_BOUND		0x21
225 #define	HERMON_CMD_BAD_PKT		0x30
226 #define	HERMON_CMD_BAD_SIZE		0x40
227 
228 /*
229  * These defines are used in the "special QP" allocation to indicate the type
230  * of special QP (SMI, GSI, or one of the raw types).  These values are
231  * specified by the Hermon PRM
232  */
233 #define	HERMON_CMD_QP_SMI		0
234 #define	HERMON_CMD_QP_GSI		1
235 #define	HERMON_CMD_QP_RAW_IPV6		2
236 #define	HERMON_CMD_QP_RAW_ETH		3
237 
238 #define	HERMON_CMD_SPEC_QP_OPMOD(smi, gsi) \
239 	((smi & 0x01) | ((gsi & 0x01) << 1))
240 
241 /*
242  * For certain Hermon QP state transition commands some optional flags are
243  * allowed.  These "opmask" flags are defined by the Hermon PRM
244  * as a bitmask.
245  */
246 
247 #define	HERMON_CMD_OP_ALT_PATH		(1 << 0)
248 #define	HERMON_CMD_OP_RRE		(1 << 1)
249 #define	HERMON_CMD_OP_RAE		(1 << 2)
250 #define	HERMON_CMD_OP_RWE		(1 << 3)
251 #define	HERMON_CMD_OP_PKEYINDX		(1 << 4) /* primary path */
252 #define	HERMON_CMD_OP_QKEY		(1 << 5)
253 #define	HERMON_CMD_OP_MINRNRNAK		(1 << 6)
254 #define	HERMON_CMD_OP_PRIM_PATH		(1 << 7)
255 #define	HERMON_CMD_OP_SRA_SET		(1 << 8)
256 #define	HERMON_CMD_OP_RRA_SET		(1 << 9)
257 #define	HERMON_CMD_OP_PM_STATE		(1 << 10) /* migration */
258 /* HERMON_CMD_OP_PRIM_PORT is obsolete, instead use HERMON_CMD_OP_SCHEDQUEUE */
259 #define	HERMON_CMD_OP_PRIM_PORT		(1 << 11)
260 #define	HERMON_CMD_OP_RETRYCNT		(1 << 12) /* Global */
261 #define	HERMON_CMD_OP_ALT_RNRRETRY	(1 << 13)
262 #define	HERMON_CMD_OP_ACKTIMEOUT	(1 << 14) /* primary path */
263 #define	HERMON_CMD_OP_PRIM_RNRRETRY	(1 << 15) /* reserved in HERMON */
264 #define	HERMON_CMD_OP_SCHEDQUEUE	(1 << 16)
265 #define	HERMON_CMD_OP_RSSCONTEXT	(1 << 17)
266 #define	HERMON_CMD_OP_SRQN		(1 << 18) /* for rss balancing */
267 #define	HERMON_CMD_OP_CQN_RCV		(1 << 19) /* for rss balancing */
268 /* Bits 20 - 31 RESERVED - per PRM 0.35c */
269 
270 
271 
272 /*
273  * The Hermon RTS2SQD command can take the following flag as part of its
274  * input modifier to request the Send Queue Drained event
275  */
276 #define	HERMON_CMD_REQ_SQD_EVENT		0x80000000
277 
278 /*
279  * The Hermon TORST command can take the following flag (as part of a bitmask)
280  * in its opcode modifier to request that the transition to reset should
281  * not go through the Error state (and, hence, should not generate "flushed-
282  * in-error" completions
283  */
284 #define	HERMON_CMD_DIRECT_TO_RESET	(1 << 1)
285 
286 /*
287  * Some Hermon commands write an OUT mailbox entry, depending on the value of
288  * the 'opmod' parameter.  These defines provide the correct opmod value to
289  * write depending on whether to write an entry or not.
290  */
291 #define	HERMON_CMD_DO_OUTMBOX		(0)
292 #define	HERMON_CMD_NO_OUTMBOX		(1 << 0)
293 
294 
295 /*
296  * The Hermon MAP_EQ command can take the following flags (and use the
297  * HERMON_CMD_UNMAP_EQ_MASK input modifier) to indicate whether the given
298  * event queue should mapped to or unmapped from the given event type.
299  */
300 
301 
302 #define	HERMON_CMD_MAP_EQ_EVT_MAP	0
303 #define	HERMON_CMD_MAP_EQ_EVT_UNMAP	1
304 #define	HERMON_CMD_UNMAP_EQ_MASK	0x80000000
305 
306 /*
307  * The following defines are used by the MAD_IFC command and the helper
308  * routines that get PortInfo, NodeInfo, GUIDInfo, and PKeyTable entries.
309  *
310  * The first indicates whether of not MKey checking should be enforced.
311  * This is passed in the opcode modifier field for MAD_IFC commands.
312  *
313  * The next set are used to define certain hardcoded management datagram (MAD)
314  * sizes, offsets, and header formats for each of the helper operations.
315  */
316 #define	HERMON_CMD_MKEY_CHECK		0
317 #define	HERMON_CMD_MKEY_DONTCHECK	1
318 #define	HERMON_CMD_BKEY_DONTCHECK	2
319 
320 #define	HERMON_CMD_MAD_IFC_SIZE		0x100
321 #define	HERMON_CMD_MADDATA_OFFSET	0x40
322 #define	HERMON_CMD_MADHDR0		0x01010101
323 #define	HERMON_CMD_MADHDR1		0x00000000
324 #define	HERMON_CMD_MADHDR2		0x00000000
325 #define	HERMON_CMD_MADHDR3		0x00000000
326 
327 #define	HERMON_CMD_PORTINFO		0x00150000
328 #define	HERMON_CMD_NODEINFO		0x00110000
329 #define	HERMON_CMD_NODEDESC		0x00100000
330 #define	HERMON_CMD_GUIDINFO		0x00140000
331 #define	HERMON_CMD_PKEYTBLE		0x00160000
332 
333 #define	HERMON_CMD_PERF_GET		0x01040101
334 #define	HERMON_CMD_PERF_SET		0x01040102
335 #define	HERMON_CMD_CLASSPORTINFO	0x00010000
336 #define	HERMON_CMD_PERFCNTRS		0x00120000
337 #define	HERMON_CMD_EXTPERFCNTRS		0x001D0000
338 #define	HERMON_CMD_PERFATTR		0x00000000
339 
340 #define	HERMON_IS_EXT_WIDTH_SUPPORTED		0x0000020000000000
341 #define	HERMON_IS_EXT_WIDTH_SUPPORTED_NOIETF	0x0000040000000000
342 
343 
344 /*
345  * The next few defines are used to indicate the size of the "reserved" area
346  * in the WRITE_MTT command, and the respective sizes of the SET_PORT and
347  * MGID_HASH commands
348  */
349 #define	HERMON_CMD_WRITEMTT_RSVD_SZ	0x10
350 #define	HERMON_CMD_SETPORT_SZ		0x8
351 #define	HERMON_CMD_MGIDHASH_SZ		0x10
352 
353 /*
354  * This last define is used by hermon_cmn_ownership_cmd_post() to keep track
355  * of the direction (from hardware ownership to software, or vice versa) of
356  * the requested operation
357  */
358 #define	HERMON_CMD_RSRC_HW2SW		0
359 #define	HERMON_CMD_RSRC_SW2HW		1
360 
361 /*
362  * The following macros are used for handling any endianness related issues
363  * that might arise from the Hermon driver's internal use of MADs.
364  *
365  *    HERMON_GETPORTINFO_SWAP	- All the necessary swapping to handle the
366  *				    response to a GetPortInfo MAD
367  *    HERMON_GETNODEINFO_SWAP	- All the necessary swapping to handle the
368  *				    response to a GetNodeInfo MAD
369  *    HERMON_GETGUIDINFO_SWAP	- All the necessary swapping to handle the
370  *				    response to a GetGUIDInfo MAD
371  *    HERMON_GETPKEYTABLE_SWAP	- All the necessary swapping to handle the
372  *				    response to a GetPKeyTable MAD
373  */
374 
375 
376 #ifdef	_LITTLE_ENDIAN
377 #define	HERMON_GETPORTINFO_SWAP(portinfo)				\
378 {									\
379 	(portinfo)->M_Key = ddi_swap64((portinfo)->M_Key);		\
380 	(portinfo)->GidPrefix = ddi_swap64((portinfo)->GidPrefix);	\
381 	(portinfo)->LID = ddi_swap16((portinfo)->LID);			\
382 	(portinfo)->MasterSMLID = ddi_swap16((portinfo)->MasterSMLID);	\
383 	(portinfo)->CapabilityMask =					\
384 	    ddi_swap32((portinfo)->CapabilityMask);			\
385 	(portinfo)->DiagCode = ddi_swap16((portinfo)->DiagCode);	\
386 	(portinfo)->M_KeyLeasePeriod =					\
387 	    ddi_swap16((portinfo)->M_KeyLeasePeriod);			\
388 	(portinfo)->M_KeyViolations =					\
389 	    ddi_swap16((portinfo)->M_KeyViolations);			\
390 	(portinfo)->P_KeyViolations =					\
391 	    ddi_swap16((portinfo)->P_KeyViolations);			\
392 	(portinfo)->Q_KeyViolations =					\
393 	    ddi_swap16((portinfo)->Q_KeyViolations);			\
394 }
395 #else
396 #define	HERMON_GETPORTINFO_SWAP(portinfo)
397 #endif
398 
399 #ifdef	_LITTLE_ENDIAN
400 #define	HERMON_GETNODEINFO_SWAP(nodeinfo)				\
401 {									\
402 	uint32_t	tmp;						\
403 									\
404 	tmp = ddi_swap32(((uint32_t *)nodeinfo)[9]);			\
405 	(nodeinfo)->VendorID	 = tmp & 0xFFFFFF;			\
406 	(nodeinfo)->LocalPortNum = tmp >> 24;				\
407 	(nodeinfo)->Revision	 =					\
408 	    ddi_swap32(((uint32_t *)nodeinfo)[8]);			\
409 	tmp = ddi_swap32(((uint32_t *)nodeinfo)[7]);			\
410 	(nodeinfo)->PartitionCap = tmp >> 16;				\
411 	(nodeinfo)->DeviceID	 = tmp & 0xFFFF;			\
412 	(nodeinfo)->PortGUID = ddi_swap64((((uint64_t)			\
413 	    (((uint32_t *)nodeinfo)[6]) << 32) |			\
414 	    ((uint32_t *)nodeinfo)[5]));				\
415 	(nodeinfo)->NodeGUID = ddi_swap64((((uint64_t)			\
416 	    (((uint32_t *)nodeinfo)[4]) << 32) |			\
417 	    ((uint32_t *)nodeinfo)[3]));				\
418 	(nodeinfo)->SystemImageGUID = ddi_swap64((((uint64_t)		\
419 	    (((uint32_t *)nodeinfo)[2]) << 32) |			\
420 	    ((uint32_t *)nodeinfo)[1]));				\
421 }
422 #else
423 #define	HERMON_GETNODEINFO_SWAP(nodeinfo)				\
424 {									\
425 	uint32_t	tmp;						\
426 									\
427 	tmp = ((uint32_t *)nodeinfo)[9];				\
428 	(nodeinfo)->VendorID	 = tmp & 0xFFFFFF;			\
429 	(nodeinfo)->LocalPortNum = tmp >> 24;				\
430 	(nodeinfo)->Revision	 = ((uint32_t *)nodeinfo)[8];		\
431 	tmp = ((uint32_t *)nodeinfo)[7];				\
432 	(nodeinfo)->PartitionCap = tmp >> 16;				\
433 	(nodeinfo)->DeviceID	 = tmp & 0xFFFF;			\
434 	(nodeinfo)->PortGUID = (((uint64_t)				\
435 	    (((uint32_t *)nodeinfo)[5]) << 32) |			\
436 	    ((uint32_t *)nodeinfo)[6]);					\
437 	(nodeinfo)->NodeGUID = (((uint64_t)				\
438 	    (((uint32_t *)nodeinfo)[3]) << 32) |			\
439 	    ((uint32_t *)nodeinfo)[4]);					\
440 	(nodeinfo)->SystemImageGUID = (((uint64_t)			\
441 	    (((uint32_t *)nodeinfo)[1]) << 32) |			\
442 	    ((uint32_t *)nodeinfo)[2]);					\
443 }
444 #endif
445 
446 #ifdef	_LITTLE_ENDIAN
447 #define	HERMON_GETGUIDINFO_SWAP(guidinfo)				\
448 {									\
449 	int	i;							\
450 									\
451 	for (i = 0; i < 8; i++) {					\
452 		(guidinfo)->GUIDBlocks[i] =				\
453 		    ddi_swap64((guidinfo)->GUIDBlocks[i]);		\
454 	}								\
455 }
456 #else
457 #define	HERMON_GETGUIDINFO_SWAP(guidinfo)
458 #endif
459 
460 #ifdef	_LITTLE_ENDIAN
461 #define	HERMON_GETPKEYTABLE_SWAP(pkeytable)				\
462 {									\
463 	int	i;							\
464 									\
465 	for (i = 0; i < 32; i++) {					\
466 		(pkeytable)->P_KeyTableBlocks[i] =			\
467 		    ddi_swap16((pkeytable)->P_KeyTableBlocks[i]);	\
468 	}								\
469 }
470 #else
471 #define	HERMON_GETPKEYTABLE_SWAP(pkeytable)
472 #endif
473 
474 /*
475  * The Hermon MODIFY_MPT command can take the following opcode modifier
476  * options to specify whether to modify for ResizeSRQ() or to swap the
477  * full MPT entry.
478  */
479 #define	HERMON_CMD_MODIFY_MPT_RESIZESRQ	3
480 #define	HERMON_CMD_MODIFY_MPT_SWAPFULL	5
481 
482 /*
483  * Hermon MOD_STAT_CFG Opcode Modifier
484  */
485 #define	HERMON_MOD_STAT_CFG_PTR		0x0
486 #define	HERMON_MOD_STAT_CFG_INLINE	0x1
487 #define	HERMON_MOD_STAT_CFG_DEFAULTS	0xF
488 
489 
490 /*
491  * The hermon_mbox_t structure is used internally by the Hermon driver to track
492  * all the information necessary to manage mailboxes for the Hermon command
493  * interface.  Specifically, by containing a pointer to the buffer, the
494  * PCI mapped address, the access handle, and a back pointer to the
495  * hermon_rsrc_t structure used to track this resource, it provides enough
496  * information allocate, use, and free any type of mailbox.
497  *
498  * The mb_indx, mb_next, and mb_prev fields are used only by the mailbox
499  * alloc/free routines (see hermon_impl_mbox_alloc/free() for more details)
500  * and are not read or modified by any mailbox consumers.  They are used
501  * to implement a fast allocation mechanism.
502  */
503 typedef struct hermon_mbox_s {
504 	void			*mb_addr;
505 	uint64_t		mb_mapaddr;
506 	ddi_acc_handle_t	mb_acchdl;
507 	hermon_rsrc_t		*mb_rsrcptr;
508 	uint_t			mb_indx;
509 	uint_t			mb_next;
510 	uint_t			mb_prev;
511 } hermon_mbox_t;
512 
513 /*
514  * The hermon_mboxlist_t structure is used to track all the information
515  * relevant to the pools of Hermon mailboxes.  Specifically, it has a pointer
516  * to an array of hermon_mbox_t structures, a lock and cv used for blocking
517  * on alloc when mailboxes are not available, and a head, tail, and entries
518  * free counter to keep track of which (if any) mailboxes are currently free.
519  * This is used (along with the mb_indx, mb_next, and mb_prev fields in the
520  * hermon_mbox_t) to implement the fast allocation mechanism.
521  */
522 typedef struct hermon_mboxlist_s {
523 	kmutex_t		mbl_lock;
524 	kcondvar_t		mbl_cv;
525 	hermon_mbox_t		*mbl_mbox;
526 	uint_t			mbl_list_sz;
527 	uint_t			mbl_num_alloc;
528 	uint_t			mbl_head_indx;
529 	uint_t			mbl_tail_indx;
530 	uint_t			mbl_entries_free;
531 	uint_t			mbl_waiters;
532 	uint_t			mbl_pollers;
533 	uint_t			mbl_signal;
534 } hermon_mboxlist_t;
535 _NOTE(MUTEX_PROTECTS_DATA(hermon_mboxlist_t::mbl_lock,
536     hermon_mboxlist_t::mbl_mbox
537     hermon_mboxlist_t::mbl_list_sz
538     hermon_mboxlist_t::mbl_num_alloc
539     hermon_mboxlist_t::mbl_cv
540     hermon_mboxlist_t::mbl_head_indx
541     hermon_mboxlist_t::mbl_tail_indx
542     hermon_mboxlist_t::mbl_entries_free
543     hermon_mboxlist_t::mbl_waiters
544     hermon_mboxlist_t::mbl_pollers
545     hermon_mboxlist_t::mbl_signal
546     hermon_mbox_t::mb_next
547     hermon_mbox_t::mb_prev))
548 
549 /*
550  * The hermon_mbox_info_t structure is used by mailbox allocators to specify
551  * the type of mailbox(es) being requested.  On a call to hermon_mbox_alloc()
552  * the mbi_alloc_flags may be set to HERMON_ALLOC_INMBOX, HERMON_ALLOC_OUTMBOX,
553  * or both.  If it is able to allocate the request type(s) of mailboxes,
554  * hermon_mbox_alloc() will fill in the "mbi_in" and/or "mbi_out" pointers
555  * to point to valid hermon_mbox_t structures from the appropriate
556  * hermon_mboxlist_t (see above).
557  * This same structure is also passed to hermon_mbox_free().  It is the
558  * responsibility of the caller to hermon_mbox_alloc() to return this exact
559  * structure (unmodified) to hermon_mbox_free().
560  *
561  * Note: If both "In" and "Out" mailboxes are requested, it is assured that
562  * no deadlock can result (from holding one mailbox while attempting to get
563  * the other).  This is assured by the fact that the "In" mailbox will always
564  * be allocated first before attempting to allocate the "Out"
565  */
566 typedef struct hermon_mbox_info_s {
567 	uint_t			mbi_alloc_flags;
568 	uint_t			mbi_sleep_context;
569 	hermon_mbox_t		*mbi_in;
570 	hermon_mbox_t		*mbi_out;
571 } hermon_mbox_info_t;
572 #define	HERMON_ALLOC_INMBOX	(1 << 0)
573 #define	HERMON_ALLOC_OUTMBOX	(1 << 1)
574 
575 
576 /*
577  * The hermon_cmd_t structure is used internally by the Hermon driver to track
578  * all the information necessary to manage outstanding firmware commands on
579  * the Hermon command interface.
580  *
581  * Each hermon_cmd_t structure contains a cv and lock which are used by the
582  * posting thread to block for completion (with cmd_status being overloaded
583  * to indicate the condition variable).  The cmd_outparam field is used to
584  * return additional status from those Hermon commands that specifically
585  * require it.
586  *
587  * The cmd_indx, cmd_next, and cmd_prev fields are used by the outstanding
588  * command alloc/free routines (see hermon_outstanding_cmd_alloc/free() for
589  * more details).  They are used (in much the same way as the mb_indx,
590  * mb_next, and mb_prev fields in hermon_mbox_t above) to implement a fast
591  * allocation mechanism.
592  */
593 typedef struct hermon_cmd_s {
594 	kmutex_t		cmd_comp_lock;
595 	kcondvar_t		cmd_comp_cv;
596 	uint64_t		cmd_outparm;
597 	uint_t			cmd_status;
598 	uint_t			cmd_indx;
599 	uint_t			cmd_next;
600 	uint_t			cmd_prev;
601 } hermon_cmd_t;
602 _NOTE(MUTEX_PROTECTS_DATA(hermon_cmd_t::cmd_comp_lock,
603     hermon_cmd_t::cmd_comp_cv
604     hermon_cmd_t::cmd_status))
605 
606 /*
607  * The hermon_cmdlist_t structure is used in almost exactly the same way as
608  * the hermon_mboxlist_t above, but instead to track all the information
609  * relevant to the pool of outstanding Hermon commands.  Specifically, it has
610  * a pointer to an array of hermon_cmd_t structures, a lock and cv used for
611  * blocking on alloc when outstanding command slots are not available, and a
612  * head, tail, and entries free counter to keep track of which (if any)
613  * command slots are currently free.  This is used (along with the cmd_indx,
614  * cmd_next, and cmd_prev fields in the hermon_cmd_t) to implement the fast
615  * allocation mechanism.
616  */
617 typedef struct hermon_cmdlist_s {
618 	kmutex_t		cml_lock;
619 	kcondvar_t		cml_cv;
620 	hermon_cmd_t		*cml_cmd;
621 	uint_t			cml_list_sz;
622 	uint_t			cml_num_alloc;
623 	uint_t			cml_head_indx;
624 	uint_t			cml_tail_indx;
625 	uint_t			cml_entries_free;
626 	uint_t			cml_waiters;
627 } hermon_cmdlist_t;
628 _NOTE(MUTEX_PROTECTS_DATA(hermon_cmdlist_t::cml_lock,
629     hermon_cmdlist_t::cml_cv
630     hermon_cmdlist_t::cml_cmd
631     hermon_cmdlist_t::cml_list_sz
632     hermon_cmdlist_t::cml_num_alloc
633     hermon_cmdlist_t::cml_head_indx
634     hermon_cmdlist_t::cml_tail_indx
635     hermon_cmdlist_t::cml_entries_free
636     hermon_cmdlist_t::cml_waiters
637     hermon_cmd_t::cmd_next
638     hermon_cmd_t::cmd_prev))
639 _NOTE(LOCK_ORDER(hermon_cmdlist_t::cml_lock
640     hermon_cmd_t::cmd_comp_lock))
641 
642 /*
643  * The hermon_cmd_post_t structure is used by all the Hermon Firmware Command
644  * routines to post to Hermon firmware.  The fields almost exactly mimic
645  * the fields in the Hermon HCR registers.  The notable exception is the
646  * addition of the "cp_flags" field (which can be set to HERMON_CMD_SPIN or
647  * HERMON_CMD_NOSPIN).  This flag really controls the value of the "e" bit
648  * in the HCR (i.e. the bit to indicate whether command should complete
649  * "in place" - in the HCR - or whether they should have their completions
650  * written to the command completion event queue.  HERMON_CMD_SPIN means
651  * to allow commands to complete "in place" and to poll the "go" bit in
652  * the HCR to determine completion.
653  *
654  * We use HERMON_SLEEP and HERMON_NOSLEEP for our HERMON_CMD_ #defines.  This is
655  * to maintain consistency with the rest of the SLEEP flags.  Additionally,
656  * because HERMON_SLEEPFLAG_FOR_CONTEXT() in hermon_rsrc.h returns HERMON_SLEEP
657  * or NOSLEEP we must be compatible with this macro.
658  */
659 typedef struct hermon_cmd_post_s {
660 	uint64_t		cp_inparm;
661 	uint64_t		cp_outparm;
662 	uint32_t		cp_inmod;
663 	uint16_t		cp_opcode;
664 	uint16_t		cp_opmod;
665 	uint32_t		cp_flags;
666 } hermon_cmd_post_t;
667 #define	HERMON_CMD_SLEEP_NOSPIN		HERMON_SLEEP
668 #define	HERMON_CMD_NOSLEEP_SPIN		HERMON_NOSLEEP
669 
670 
671 /*
672  * The following are the Hermon Firmware Command routines that accessible
673  * externally (i.e. throughout the rest of the Hermon driver software).
674  * These include the all the alloc/free routines, some initialization
675  * and cleanup routines, and the various specific Hermon firmware commands.
676  */
677 int hermon_cmd_post(hermon_state_t *state, hermon_cmd_post_t *cmdpost);
678 int hermon_mbox_alloc(hermon_state_t *state, hermon_mbox_info_t *mbox_info,
679     uint_t mbox_wait);
680 void hermon_mbox_free(hermon_state_t *state, hermon_mbox_info_t *mbox_info);
681 int hermon_cmd_complete_handler(hermon_state_t *state, hermon_eqhdl_t eq,
682     hermon_hw_eqe_t *eqe);
683 int hermon_inmbox_list_init(hermon_state_t *state);
684 int hermon_intr_inmbox_list_init(hermon_state_t *state);
685 int hermon_outmbox_list_init(hermon_state_t *state);
686 int hermon_intr_outmbox_list_init(hermon_state_t *state);
687 void hermon_inmbox_list_fini(hermon_state_t *state);
688 void hermon_intr_inmbox_list_fini(hermon_state_t *state);
689 void hermon_outmbox_list_fini(hermon_state_t *state);
690 void hermon_intr_outmbox_list_fini(hermon_state_t *state);
691 int hermon_outstanding_cmdlist_init(hermon_state_t *state);
692 void hermon_outstanding_cmdlist_fini(hermon_state_t *state);
693 
694 /* Added for MemFree */
695 int hermon_map_cmd_post(hermon_state_t *state, hermon_dma_info_t *dinfo,
696     uint16_t opcode, ddi_dma_cookie_t cookie, uint_t ccount);
697 int hermon_map_fa_cmd_post(hermon_state_t *state);
698 int hermon_run_fw_cmd_post(hermon_state_t *state);
699 int hermon_set_icm_size_cmd_post(hermon_state_t *state);
700 int hermon_map_icm_aux_cmd_post(hermon_state_t *state);
701 int hermon_map_icm_cmd_post(hermon_state_t *state);
702 int hermon_disable_lam_cmd_post(hermon_state_t *state);
703 int hermon_unmap_icm_cmd_post(hermon_state_t *state,
704     hermon_dma_info_t *dma_info);
705 int hermon_unmap_icm_aux_cmd_post(hermon_state_t *state);
706 int hermon_unmap_fa_cmd_post(hermon_state_t *state);
707 
708 /*
709  * INIT_HCA and CLOSE_HCA - used for initialization and teardown of Hermon
710  * device configuration
711  */
712 int hermon_init_hca_cmd_post(hermon_state_t *state,
713     hermon_hw_initqueryhca_t *inithca, uint_t sleepflag);
714 int hermon_close_hca_cmd_post(hermon_state_t *state, uint_t sleepflag);
715 
716 /*
717  * INIT_PORT, CLOSE_PORT, and SET_PORT - used for bring Hermon ports up and
718  * down, and to set properties of each port (e.g. PortInfo capability mask)
719  * NOTE:  New names for the commands in Hermon (previously init_ close_ and
720  * set_ib
721  */
722 int hermon_set_port_cmd_post(hermon_state_t *state,
723     hermon_hw_set_port_t *initport, uint_t port, uint_t sleepflag);
724 int hermon_init_port_cmd_post(hermon_state_t *state, uint_t port,
725     uint_t sleepflag);
726 int hermon_close_port_cmd_post(hermon_state_t *state, uint_t port,
727     uint_t sleepflag);
728 
729 /*
730  * This common function is used to post the following Hermon QP state
731  * transition firmware commands:
732  * RTS2SQD, TOERR, TORST, RST2INIT, INIT2INIT, INIT2RTR, RTR2RTS, RTS2RTS,
733  * SQD2SQD, SQD2RTS, and SQERR2RTS.
734  */
735 int hermon_cmn_qp_cmd_post(hermon_state_t *state, uint_t opcode,
736     hermon_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask, uint_t sleepflag);
737 
738 /*
739  * This common function is used to post the following Hermon query firmware
740  * commands:
741  * QUERY_DEV_LIM/CAP, QUERY_FW, QUERY_ADAPTER, QUERY_HCA, QUERY_MPT,
742  * QUERY_EQ, QUERY_CQ, and QUERY_QP.
743  * New with FCoIB, QUERY_FC
744  */
745 int hermon_cmn_query_cmd_post(hermon_state_t *state, uint_t opcode,
746     uint_t opmod, uint_t queryindx, void *query, uint_t size, uint_t sleepflag);
747 
748 /*
749  * This common function is used to post the following Hermon resource ownership
750  * firmware commands:
751  * HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and SW2HW_CQ
752  */
753 int hermon_cmn_ownership_cmd_post(hermon_state_t *state, uint_t opcode,
754     void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag);
755 
756 /*
757  * MAD_IFC and helper functions - used for posting IB MADs to Hermon firmware.
758  * The helper functions are for the MADs most frequently used by the Hermon
759  * driver (internally).
760  */
761 int hermon_mad_ifc_cmd_post(hermon_state_t *state, uint_t port,
762     uint_t sleepflag, uint32_t *mad, uint32_t *resp);
763 int hermon_getportinfo_cmd_post(hermon_state_t *state, uint_t port,
764     uint_t sleepflag, sm_portinfo_t *portinfo);
765 int hermon_getnodeinfo_cmd_post(hermon_state_t *state, uint_t sleepflag,
766     sm_nodeinfo_t *nodeinfo);
767 int hermon_getnodedesc_cmd_post(hermon_state_t *state, uint_t sleepflag,
768     sm_nodedesc_t *nodedesc);
769 int hermon_getguidinfo_cmd_post(hermon_state_t *state, uint_t port,
770     uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo);
771 int hermon_getpkeytable_cmd_post(hermon_state_t *state, uint_t port,
772     uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable);
773 int hermon_is_ext_port_counters_supported(hermon_state_t *state, uint_t port,
774     uint_t sleepflag, int *ext_width_supported);
775 int hermon_getextperfcntr_cmd_post(hermon_state_t *state, uint_t port,
776     uint_t sleepflag, hermon_hw_sm_extperfcntr_t *perfinfo);
777 int hermon_getperfcntr_cmd_post(hermon_state_t *state, uint_t port,
778     uint_t sleepflag, hermon_hw_sm_perfcntr_t *perfinfo, int reset);
779 /*
780  * WRITE_MTT - used for write MTT entries to the Hermon MTT table
781  */
782 int hermon_write_mtt_cmd_post(hermon_state_t *state, hermon_rsrc_t *mtt,
783     uint64_t start_addr, uint_t nummtt, uint_t sleepflag);
784 
785 /*
786  * SYNC_TPT - used to sync Hermon TPT caches
787  */
788 int hermon_sync_tpt_cmd_post(hermon_state_t *state, uint_t sleepflag);
789 
790 /*
791  * MAP_EQ - used for map classes of events to Hermon event queues (EQ)
792  */
793 int hermon_map_eq_cmd_post(hermon_state_t *state, uint_t map,
794     uint_t eqcindx, uint64_t eqmapmask, uint_t sleepflag);
795 
796 /*
797  * RESIZE_CQ - used for resize completion queue (CQ)
798  *	opmod 0 is resize cq.  opmod 1 is modify interrupt moderation.
799  */
800 int hermon_resize_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc,
801     uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag);
802 int hermon_modify_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc,
803     uint_t cqcindx, uint_t opmod, uint_t sleepflag);
804 
805 /*
806  * CONF_SPECIAL_QP - used to configure a pair of queue pairs for use as
807  * special QP.  Necessary to enable full QP0 and/or QP1 operation.
808  */
809 int hermon_conf_special_qp_cmd_post(hermon_state_t *state, uint_t qpindx,
810     uint_t qptype, uint_t sleepflag, uint_t opmod);
811 
812 /*
813  * Get FEXCH HEART BEAT
814  */
815 int hermon_get_heart_beat_rq_cmd_post(hermon_state_t *state, uint_t qpindx,
816     uint64_t *outparm);
817 
818 /*
819  * MGID_HASH, READ_MGM, and WRITE_MGM - used for manipulation of the
820  * hardware resource tables for multicast groups.
821  *	NOTE: for intial implementation these functions retain their original
822  *		names, though the proper hermon terminology is READ_MCG and
823  *		WRITE_MCG - MGID_HASH retains its original name
824  */
825 int hermon_mgid_hash_cmd_post(hermon_state_t *state, uint64_t mgid_h,
826     uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag);
827 int hermon_read_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg,
828     uint_t mcgindx, uint_t sleepflag);
829 int hermon_write_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg,
830     uint_t mcgindx, uint_t sleepflag);
831 
832 /*
833  * MOD_STAT_CFG - used to configure (override) settings set in NVRAM before
834  * a call to QUERY_DEV_LIM.  This is primarily used for SRQ settings in
835  * the firmware.
836  */
837 int hermon_mod_stat_cfg_cmd_post(hermon_state_t *state);
838 
839 /*
840  * MODIFY_MPT - used to change MPT attributes of a memory region.  This
841  * was (Tavor/Arbel) primarily used for Resizing SRQs -- now may be used
842  * to modify MPT paramters
843  */
844 int hermon_modify_mpt_cmd_post(hermon_state_t *state, hermon_hw_dmpt_t *mpt,
845     uint_t mptindx, uint_t flags, uint_t sleepflag);
846 
847 /*
848  * RESIZE_SRQ is new in hermon, replacing opcodes in modify_mpt.  It is used
849  * to resize the SRQ, by passing the new information in the same format as
850  * the original srqc, which the HCA will update appropriately
851  */
852 int hermon_resize_srq_cmd_post(hermon_state_t *state, hermon_hw_srqc_t *srq,
853     uint_t srqnum, uint_t sleepflag);
854 
855 /*
856  * CMD_NOP - used to test the interrupt/Event Queue mechanism.
857  */
858 int hermon_nop_post(hermon_state_t *state, uint_t interval, uint_t sleep);
859 int hermon_setdebug_post(hermon_state_t *state);
860 
861 /*
862  * READ_MTT - used to read an mtt entry at address.
863  */
864 int hermon_read_mtt_cmd_post(hermon_state_t *state, uint64_t mtt_addr,
865     hermon_hw_mtt_t *mtt);
866 
867 /*
868  * SENSE_PORT - used to send protocol running on a port
869  */
870 int hermon_sense_port_post(hermon_state_t *state, uint_t portnum,
871     uint32_t *protocol);
872 
873 /*
874  * CONFIG_FC - used to do either a basic config passing in
875  * 	*hermon_hw_config_fc_basic_s, or config the N_Port table.
876  *	passing in pointer to an array of 32-bit id's
877  *	Note that either one needs to be cast to void *
878  */
879 int hermon_config_fc_cmd_post(hermon_state_t *state, void *cfginfo, int enable,
880     int selector, int n_ports, int portnum, uint_t sleepflag);
881 
882 /*
883  * CONFIG_INT_MOD - used to configure INTERRUPT moderation
884  */
885 int hermon_config_int_mod(hermon_state_t *state, uint_t min_delay,
886     uint_t vector);
887 
888 /*
889  * HW_HEALTH_CHECK - tests state of the HCA
890  *	if command fails, *health is invalid/undefined
891  */
892 int hermon_hw_health_check(hermon_state_t *state, int *health);
893 
894 #ifdef __cplusplus
895 }
896 #endif
897 
898 #endif	/* _SYS_IB_ADAPTERS_HERMON_CMD_H */
899