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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_IB_ADAPTERS_TAVOR_EVENT_H
28 #define	_SYS_IB_ADAPTERS_TAVOR_EVENT_H
29 
30 /*
31  * tavor_event.h
32  *    Contains all of the prototypes, #defines, and structures necessary
33  *    for the Interrupt and Event Processing routines
34  *    Specifically it contains the various event types, event flags,
35  *    structures used for managing Tavor event queues, and prototypes for
36  *    many of the functions consumed by other parts of the Tavor 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 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /*
49  * Tavor UAR Doorbell Write Macro
50  *
51  * If on a 32-bit system, we must hold a lock around the ddi_put64() to
52  * ensure that the 64-bit write is an atomic operation.  This is a
53  * requirement of the Tavor hardware and is to protect from the race
54  * condition present when more than one kernel thread attempts to do each
55  * of their two 32-bit accesses (for 64-bit doorbell) simultaneously.
56  *
57  * If we are on a 64-bit system then the ddi_put64() is completed as one
58  * 64-bit instruction, and the lock is not needed.
59  *
60  * This is done as a preprocessor #if to speed up execution at run-time
61  * since doorbell ringing is a "fast-path" operation.
62  */
63 #if (DATAMODEL_NATIVE == DATAMODEL_ILP32)
64 #define	TAVOR_UAR_DOORBELL(state, ts_uar, doorbell)		{	\
65 	mutex_enter(&state->ts_uar_lock);				\
66 	ddi_put64(state->ts_reg_uarhdl, ts_uar, doorbell);		\
67 	mutex_exit(&state->ts_uar_lock);				\
68 }
69 #else
70 #define	TAVOR_UAR_DOORBELL(state, ts_uar, doorbell)		{	\
71 	ddi_put64(state->ts_reg_uarhdl, ts_uar, doorbell);		\
72 }
73 #endif
74 
75 /*
76  * The following defines specify the default number of Event Queues (EQ) and
77  * their default size.  By default the size of each EQ is set to 4K entries,
78  * but this value is controllable through the "log_default_eq_sz"
79  * configuration variable.  We also specify the number of EQs which the Tavor
80  * driver currently uses (TAVOR_NUM_EQ_USED).  Note: this value should be
81  * less than or equal to TAVOR_NUM_EQ.  Because there are only so many classes
82  * of events today, it is unnecessary to allocate all 64 EQs only to leave
83  * several of them unused.
84  */
85 #define	TAVOR_NUM_EQ_SHIFT			0x6
86 #define	TAVOR_NUM_EQ				(1 << TAVOR_NUM_EQ_SHIFT)
87 #define	TAVOR_NUM_EQ_USED			47
88 #define	TAVOR_DEFAULT_EQ_SZ_SHIFT		0xC
89 
90 /*
91  * The following macro determines whether the contents of EQ memory (EQEs)
92  * need to be sync'd (with ddi_dma_sync()).  This decision is based on whether
93  * the EQ memory is in DDR memory (no sync) or system memory (sync required).
94  * Note: It doesn't make much sense to put EQEs in DDR memory (since they are
95  * primarily written by HW and read by the CPU), but the driver does support
96  * that possibility.  And it also supports the possibility that if a CQ in
97  * system memory is mapped DDI_DMA_CONSISTENT, it can be configured to not be
98  * sync'd because of the "sync override" parameter in the config profile.
99  */
100 #define	TAVOR_EQ_IS_SYNC_REQ(state, eqinfo)				\
101 	((((((state)->ts_cfg_profile->cp_streaming_consistent) &&	\
102 	((state)->ts_cfg_profile->cp_consistent_syncoverride))) ||      \
103 	((eqinfo).qa_location == TAVOR_QUEUE_LOCATION_INDDR))	\
104 	? 0 : 1)
105 
106 /*
107  * The following defines specify the size of the individual Event Queue
108  * Context (EQC) entries
109  */
110 #define	TAVOR_EQC_SIZE_SHIFT			0x6
111 #define	TAVOR_EQC_SIZE				(1 << TAVOR_EQC_SIZE_SHIFT)
112 
113 /*
114  * These are the defines for the Tavor event types.  They are specified by
115  * the Tavor register specification.  Below are the "event type masks" in
116  * which each event type corresponds to one of the 64-bits in the mask.
117  */
118 #define	TAVOR_EVT_COMPLETION			0x00
119 #define	TAVOR_EVT_PATH_MIGRATED			0x01
120 #define	TAVOR_EVT_COMM_ESTABLISHED		0x02
121 #define	TAVOR_EVT_SEND_QUEUE_DRAINED		0x03
122 #define	TAVOR_EVT_CQ_ERRORS			0x04
123 #define	TAVOR_EVT_LOCAL_WQ_CAT_ERROR		0x05
124 #define	TAVOR_EVT_LOCAL_EEC_CAT_ERROR		0x06	/* unsupported: RD */
125 #define	TAVOR_EVT_PATH_MIGRATE_FAILED		0x07
126 #define	TAVOR_EVT_LOCAL_CAT_ERROR		0x08
127 #define	TAVOR_EVT_PORT_STATE_CHANGE		0x09
128 #define	TAVOR_EVT_COMMAND_INTF_COMP		0x0A
129 #define	TAVOR_EVT_WQE_PG_FAULT			0x0B
130 #define	TAVOR_EVT_UNSUPPORTED_PG_FAULT		0x0C
131 #define	TAVOR_EVT_ECC_DETECTION			0x0E
132 #define	TAVOR_EVT_EQ_OVERFLOW			0x0F
133 #define	TAVOR_EVT_INV_REQ_LOCAL_WQ_ERROR	0x10
134 #define	TAVOR_EVT_LOCAL_ACC_VIO_WQ_ERROR	0x11
135 #define	TAVOR_EVT_SRQ_CATASTROPHIC_ERROR	0x12
136 #define	TAVOR_EVT_SRQ_LAST_WQE_REACHED		0x13
137 
138 #define	TAVOR_EVT_MSK_COMPLETION		\
139 	(1 << TAVOR_EVT_COMPLETION)
140 #define	TAVOR_EVT_MSK_PATH_MIGRATED		\
141 	(1 << TAVOR_EVT_PATH_MIGRATED)
142 #define	TAVOR_EVT_MSK_COMM_ESTABLISHED		\
143 	(1 << TAVOR_EVT_COMM_ESTABLISHED)
144 #define	TAVOR_EVT_MSK_SEND_QUEUE_DRAINED	\
145 	(1 << TAVOR_EVT_SEND_QUEUE_DRAINED)
146 #define	TAVOR_EVT_MSK_CQ_ERRORS			\
147 	(1 << TAVOR_EVT_CQ_ERRORS)
148 #define	TAVOR_EVT_MSK_LOCAL_WQ_CAT_ERROR	\
149 	(1 << TAVOR_EVT_LOCAL_WQ_CAT_ERROR)
150 #define	TAVOR_EVT_MSK_LOCAL_EEC_CAT_ERROR	\
151 	(1 << TAVOR_EVT_LOCAL_EEC_CAT_ERROR)		/* unsupported: RD */
152 #define	TAVOR_EVT_MSK_PATH_MIGRATE_FAILED	\
153 	(1 << TAVOR_EVT_PATH_MIGRATE_FAILED)
154 #define	TAVOR_EVT_MSK_LOCAL_CAT_ERROR		\
155 	(1 << TAVOR_EVT_LOCAL_CAT_ERROR)
156 #define	TAVOR_EVT_MSK_PORT_STATE_CHANGE		\
157 	(1 << TAVOR_EVT_PORT_STATE_CHANGE)
158 #define	TAVOR_EVT_MSK_COMMAND_INTF_COMP		\
159 	(1 << TAVOR_EVT_COMMAND_INTF_COMP)
160 #define	TAVOR_EVT_MSK_WQE_PG_FAULT		\
161 	(1 << TAVOR_EVT_WQE_PG_FAULT)
162 #define	TAVOR_EVT_MSK_UNSUPPORTED_PG_FAULT	\
163 	(1 << TAVOR_EVT_UNSUPPORTED_PG_FAULT)
164 #define	TAVOR_EVT_MSK_INV_REQ_LOCAL_WQ_ERROR	\
165 	(1 << TAVOR_EVT_INV_REQ_LOCAL_WQ_ERROR)
166 #define	TAVOR_EVT_MSK_LOCAL_ACC_VIO_WQ_ERROR	\
167 	(1 << TAVOR_EVT_LOCAL_ACC_VIO_WQ_ERROR)
168 #define	TAVOR_EVT_MSK_SRQ_CATASTROPHIC_ERROR	\
169 	(1 << TAVOR_EVT_SRQ_CATASTROPHIC_ERROR)
170 #define	TAVOR_EVT_MSK_SRQ_LAST_WQE_REACHED	\
171 	(1 << TAVOR_EVT_SRQ_LAST_WQE_REACHED)
172 #define	TAVOR_EVT_MSK_ECC_DETECTION		\
173 	(1 << TAVOR_EVT_ECC_DETECTION)
174 #define	TAVOR_EVT_NO_MASK			0
175 #define	TAVOR_EVT_CATCHALL_MASK			0x1840
176 
177 /*
178  * The last defines are used by tavor_eqe_sync() to indicate whether or not
179  * to force a DMA sync.  The case for forcing a DMA sync on a EQE comes from
180  * the possibility that we could receive an interrupt, read of the ECR, and
181  * have each of these operations complete successfully _before_ the hardware
182  * has finished its DMA to the event queue.
183  */
184 #define	TAVOR_EQ_SYNC_NORMAL			0x0
185 #define	TAVOR_EQ_SYNC_FORCE			0x1
186 
187 /*
188  * Catastrophic error values.  In case of a catastrophic error, the following
189  * errors are reported in a special buffer space.  The buffer location is
190  * returned from a QUERY_FW command.  We check that buffer against these error
191  * values to determine what kind of error occurred.
192  */
193 #define	TAVOR_CATASTROPHIC_INTERNAL_ERROR		0x0
194 #define	TAVOR_CATASTROPHIC_UPLINK_BUS_ERROR		0x3
195 #define	TAVOR_CATASTROPHIC_DDR_DATA_ERROR		0x4
196 #define	TAVOR_CATASTROPHIC_INTERNAL_PARITY_ERROR	0x5
197 
198 /*
199  * This define is the 'enable' flag used when programming the MSI number
200  * into event queues.  It is or'd with the MSI number and the result is
201  * written into the EX context.
202  */
203 
204 #define	TAVOR_EQ_MSI_ENABLE_FLAG		0x80
205 
206 /*
207  * The tavor_sw_eq_s structure is also referred to using the "tavor_eqhdl_t"
208  * typedef (see tavor_typedef.h).  It encodes all the information necessary
209  * to track the various resources needed to allocate, initialize, poll, and
210  * (later) free an event queue (EQ).
211  *
212  * Specifically, it has a consumer index and a lock to ensure single threaded
213  * access to it.  It has pointers to the various resources allocated for the
214  * event queue, i.e. an EQC resource and the memory for the event queue
215  * itself.  It has flags to indicate whether the EQ requires ddi_dma_sync()
216  * ("eq_sync") or to indicate which type of event class(es) the EQ has been
217  * mapped to (eq_evttypemask).
218  *
219  * It also has a pointer to the associated MR handle (for the mapped queue
220  * memory) and a function pointer that points to the handler that should
221  * be called when the corresponding EQ has fired.  Note: the "eq_func"
222  * handler takes a Tavor softstate pointer, a pointer to the EQ handle, and a
223  * pointer to a generic tavor_hw_eqe_t structure.  It is up to the "eq_func"
224  * handler function to determine what specific type of event is being passed.
225  *
226  * Lastly, we have the always necessary backpointer to the resource for the
227  * EQ handle structure itself.
228  */
229 struct tavor_sw_eq_s {
230 	uint32_t		eq_consindx;
231 	uint32_t		eq_eqnum;
232 	tavor_hw_eqe_t		*eq_buf;
233 	tavor_mrhdl_t		eq_mrhdl;
234 	uint32_t		eq_bufsz;
235 	uint_t			eq_sync;
236 	uint_t			eq_evttypemask;
237 	tavor_rsrc_t		*eq_eqcrsrcp;
238 	tavor_rsrc_t		*eq_rsrcp;
239 	int (*eq_func)(tavor_state_t *state, tavor_eqhdl_t eq,
240 	    tavor_hw_eqe_t *eqe);
241 
242 	struct tavor_qalloc_info_s eq_eqinfo;
243 };
244 
245 int tavor_eq_init_all(tavor_state_t *state);
246 int tavor_eq_fini_all(tavor_state_t *state);
247 void tavor_eq_arm_all(tavor_state_t *state);
248 uint_t tavor_isr(caddr_t arg1, caddr_t arg2);
249 void tavor_eq_doorbell(tavor_state_t *state, uint32_t eq_cmd, uint32_t eqn,
250     uint32_t eq_param);
251 void tavor_eq_overflow_handler(tavor_state_t *state, tavor_eqhdl_t eq,
252     tavor_hw_eqe_t *eqe);
253 
254 #ifdef __cplusplus
255 }
256 #endif
257 
258 #endif	/* _SYS_IB_ADAPTERS_TAVOR_EVENT_H */
259