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