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 /*
28  * tavor_event.c
29  *    Tavor Interrupt and Event Processing Routines
30  *
31  *    Implements all the routines necessary for allocating, freeing, and
32  *    handling all of the various event types that the Tavor hardware can
33  *    generate.
34  *    These routines include the main Tavor interrupt service routine
35  *    (tavor_isr()) as well as all the code necessary to setup and handle
36  *    events from each of the many event queues used by the Tavor device.
37  */
38 
39 #include <sys/types.h>
40 #include <sys/conf.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/modctl.h>
44 
45 #include <sys/ib/adapters/tavor/tavor.h>
46 
47 static void tavor_eq_poll(tavor_state_t *state, tavor_eqhdl_t eq);
48 static void tavor_eq_catastrophic(tavor_state_t *state);
49 static int tavor_eq_alloc(tavor_state_t *state, uint32_t log_eq_size,
50     uint_t intr, tavor_eqhdl_t *eqhdl);
51 static int tavor_eq_free(tavor_state_t *state, tavor_eqhdl_t *eqhdl);
52 static int tavor_eq_handler_init(tavor_state_t *state, tavor_eqhdl_t eq,
53     uint_t evt_type_mask, int (*eqfunc)(tavor_state_t *state,
54     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe));
55 static int tavor_eq_handler_fini(tavor_state_t *state, tavor_eqhdl_t eq);
56 static void tavor_eqe_sync(tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe, uint_t flag,
57     uint_t force_sync);
58 static int tavor_port_state_change_handler(tavor_state_t *state,
59     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
60 static int tavor_comm_estbl_handler(tavor_state_t *state,
61     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
62 static int tavor_local_wq_cat_err_handler(tavor_state_t *state,
63     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
64 static int tavor_invreq_local_wq_err_handler(tavor_state_t *state,
65     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
66 static int tavor_local_acc_vio_wq_err_handler(tavor_state_t *state,
67     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
68 static int tavor_sendq_drained_handler(tavor_state_t *state,
69     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
70 static int tavor_path_mig_handler(tavor_state_t *state,
71     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
72 static int tavor_path_mig_err_handler(tavor_state_t *state,
73     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
74 static int tavor_srq_catastrophic_handler(tavor_state_t *state,
75     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
76 static int tavor_srq_last_wqe_reached_handler(tavor_state_t *state,
77     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
78 static int tavor_ecc_detection_handler(tavor_state_t *state,
79     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe);
80 static int tavor_no_eqhandler(tavor_state_t *state, tavor_eqhdl_t eq,
81     tavor_hw_eqe_t *eqe);
82 
83 
84 /*
85  * tavor_eq_init_all
86  *    Context: Only called from attach() path context
87  */
88 int
89 tavor_eq_init_all(tavor_state_t *state)
90 {
91 	uint_t		log_eq_size, intr_num;
92 	uint_t		num_eq, num_eq_init, num_eq_unmap;
93 	int		status, i;
94 	char		*errormsg;
95 
96 	TAVOR_TNF_ENTER(tavor_eq_init_all);
97 
98 	/*
99 	 * For now, all Event Queues default to the same size (pulled from
100 	 * the current configuration profile) and are all assigned to the
101 	 * same interrupt or MSI.  In the future we may support assigning
102 	 * EQs to specific interrupts or MSIs XXX
103 	 */
104 	log_eq_size = state->ts_cfg_profile->cp_log_default_eq_sz;
105 
106 	/*
107 	 * If MSI is to be used, then set intr_num to the MSI number
108 	 * (currently zero because we're using only one) or'd with the
109 	 * MSI enable flag.  Otherwise, for regular (i.e. 'legacy') interrupt,
110 	 * use the 'inta_pin' value returned by QUERY_ADAPTER.
111 	 */
112 	if (state->ts_intr_type_chosen == DDI_INTR_TYPE_MSI) {
113 		intr_num = TAVOR_EQ_MSI_ENABLE_FLAG | 0;
114 	} else {
115 		intr_num = state->ts_adapter.inta_pin;
116 	}
117 
118 	/*
119 	 * Total number of supported EQs is hardcoded.  Tavor hardware
120 	 * supports up to 64 EQs.  We are currently using only 45 of them
121 	 * We will set aside the first 32 for use with Completion Queues (CQ)
122 	 * and reserve a few of the other 32 for each specific class of event
123 	 * (see below for more details).
124 	 */
125 	num_eq = TAVOR_NUM_EQ_USED;
126 
127 	/*
128 	 * The "num_eq_unmap" variable is used in any possible failure
129 	 * cleanup (below) to indicate which events queues might require
130 	 * possible event class unmapping.
131 	 */
132 	num_eq_unmap = 0;
133 
134 	/*
135 	 * Allocate and initialize all the Event Queues.  If any of these
136 	 * EQ allocations fail then jump to the end, cleanup what had been
137 	 * successfully initialized, and return an error.
138 	 */
139 	for (i = 0; i < num_eq; i++) {
140 		status = tavor_eq_alloc(state, log_eq_size, intr_num,
141 		    &state->ts_eqhdl[i]);
142 		if (status != DDI_SUCCESS) {
143 			/* Set "status" and "errormsg" and goto failure */
144 			TAVOR_TNF_FAIL(status, "failed EQ alloc");
145 			num_eq_init = i;
146 			goto all_eq_init_fail;
147 		}
148 	}
149 	num_eq_init = num_eq;
150 
151 	/*
152 	 * Setup EQ0-EQ31 for use with Completion Queues.  Note: We can
153 	 * cast the return value to void here because, when we use the
154 	 * TAVOR_EVT_NO_MASK flag, it is not possible for
155 	 * tavor_eq_handler_init() to return an error.
156 	 */
157 	for (i = 0; i < 32; i++) {
158 		(void) tavor_eq_handler_init(state, state->ts_eqhdl[i],
159 		    TAVOR_EVT_NO_MASK, tavor_cq_handler);
160 	}
161 	num_eq_unmap = 32;
162 
163 	/*
164 	 * Setup EQ32 for handling Completion Queue Error Events.
165 	 *
166 	 * These events include things like CQ overflow or CQ access
167 	 * violation errors.  If this setup fails for any reason (which, in
168 	 * general, it really never should), then jump to the end, cleanup
169 	 * everything that has been successfully initialized, and return an
170 	 * error.
171 	 */
172 	status = tavor_eq_handler_init(state, state->ts_eqhdl[32],
173 	    TAVOR_EVT_MSK_CQ_ERRORS, tavor_cq_err_handler);
174 	if (status != DDI_SUCCESS) {
175 		/* Set "status" and "errormsg" and goto failure */
176 		TAVOR_TNF_FAIL(status, "completion queue error event");
177 		goto all_eq_init_fail;
178 	}
179 	num_eq_unmap = 33;
180 
181 	/*
182 	 * Setup EQ33 for handling Port State Change Events
183 	 *
184 	 * These events include things like Port Up and Port Down events.
185 	 * If this setup fails for any reason (which, in general, it really
186 	 * never should), then undo all previous EQ mapping, jump to the end,
187 	 * cleanup everything that has been successfully initialized, and
188 	 * return an error.
189 	 */
190 	status = tavor_eq_handler_init(state, state->ts_eqhdl[33],
191 	    TAVOR_EVT_MSK_PORT_STATE_CHANGE, tavor_port_state_change_handler);
192 	if (status != DDI_SUCCESS) {
193 		/* Set "status" and "errormsg" and goto failure */
194 		TAVOR_TNF_FAIL(status, "port state change event");
195 		goto all_eq_init_fail;
196 	}
197 	num_eq_unmap = 34;
198 
199 	/*
200 	 * Setup EQ34 for handling Communication Established Events
201 	 *
202 	 * These events correspond to the IB affiliated asynchronous events
203 	 * that are used for connection management.  If this setup fails for
204 	 * any reason (which, in general, it really never should), then undo
205 	 * all previous EQ mapping, jump to the end, cleanup everything that
206 	 * has been successfully initialized, and return an error.
207 	 */
208 	status = tavor_eq_handler_init(state, state->ts_eqhdl[34],
209 	    TAVOR_EVT_MSK_COMM_ESTABLISHED, tavor_comm_estbl_handler);
210 	if (status != DDI_SUCCESS) {
211 		/* Set "status" and "errormsg" and goto failure */
212 		TAVOR_TNF_FAIL(status, "communication established event");
213 		goto all_eq_init_fail;
214 	}
215 	num_eq_unmap = 35;
216 
217 	/*
218 	 * Setup EQ35 for handling Command Completion Events
219 	 *
220 	 * These events correspond to the Tavor generated events that are used
221 	 * to indicate Tavor firmware command completion.  These events are
222 	 * only generated when Tavor firmware commands are posted using the
223 	 * asynchronous completion mechanism.  If this setup fails for any
224 	 * reason (which, in general, it really never should), then undo all
225 	 * previous EQ mapping, jump to the end, cleanup everything that has
226 	 * been successfully initialized, and return an error.
227 	 */
228 	status = tavor_eq_handler_init(state, state->ts_eqhdl[35],
229 	    TAVOR_EVT_MSK_COMMAND_INTF_COMP, tavor_cmd_complete_handler);
230 	if (status != DDI_SUCCESS) {
231 		/* Set "status" and "errormsg" and goto failure */
232 		TAVOR_TNF_FAIL(status, "command completion event");
233 		goto all_eq_init_fail;
234 	}
235 	num_eq_unmap = 36;
236 
237 	/*
238 	 * Setup EQ36 for handling Local WQ Catastrophic Error Events
239 	 *
240 	 * These events correspond to the similarly-named IB affiliated
241 	 * asynchronous error type.  If this setup fails for any reason
242 	 * (which, in general, it really never should), then undo all previous
243 	 * EQ mapping, jump to the end, cleanup everything that has been
244 	 * successfully initialized, and return an error.
245 	 */
246 	status = tavor_eq_handler_init(state, state->ts_eqhdl[36],
247 	    TAVOR_EVT_MSK_LOCAL_WQ_CAT_ERROR, tavor_local_wq_cat_err_handler);
248 	if (status != DDI_SUCCESS) {
249 		/* Set "status" and "errormsg" and goto failure */
250 		TAVOR_TNF_FAIL(status, "local WQ catastrophic error event");
251 		goto all_eq_init_fail;
252 	}
253 	num_eq_unmap = 37;
254 
255 	/*
256 	 * Setup EQ37 for handling Invalid Req Local WQ Error Events
257 	 *
258 	 * These events also correspond to the similarly-named IB affiliated
259 	 * asynchronous error type.  If this setup fails for any reason
260 	 * (which, in general, it really never should), then undo all previous
261 	 * EQ mapping, jump to the end, cleanup everything that has been
262 	 * successfully initialized, and return an error.
263 	 */
264 	status = tavor_eq_handler_init(state, state->ts_eqhdl[37],
265 	    TAVOR_EVT_MSK_INV_REQ_LOCAL_WQ_ERROR,
266 	    tavor_invreq_local_wq_err_handler);
267 	if (status != DDI_SUCCESS) {
268 		/* Set "status" and "errormsg" and goto failure */
269 		TAVOR_TNF_FAIL(status, "invalid req local WQ error event");
270 		goto all_eq_init_fail;
271 	}
272 	num_eq_unmap = 38;
273 
274 	/*
275 	 * Setup EQ38 for handling Local Access Violation WQ Error Events
276 	 *
277 	 * These events also correspond to the similarly-named IB affiliated
278 	 * asynchronous error type.  If this setup fails for any reason
279 	 * (which, in general, it really never should), then undo all previous
280 	 * EQ mapping, jump to the end, cleanup everything that has been
281 	 * successfully initialized, and return an error.
282 	 */
283 	status = tavor_eq_handler_init(state, state->ts_eqhdl[38],
284 	    TAVOR_EVT_MSK_LOCAL_ACC_VIO_WQ_ERROR,
285 	    tavor_local_acc_vio_wq_err_handler);
286 	if (status != DDI_SUCCESS) {
287 		/* Set "status" and "errormsg" and goto failure */
288 		TAVOR_TNF_FAIL(status, "local access violation WQ error event");
289 		goto all_eq_init_fail;
290 	}
291 	num_eq_unmap = 39;
292 
293 	/*
294 	 * Setup EQ39 for handling Send Queue Drained Events
295 	 *
296 	 * These events correspond to the IB affiliated asynchronous events
297 	 * that are used to indicate completion of a Send Queue Drained QP
298 	 * state transition.  If this setup fails for any reason (which, in
299 	 * general, it really never should), then undo all previous EQ
300 	 * mapping, jump to the end, cleanup everything that has been
301 	 * successfully initialized, and return an error.
302 	 */
303 	status = tavor_eq_handler_init(state, state->ts_eqhdl[39],
304 	    TAVOR_EVT_MSK_SEND_QUEUE_DRAINED, tavor_sendq_drained_handler);
305 	if (status != DDI_SUCCESS) {
306 		/* Set "status" and "errormsg" and goto failure */
307 		TAVOR_TNF_FAIL(status, "send queue drained event");
308 		goto all_eq_init_fail;
309 	}
310 	num_eq_unmap = 40;
311 
312 	/*
313 	 * Setup EQ40 for handling Path Migration Succeeded Events
314 	 *
315 	 * These events correspond to the IB affiliated asynchronous events
316 	 * that are used to indicate successful completion of a path
317 	 * migration.  If this setup fails for any reason (which, in general,
318 	 * it really never should), then undo all previous EQ mapping, jump
319 	 * to the end, cleanup everything that has been successfully
320 	 * initialized, and return an error.
321 	 */
322 	status = tavor_eq_handler_init(state, state->ts_eqhdl[40],
323 	    TAVOR_EVT_MSK_PATH_MIGRATED, tavor_path_mig_handler);
324 	if (status != DDI_SUCCESS) {
325 		/* Set "status" and "errormsg" and goto failure */
326 		TAVOR_TNF_FAIL(status, "path migration succeeded event");
327 		goto all_eq_init_fail;
328 	}
329 	num_eq_unmap = 41;
330 
331 	/*
332 	 * Setup EQ41 for handling Path Migration Failed Events
333 	 *
334 	 * These events correspond to the IB affiliated asynchronous events
335 	 * that are used to indicate that path migration was not successful.
336 	 * If this setup fails for any reason (which, in general, it really
337 	 * never should), then undo all previous EQ mapping, jump to the end,
338 	 * cleanup everything that has been successfully initialized, and
339 	 * return an error.
340 	 */
341 	status = tavor_eq_handler_init(state, state->ts_eqhdl[41],
342 	    TAVOR_EVT_MSK_PATH_MIGRATE_FAILED, tavor_path_mig_err_handler);
343 	if (status != DDI_SUCCESS) {
344 		/* Set "status" and "errormsg" and goto failure */
345 		TAVOR_TNF_FAIL(status, "path migration failed event");
346 		goto all_eq_init_fail;
347 	}
348 	num_eq_unmap = 42;
349 
350 	/*
351 	 * Setup EQ42 for handling Local Catastrophic Error Events
352 	 *
353 	 * These events correspond to the similarly-named IB unaffiliated
354 	 * asynchronous error type.  If this setup fails for any reason
355 	 * (which, in general, it really never should), then undo all previous
356 	 * EQ mapping, jump to the end, cleanup everything that has been
357 	 * successfully initialized, and return an error.
358 	 *
359 	 * This error is unique, in that an EQE is not generated if this event
360 	 * occurs.  Instead, an interrupt is called and we must poll the
361 	 * Catastrophic Error buffer in CR-Space.  This mapping is setup simply
362 	 * to enable this error reporting.  We pass in a NULL handler since it
363 	 * will never be called.
364 	 */
365 	status = tavor_eq_handler_init(state, state->ts_eqhdl[42],
366 	    TAVOR_EVT_MSK_LOCAL_CAT_ERROR, NULL);
367 	if (status != DDI_SUCCESS) {
368 		/* Set "status" and "errormsg" and goto failure */
369 		TAVOR_TNF_FAIL(status, "local catastrophic error event");
370 		goto all_eq_init_fail;
371 	}
372 	num_eq_unmap = 43;
373 
374 	/*
375 	 * Setup EQ43 for handling SRQ Catastrophic Error Events
376 	 *
377 	 * These events correspond to the similarly-named IB affiliated
378 	 * asynchronous error type.  If this setup fails for any reason
379 	 * (which, in general, it really never should), then undo all previous
380 	 * EQ mapping, jump to the end, cleanup everything that has been
381 	 * successfully initialized, and return an error.
382 	 */
383 	status = tavor_eq_handler_init(state, state->ts_eqhdl[43],
384 	    TAVOR_EVT_MSK_SRQ_CATASTROPHIC_ERROR,
385 	    tavor_srq_catastrophic_handler);
386 	if (status != DDI_SUCCESS) {
387 		/* Set "status" and "errormsg" and goto failure */
388 		TAVOR_TNF_FAIL(status, "srq catastrophic error event");
389 		goto all_eq_init_fail;
390 	}
391 	num_eq_unmap = 44;
392 
393 	/*
394 	 * Setup EQ44 for handling SRQ Last WQE Reached Events
395 	 *
396 	 * These events correspond to the similarly-named IB affiliated
397 	 * asynchronous event type.  If this setup fails for any reason
398 	 * (which, in general, it really never should), then undo all previous
399 	 * EQ mapping, jump to the end, cleanup everything that has been
400 	 * successfully initialized, and return an error.
401 	 */
402 	status = tavor_eq_handler_init(state, state->ts_eqhdl[44],
403 	    TAVOR_EVT_MSK_SRQ_LAST_WQE_REACHED,
404 	    tavor_srq_last_wqe_reached_handler);
405 	if (status != DDI_SUCCESS) {
406 		/* Set "status" and "errormsg" and goto failure */
407 		TAVOR_TNF_FAIL(status, "srq last wqe reached event");
408 		goto all_eq_init_fail;
409 	}
410 	num_eq_unmap = 45;
411 
412 	/*
413 	 * Setup EQ45 for handling ECC error detection events
414 	 *
415 	 * These events correspond to the similarly-named IB affiliated
416 	 * asynchronous event type.  If this setup fails for any reason
417 	 * (which, in general, it really never should), then undo all previous
418 	 * EQ mapping, jump to the end, cleanup everything that has been
419 	 * successfully initialized, and return an error.
420 	 */
421 	status = tavor_eq_handler_init(state, state->ts_eqhdl[45],
422 	    TAVOR_EVT_MSK_ECC_DETECTION,
423 	    tavor_ecc_detection_handler);
424 	if (status != DDI_SUCCESS) {
425 		/* Set "status" and "errormsg" and goto failure */
426 		TAVOR_TNF_FAIL(status, "ecc detection event");
427 		goto all_eq_init_fail;
428 	}
429 	num_eq_unmap = 46;
430 
431 	/*
432 	 * Setup EQ46 to catch all other types of events.  Specifically, we
433 	 * do not catch the "Local EEC Catastrophic Error Event" because we
434 	 * should have no EEC (the Tavor driver does not support RD).  We also
435 	 * choose not to handle any of the address translation page fault
436 	 * event types.  Since we are not doing any page fault handling (and
437 	 * since the Tavor firmware does not currently support any such
438 	 * handling), we allow these events to go to the catch-all handler.
439 	 */
440 	status = tavor_eq_handler_init(state, state->ts_eqhdl[46],
441 	    TAVOR_EVT_CATCHALL_MASK, tavor_no_eqhandler);
442 	if (status != DDI_SUCCESS) {
443 		/* Set "status" and "errormsg" and goto failure */
444 		TAVOR_TNF_FAIL(status, "all other events");
445 		TNF_PROBE_0(tavor_eq_init_all_allothershdlr_fail,
446 		    TAVOR_TNF_ERROR, "");
447 		goto all_eq_init_fail;
448 	}
449 
450 	TAVOR_TNF_EXIT(tavor_eq_init_all);
451 	return (DDI_SUCCESS);
452 
453 all_eq_init_fail:
454 	/* Unmap any of the partially mapped EQs from above */
455 	for (i = 0; i < num_eq_unmap; i++) {
456 		(void) tavor_eq_handler_fini(state, state->ts_eqhdl[i]);
457 	}
458 
459 	/* Free up any of the partially allocated EQs from above */
460 	for (i = 0; i < num_eq_init; i++) {
461 		(void) tavor_eq_free(state, &state->ts_eqhdl[i]);
462 	}
463 	TNF_PROBE_1(tavor_eq_init_all_fail, TAVOR_TNF_ERROR, "",
464 	    tnf_string, msg, errormsg);
465 	TAVOR_TNF_EXIT(tavor_eq_init_all);
466 	return (status);
467 }
468 
469 
470 /*
471  * tavor_eq_fini_all
472  *    Context: Only called from attach() and/or detach() path contexts
473  */
474 int
475 tavor_eq_fini_all(tavor_state_t *state)
476 {
477 	uint_t		num_eq;
478 	int		status, i;
479 
480 	TAVOR_TNF_ENTER(tavor_eq_fini_all);
481 
482 	/*
483 	 * Grab the total number of supported EQs again.  This is the same
484 	 * hardcoded value that was used above (during the event queue
485 	 * initialization.)
486 	 */
487 	num_eq = TAVOR_NUM_EQ_USED;
488 
489 	/*
490 	 * For each of the event queues that we initialized and mapped
491 	 * earlier, attempt to unmap the events from the EQ.
492 	 */
493 	for (i = 0; i < num_eq; i++) {
494 		status = tavor_eq_handler_fini(state, state->ts_eqhdl[i]);
495 		if (status != DDI_SUCCESS) {
496 			TNF_PROBE_0(tavor_eq_fini_all_eqhdlfini_fail,
497 			    TAVOR_TNF_ERROR, "");
498 			TAVOR_TNF_EXIT(tavor_eq_fini_all);
499 			return (DDI_FAILURE);
500 		}
501 	}
502 
503 	/*
504 	 * Teardown and free up all the Event Queues that were allocated
505 	 * earlier.
506 	 */
507 	for (i = 0; i < num_eq; i++) {
508 		status = tavor_eq_free(state, &state->ts_eqhdl[i]);
509 		if (status != DDI_SUCCESS) {
510 			TNF_PROBE_0(tavor_eq_fini_all_eqfree_fail,
511 			    TAVOR_TNF_ERROR, "");
512 			TAVOR_TNF_EXIT(tavor_eq_fini_all);
513 			return (DDI_FAILURE);
514 		}
515 	}
516 
517 	TAVOR_TNF_EXIT(tavor_eq_fini_all);
518 	return (DDI_SUCCESS);
519 }
520 
521 
522 /*
523  * tavor_eq_arm_all
524  *    Context: Only called from attach() and/or detach() path contexts
525  */
526 void
527 tavor_eq_arm_all(tavor_state_t *state)
528 {
529 	uint_t		num_eq;
530 	int		i;
531 
532 	TAVOR_TNF_ENTER(tavor_eq_arm_all);
533 
534 	/*
535 	 * Grab the total number of supported EQs again.  This is the same
536 	 * hardcoded value that was used above (during the event queue
537 	 * initialization.)
538 	 */
539 	num_eq = TAVOR_NUM_EQ_USED;
540 
541 	/*
542 	 * For each of the event queues that we initialized and mapped
543 	 * earlier, attempt to arm it for event generation.
544 	 */
545 	for (i = 0; i < num_eq; i++) {
546 		tavor_eq_doorbell(state, TAVOR_EQDB_REARM_EQ, i, 0);
547 	}
548 
549 	TAVOR_TNF_EXIT(tavor_eq_arm_all);
550 }
551 
552 
553 /*
554  * tavor_isr()
555  *    Context: Only called from interrupt context (and during panic)
556  */
557 /* ARGSUSED */
558 uint_t
559 tavor_isr(caddr_t arg1, caddr_t arg2)
560 {
561 	tavor_state_t	*state;
562 	uint64_t	*ecr, *clr_int;
563 	uint64_t	ecrreg, int_mask;
564 	uint_t		status;
565 	int		i;
566 
567 	TAVOR_TNF_ENTER(tavor_isr);
568 
569 	/*
570 	 * Grab the Tavor softstate pointer from the input parameter
571 	 */
572 	state	= (tavor_state_t *)arg1;
573 
574 	/*
575 	 * Find the pointers to the ECR and clr_INT registers
576 	 */
577 	ecr	= state->ts_cmd_regs.ecr;
578 	clr_int = state->ts_cmd_regs.clr_int;
579 
580 	/*
581 	 * Read the ECR register.  Each of the 64 bits in the ECR register
582 	 * corresponds to an event queue.  If a bit is set, then the
583 	 * corresponding event queue has fired.
584 	 */
585 	ecrreg = ddi_get64(state->ts_reg_cmdhdl, ecr);
586 
587 	/*
588 	 * As long as there are bits set (i.e. as long as there are still
589 	 * EQs in the "fired" state), call tavor_eq_poll() to process each
590 	 * fired EQ.  If no ECR bits are set, do not claim the interrupt.
591 	 */
592 	status = DDI_INTR_UNCLAIMED;
593 	do {
594 		i = 0;
595 		while (ecrreg != 0x0) {
596 			if (ecrreg & 0x1) {
597 				tavor_eq_poll(state, state->ts_eqhdl[i]);
598 				status = DDI_INTR_CLAIMED;
599 			}
600 			ecrreg = ecrreg >> 1;
601 			i++;
602 		}
603 
604 		/*
605 		 * Clear the interrupt.  Note: Depending on the type of
606 		 * event (interrupt or MSI), we need to use a different
607 		 * mask to clear the event.  In the case of MSI, the bit
608 		 * to clear corresponds to the MSI number, and for legacy
609 		 * interrupts the bit corresponds to the value in 'inta_pin'.
610 		 */
611 		if (state->ts_intr_type_chosen == DDI_INTR_TYPE_MSI) {
612 			int_mask = ((uint64_t)1 << 0);
613 		} else {
614 			int_mask = ((uint64_t)1 << state->ts_adapter.inta_pin);
615 		}
616 		ddi_put64(state->ts_reg_cmdhdl, clr_int, int_mask);
617 
618 		/* Reread the ECR register */
619 		ecrreg = ddi_get64(state->ts_reg_cmdhdl, ecr);
620 
621 	} while (ecrreg != 0x0);
622 
623 	TAVOR_TNF_EXIT(tavor_isr);
624 	return (status);
625 }
626 
627 
628 /*
629  * tavor_eq_doorbell
630  *    Context: Only called from interrupt context
631  */
632 void
633 tavor_eq_doorbell(tavor_state_t *state, uint32_t eq_cmd, uint32_t eqn,
634     uint32_t eq_param)
635 {
636 	uint64_t	doorbell = 0;
637 
638 	/* Build the doorbell from the parameters */
639 	doorbell = ((uint64_t)eq_cmd << TAVOR_EQDB_CMD_SHIFT) |
640 	    ((uint64_t)eqn << TAVOR_EQDB_EQN_SHIFT) | eq_param;
641 
642 	TNF_PROBE_1_DEBUG(tavor_eq_doorbell, TAVOR_TNF_TRACE, "",
643 	    tnf_ulong, doorbell, doorbell);
644 
645 	/* Write the doorbell to UAR */
646 	TAVOR_UAR_DOORBELL(state, (uint64_t *)&state->ts_uar->eq,
647 	    doorbell);
648 }
649 
650 /*
651  * tavor_eq_poll
652  *    Context: Only called from interrupt context (and during panic)
653  */
654 static void
655 tavor_eq_poll(tavor_state_t *state, tavor_eqhdl_t eq)
656 {
657 	uint64_t	*clr_ecr;
658 	tavor_hw_eqe_t	*eqe;
659 	uint64_t	ecr_mask;
660 	uint32_t	cons_indx, wrap_around_mask;
661 	int (*eqfunction)(tavor_state_t *state, tavor_eqhdl_t eq,
662 	    tavor_hw_eqe_t *eqe);
663 
664 	TAVOR_TNF_ENTER(tavor_eq_poll);
665 
666 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*eq))
667 
668 	/* Find the pointer to the clr_ECR register */
669 	clr_ecr = state->ts_cmd_regs.clr_ecr;
670 
671 	/*
672 	 * Check for Local Catastrophic Error If we have this kind of error,
673 	 * then we don't need to do anything else here, as this kind of
674 	 * catastrophic error is handled separately.  So we call the
675 	 * catastrophic handler, clear the ECR and then return.
676 	 */
677 	if (eq->eq_evttypemask == TAVOR_EVT_MSK_LOCAL_CAT_ERROR) {
678 		/*
679 		 * Call Catastrophic Error handler
680 		 */
681 		tavor_eq_catastrophic(state);
682 
683 		/*
684 		 * Clear the ECR.  Specifically, clear the bit corresponding
685 		 * to the event queue just processed.
686 		 */
687 		ecr_mask = ((uint64_t)1 << eq->eq_eqnum);
688 		ddi_put64(state->ts_reg_cmdhdl, clr_ecr, ecr_mask);
689 
690 		TAVOR_TNF_EXIT(tavor_eq_poll);
691 		return;
692 	}
693 
694 	/* Get the consumer pointer index */
695 	cons_indx = eq->eq_consindx;
696 
697 	/*
698 	 * Calculate the wrap around mask.  Note: This operation only works
699 	 * because all Tavor event queues have power-of-2 sizes
700 	 */
701 	wrap_around_mask = (eq->eq_bufsz - 1);
702 
703 	/* Calculate the pointer to the first EQ entry */
704 	eqe = &eq->eq_buf[cons_indx];
705 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*eqe))
706 
707 	/*
708 	 * Sync the current EQE to read
709 	 *    We need to force a ddi_dma_sync() here (independent of how the
710 	 *    EQ was mapped) because it is possible for us to receive the
711 	 *    interrupt, do a read of the ECR, and have each of these
712 	 *    operations complete successfully even though the hardware's DMA
713 	 *    to the EQ has not yet completed.
714 	 */
715 	tavor_eqe_sync(eq, eqe, DDI_DMA_SYNC_FORCPU, TAVOR_EQ_SYNC_FORCE);
716 
717 	/*
718 	 * Pull the handler function for this EQ from the Tavor Event Queue
719 	 * handle
720 	 */
721 	eqfunction = eq->eq_func;
722 
723 	/*
724 	 * Keep pulling entries from the EQ until we find an entry owner by
725 	 * the hardware.  As long as there the EQE's owned by SW, process
726 	 * each entry by calling its handler function and updating the EQ
727 	 * consumer index.
728 	 */
729 	do {
730 		while (TAVOR_EQE_OWNER_IS_SW(eq, eqe)) {
731 			/*
732 			 * Call the EQ handler function.  But only call if we
733 			 * are not in polled I/O mode (i.e. not processing
734 			 * because of a system panic).  Note: We don't call
735 			 * the EQ handling functions from a system panic
736 			 * because we are primarily concerned only with
737 			 * ensuring that the event queues do not overflow (or,
738 			 * more specifically, the event queue associated with
739 			 * the CQ that is being used in the sync/dump process).
740 			 * Also, we don't want to make any upcalls (to the
741 			 * IBTF) because we can't guarantee when/if those
742 			 * calls would ever return.  And, if we're in panic,
743 			 * then we reached here through a PollCQ() call (from
744 			 * tavor_cq_poll()), and we need to ensure that we
745 			 * successfully return any work completions to the
746 			 * caller.
747 			 */
748 			if (ddi_in_panic() == 0) {
749 				eqfunction(state, eq, eqe);
750 			}
751 
752 			/* Reset entry to hardware ownership */
753 			TAVOR_EQE_OWNER_SET_HW(eq, eqe);
754 
755 			/* Sync the current EQE for device */
756 			tavor_eqe_sync(eq, eqe, DDI_DMA_SYNC_FORDEV,
757 			    TAVOR_EQ_SYNC_NORMAL);
758 
759 			/* Increment the consumer index */
760 			cons_indx = (cons_indx + 1) & wrap_around_mask;
761 
762 			/* Update the pointer to the next EQ entry */
763 			eqe = &eq->eq_buf[cons_indx];
764 
765 			/* Sync the next EQE to read */
766 			tavor_eqe_sync(eq, eqe, DDI_DMA_SYNC_FORCPU,
767 			    TAVOR_EQ_SYNC_NORMAL);
768 		}
769 
770 		/*
771 		 * Clear the ECR.  Specifically, clear the bit corresponding
772 		 * to the event queue just processed.
773 		 */
774 		ecr_mask = ((uint64_t)1 << eq->eq_eqnum);
775 		ddi_put64(state->ts_reg_cmdhdl, clr_ecr, ecr_mask);
776 
777 		/* Write an EQ doorbell to update the consumer index */
778 		eq->eq_consindx = cons_indx;
779 		tavor_eq_doorbell(state, TAVOR_EQDB_SET_CONSINDX, eq->eq_eqnum,
780 		    cons_indx);
781 
782 		/* Write another EQ doorbell to rearm */
783 		tavor_eq_doorbell(state, TAVOR_EQDB_REARM_EQ, eq->eq_eqnum, 0);
784 
785 		/*
786 		 * NOTE: Due to the nature of Mellanox hardware, we do not have
787 		 * to do an explicit PIO read to ensure that the doorbell write
788 		 * has been flushed to the hardware.  There is state encoded in
789 		 * the doorbell information we write which makes this
790 		 * unnecessary.  We can be assured that if an event needs to be
791 		 * generated, the hardware will make sure that it is, solving
792 		 * the possible race condition.
793 		 */
794 
795 		/* Sync the next EQE to read */
796 		tavor_eqe_sync(eq, eqe, DDI_DMA_SYNC_FORCPU,
797 		    TAVOR_EQ_SYNC_NORMAL);
798 
799 	} while (TAVOR_EQE_OWNER_IS_SW(eq, eqe));
800 
801 	TAVOR_TNF_EXIT(tavor_eq_poll);
802 }
803 
804 
805 /*
806  * tavor_eq_catastrophic
807  *    Context: Only called from interrupt context (and during panic)
808  */
809 static void
810 tavor_eq_catastrophic(tavor_state_t *state)
811 {
812 	ibt_async_code_t	type;
813 	ibc_async_event_t	event;
814 	uint32_t		*base_addr;
815 	uint32_t		buf_size;
816 	uint32_t		word;
817 	uint8_t			err_type;
818 	uint32_t		err_buf;
819 	int			i;
820 
821 	TAVOR_TNF_ENTER(tavor_eq_catastrophic);
822 
823 	bzero(&event, sizeof (ibc_async_event_t));
824 
825 	base_addr = (uint32_t *)(uintptr_t)(
826 	    (uintptr_t)state->ts_reg_cmd_baseaddr +
827 	    state->ts_fw.error_buf_addr);
828 	buf_size = state->ts_fw.error_buf_sz;
829 
830 	word = ddi_get32(state->ts_reg_cmdhdl, base_addr);
831 
832 	err_type = (word & 0xFF000000) >> 24;
833 	type	 = IBT_ERROR_LOCAL_CATASTROPHIC;
834 
835 	switch (err_type) {
836 	case TAVOR_CATASTROPHIC_INTERNAL_ERROR:
837 		cmn_err(CE_WARN, "Catastrophic Internal Error: 0x%02x",
838 		    err_type);
839 
840 		break;
841 
842 	case TAVOR_CATASTROPHIC_UPLINK_BUS_ERROR:
843 		cmn_err(CE_WARN, "Catastrophic Uplink Bus Error: 0x%02x",
844 		    err_type);
845 
846 		break;
847 
848 	case TAVOR_CATASTROPHIC_DDR_DATA_ERROR:
849 		cmn_err(CE_WARN, "Catastrophic DDR Data Error: 0x%02x",
850 		    err_type);
851 
852 		break;
853 
854 	case TAVOR_CATASTROPHIC_INTERNAL_PARITY_ERROR:
855 		cmn_err(CE_WARN, "Catastrophic Internal Parity Error: 0x%02x",
856 		    err_type);
857 
858 		break;
859 
860 	default:
861 		/* Unknown type of Catastrophic error */
862 		cmn_err(CE_WARN, "Catastrophic Unknown Error: 0x%02x",
863 		    err_type);
864 
865 		break;
866 	}
867 
868 	/*
869 	 * Read in the catastrophic error buffer from the hardware, printing
870 	 * only to the log file only
871 	 */
872 	for (i = 0; i < buf_size; i += 4) {
873 		base_addr = (uint32_t *)((uintptr_t)(state->ts_reg_cmd_baseaddr
874 		    + state->ts_fw.error_buf_addr + (i * 4)));
875 		err_buf = ddi_get32(state->ts_reg_cmdhdl, base_addr);
876 		cmn_err(CE_WARN, "catastrophic_error[%02x]: %08X", i, err_buf);
877 	}
878 
879 	/*
880 	 * We also call the IBTF here to inform it of the catastrophic error.
881 	 * Note: Since no event information (i.e. QP handles, CQ handles,
882 	 * etc.) is necessary, we pass a NULL pointer instead of a pointer to
883 	 * an empty ibc_async_event_t struct.
884 	 *
885 	 * But we also check if "ts_ibtfpriv" is NULL.  If it is then it
886 	 * means that we've have either received this event before we
887 	 * finished attaching to the IBTF or we've received it while we
888 	 * are in the process of detaching.
889 	 */
890 	if (state->ts_ibtfpriv != NULL) {
891 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
892 	}
893 
894 	TAVOR_TNF_EXIT(tavor_eq_catastrophic);
895 }
896 
897 
898 /*
899  * tavor_eq_alloc()
900  *    Context: Only called from attach() path context
901  */
902 static int
903 tavor_eq_alloc(tavor_state_t *state, uint32_t log_eq_size, uint_t intr,
904     tavor_eqhdl_t *eqhdl)
905 {
906 	tavor_rsrc_t		*eqc, *rsrc;
907 	tavor_hw_eqc_t		eqc_entry;
908 	tavor_eqhdl_t		eq;
909 	ibt_mr_attr_t		mr_attr;
910 	tavor_mr_options_t	op;
911 	tavor_pdhdl_t		pd;
912 	tavor_mrhdl_t		mr;
913 	tavor_hw_eqe_t		*buf;
914 	uint64_t		addr;
915 	uint32_t		lkey;
916 	uint_t			dma_xfer_mode;
917 	int			status, i;
918 	char			*errormsg;
919 
920 	TAVOR_TNF_ENTER(tavor_eq_alloc);
921 
922 	/* Use the internal protection domain (PD) for setting up EQs */
923 	pd = state->ts_pdhdl_internal;
924 
925 	/* Increment the reference count on the protection domain (PD) */
926 	tavor_pd_refcnt_inc(pd);
927 
928 	/*
929 	 * Allocate an EQ context entry.  This will be filled in with all
930 	 * the necessary parameters to define the Event Queue.  And then
931 	 * ownership will be passed to the hardware in the final step
932 	 * below.  If we fail here, we must undo the protection domain
933 	 * reference count.
934 	 */
935 	status = tavor_rsrc_alloc(state, TAVOR_EQC, 1, TAVOR_SLEEP, &eqc);
936 	if (status != DDI_SUCCESS) {
937 		/* Set "status" and "errormsg" and goto failure */
938 		TAVOR_TNF_FAIL(DDI_FAILURE, "failed EQ context");
939 		goto eqalloc_fail1;
940 	}
941 
942 	/*
943 	 * Allocate the software structure for tracking the event queue (i.e.
944 	 * the Tavor Event Queue handle).  If we fail here, we must undo the
945 	 * protection domain reference count and the previous resource
946 	 * allocation.
947 	 */
948 	status = tavor_rsrc_alloc(state, TAVOR_EQHDL, 1, TAVOR_SLEEP, &rsrc);
949 	if (status != DDI_SUCCESS) {
950 		/* Set "status" and "errormsg" and goto failure */
951 		TAVOR_TNF_FAIL(DDI_FAILURE, "failed EQ handler");
952 		goto eqalloc_fail2;
953 	}
954 	eq = (tavor_eqhdl_t)rsrc->tr_addr;
955 
956 	/*
957 	 * Allocate the memory for Event Queue.  Note: Although we use the
958 	 * common queue allocation routine, we always specify
959 	 * TAVOR_QUEUE_LOCATION_NORMAL (i.e. EQ located in system memory)
960 	 * because it would be inefficient to have EQs located in DDR memory.
961 	 * This is primarily because EQs are read from (by software) more
962 	 * than they are written to.  Also note that, unlike Tavor QP work
963 	 * queues, event queues do not have the same strict alignment
964 	 * requirements.  It is sufficient for the EQ memory to be both
965 	 * aligned to and bound to addresses which are a multiple of EQE size.
966 	 */
967 	eq->eq_eqinfo.qa_size = (1 << log_eq_size) * sizeof (tavor_hw_eqe_t);
968 	eq->eq_eqinfo.qa_alloc_align = sizeof (tavor_hw_eqe_t);
969 	eq->eq_eqinfo.qa_bind_align  = sizeof (tavor_hw_eqe_t);
970 	eq->eq_eqinfo.qa_location = TAVOR_QUEUE_LOCATION_NORMAL;
971 	status = tavor_queue_alloc(state, &eq->eq_eqinfo, TAVOR_SLEEP);
972 	if (status != DDI_SUCCESS) {
973 		/* Set "status" and "errormsg" and goto failure */
974 		TAVOR_TNF_FAIL(DDI_FAILURE, "failed event queue");
975 		goto eqalloc_fail3;
976 	}
977 	buf = (tavor_hw_eqe_t *)eq->eq_eqinfo.qa_buf_aligned;
978 
979 	/*
980 	 * Initialize each of the Event Queue Entries (EQE) by setting their
981 	 * ownership to hardware ("owner" bit set to HW).  This is in
982 	 * preparation for the final transfer of ownership (below) of the
983 	 * EQ context itself.
984 	 */
985 	for (i = 0; i < (1 << log_eq_size); i++) {
986 		TAVOR_EQE_OWNER_SET_HW(eq, &buf[i]);
987 	}
988 
989 	/*
990 	 * Register the memory for the EQ.  The memory for the EQ must
991 	 * be registered in the Tavor TPT tables.  This gives us the LKey
992 	 * to specify in the EQ context below.
993 	 *
994 	 * Because we are in the attach path we use NOSLEEP here so that we
995 	 * SPIN in the HCR since the event queues are not setup yet, and we
996 	 * cannot NOSPIN at this point in time.
997 	 */
998 	mr_attr.mr_vaddr = (uint64_t)(uintptr_t)buf;
999 	mr_attr.mr_len	 = eq->eq_eqinfo.qa_size;
1000 	mr_attr.mr_as	 = NULL;
1001 	mr_attr.mr_flags = IBT_MR_NOSLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
1002 	dma_xfer_mode	 = state->ts_cfg_profile->cp_streaming_consistent;
1003 	if (dma_xfer_mode == DDI_DMA_STREAMING) {
1004 		mr_attr.mr_flags |= IBT_MR_NONCOHERENT;
1005 	}
1006 	op.mro_bind_type   = state->ts_cfg_profile->cp_iommu_bypass;
1007 	op.mro_bind_dmahdl = eq->eq_eqinfo.qa_dmahdl;
1008 	op.mro_bind_override_addr = 0;
1009 	status = tavor_mr_register(state, pd, &mr_attr, &mr, &op);
1010 	if (status != DDI_SUCCESS) {
1011 		/* Set "status" and "errormsg" and goto failure */
1012 		TAVOR_TNF_FAIL(DDI_FAILURE, "failed register mr");
1013 		goto eqalloc_fail4;
1014 	}
1015 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr))
1016 	addr = mr->mr_bindinfo.bi_addr;
1017 	lkey = mr->mr_lkey;
1018 
1019 	/* Determine if later ddi_dma_sync will be necessary */
1020 	eq->eq_sync = TAVOR_EQ_IS_SYNC_REQ(state, eq->eq_eqinfo);
1021 
1022 	/* Sync entire EQ for use by the hardware (if necessary) */
1023 	if (eq->eq_sync) {
1024 		(void) ddi_dma_sync(mr->mr_bindinfo.bi_dmahdl, 0,
1025 		    eq->eq_eqinfo.qa_size, DDI_DMA_SYNC_FORDEV);
1026 	}
1027 
1028 	/*
1029 	 * Fill in the EQC entry.  This is the final step before passing
1030 	 * ownership of the EQC entry to the Tavor hardware.  We use all of
1031 	 * the information collected/calculated above to fill in the
1032 	 * requisite portions of the EQC.  Note:  We create all EQs in the
1033 	 * "fired" state.  We will arm them later (after our interrupt
1034 	 * routine had been registered.)
1035 	 */
1036 	bzero(&eqc_entry, sizeof (tavor_hw_eqc_t));
1037 	eqc_entry.owner		= TAVOR_HW_OWNER;
1038 	eqc_entry.xlat		= TAVOR_VA2PA_XLAT_ENABLED;
1039 	eqc_entry.state		= TAVOR_EQ_FIRED;
1040 	eqc_entry.start_addr_h	= (addr >> 32);
1041 	eqc_entry.start_addr_l	= (addr & 0xFFFFFFFF);
1042 	eqc_entry.log_eq_sz	= log_eq_size;
1043 	eqc_entry.usr_page	= 0;
1044 	eqc_entry.pd		= pd->pd_pdnum;
1045 	eqc_entry.intr		= intr;
1046 	eqc_entry.lkey		= lkey;
1047 
1048 	/*
1049 	 * Write the EQC entry to hardware.  Lastly, we pass ownership of
1050 	 * the entry to the hardware (using the Tavor SW2HW_EQ firmware
1051 	 * command).  Note: in general, this operation shouldn't fail.  But
1052 	 * if it does, we have to undo everything we've done above before
1053 	 * returning error.
1054 	 */
1055 	status = tavor_cmn_ownership_cmd_post(state, SW2HW_EQ, &eqc_entry,
1056 	    sizeof (tavor_hw_eqc_t), eqc->tr_indx, TAVOR_CMD_NOSLEEP_SPIN);
1057 	if (status != TAVOR_CMD_SUCCESS) {
1058 		cmn_err(CE_CONT, "Tavor: SW2HW_EQ command failed: %08x\n",
1059 		    status);
1060 		TNF_PROBE_1(tavor_eq_alloc_sw2hw_eq_cmd_fail,
1061 		    TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1062 		/* Set "status" and "errormsg" and goto failure */
1063 		TAVOR_TNF_FAIL(ibc_get_ci_failure(0), "tavor SW2HW_EQ command");
1064 		goto eqalloc_fail5;
1065 	}
1066 
1067 	/*
1068 	 * Fill in the rest of the Tavor Event Queue handle.  Having
1069 	 * successfully transferred ownership of the EQC, we can update the
1070 	 * following fields for use in further operations on the EQ.
1071 	 */
1072 	eq->eq_eqcrsrcp	 = eqc;
1073 	eq->eq_rsrcp	 = rsrc;
1074 	eq->eq_consindx	 = 0;
1075 	eq->eq_eqnum	 = eqc->tr_indx;
1076 	eq->eq_buf	 = buf;
1077 	eq->eq_bufsz	 = (1 << log_eq_size);
1078 	eq->eq_mrhdl	 = mr;
1079 	*eqhdl		 = eq;
1080 
1081 	TAVOR_TNF_EXIT(tavor_eq_alloc);
1082 	return (DDI_SUCCESS);
1083 
1084 /*
1085  * The following is cleanup for all possible failure cases in this routine
1086  */
1087 eqalloc_fail5:
1088 	if (tavor_mr_deregister(state, &mr, TAVOR_MR_DEREG_ALL,
1089 	    TAVOR_NOSLEEP) != DDI_SUCCESS) {
1090 		TAVOR_WARNING(state, "failed to deregister EQ memory");
1091 	}
1092 eqalloc_fail4:
1093 	tavor_queue_free(state, &eq->eq_eqinfo);
1094 eqalloc_fail3:
1095 	tavor_rsrc_free(state, &rsrc);
1096 eqalloc_fail2:
1097 	tavor_rsrc_free(state, &eqc);
1098 eqalloc_fail1:
1099 	tavor_pd_refcnt_dec(pd);
1100 eqalloc_fail:
1101 	TNF_PROBE_1(tavor_eq_alloc_fail, TAVOR_TNF_ERROR, "",
1102 	    tnf_string, msg, errormsg);
1103 	TAVOR_TNF_EXIT(tavor_eq_alloc);
1104 	return (status);
1105 }
1106 
1107 
1108 /*
1109  * tavor_eq_free()
1110  *    Context: Only called from attach() and/or detach() path contexts
1111  */
1112 static int
1113 tavor_eq_free(tavor_state_t *state, tavor_eqhdl_t *eqhdl)
1114 {
1115 	tavor_rsrc_t		*eqc, *rsrc;
1116 	tavor_hw_eqc_t		eqc_entry;
1117 	tavor_pdhdl_t		pd;
1118 	tavor_mrhdl_t		mr;
1119 	tavor_eqhdl_t		eq;
1120 	uint32_t		eqnum;
1121 	int			status;
1122 
1123 	TAVOR_TNF_ENTER(tavor_eq_free);
1124 
1125 	/*
1126 	 * Pull all the necessary information from the Tavor Event Queue
1127 	 * handle.  This is necessary here because the resource for the
1128 	 * EQ handle is going to be freed up as part of this operation.
1129 	 */
1130 	eq	= *eqhdl;
1131 	eqc	= eq->eq_eqcrsrcp;
1132 	rsrc	= eq->eq_rsrcp;
1133 	pd	= state->ts_pdhdl_internal;
1134 	mr	= eq->eq_mrhdl;
1135 	eqnum	= eq->eq_eqnum;
1136 
1137 	/*
1138 	 * Reclaim EQC entry from hardware (using the Tavor HW2SW_EQ
1139 	 * firmware command).  If the ownership transfer fails for any reason,
1140 	 * then it is an indication that something (either in HW or SW) has
1141 	 * gone seriously wrong.
1142 	 */
1143 	status = tavor_cmn_ownership_cmd_post(state, HW2SW_EQ, &eqc_entry,
1144 	    sizeof (tavor_hw_eqc_t), eqnum, TAVOR_CMD_NOSLEEP_SPIN);
1145 	if (status != TAVOR_CMD_SUCCESS) {
1146 		TAVOR_WARNING(state, "failed to reclaim EQC ownership");
1147 		cmn_err(CE_CONT, "Tavor: HW2SW_EQ command failed: %08x\n",
1148 		    status);
1149 		TNF_PROBE_1(tavor_eq_free_hw2sw_eq_cmd_fail,
1150 		    TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1151 		TAVOR_TNF_EXIT(tavor_eq_free);
1152 		return (DDI_FAILURE);
1153 	}
1154 
1155 	/*
1156 	 * Deregister the memory for the Event Queue.  If this fails
1157 	 * for any reason, then it is an indication that something (either
1158 	 * in HW or SW) has gone seriously wrong.  So we print a warning
1159 	 * message and continue.
1160 	 */
1161 	status = tavor_mr_deregister(state, &mr, TAVOR_MR_DEREG_ALL,
1162 	    TAVOR_NOSLEEP);
1163 	if (status != DDI_SUCCESS) {
1164 		TAVOR_WARNING(state, "failed to deregister EQ memory");
1165 		TNF_PROBE_0(tavor_eq_free_dereg_mr_fail, TAVOR_TNF_ERROR, "");
1166 		TAVOR_TNF_EXIT(tavor_eq_free);
1167 	}
1168 
1169 	/* Free the memory for the EQ */
1170 	tavor_queue_free(state, &eq->eq_eqinfo);
1171 
1172 	/* Free the Tavor Event Queue handle */
1173 	tavor_rsrc_free(state, &rsrc);
1174 
1175 	/* Free up the EQC entry resource */
1176 	tavor_rsrc_free(state, &eqc);
1177 
1178 	/* Decrement the reference count on the protection domain (PD) */
1179 	tavor_pd_refcnt_dec(pd);
1180 
1181 	/* Set the eqhdl pointer to NULL and return success */
1182 	*eqhdl = NULL;
1183 
1184 	TAVOR_TNF_EXIT(tavor_eq_free);
1185 	return (DDI_SUCCESS);
1186 }
1187 
1188 
1189 /*
1190  * tavor_eq_handler_init
1191  *    Context: Only called from attach() path context
1192  */
1193 static int
1194 tavor_eq_handler_init(tavor_state_t *state, tavor_eqhdl_t eq,
1195     uint_t evt_type_mask, int (*eq_func)(tavor_state_t *state,
1196     tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe))
1197 {
1198 	int		status;
1199 
1200 	TAVOR_TNF_ENTER(tavor_eq_handler_init);
1201 
1202 	/*
1203 	 * Save away the EQ handler function and the event type mask.  These
1204 	 * will be used later during interrupt and event queue processing.
1205 	 */
1206 	eq->eq_func	   = eq_func;
1207 	eq->eq_evttypemask = evt_type_mask;
1208 
1209 	/*
1210 	 * Map the EQ to a specific class of event (or events) depending
1211 	 * on the mask value passed in.  The TAVOR_EVT_NO_MASK means not
1212 	 * to attempt associating the EQ with any specific class of event.
1213 	 * This is particularly useful when initializing the events queues
1214 	 * used for CQ events.   The mapping is done using the Tavor MAP_EQ
1215 	 * firmware command.  Note: This command should not, in general, fail.
1216 	 * If it does, then something (probably HW related) has gone seriously
1217 	 * wrong.
1218 	 */
1219 	if (evt_type_mask != TAVOR_EVT_NO_MASK) {
1220 		status = tavor_map_eq_cmd_post(state,
1221 		    TAVOR_CMD_MAP_EQ_EVT_MAP, eq->eq_eqnum, evt_type_mask,
1222 		    TAVOR_CMD_NOSLEEP_SPIN);
1223 		if (status != TAVOR_CMD_SUCCESS) {
1224 			cmn_err(CE_CONT, "Tavor: MAP_EQ command failed: "
1225 			    "%08x\n", status);
1226 			TNF_PROBE_1(tavor_eq_handler_init_map_eq_cmd_fail,
1227 			    TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1228 			TAVOR_TNF_EXIT(tavor_eq_handler_init);
1229 			return (DDI_FAILURE);
1230 		}
1231 	}
1232 
1233 	TAVOR_TNF_EXIT(tavor_eq_handler_init);
1234 	return (DDI_SUCCESS);
1235 }
1236 
1237 
1238 /*
1239  * tavor_eq_handler_fini
1240  *    Context: Only called from attach() and/or detach() path contexts
1241  */
1242 static int
1243 tavor_eq_handler_fini(tavor_state_t *state, tavor_eqhdl_t eq)
1244 {
1245 	int			status;
1246 
1247 	TAVOR_TNF_ENTER(tavor_eq_handler_fini);
1248 
1249 	/*
1250 	 * Unmap the EQ from the event class to which it had been previously
1251 	 * mapped.  The unmapping is done using the Tavor MAP_EQ (in much
1252 	 * the same way that the initial mapping was done).  The difference,
1253 	 * however, is in the TAVOR_EQ_EVT_UNMAP flag that is passed to the
1254 	 * MAP_EQ firmware command.  The TAVOR_EVT_NO_MASK (which may have
1255 	 * been passed in at init time) still means that no association has
1256 	 * been made between the EQ and any specific class of event (and,
1257 	 * hence, no unmapping is necessary).  Note: This command should not,
1258 	 * in general, fail.  If it does, then something (probably HW related)
1259 	 * has gone seriously wrong.
1260 	 */
1261 	if (eq->eq_evttypemask != TAVOR_EVT_NO_MASK) {
1262 		status = tavor_map_eq_cmd_post(state,
1263 		    TAVOR_CMD_MAP_EQ_EVT_UNMAP, eq->eq_eqnum,
1264 		    eq->eq_evttypemask, TAVOR_CMD_NOSLEEP_SPIN);
1265 		if (status != TAVOR_CMD_SUCCESS) {
1266 			cmn_err(CE_CONT, "Tavor: MAP_EQ command failed: "
1267 			    "%08x\n", status);
1268 			TNF_PROBE_1(tavor_eq_handler_fini_map_eq_cmd_fail,
1269 			    TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1270 			TAVOR_TNF_EXIT(tavor_eq_handler_fini);
1271 			return (DDI_FAILURE);
1272 		}
1273 	}
1274 
1275 	TAVOR_TNF_EXIT(tavor_eq_handler_fini);
1276 	return (DDI_SUCCESS);
1277 }
1278 
1279 
1280 /*
1281  * tavor_eqe_sync()
1282  *    Context: Can be called from interrupt or base context.
1283  *
1284  *    Typically, this routine does nothing unless the EQ memory is
1285  *    mapped as DDI_DMA_STREAMING.  However, there is a condition where
1286  *    ddi_dma_sync() is necessary even if the memory was mapped in
1287  *    consistent mode.  The "force_sync" parameter is used here to force
1288  *    the call to ddi_dma_sync() independent of how the EQ memory was
1289  *    mapped.
1290  */
1291 static void
1292 tavor_eqe_sync(tavor_eqhdl_t eq, tavor_hw_eqe_t *eqe, uint_t flag,
1293     uint_t force_sync)
1294 {
1295 	ddi_dma_handle_t	dmahdl;
1296 	off_t			offset;
1297 	int			status;
1298 
1299 	TAVOR_TNF_ENTER(tavor_eqe_sync);
1300 
1301 	/* Determine if EQ needs to be synced or not */
1302 	if ((eq->eq_sync == 0) && (force_sync == TAVOR_EQ_SYNC_NORMAL)) {
1303 		TAVOR_TNF_EXIT(tavor_eqe_sync);
1304 		return;
1305 	}
1306 
1307 	/* Get the DMA handle from EQ context */
1308 	dmahdl = eq->eq_mrhdl->mr_bindinfo.bi_dmahdl;
1309 
1310 	/* Calculate offset of next EQE */
1311 	offset = (off_t)((uintptr_t)eqe - (uintptr_t)&eq->eq_buf[0]);
1312 	status = ddi_dma_sync(dmahdl, offset, sizeof (tavor_hw_eqe_t), flag);
1313 	if (status != DDI_SUCCESS) {
1314 		TNF_PROBE_0(tavor_eqe_sync_getnextentry_fail,
1315 		    TAVOR_TNF_ERROR, "");
1316 		TAVOR_TNF_EXIT(tavor_eqe_sync);
1317 		return;
1318 	}
1319 
1320 	TAVOR_TNF_EXIT(tavor_eqe_sync);
1321 }
1322 
1323 
1324 /*
1325  * tavor_port_state_change_handler()
1326  *    Context: Only called from interrupt context
1327  */
1328 static int
1329 tavor_port_state_change_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1330     tavor_hw_eqe_t *eqe)
1331 {
1332 	ibc_async_event_t	event;
1333 	ibt_async_code_t	type;
1334 	uint_t			port, subtype;
1335 	uint_t			eqe_evttype;
1336 	char			link_msg[24];
1337 
1338 	TAVOR_TNF_ENTER(tavor_port_state_change_handler);
1339 
1340 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1341 
1342 	ASSERT(eqe_evttype == TAVOR_EVT_PORT_STATE_CHANGE ||
1343 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1344 
1345 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1346 		TNF_PROBE_0(tavor_port_state_change_eq_overflow_condition,
1347 		    TAVOR_TNF_ERROR, "");
1348 		tavor_eq_overflow_handler(state, eq, eqe);
1349 
1350 		TAVOR_TNF_EXIT(tavor_port_state_change_handler);
1351 		return (DDI_FAILURE);
1352 	}
1353 
1354 	/*
1355 	 * Depending on the type of Port State Change event, pass the
1356 	 * appropriate asynch event to the IBTF.
1357 	 */
1358 	port = TAVOR_EQE_PORTNUM_GET(eq, eqe);
1359 
1360 	/* Check for valid port number in event */
1361 	if ((port == 0) || (port > state->ts_cfg_profile->cp_num_ports)) {
1362 		TAVOR_WARNING(state, "Unexpected port number in port state "
1363 		    "change event");
1364 		cmn_err(CE_CONT, "  Port number: %02x\n", port);
1365 		TAVOR_TNF_EXIT(tavor_port_state_change_handler);
1366 		return (DDI_FAILURE);
1367 	}
1368 
1369 	subtype = TAVOR_EQE_EVTSUBTYPE_GET(eq, eqe);
1370 	if (subtype == TAVOR_PORT_LINK_ACTIVE) {
1371 		event.ev_port 	= port;
1372 		type		= IBT_EVENT_PORT_UP;
1373 
1374 		(void) snprintf(link_msg, 23, "port %d up", port);
1375 		ddi_dev_report_fault(state->ts_dip, DDI_SERVICE_RESTORED,
1376 		    DDI_EXTERNAL_FAULT, link_msg);
1377 	} else if (subtype == TAVOR_PORT_LINK_DOWN) {
1378 		event.ev_port	= port;
1379 		type		= IBT_ERROR_PORT_DOWN;
1380 
1381 		(void) snprintf(link_msg, 23, "port %d down", port);
1382 		ddi_dev_report_fault(state->ts_dip, DDI_SERVICE_LOST,
1383 		    DDI_EXTERNAL_FAULT, link_msg);
1384 	} else {
1385 		TAVOR_WARNING(state, "Unexpected subtype in port state change "
1386 		    "event");
1387 		cmn_err(CE_CONT, "  Event type: %02x, subtype: %02x\n",
1388 		    TAVOR_EQE_EVTTYPE_GET(eq, eqe), subtype);
1389 		TAVOR_TNF_EXIT(tavor_port_state_change_handler);
1390 		return (DDI_FAILURE);
1391 	}
1392 
1393 	/*
1394 	 * Deliver the event to the IBTF.  Note: If "ts_ibtfpriv" is NULL,
1395 	 * then we have either received this event before we finished
1396 	 * attaching to the IBTF or we've received it while we are in the
1397 	 * process of detaching.
1398 	 */
1399 	if (state->ts_ibtfpriv != NULL) {
1400 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1401 	}
1402 
1403 	TAVOR_TNF_EXIT(tavor_port_state_change_handler);
1404 	return (DDI_SUCCESS);
1405 }
1406 
1407 
1408 /*
1409  * tavor_comm_estbl_handler()
1410  *    Context: Only called from interrupt context
1411  */
1412 static int
1413 tavor_comm_estbl_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1414     tavor_hw_eqe_t *eqe)
1415 {
1416 	tavor_qphdl_t		qp;
1417 	uint_t			qpnum;
1418 	ibc_async_event_t	event;
1419 	ibt_async_code_t	type;
1420 	uint_t			eqe_evttype;
1421 
1422 	TAVOR_TNF_ENTER(tavor_comm_estbl_handler);
1423 
1424 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1425 
1426 	ASSERT(eqe_evttype == TAVOR_EVT_COMM_ESTABLISHED ||
1427 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1428 
1429 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1430 		TNF_PROBE_0(tavor_comm_estbl_eq_overflow_condition,
1431 		    TAVOR_TNF_ERROR, "");
1432 		tavor_eq_overflow_handler(state, eq, eqe);
1433 
1434 		TAVOR_TNF_EXIT(tavor_comm_estbl_handler);
1435 		return (DDI_FAILURE);
1436 	}
1437 
1438 	/* Get the QP handle from QP number in event descriptor */
1439 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1440 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1441 
1442 	/*
1443 	 * If the QP handle is NULL, this is probably an indication
1444 	 * that the QP has been freed already.  In which case, we
1445 	 * should not deliver this event.
1446 	 *
1447 	 * We also check that the QP number in the handle is the
1448 	 * same as the QP number in the event queue entry.  This
1449 	 * extra check allows us to handle the case where a QP was
1450 	 * freed and then allocated again in the time it took to
1451 	 * handle the event queue processing.  By constantly incrementing
1452 	 * the non-constrained portion of the QP number every time
1453 	 * a new QP is allocated, we mitigate (somewhat) the chance
1454 	 * that a stale event could be passed to the client's QP
1455 	 * handler.
1456 	 *
1457 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
1458 	 * means that we've have either received this event before we
1459 	 * finished attaching to the IBTF or we've received it while we
1460 	 * are in the process of detaching.
1461 	 */
1462 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1463 	    (state->ts_ibtfpriv != NULL)) {
1464 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
1465 		type		= IBT_EVENT_COM_EST_QP;
1466 
1467 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1468 	} else {
1469 		TNF_PROBE_2(tavor_comm_estbl_handler_dropped_event,
1470 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1471 		    tnf_uint, hdl_qpnum, qpnum);
1472 	}
1473 
1474 	TAVOR_TNF_EXIT(tavor_comm_estbl_handler);
1475 	return (DDI_SUCCESS);
1476 }
1477 
1478 
1479 /*
1480  * tavor_local_wq_cat_err_handler()
1481  *    Context: Only called from interrupt context
1482  */
1483 static int
1484 tavor_local_wq_cat_err_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1485     tavor_hw_eqe_t *eqe)
1486 {
1487 	tavor_qphdl_t		qp;
1488 	uint_t			qpnum;
1489 	ibc_async_event_t	event;
1490 	ibt_async_code_t	type;
1491 	uint_t			eqe_evttype;
1492 
1493 	TAVOR_TNF_ENTER(tavor_local_wq_cat_err_handler);
1494 
1495 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1496 
1497 	ASSERT(eqe_evttype == TAVOR_EVT_LOCAL_WQ_CAT_ERROR ||
1498 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1499 
1500 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1501 		TNF_PROBE_0(tavor_local_wq_cat_err_eq_overflow_condition,
1502 		    TAVOR_TNF_ERROR, "");
1503 		tavor_eq_overflow_handler(state, eq, eqe);
1504 
1505 		TAVOR_TNF_EXIT(tavor_local_wq_cat_err_handler);
1506 		return (DDI_FAILURE);
1507 	}
1508 
1509 	/* Get the QP handle from QP number in event descriptor */
1510 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1511 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1512 
1513 	/*
1514 	 * If the QP handle is NULL, this is probably an indication
1515 	 * that the QP has been freed already.  In which case, we
1516 	 * should not deliver this event.
1517 	 *
1518 	 * We also check that the QP number in the handle is the
1519 	 * same as the QP number in the event queue entry.  This
1520 	 * extra check allows us to handle the case where a QP was
1521 	 * freed and then allocated again in the time it took to
1522 	 * handle the event queue processing.  By constantly incrementing
1523 	 * the non-constrained portion of the QP number every time
1524 	 * a new QP is allocated, we mitigate (somewhat) the chance
1525 	 * that a stale event could be passed to the client's QP
1526 	 * handler.
1527 	 *
1528 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
1529 	 * means that we've have either received this event before we
1530 	 * finished attaching to the IBTF or we've received it while we
1531 	 * are in the process of detaching.
1532 	 */
1533 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1534 	    (state->ts_ibtfpriv != NULL)) {
1535 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
1536 		type		= IBT_ERROR_CATASTROPHIC_QP;
1537 
1538 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1539 	} else {
1540 		TNF_PROBE_2(tavor_local_wq_cat_err_handler_dropped_event,
1541 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1542 		    tnf_uint, hdl_qpnum, qpnum);
1543 	}
1544 
1545 	TAVOR_TNF_EXIT(tavor_local_wq_cat_err_handler);
1546 	return (DDI_SUCCESS);
1547 }
1548 
1549 
1550 /*
1551  * tavor_invreq_local_wq_err_handler()
1552  *    Context: Only called from interrupt context
1553  */
1554 static int
1555 tavor_invreq_local_wq_err_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1556     tavor_hw_eqe_t *eqe)
1557 {
1558 	tavor_qphdl_t		qp;
1559 	uint_t			qpnum;
1560 	ibc_async_event_t	event;
1561 	ibt_async_code_t	type;
1562 	uint_t			eqe_evttype;
1563 
1564 	TAVOR_TNF_ENTER(tavor_invreq_local_wq_err_handler);
1565 
1566 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1567 
1568 	ASSERT(eqe_evttype == TAVOR_EVT_INV_REQ_LOCAL_WQ_ERROR ||
1569 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1570 
1571 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1572 		TNF_PROBE_0(tavor_invreq_local_wq_err_eq_overflow_condition,
1573 		    TAVOR_TNF_ERROR, "");
1574 		tavor_eq_overflow_handler(state, eq, eqe);
1575 
1576 		TAVOR_TNF_EXIT(tavor_port_state_change_handler);
1577 		return (DDI_FAILURE);
1578 	}
1579 
1580 	/* Get the QP handle from QP number in event descriptor */
1581 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1582 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1583 
1584 	/*
1585 	 * If the QP handle is NULL, this is probably an indication
1586 	 * that the QP has been freed already.  In which case, we
1587 	 * should not deliver this event.
1588 	 *
1589 	 * We also check that the QP number in the handle is the
1590 	 * same as the QP number in the event queue entry.  This
1591 	 * extra check allows us to handle the case where a QP was
1592 	 * freed and then allocated again in the time it took to
1593 	 * handle the event queue processing.  By constantly incrementing
1594 	 * the non-constrained portion of the QP number every time
1595 	 * a new QP is allocated, we mitigate (somewhat) the chance
1596 	 * that a stale event could be passed to the client's QP
1597 	 * handler.
1598 	 *
1599 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
1600 	 * means that we've have either received this event before we
1601 	 * finished attaching to the IBTF or we've received it while we
1602 	 * are in the process of detaching.
1603 	 */
1604 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1605 	    (state->ts_ibtfpriv != NULL)) {
1606 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
1607 		type		= IBT_ERROR_INVALID_REQUEST_QP;
1608 
1609 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1610 	} else {
1611 		TNF_PROBE_2(tavor_invreq_local_wq_err_handler_dropped_event,
1612 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1613 		    tnf_uint, hdl_qpnum, qpnum);
1614 	}
1615 
1616 	TAVOR_TNF_EXIT(tavor_invreq_local_wq_err_handler);
1617 	return (DDI_SUCCESS);
1618 }
1619 
1620 
1621 /*
1622  * tavor_local_acc_vio_wq_err_handler()
1623  *    Context: Only called from interrupt context
1624  */
1625 static int
1626 tavor_local_acc_vio_wq_err_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1627     tavor_hw_eqe_t *eqe)
1628 {
1629 	tavor_qphdl_t		qp;
1630 	uint_t			qpnum;
1631 	ibc_async_event_t	event;
1632 	ibt_async_code_t	type;
1633 	uint_t			eqe_evttype;
1634 
1635 	TAVOR_TNF_ENTER(tavor_local_acc_vio_wq_err_handler);
1636 
1637 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1638 
1639 	ASSERT(eqe_evttype == TAVOR_EVT_LOCAL_ACC_VIO_WQ_ERROR ||
1640 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1641 
1642 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1643 		TNF_PROBE_0(tavor_local_acc_vio_wq_err_eq_overflow_condition,
1644 		    TAVOR_TNF_ERROR, "");
1645 		tavor_eq_overflow_handler(state, eq, eqe);
1646 
1647 		TAVOR_TNF_EXIT(tavor_local_acc_vio_wq_err_handler);
1648 		return (DDI_FAILURE);
1649 	}
1650 
1651 	/* Get the QP handle from QP number in event descriptor */
1652 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1653 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1654 
1655 	/*
1656 	 * If the QP handle is NULL, this is probably an indication
1657 	 * that the QP has been freed already.  In which case, we
1658 	 * should not deliver this event.
1659 	 *
1660 	 * We also check that the QP number in the handle is the
1661 	 * same as the QP number in the event queue entry.  This
1662 	 * extra check allows us to handle the case where a QP was
1663 	 * freed and then allocated again in the time it took to
1664 	 * handle the event queue processing.  By constantly incrementing
1665 	 * the non-constrained portion of the QP number every time
1666 	 * a new QP is allocated, we mitigate (somewhat) the chance
1667 	 * that a stale event could be passed to the client's QP
1668 	 * handler.
1669 	 *
1670 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
1671 	 * means that we've have either received this event before we
1672 	 * finished attaching to the IBTF or we've received it while we
1673 	 * are in the process of detaching.
1674 	 */
1675 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1676 	    (state->ts_ibtfpriv != NULL)) {
1677 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
1678 		type		= IBT_ERROR_ACCESS_VIOLATION_QP;
1679 
1680 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1681 	} else {
1682 		TNF_PROBE_2(tavor_local_acc_vio_wq_err_handler_dropped_event,
1683 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1684 		    tnf_uint, hdl_qpnum, qpnum);
1685 	}
1686 
1687 	TAVOR_TNF_EXIT(tavor_local_acc_vio_wq_err_handler);
1688 	return (DDI_SUCCESS);
1689 }
1690 
1691 
1692 /*
1693  * tavor_sendq_drained_handler()
1694  *    Context: Only called from interrupt context
1695  */
1696 static int
1697 tavor_sendq_drained_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1698     tavor_hw_eqe_t *eqe)
1699 {
1700 	tavor_qphdl_t		qp;
1701 	uint_t			qpnum;
1702 	ibc_async_event_t	event;
1703 	uint_t			forward_sqd_event;
1704 	ibt_async_code_t	type;
1705 	uint_t			eqe_evttype;
1706 
1707 	TAVOR_TNF_ENTER(tavor_sendq_drained_handler);
1708 
1709 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1710 
1711 	ASSERT(eqe_evttype == TAVOR_EVT_SEND_QUEUE_DRAINED ||
1712 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1713 
1714 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1715 		TNF_PROBE_0(tavor_sendq_drained_eq_overflow_condition,
1716 		    TAVOR_TNF_ERROR, "");
1717 		tavor_eq_overflow_handler(state, eq, eqe);
1718 
1719 		TAVOR_TNF_EXIT(tavor_sendq_drained_handler);
1720 		return (DDI_FAILURE);
1721 	}
1722 
1723 	/* Get the QP handle from QP number in event descriptor */
1724 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1725 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1726 
1727 	/*
1728 	 * If the QP handle is NULL, this is probably an indication
1729 	 * that the QP has been freed already.  In which case, we
1730 	 * should not deliver this event.
1731 	 *
1732 	 * We also check that the QP number in the handle is the
1733 	 * same as the QP number in the event queue entry.  This
1734 	 * extra check allows us to handle the case where a QP was
1735 	 * freed and then allocated again in the time it took to
1736 	 * handle the event queue processing.  By constantly incrementing
1737 	 * the non-constrained portion of the QP number every time
1738 	 * a new QP is allocated, we mitigate (somewhat) the chance
1739 	 * that a stale event could be passed to the client's QP
1740 	 * handler.
1741 	 *
1742 	 * And then we check if "ts_ibtfpriv" is NULL.  If it is then it
1743 	 * means that we've have either received this event before we
1744 	 * finished attaching to the IBTF or we've received it while we
1745 	 * are in the process of detaching.
1746 	 */
1747 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1748 	    (state->ts_ibtfpriv != NULL)) {
1749 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
1750 		type		= IBT_EVENT_SQD;
1751 
1752 		/*
1753 		 * Grab the QP lock and update the QP state to reflect that
1754 		 * the Send Queue Drained event has arrived.  Also determine
1755 		 * whether the event is intended to be forwarded on to the
1756 		 * consumer or not.  This information is used below in
1757 		 * determining whether or not to call the IBTF.
1758 		 */
1759 		mutex_enter(&qp->qp_lock);
1760 		forward_sqd_event = qp->qp_forward_sqd_event;
1761 		qp->qp_forward_sqd_event  = 0;
1762 		qp->qp_sqd_still_draining = 0;
1763 		mutex_exit(&qp->qp_lock);
1764 
1765 		if (forward_sqd_event != 0) {
1766 			TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1767 		}
1768 	} else {
1769 		TNF_PROBE_2(tavor_sendq_drained_handler_dropped_event,
1770 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1771 		    tnf_uint, hdl_qpnum, qpnum);
1772 	}
1773 
1774 	TAVOR_TNF_EXIT(tavor_sendq_drained_handler);
1775 	return (DDI_SUCCESS);
1776 }
1777 
1778 
1779 /*
1780  * tavor_path_mig_handler()
1781  *    Context: Only called from interrupt context
1782  */
1783 static int
1784 tavor_path_mig_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1785     tavor_hw_eqe_t *eqe)
1786 {
1787 	tavor_qphdl_t		qp;
1788 	uint_t			qpnum;
1789 	ibc_async_event_t	event;
1790 	ibt_async_code_t	type;
1791 	uint_t			eqe_evttype;
1792 
1793 	TAVOR_TNF_ENTER(tavor_path_mig_handler);
1794 
1795 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1796 
1797 	ASSERT(eqe_evttype == TAVOR_EVT_PATH_MIGRATED ||
1798 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1799 
1800 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1801 		TNF_PROBE_0(tavor_path_mig_eq_overflow_condition,
1802 		    TAVOR_TNF_ERROR, "");
1803 		tavor_eq_overflow_handler(state, eq, eqe);
1804 
1805 		TAVOR_TNF_EXIT(tavor_path_mig_handler);
1806 		return (DDI_FAILURE);
1807 	}
1808 
1809 	/* Get the QP handle from QP number in event descriptor */
1810 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1811 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1812 
1813 	/*
1814 	 * If the QP handle is NULL, this is probably an indication
1815 	 * that the QP has been freed already.  In which case, we
1816 	 * should not deliver this event.
1817 	 *
1818 	 * We also check that the QP number in the handle is the
1819 	 * same as the QP number in the event queue entry.  This
1820 	 * extra check allows us to handle the case where a QP was
1821 	 * freed and then allocated again in the time it took to
1822 	 * handle the event queue processing.  By constantly incrementing
1823 	 * the non-constrained portion of the QP number every time
1824 	 * a new QP is allocated, we mitigate (somewhat) the chance
1825 	 * that a stale event could be passed to the client's QP
1826 	 * handler.
1827 	 *
1828 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
1829 	 * means that we've have either received this event before we
1830 	 * finished attaching to the IBTF or we've received it while we
1831 	 * are in the process of detaching.
1832 	 */
1833 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1834 	    (state->ts_ibtfpriv != NULL)) {
1835 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
1836 		type		= IBT_EVENT_PATH_MIGRATED_QP;
1837 
1838 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1839 	} else {
1840 		TNF_PROBE_2(tavor_path_mig_handler_dropped_event,
1841 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1842 		    tnf_uint, hdl_qpnum, qpnum);
1843 	}
1844 
1845 	TAVOR_TNF_EXIT(tavor_path_mig_handler);
1846 	return (DDI_SUCCESS);
1847 }
1848 
1849 
1850 /*
1851  * tavor_path_mig_err_handler()
1852  *    Context: Only called from interrupt context
1853  */
1854 static int
1855 tavor_path_mig_err_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1856     tavor_hw_eqe_t *eqe)
1857 {
1858 	tavor_qphdl_t		qp;
1859 	uint_t			qpnum;
1860 	ibc_async_event_t	event;
1861 	ibt_async_code_t	type;
1862 	uint_t			eqe_evttype;
1863 
1864 	TAVOR_TNF_ENTER(tavor_path_mig_err_handler);
1865 
1866 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1867 
1868 	ASSERT(eqe_evttype == TAVOR_EVT_PATH_MIGRATE_FAILED ||
1869 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1870 
1871 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1872 		TNF_PROBE_0(tavor_path_mig_err_eq_overflow_condition,
1873 		    TAVOR_TNF_ERROR, "");
1874 		tavor_eq_overflow_handler(state, eq, eqe);
1875 
1876 		TAVOR_TNF_EXIT(tavor_path_mig_err_handler);
1877 		return (DDI_FAILURE);
1878 	}
1879 
1880 	/* Get the QP handle from QP number in event descriptor */
1881 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1882 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1883 
1884 	/*
1885 	 * If the QP handle is NULL, this is probably an indication
1886 	 * that the QP has been freed already.  In which case, we
1887 	 * should not deliver this event.
1888 	 *
1889 	 * We also check that the QP number in the handle is the
1890 	 * same as the QP number in the event queue entry.  This
1891 	 * extra check allows us to handle the case where a QP was
1892 	 * freed and then allocated again in the time it took to
1893 	 * handle the event queue processing.  By constantly incrementing
1894 	 * the non-constrained portion of the QP number every time
1895 	 * a new QP is allocated, we mitigate (somewhat) the chance
1896 	 * that a stale event could be passed to the client's QP
1897 	 * handler.
1898 	 *
1899 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
1900 	 * means that we've have either received this event before we
1901 	 * finished attaching to the IBTF or we've received it while we
1902 	 * are in the process of detaching.
1903 	 */
1904 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1905 	    (state->ts_ibtfpriv != NULL)) {
1906 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
1907 		type		= IBT_ERROR_PATH_MIGRATE_REQ_QP;
1908 
1909 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1910 	} else {
1911 		TNF_PROBE_2(tavor_path_mig_err_handler_dropped_event,
1912 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1913 		    tnf_uint, hdl_qpnum, qpnum);
1914 	}
1915 
1916 	TAVOR_TNF_EXIT(tavor_path_mig_err_handler);
1917 	return (DDI_SUCCESS);
1918 }
1919 
1920 
1921 /*
1922  * tavor_srq_catastrophic_handler()
1923  *    Context: Only called from interrupt context
1924  */
1925 static int
1926 tavor_srq_catastrophic_handler(tavor_state_t *state, tavor_eqhdl_t eq,
1927     tavor_hw_eqe_t *eqe)
1928 {
1929 	tavor_qphdl_t		qp;
1930 	uint_t			qpnum;
1931 	ibc_async_event_t	event;
1932 	ibt_async_code_t	type;
1933 	uint_t			eqe_evttype;
1934 
1935 	TAVOR_TNF_ENTER(tavor_srq_catastrophic_handler);
1936 
1937 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
1938 
1939 	ASSERT(eqe_evttype == TAVOR_EVT_SRQ_CATASTROPHIC_ERROR ||
1940 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
1941 
1942 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
1943 		TNF_PROBE_0(tavor_srq_catastrophic_overflow_condition,
1944 		    TAVOR_TNF_ERROR, "");
1945 		tavor_eq_overflow_handler(state, eq, eqe);
1946 
1947 		TAVOR_TNF_EXIT(tavor_srq_catastrophic_handler);
1948 		return (DDI_FAILURE);
1949 	}
1950 
1951 	/* Get the QP handle from QP number in event descriptor */
1952 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
1953 	qp = tavor_qphdl_from_qpnum(state, qpnum);
1954 
1955 	/*
1956 	 * If the QP handle is NULL, this is probably an indication
1957 	 * that the QP has been freed already.  In which case, we
1958 	 * should not deliver this event.
1959 	 *
1960 	 * We also check that the QP number in the handle is the
1961 	 * same as the QP number in the event queue entry.  This
1962 	 * extra check allows us to handle the case where a QP was
1963 	 * freed and then allocated again in the time it took to
1964 	 * handle the event queue processing.  By constantly incrementing
1965 	 * the non-constrained portion of the QP number every time
1966 	 * a new QP is allocated, we mitigate (somewhat) the chance
1967 	 * that a stale event could be passed to the client's QP
1968 	 * handler.
1969 	 *
1970 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
1971 	 * means that we've have either received this event before we
1972 	 * finished attaching to the IBTF or we've received it while we
1973 	 * are in the process of detaching.
1974 	 */
1975 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
1976 	    (state->ts_ibtfpriv != NULL)) {
1977 		event.ev_srq_hdl = (ibt_srq_hdl_t)qp->qp_srqhdl->srq_hdlrarg;
1978 		type		= IBT_ERROR_CATASTROPHIC_SRQ;
1979 
1980 		mutex_enter(&qp->qp_srqhdl->srq_lock);
1981 		qp->qp_srqhdl->srq_state = TAVOR_SRQ_STATE_ERROR;
1982 		mutex_exit(&qp->qp_srqhdl->srq_lock);
1983 
1984 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
1985 	} else {
1986 		TNF_PROBE_2(tavor_srq_catastrophic_handler_dropped_event,
1987 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
1988 		    tnf_uint, hdl_qpnum, qpnum);
1989 	}
1990 
1991 	TAVOR_TNF_EXIT(tavor_srq_catastrophic_handler);
1992 	return (DDI_SUCCESS);
1993 }
1994 
1995 
1996 /*
1997  * tavor_srq_last_wqe_reached_handler()
1998  *    Context: Only called from interrupt context
1999  */
2000 static int
2001 tavor_srq_last_wqe_reached_handler(tavor_state_t *state, tavor_eqhdl_t eq,
2002     tavor_hw_eqe_t *eqe)
2003 {
2004 	tavor_qphdl_t		qp;
2005 	uint_t			qpnum;
2006 	ibc_async_event_t	event;
2007 	ibt_async_code_t	type;
2008 	uint_t			eqe_evttype;
2009 
2010 	TAVOR_TNF_ENTER(tavor_srq_last_wqe_reached_handler);
2011 
2012 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
2013 
2014 	ASSERT(eqe_evttype == TAVOR_EVT_SRQ_LAST_WQE_REACHED ||
2015 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
2016 
2017 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
2018 		TNF_PROBE_0(tavor_srq_last_wqe_reached_over_condition,
2019 		    TAVOR_TNF_ERROR, "");
2020 		tavor_eq_overflow_handler(state, eq, eqe);
2021 
2022 		TAVOR_TNF_EXIT(tavor_srq_last_wqe_reached_handler);
2023 		return (DDI_FAILURE);
2024 	}
2025 
2026 	/* Get the QP handle from QP number in event descriptor */
2027 	qpnum = TAVOR_EQE_QPNUM_GET(eq, eqe);
2028 	qp = tavor_qphdl_from_qpnum(state, qpnum);
2029 
2030 	/*
2031 	 * If the QP handle is NULL, this is probably an indication
2032 	 * that the QP has been freed already.  In which case, we
2033 	 * should not deliver this event.
2034 	 *
2035 	 * We also check that the QP number in the handle is the
2036 	 * same as the QP number in the event queue entry.  This
2037 	 * extra check allows us to handle the case where a QP was
2038 	 * freed and then allocated again in the time it took to
2039 	 * handle the event queue processing.  By constantly incrementing
2040 	 * the non-constrained portion of the QP number every time
2041 	 * a new QP is allocated, we mitigate (somewhat) the chance
2042 	 * that a stale event could be passed to the client's QP
2043 	 * handler.
2044 	 *
2045 	 * Lastly, we check if "ts_ibtfpriv" is NULL.  If it is then it
2046 	 * means that we've have either received this event before we
2047 	 * finished attaching to the IBTF or we've received it while we
2048 	 * are in the process of detaching.
2049 	 */
2050 	if ((qp != NULL) && (qp->qp_qpnum == qpnum) &&
2051 	    (state->ts_ibtfpriv != NULL)) {
2052 		event.ev_qp_hdl = (ibtl_qp_hdl_t)qp->qp_hdlrarg;
2053 		type		= IBT_EVENT_EMPTY_CHAN;
2054 
2055 		TAVOR_DO_IBTF_ASYNC_CALLB(state, type, &event);
2056 	} else {
2057 		TNF_PROBE_2(tavor_srq_last_wqe_reached_dropped_event,
2058 		    TAVOR_TNF_ERROR, "", tnf_uint, ev_qpnum, qpnum,
2059 		    tnf_uint, hdl_qpnum, qpnum);
2060 	}
2061 
2062 	TAVOR_TNF_EXIT(tavor_srq_last_wqe_reached_handler);
2063 	return (DDI_SUCCESS);
2064 }
2065 
2066 
2067 /*
2068  * tavor_ecc_detection_handler()
2069  *    Context: Only called from interrupt context
2070  */
2071 static int
2072 tavor_ecc_detection_handler(tavor_state_t *state, tavor_eqhdl_t eq,
2073     tavor_hw_eqe_t *eqe)
2074 {
2075 	uint_t			eqe_evttype;
2076 	uint_t			data;
2077 	int			i;
2078 
2079 	TAVOR_TNF_ENTER(tavor_ecc_detection_handler);
2080 
2081 	eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
2082 
2083 	ASSERT(eqe_evttype == TAVOR_EVT_ECC_DETECTION ||
2084 	    eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
2085 
2086 	if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
2087 		TNF_PROBE_0(tavor_ecc_detection_eq_overflow_condition,
2088 		    TAVOR_TNF_ERROR, "");
2089 		tavor_eq_overflow_handler(state, eq, eqe);
2090 
2091 		TAVOR_TNF_EXIT(tavor_ecc_detection_handler);
2092 		return (DDI_FAILURE);
2093 	}
2094 
2095 	/*
2096 	 * The "ECC Detection Event" indicates that a correctable single-bit
2097 	 * has occurred with the attached DDR.  The EQE provides some
2098 	 * additional information about the errored EQ.  So we print a warning
2099 	 * message here along with that additional information.
2100 	 */
2101 	TAVOR_WARNING(state, "ECC Correctable Error Event Detected");
2102 	for (i = 0; i < sizeof (tavor_hw_eqe_t) >> 2; i++) {
2103 		data = ((uint_t *)eqe)[i];
2104 		cmn_err(CE_CONT, "!  EQE[%02x]: %08x\n", i, data);
2105 	}
2106 
2107 	TAVOR_TNF_EXIT(tavor_ecc_detection_handler);
2108 	return (DDI_SUCCESS);
2109 }
2110 
2111 
2112 /*
2113  * tavor_eq_overflow_handler()
2114  *    Context: Only called from interrupt context
2115  */
2116 void
2117 tavor_eq_overflow_handler(tavor_state_t *state, tavor_eqhdl_t eq,
2118     tavor_hw_eqe_t *eqe)
2119 {
2120 	uint_t		error_type, data;
2121 
2122 	TAVOR_TNF_ENTER(tavor_eq_overflow_handler);
2123 
2124 	ASSERT(TAVOR_EQE_EVTTYPE_GET(eq, eqe) == TAVOR_EVT_EQ_OVERFLOW);
2125 
2126 	/*
2127 	 * The "Event Queue Overflow Event" indicates that something has
2128 	 * probably gone seriously wrong with some hardware (or, perhaps,
2129 	 * with the software... though it's unlikely in this case).  The EQE
2130 	 * provides some additional information about the errored EQ.  So we
2131 	 * print a warning message here along with that additional information.
2132 	 */
2133 	error_type = TAVOR_EQE_OPERRTYPE_GET(eq, eqe);
2134 	data	   = TAVOR_EQE_OPERRDATA_GET(eq, eqe);
2135 
2136 	TAVOR_WARNING(state, "Event Queue overflow");
2137 	cmn_err(CE_CONT, "  Error type: %02x, data: %08x\n", error_type, data);
2138 
2139 	TAVOR_TNF_EXIT(tavor_eq_overflow_handler);
2140 }
2141 
2142 
2143 /*
2144  * tavor_no_eqhandler
2145  *    Context: Only called from interrupt context
2146  */
2147 /* ARGSUSED */
2148 static int
2149 tavor_no_eqhandler(tavor_state_t *state, tavor_eqhdl_t eq,
2150     tavor_hw_eqe_t *eqe)
2151 {
2152 	uint_t		data;
2153 	int		i;
2154 
2155 	TAVOR_TNF_ENTER(tavor_no_eqhandler);
2156 
2157 	/*
2158 	 * This "unexpected event" handler (or "catch-all" handler) will
2159 	 * receive all events for which no other handler has been registered.
2160 	 * If we end up here, then something has probably gone seriously wrong
2161 	 * with the Tavor hardware (or, perhaps, with the software... though
2162 	 * it's unlikely in this case).  The EQE provides all the information
2163 	 * about the event.  So we print a warning message here along with
2164 	 * the contents of the EQE.
2165 	 */
2166 	TAVOR_WARNING(state, "Unexpected Event handler");
2167 	cmn_err(CE_CONT, "  Event type: %02x, subtype: %02x\n",
2168 	    TAVOR_EQE_EVTTYPE_GET(eq, eqe), TAVOR_EQE_EVTSUBTYPE_GET(eq, eqe));
2169 	for (i = 0; i < sizeof (tavor_hw_eqe_t) >> 2; i++) {
2170 		data = ((uint_t *)eqe)[i];
2171 		cmn_err(CE_CONT, "  EQE[%02x]: %08x\n", i, data);
2172 	}
2173 
2174 	TAVOR_TNF_EXIT(tavor_no_eqhandler);
2175 	return (DDI_SUCCESS);
2176 }
2177