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_rsrc.c
29  *    Tavor Resource Management Routines
30  *
31  *    Implements all the routines necessary for setup, teardown, and
32  *    alloc/free of all Tavor resources, including those that are managed
33  *    by Tavor hardware or which live in Tavor's direct attached DDR memory.
34  */
35 
36 #include <sys/sysmacros.h>
37 #include <sys/types.h>
38 #include <sys/conf.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/modctl.h>
42 #include <sys/vmem.h>
43 #include <sys/bitmap.h>
44 
45 #include <sys/ib/adapters/tavor/tavor.h>
46 
47 /*
48  * The following routines are used for initializing and destroying
49  * the resource pools used by the Tavor resource allocation routines.
50  * They consist of four classes of object:
51  *
52  * Mailboxes:  The "In" and "Out" mailbox types are used by the Tavor
53  *    command interface routines.  Mailboxes are used to pass information
54  *    back and forth to the Tavor firmware.  Either type of mailbox may
55  *    be allocated from Tavor's direct attached DDR memory or from system
56  *    memory (although currently all "In" mailboxes are in DDR and all "out"
57  *    mailboxes come from system memory.
58  *
59  * HW entry objects:  These objects represent resources required by the Tavor
60  *    hardware.  These objects include things like Queue Pair contexts (QPC),
61  *    Completion Queue contexts (CQC), Event Queue contexts (EQC), RDB (for
62  *    supporting RDMA Read/Atomic), Multicast Group entries (MCG), Memory
63  *    Protection Table entries (MPT), Memory Translation Table entries (MTT).
64  *
65  *    What these objects all have in common is that they are each required
66  *    to come from DDR memory, they are always allocated from tables, and
67  *    they are not to be directly accessed (read or written) by driver
68  *    software.
69  *    One notable exceptions to this rule are the Extended QP contexts (EQPC),
70  *    and the UAR scratch area (UAR_SCR), both of which are not directly
71  *    accessible through the Tavor resource allocation routines, but both
72  *    of which are also required to reside in DDR memory and are not to be
73  *    manipulated by driver software (they are privately managed by Tavor
74  *    hardware).
75  *    The other notable exceptions are the UAR pages (UAR_PG) which are
76  *    allocated from the UAR address space rather than DDR, and the UD
77  *    address vectors (UDAV) which are similar to the common object types
78  *    with the major difference being that UDAVs _are_ directly read and
79  *    written by driver software.
80  *
81  * SW handle objects: These objects represent resources required by Tavor
82  *    driver software.  They are primarily software tracking structures,
83  *    which are allocated from system memory (using kmem_cache).  Several of
84  *    the objects have both a "constructor" and "destructor" method
85  *    associated with them (see below).
86  *
87  * Protection Domain (PD) handle objects:  These objects are very much like
88  *    a SW handle object with the notable difference that all PD handle
89  *    objects have an actual Protection Domain number (PD) associated with
90  *    them (and the PD number is allocated/managed through a separate
91  *    vmem_arena specifically set aside for this purpose.
92  */
93 
94 static int tavor_rsrc_mbox_init(tavor_state_t *state,
95     tavor_rsrc_mbox_info_t *info);
96 static void tavor_rsrc_mbox_fini(tavor_state_t *state,
97     tavor_rsrc_mbox_info_t *info);
98 
99 static int tavor_rsrc_hw_entries_init(tavor_state_t *state,
100     tavor_rsrc_hw_entry_info_t *info);
101 static void tavor_rsrc_hw_entries_fini(tavor_state_t *state,
102     tavor_rsrc_hw_entry_info_t *info);
103 
104 static int tavor_rsrc_sw_handles_init(tavor_state_t *state,
105     tavor_rsrc_sw_hdl_info_t *info);
106 static void tavor_rsrc_sw_handles_fini(tavor_state_t *state,
107     tavor_rsrc_sw_hdl_info_t *info);
108 
109 static int tavor_rsrc_pd_handles_init(tavor_state_t *state,
110     tavor_rsrc_sw_hdl_info_t *info);
111 static void tavor_rsrc_pd_handles_fini(tavor_state_t *state,
112     tavor_rsrc_sw_hdl_info_t *info);
113 
114 /*
115  * The following routines are used for allocating and freeing the specific
116  * types of objects described above from their associated resource pools.
117  */
118 static int tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t *pool_info,
119     uint_t num, tavor_rsrc_t *hdl);
120 static void tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t *pool_info,
121     tavor_rsrc_t *hdl);
122 
123 static int tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t *pool_info,
124     uint_t num, uint_t num_align, ddi_acc_handle_t acc_handle,
125     uint_t sleepflag, tavor_rsrc_t *hdl);
126 static void tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t *pool_info,
127     tavor_rsrc_t *hdl);
128 
129 static int tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t *pool_info,
130     uint_t sleepflag, tavor_rsrc_t *hdl);
131 static void tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t *pool_info,
132     tavor_rsrc_t *hdl);
133 
134 static int tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t *pool_info,
135     uint_t sleepflag, tavor_rsrc_t *hdl);
136 static void tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t *pool_info,
137     tavor_rsrc_t *hdl);
138 
139 /*
140  * The following routines are the constructors and destructors for several
141  * of the SW handle type objects.  For certain types of SW handles objects
142  * (all of which are implemented using kmem_cache), we need to do some
143  * special field initialization (specifically, mutex_init/destroy).  These
144  * routines enable that init and teardown.
145  */
146 static int tavor_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
147 static void tavor_rsrc_pdhdl_destructor(void *pd, void *state);
148 static int tavor_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
149 static void tavor_rsrc_cqhdl_destructor(void *cq, void *state);
150 static int tavor_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
151 static void tavor_rsrc_qphdl_destructor(void *cq, void *state);
152 static int tavor_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
153 static void tavor_rsrc_srqhdl_destructor(void *srq, void *state);
154 static int tavor_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
155 static void tavor_rsrc_refcnt_destructor(void *rc, void *state);
156 static int tavor_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
157 static void tavor_rsrc_ahhdl_destructor(void *ah, void *state);
158 static int tavor_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
159 static void tavor_rsrc_mrhdl_destructor(void *mr, void *state);
160 
161 /*
162  * Special routine to calculate and return the size of a MCG object based
163  * on current driver configuration (specifically, the number of QP per MCG
164  * that has been configured.
165  */
166 static int tavor_rsrc_mcg_entry_get_size(tavor_state_t *state,
167     uint_t *mcg_size_shift);
168 
169 
170 /*
171  * tavor_rsrc_alloc()
172  *
173  *    Context: Can be called from interrupt or base context.
174  *    The "sleepflag" parameter is used by all object allocators to
175  *    determine whether to SLEEP for resources or not.
176  */
177 int
178 tavor_rsrc_alloc(tavor_state_t *state, tavor_rsrc_type_t rsrc, uint_t num,
179     uint_t sleepflag, tavor_rsrc_t **hdl)
180 {
181 	tavor_rsrc_pool_info_t	*rsrc_pool;
182 	tavor_rsrc_t		*tmp_rsrc_hdl;
183 	int			flag, status = DDI_FAILURE;
184 
185 	TAVOR_TNF_ENTER(tavor_rsrc_alloc);
186 
187 	ASSERT(state != NULL);
188 	ASSERT(hdl != NULL);
189 
190 	rsrc_pool = &state->ts_rsrc_hdl[rsrc];
191 	ASSERT(rsrc_pool != NULL);
192 
193 	/*
194 	 * Allocate space for the object used to track the resource handle
195 	 */
196 	flag = (sleepflag == TAVOR_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
197 	tmp_rsrc_hdl = (tavor_rsrc_t *)kmem_cache_alloc(state->ts_rsrc_cache,
198 	    flag);
199 	if (tmp_rsrc_hdl == NULL) {
200 		TNF_PROBE_0(tavor_rsrc_alloc_kmca_fail, TAVOR_TNF_ERROR, "");
201 		TAVOR_TNF_EXIT(tavor_rsrc_alloc);
202 		return (DDI_FAILURE);
203 	}
204 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
205 
206 	/*
207 	 * Set rsrc_hdl type.  This is later used by the tavor_rsrc_free call
208 	 * to know what type of resource is being freed.
209 	 */
210 	tmp_rsrc_hdl->rsrc_type = rsrc;
211 
212 	/*
213 	 * Depending on resource type, call the appropriate alloc routine
214 	 */
215 	switch (rsrc_pool->rsrc_type) {
216 	case TAVOR_IN_MBOX:
217 	case TAVOR_OUT_MBOX:
218 	case TAVOR_INTR_IN_MBOX:
219 	case TAVOR_INTR_OUT_MBOX:
220 		status = tavor_rsrc_mbox_alloc(rsrc_pool, num, tmp_rsrc_hdl);
221 		break;
222 
223 	case TAVOR_QPC:
224 	case TAVOR_CQC:
225 	case TAVOR_SRQC:
226 	case TAVOR_EQC:
227 	case TAVOR_RDB:
228 		/*
229 		 * Because these objects are NOT accessed by Tavor driver
230 		 * software, we set the acc_handle parameter to zero.  But
231 		 * if they are allocated in multiples, we specify here that
232 		 * they must be aligned on a more restrictive boundary.
233 		 */
234 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, num, 0,
235 		    sleepflag, tmp_rsrc_hdl);
236 		break;
237 
238 	case TAVOR_MPT:
239 		/*
240 		 * Because these MPT objects are sometimes accessed by Tavor
241 		 * driver software (FMR), we set the acc_handle parameter.  But
242 		 * if they are allocated in multiples, we specify here that
243 		 * they must be aligned on a more restrictive boundary.
244 		 */
245 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, num,
246 		    state->ts_reg_ddrhdl, sleepflag, tmp_rsrc_hdl);
247 		break;
248 
249 	case TAVOR_MCG:
250 		/*
251 		 * Tavor MCG entries are also NOT accessed by Tavor driver
252 		 * software, but because MCG entries do not have the same
253 		 * alignnment restrictions we loosen the constraint here.
254 		 */
255 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1, 0,
256 		    sleepflag, tmp_rsrc_hdl);
257 		break;
258 
259 	case TAVOR_MTT:
260 	case TAVOR_UDAV:
261 		/*
262 		 * Because MTT segments are among the few HW resources that
263 		 * may be allocated in odd numbers, we specify a less
264 		 * restrictive alignment than for the above resources.
265 		 *
266 		 * Also because both UDAV and MTT segment objects are read
267 		 * and/or written by Tavor driver software, we set the
268 		 * acc_handle parameter to point to the ddi_acc_handle_t for
269 		 * the Tavor DDR memory.
270 		 */
271 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
272 		    state->ts_reg_ddrhdl, sleepflag, tmp_rsrc_hdl);
273 		break;
274 
275 	case TAVOR_UARPG:
276 		/*
277 		 * Because UAR pages are written by Tavor driver software (for
278 		 * doorbells), we set the acc_handle parameter to point to
279 		 * the ddi_acc_handle_t for the Tavor UAR memory.
280 		 */
281 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
282 		    state->ts_reg_uarhdl, sleepflag, tmp_rsrc_hdl);
283 		break;
284 
285 	case TAVOR_MRHDL:
286 	case TAVOR_EQHDL:
287 	case TAVOR_CQHDL:
288 	case TAVOR_SRQHDL:
289 	case TAVOR_AHHDL:
290 	case TAVOR_QPHDL:
291 	case TAVOR_REFCNT:
292 		status = tavor_rsrc_swhdl_alloc(rsrc_pool, sleepflag,
293 		    tmp_rsrc_hdl);
294 		break;
295 
296 	case TAVOR_PDHDL:
297 		status = tavor_rsrc_pdhdl_alloc(rsrc_pool, sleepflag,
298 		    tmp_rsrc_hdl);
299 		break;
300 
301 	default:
302 		TAVOR_WARNING(state, "unexpected resource type in alloc");
303 		TNF_PROBE_0(tavor_rsrc_alloc_inv_rsrctype_fail,
304 		    TAVOR_TNF_ERROR, "");
305 		break;
306 	}
307 
308 	/*
309 	 * If the resource allocation failed, then free the special resource
310 	 * tracking structure and return failure.  Otherwise return the
311 	 * handle for the resource tracking structure.
312 	 */
313 	if (status != DDI_SUCCESS) {
314 		kmem_cache_free(state->ts_rsrc_cache, tmp_rsrc_hdl);
315 		tmp_rsrc_hdl = NULL;
316 		TNF_PROBE_1(tavor_rsrc_alloc_fail, TAVOR_TNF_ERROR, "",
317 		    tnf_uint, rsrc_type, rsrc_pool->rsrc_type);
318 		TAVOR_TNF_EXIT(tavor_rsrc_alloc);
319 		return (DDI_FAILURE);
320 	} else {
321 		*hdl = tmp_rsrc_hdl;
322 		TAVOR_TNF_EXIT(tavor_rsrc_alloc);
323 		return (DDI_SUCCESS);
324 	}
325 }
326 
327 
328 /*
329  * tavor_rsrc_free()
330  *    Context: Can be called from interrupt or base context.
331  */
332 void
333 tavor_rsrc_free(tavor_state_t *state, tavor_rsrc_t **hdl)
334 {
335 	tavor_rsrc_pool_info_t	*rsrc_pool;
336 
337 	TAVOR_TNF_ENTER(tavor_rsrc_free);
338 
339 	ASSERT(state != NULL);
340 	ASSERT(hdl != NULL);
341 
342 	rsrc_pool = &state->ts_rsrc_hdl[(*hdl)->rsrc_type];
343 	ASSERT(rsrc_pool != NULL);
344 
345 	/*
346 	 * Depending on resource type, call the appropriate free routine
347 	 */
348 	switch (rsrc_pool->rsrc_type) {
349 	case TAVOR_IN_MBOX:
350 	case TAVOR_OUT_MBOX:
351 	case TAVOR_INTR_IN_MBOX:
352 	case TAVOR_INTR_OUT_MBOX:
353 		tavor_rsrc_mbox_free(rsrc_pool, *hdl);
354 		break;
355 
356 	case TAVOR_QPC:
357 	case TAVOR_CQC:
358 	case TAVOR_SRQC:
359 	case TAVOR_EQC:
360 	case TAVOR_RDB:
361 	case TAVOR_MCG:
362 	case TAVOR_MPT:
363 	case TAVOR_MTT:
364 	case TAVOR_UDAV:
365 	case TAVOR_UARPG:
366 		tavor_rsrc_hw_entry_free(rsrc_pool, *hdl);
367 		break;
368 
369 	case TAVOR_MRHDL:
370 	case TAVOR_EQHDL:
371 	case TAVOR_CQHDL:
372 	case TAVOR_SRQHDL:
373 	case TAVOR_AHHDL:
374 	case TAVOR_QPHDL:
375 	case TAVOR_REFCNT:
376 		tavor_rsrc_swhdl_free(rsrc_pool, *hdl);
377 		break;
378 
379 	case TAVOR_PDHDL:
380 		tavor_rsrc_pdhdl_free(rsrc_pool, *hdl);
381 		break;
382 
383 	default:
384 		TAVOR_WARNING(state, "unexpected resource type in free");
385 		TNF_PROBE_0(tavor_rsrc_free_inv_rsrctype_fail,
386 		    TAVOR_TNF_ERROR, "");
387 		break;
388 	}
389 
390 	/*
391 	 * Free the special resource tracking structure, set the handle to
392 	 * NULL, and return.
393 	 */
394 	kmem_cache_free(state->ts_rsrc_cache, *hdl);
395 	*hdl = NULL;
396 
397 	TAVOR_TNF_EXIT(tavor_rsrc_free);
398 }
399 
400 
401 /*
402  * tavor_rsrc_init_phase1()
403  *
404  *    Completes the first phase of Tavor resource/configuration init.
405  *    This involves creating the kmem_cache for the "tavor_rsrc_t"
406  *    structs, allocating the space for the resource pool handles,
407  *    and setting up the "Out" mailboxes.
408  *
409  *    When this function completes, the Tavor driver is ready to
410  *    post the following commands which return information only in the
411  *    "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
412  *    If any of these commands are to be posted at this time, they must be
413  *    done so only when "spinning" (as the outstanding command list and
414  *    EQ setup code has not yet run)
415  *
416  *    Context: Only called from attach() path context
417  */
418 int
419 tavor_rsrc_init_phase1(tavor_state_t *state)
420 {
421 	tavor_rsrc_pool_info_t		*rsrc_pool;
422 	tavor_rsrc_mbox_info_t 		mbox_info;
423 	tavor_rsrc_cleanup_level_t	cleanup;
424 	tavor_cfg_profile_t		*cfgprof;
425 	uint64_t			num, size;
426 	int				status;
427 	char				*errormsg, *rsrc_name;
428 
429 	TAVOR_TNF_ENTER(tavor_rsrc_init_phase1);
430 
431 	ASSERT(state != NULL);
432 
433 	/* This is where Phase 1 of resource initialization begins */
434 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL0;
435 
436 	/* Build kmem cache name from Tavor instance */
437 	rsrc_name = (char *)kmem_zalloc(TAVOR_RSRC_NAME_MAXLEN, KM_SLEEP);
438 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_RSRC_CACHE);
439 
440 	/*
441 	 * Create the kmem_cache for "tavor_rsrc_t" structures
442 	 * (kmem_cache_create will SLEEP until successful)
443 	 */
444 	state->ts_rsrc_cache = kmem_cache_create(rsrc_name,
445 	    sizeof (tavor_rsrc_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
446 
447 	/*
448 	 * Allocate an array of tavor_rsrc_pool_info_t's (used in all
449 	 * subsequent resource allocations)
450 	 */
451 	state->ts_rsrc_hdl = kmem_zalloc(TAVOR_NUM_RESOURCES *
452 	    sizeof (tavor_rsrc_pool_info_t), KM_SLEEP);
453 
454 	cfgprof = state->ts_cfg_profile;
455 
456 	/*
457 	 * Initialize the resource pool for "Out" mailboxes.  Notice that
458 	 * the number of "Out" mailboxes, their size, and their location
459 	 * (DDR or system memory) is configurable.  By default, however,
460 	 * all "Out" mailboxes are located in system memory only (because
461 	 * they are primarily read from and never written to)
462 	 */
463 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_outmbox);
464 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
465 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_OUT_MBOX];
466 	rsrc_pool->rsrc_type	  = TAVOR_OUT_MBOX;
467 	rsrc_pool->rsrc_loc	  = TAVOR_IN_SYSMEM;
468 	rsrc_pool->rsrc_pool_size = (size * num);
469 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
470 	rsrc_pool->rsrc_quantum	  = size;
471 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
472 	rsrc_pool->rsrc_state	  = state;
473 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_OUTMBOX_VMEM);
474 	mbox_info.mbi_num	  = num;
475 	mbox_info.mbi_size	  = size;
476 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
477 	mbox_info.mbi_rsrcname	  = rsrc_name;
478 	status = tavor_rsrc_mbox_init(state, &mbox_info);
479 	if (status != DDI_SUCCESS) {
480 		tavor_rsrc_fini(state, cleanup);
481 		/* Set "status" and "errormsg" and goto failure */
482 		TAVOR_TNF_FAIL(DDI_FAILURE, "out mailboxes");
483 		goto rsrcinitp1_fail;
484 	}
485 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL1;
486 
487 	/*
488 	 * Initialize the Tavor "Out" mailbox list.  This step actually uses
489 	 * the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
490 	 * "Out" mailboxes, bind them for DMA access, and arrange them into
491 	 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
492 	 * for more details)
493 	 */
494 	status = tavor_outmbox_list_init(state);
495 	if (status != DDI_SUCCESS) {
496 		tavor_rsrc_fini(state, cleanup);
497 		/* Set "status" and "errormsg" and goto failure */
498 		TAVOR_TNF_FAIL(DDI_FAILURE, "out mailbox list");
499 		goto rsrcinitp1_fail;
500 	}
501 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL2;
502 
503 	/*
504 	 * Initialize the resource pool for interrupt "Out" mailboxes.  Notice
505 	 * that the number of interrupt "Out" mailboxes, their size, and their
506 	 * location (DDR or system memory) is configurable.  By default,
507 	 * however, all interrupt "Out" mailboxes are located in system memory
508 	 * only (because they are primarily read from and never written to)
509 	 */
510 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_outmbox);
511 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
512 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_INTR_OUT_MBOX];
513 	rsrc_pool->rsrc_type	  = TAVOR_INTR_OUT_MBOX;
514 	rsrc_pool->rsrc_loc	  = TAVOR_IN_SYSMEM;
515 	rsrc_pool->rsrc_pool_size = (size * num);
516 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
517 	rsrc_pool->rsrc_quantum	  = size;
518 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
519 	rsrc_pool->rsrc_state	  = state;
520 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INTR_OUTMBOX_VMEM);
521 	mbox_info.mbi_num	  = num;
522 	mbox_info.mbi_size	  = size;
523 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
524 	mbox_info.mbi_rsrcname	  = rsrc_name;
525 	status = tavor_rsrc_mbox_init(state, &mbox_info);
526 	if (status != DDI_SUCCESS) {
527 		tavor_rsrc_fini(state, cleanup);
528 		/* Set "status" and "errormsg" and goto failure */
529 		TAVOR_TNF_FAIL(DDI_FAILURE, "out intr mailboxes");
530 		goto rsrcinitp1_fail;
531 	}
532 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL3;
533 
534 	/*
535 	 * Initialize the Tavor "Out" mailbox list.  This step actually uses
536 	 * the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
537 	 * "Out" mailboxes, bind them for DMA access, and arrange them into
538 	 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
539 	 * for more details)
540 	 */
541 	status = tavor_intr_outmbox_list_init(state);
542 	if (status != DDI_SUCCESS) {
543 		tavor_rsrc_fini(state, cleanup);
544 		/* Set "status" and "errormsg" and goto failure */
545 		TAVOR_TNF_FAIL(DDI_FAILURE, "out intr mailbox list");
546 		goto rsrcinitp1_fail;
547 	}
548 	cleanup = TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE;
549 
550 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
551 	TAVOR_TNF_EXIT(tavor_rsrc_init_phase1);
552 	return (DDI_SUCCESS);
553 
554 rsrcinitp1_fail:
555 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
556 	TNF_PROBE_1(tavor_rsrc_init_phase1_fail, TAVOR_TNF_ERROR, "",
557 	    tnf_string, msg, errormsg);
558 	TAVOR_TNF_EXIT(tavor_rsrc_init_phase1);
559 	return (status);
560 }
561 
562 
563 /*
564  * tavor_rsrc_init_phase2()
565  *    Context: Only called from attach() path context
566  */
567 int
568 tavor_rsrc_init_phase2(tavor_state_t *state)
569 {
570 	tavor_rsrc_sw_hdl_info_t	hdl_info;
571 	tavor_rsrc_hw_entry_info_t	entry_info;
572 	tavor_rsrc_mbox_info_t		mbox_info;
573 	tavor_rsrc_pool_info_t		*rsrc_pool;
574 	tavor_rsrc_cleanup_level_t	cleanup;
575 	tavor_cfg_profile_t		*cfgprof;
576 	uint64_t			num, max, size, num_prealloc;
577 	uint64_t			ddr_size, fw_size;
578 	uint_t				mcg_size, mcg_size_shift;
579 	uint_t				uarscr_size, mttsegment_sz;
580 	int				status;
581 	char				*errormsg, *rsrc_name;
582 
583 	TAVOR_TNF_ENTER(tavor_rsrc_init_phase2);
584 
585 	ASSERT(state != NULL);
586 
587 	/* Phase 2 initialization begins where Phase 1 left off */
588 	cleanup = TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE;
589 
590 	/*
591 	 * Calculate the extent of the DDR size and portion of which that
592 	 * is already reserved for Tavor firmware.  (Note: this information
593 	 * is available because the QUERY_DDR and QUERY_FW commands have
594 	 * been posted to Tavor firmware prior to calling this routine)
595 	 */
596 	ddr_size = state->ts_ddr.ddr_endaddr - state->ts_ddr.ddr_baseaddr + 1;
597 	fw_size  = state->ts_fw.fw_endaddr - state->ts_fw.fw_baseaddr + 1;
598 
599 	/* Build the DDR vmem arena name from Tavor instance */
600 	rsrc_name = (char *)kmem_zalloc(TAVOR_RSRC_NAME_MAXLEN, KM_SLEEP);
601 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_VMEM);
602 
603 	/*
604 	 * Do a vmem_create for the entire DDR range (not including the
605 	 * portion consumed by Tavor firmware).  This creates the vmem arena
606 	 * from which all other DDR objects (specifically, tables of HW
607 	 * entries) will be allocated.
608 	 */
609 	state->ts_ddrvmem = vmem_create(rsrc_name,
610 	    (void *)(uintptr_t)state->ts_ddr.ddr_baseaddr, (ddr_size - fw_size),
611 	    sizeof (uint64_t), NULL, NULL, NULL, 0, VM_SLEEP);
612 	if (state->ts_ddrvmem == NULL) {
613 		tavor_rsrc_fini(state, cleanup);
614 		/* Set "status" and "errormsg" and goto failure */
615 		TAVOR_TNF_FAIL(DDI_FAILURE, "DDR vmem");
616 		goto rsrcinitp2_fail;
617 	}
618 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL5;
619 
620 	/*
621 	 * Initialize the resource pools for all objects that exist in
622 	 * Tavor DDR memory.  This includes ("In") mailboxes, context tables
623 	 * (QPC, CQC, EQC, etc...), and other miscellaneous HW objects.
624 	 */
625 	cfgprof = state->ts_cfg_profile;
626 
627 	/*
628 	 * Initialize the resource pool for the MPT table entries.  Notice
629 	 * that the number of MPTs is configurable.  The configured value must
630 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
631 	 * command) or the initialization will fail.  Note also that a certain
632 	 * number of MPTs must be set aside for Tavor firmware use.
633 	 */
634 	num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
635 	max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
636 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_mpt);
637 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MPT];
638 	rsrc_pool->rsrc_type	  = TAVOR_MPT;
639 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
640 	rsrc_pool->rsrc_pool_size = (TAVOR_MPT_SIZE * num);
641 	rsrc_pool->rsrc_shift	  = TAVOR_MPT_SIZE_SHIFT;
642 	rsrc_pool->rsrc_quantum	  = TAVOR_MPT_SIZE;
643 	rsrc_pool->rsrc_align	  = (TAVOR_MPT_SIZE * num);
644 	rsrc_pool->rsrc_state	  = state;
645 	rsrc_pool->rsrc_start	  = NULL;
646 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MPT_VMEM);
647 	entry_info.hwi_num	  = num;
648 	entry_info.hwi_max	  = max;
649 	entry_info.hwi_prealloc	  = num_prealloc;
650 	entry_info.hwi_rsrcpool	  = rsrc_pool;
651 	entry_info.hwi_rsrcname	  = rsrc_name;
652 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
653 	if (status != DDI_SUCCESS) {
654 		tavor_rsrc_fini(state, cleanup);
655 		/* Set "status" and "errormsg" and goto failure */
656 		TAVOR_TNF_FAIL(DDI_FAILURE, "MPT table");
657 		goto rsrcinitp2_fail;
658 	}
659 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL6;
660 
661 	/*
662 	 * Initialize the resource pool for the MTT table entries.  Notice
663 	 * that the number of MTTs is configurable.  The configured value must
664 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
665 	 * command) or the initialization will fail.  Note also that a certain
666 	 * number of MTT segments must be set aside for Tavor firmware use.
667 	 */
668 	mttsegment_sz = (TAVOR_MTTSEG_SIZE << TAVOR_MTT_SIZE_SHIFT);
669 	num = ((uint64_t)1 << cfgprof->cp_log_num_mttseg);
670 	max = ((uint64_t)1 << state->ts_devlim.log_max_mttseg);
671 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_mttseg);
672 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MTT];
673 	rsrc_pool->rsrc_type	  = TAVOR_MTT;
674 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
675 	rsrc_pool->rsrc_pool_size = (TAVOR_MTT_SIZE * num);
676 	rsrc_pool->rsrc_shift	  = TAVOR_MTT_SIZE_SHIFT;
677 	rsrc_pool->rsrc_quantum	  = mttsegment_sz;
678 	rsrc_pool->rsrc_align	  = (TAVOR_MTT_SIZE * num);
679 	rsrc_pool->rsrc_state	  = state;
680 	rsrc_pool->rsrc_start	  = NULL;
681 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MTT_VMEM);
682 	entry_info.hwi_num	  = num;
683 	entry_info.hwi_max	  = max;
684 	entry_info.hwi_prealloc	  = num_prealloc;
685 	entry_info.hwi_rsrcpool	  = rsrc_pool;
686 	entry_info.hwi_rsrcname	  = rsrc_name;
687 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
688 	if (status != DDI_SUCCESS) {
689 		tavor_rsrc_fini(state, cleanup);
690 		/* Set "status" and "errormsg" and goto failure */
691 		TAVOR_TNF_FAIL(DDI_FAILURE, "MTT table");
692 		goto rsrcinitp2_fail;
693 	}
694 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL7;
695 
696 	/*
697 	 * Initialize the resource pool for the QPC table entries.  Notice
698 	 * that the number of QPs is configurable.  The configured value must
699 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
700 	 * command) or the initialization will fail.  Note also that a certain
701 	 * number of QP contexts must be set aside for Tavor firmware use.
702 	 */
703 	num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
704 	max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
705 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_qp);
706 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_QPC];
707 	rsrc_pool->rsrc_type	  = TAVOR_QPC;
708 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
709 	rsrc_pool->rsrc_pool_size = (TAVOR_QPC_SIZE * num);
710 	rsrc_pool->rsrc_shift	  = TAVOR_QPC_SIZE_SHIFT;
711 	rsrc_pool->rsrc_quantum	  = TAVOR_QPC_SIZE;
712 	rsrc_pool->rsrc_align	  = (TAVOR_QPC_SIZE * num);
713 	rsrc_pool->rsrc_state	  = state;
714 	rsrc_pool->rsrc_start	  = NULL;
715 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_QPC_VMEM);
716 	entry_info.hwi_num	  = num;
717 	entry_info.hwi_max	  = max;
718 	entry_info.hwi_prealloc	  = num_prealloc;
719 	entry_info.hwi_rsrcpool	  = rsrc_pool;
720 	entry_info.hwi_rsrcname	  = rsrc_name;
721 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
722 	if (status != DDI_SUCCESS) {
723 		tavor_rsrc_fini(state, cleanup);
724 		/* Set "status" and "errormsg" and goto failure */
725 		TAVOR_TNF_FAIL(DDI_FAILURE, "QPC table");
726 		goto rsrcinitp2_fail;
727 	}
728 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL8;
729 
730 	/*
731 	 * Initialize the resource pool for the RDB table entries.  Notice
732 	 * that the number of RDBs is configurable.  The configured value must
733 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
734 	 * command) or the initialization will fail.
735 	 */
736 	num = ((uint64_t)1 << cfgprof->cp_log_num_rdb);
737 	max = ((uint64_t)1 << state->ts_devlim.log_max_ra_glob);
738 	num_prealloc = 0;
739 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_RDB];
740 	rsrc_pool->rsrc_type	  = TAVOR_RDB;
741 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
742 	rsrc_pool->rsrc_pool_size = (TAVOR_RDB_SIZE * num);
743 	rsrc_pool->rsrc_shift	  = TAVOR_RDB_SIZE_SHIFT;
744 	rsrc_pool->rsrc_quantum	  = TAVOR_RDB_SIZE;
745 	rsrc_pool->rsrc_align	  = (TAVOR_RDB_SIZE * num);
746 	rsrc_pool->rsrc_state	  = state;
747 	rsrc_pool->rsrc_start	  = NULL;
748 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_RDB_VMEM);
749 	entry_info.hwi_num	  = num;
750 	entry_info.hwi_max	  = max;
751 	entry_info.hwi_prealloc	  = num_prealloc;
752 	entry_info.hwi_rsrcpool	  = rsrc_pool;
753 	entry_info.hwi_rsrcname	  = rsrc_name;
754 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
755 	if (status != DDI_SUCCESS) {
756 		tavor_rsrc_fini(state, cleanup);
757 		/* Set "status" and "errormsg" and goto failure */
758 		TAVOR_TNF_FAIL(DDI_FAILURE, "RDB table");
759 		goto rsrcinitp2_fail;
760 	}
761 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL9;
762 
763 	/*
764 	 * Initialize the resource pool for the CQC table entries.  Notice
765 	 * that the number of CQs is configurable.  The configured value must
766 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
767 	 * command) or the initialization will fail.  Note also that a certain
768 	 * number of CQ contexts must be set aside for Tavor firmware use.
769 	 */
770 	num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
771 	max = ((uint64_t)1 << state->ts_devlim.log_max_cq);
772 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_cq);
773 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_CQC];
774 	rsrc_pool->rsrc_type	  = TAVOR_CQC;
775 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
776 	rsrc_pool->rsrc_pool_size = (TAVOR_CQC_SIZE * num);
777 	rsrc_pool->rsrc_shift	  = TAVOR_CQC_SIZE_SHIFT;
778 	rsrc_pool->rsrc_quantum	  = TAVOR_CQC_SIZE;
779 	rsrc_pool->rsrc_align	  = (TAVOR_CQC_SIZE * num);
780 	rsrc_pool->rsrc_state	  = state;
781 	rsrc_pool->rsrc_start	  = NULL;
782 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_CQC_VMEM);
783 	entry_info.hwi_num	  = num;
784 	entry_info.hwi_max	  = max;
785 	entry_info.hwi_prealloc	  = num_prealloc;
786 	entry_info.hwi_rsrcpool	  = rsrc_pool;
787 	entry_info.hwi_rsrcname	  = rsrc_name;
788 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
789 	if (status != DDI_SUCCESS) {
790 		tavor_rsrc_fini(state, cleanup);
791 		/* Set "status" and "errormsg" and goto failure */
792 		TAVOR_TNF_FAIL(DDI_FAILURE, "CQC table");
793 		goto rsrcinitp2_fail;
794 	}
795 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL10;
796 
797 	/*
798 	 * Initialize the resource pool for the Extended QPC table entries.
799 	 * Notice that the number of EQPCs must be the same as the number
800 	 * of QP contexts.  So the initialization is constructed in a
801 	 * similar way as above (for TAVOR_QPC).  One notable difference
802 	 * here, however, is that by setting the rsrc_quantum field to
803 	 * zero (indicating a zero-sized object) we indicate that the
804 	 * object is not allocatable.  The EQPC table is, in fact, managed
805 	 * internally by the hardware and it is, therefore, unnecessary to
806 	 * initialize an additional vmem_arena for this type of object.
807 	 */
808 	num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
809 	max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
810 	num_prealloc = 0;
811 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQPC];
812 	rsrc_pool->rsrc_type	  = TAVOR_EQPC;
813 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
814 	rsrc_pool->rsrc_pool_size = (TAVOR_EQPC_SIZE * num);
815 	rsrc_pool->rsrc_shift	  = 0;
816 	rsrc_pool->rsrc_quantum	  = 0;
817 	rsrc_pool->rsrc_align	  = TAVOR_EQPC_SIZE;
818 	rsrc_pool->rsrc_state	  = state;
819 	rsrc_pool->rsrc_start	  = NULL;
820 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_EQPC_VMEM);
821 	entry_info.hwi_num	  = num;
822 	entry_info.hwi_max	  = max;
823 	entry_info.hwi_prealloc	  = num_prealloc;
824 	entry_info.hwi_rsrcpool	  = rsrc_pool;
825 	entry_info.hwi_rsrcname	  = rsrc_name;
826 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
827 	if (status != DDI_SUCCESS) {
828 		tavor_rsrc_fini(state, cleanup);
829 		/* Set "status" and "errormsg" and goto failure */
830 		TAVOR_TNF_FAIL(DDI_FAILURE, "Extended QPC table");
831 		goto rsrcinitp2_fail;
832 	}
833 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL11;
834 
835 	/*
836 	 * Initialize the resource pool for the UD address vector table
837 	 * entries.  Notice that the number of UDAVs is configurable.  The
838 	 * configured value must be less that the maximum value (obtained
839 	 * from the QUERY_DEV_LIM command) or the initialization will fail.
840 	 */
841 	num = ((uint64_t)1 << cfgprof->cp_log_num_ah);
842 	max = ((uint64_t)1 << state->ts_devlim.log_max_av);
843 	num_prealloc = 0;
844 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UDAV];
845 	rsrc_pool->rsrc_type	  = TAVOR_UDAV;
846 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
847 	rsrc_pool->rsrc_pool_size = (TAVOR_UDAV_SIZE * num);
848 	rsrc_pool->rsrc_shift	  = TAVOR_UDAV_SIZE_SHIFT;
849 	rsrc_pool->rsrc_quantum	  = TAVOR_UDAV_SIZE;
850 	rsrc_pool->rsrc_align	  = TAVOR_UDAV_SIZE;
851 	rsrc_pool->rsrc_state	  = state;
852 	rsrc_pool->rsrc_start	  = NULL;
853 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_UDAV_VMEM);
854 	entry_info.hwi_num	  = num;
855 	entry_info.hwi_max	  = max;
856 	entry_info.hwi_prealloc	  = num_prealloc;
857 	entry_info.hwi_rsrcpool	  = rsrc_pool;
858 	entry_info.hwi_rsrcname	  = rsrc_name;
859 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
860 	if (status != DDI_SUCCESS) {
861 		tavor_rsrc_fini(state, cleanup);
862 		/* Set "status" and "errormsg" and goto failure */
863 		TAVOR_TNF_FAIL(DDI_FAILURE, "UDAV table");
864 		goto rsrcinitp2_fail;
865 	}
866 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL12;
867 
868 	/*
869 	 * Initialize the resource pool for the UAR scratch table entries.
870 	 * Notice that the number of UARSCRs is configurable.  The configured
871 	 * value must be less that the maximum value (obtained from the
872 	 * QUERY_DEV_LIM command) or the initialization will fail.
873 	 * Like the EQPCs above, UARSCR objects are not allocatable.  The
874 	 * UARSCR table is also managed internally by the hardware and it
875 	 * is, therefore, unnecessary to initialize an additional vmem_arena
876 	 * for this type of object.  We indicate this by setting the
877 	 * rsrc_quantum field to zero (indicating a zero-sized object).
878 	 */
879 	uarscr_size = state->ts_devlim.uarscr_entry_sz;
880 	num = ((uint64_t)1 << cfgprof->cp_log_num_uar);
881 	max = ((uint64_t)1 << (state->ts_devlim.log_max_uar_sz + 20 -
882 	    PAGESHIFT));
883 	num_prealloc = 0;
884 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UAR_SCR];
885 	rsrc_pool->rsrc_type	  = TAVOR_UAR_SCR;
886 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
887 	rsrc_pool->rsrc_pool_size = (uarscr_size * num);
888 	rsrc_pool->rsrc_shift	  = 0;
889 	rsrc_pool->rsrc_quantum	  = 0;
890 	rsrc_pool->rsrc_align	  = uarscr_size;
891 	rsrc_pool->rsrc_state	  = state;
892 	rsrc_pool->rsrc_start	  = NULL;
893 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_UARSCR_VMEM);
894 	entry_info.hwi_num	  = num;
895 	entry_info.hwi_max	  = max;
896 	entry_info.hwi_prealloc	  = num_prealloc;
897 	entry_info.hwi_rsrcpool	  = rsrc_pool;
898 	entry_info.hwi_rsrcname	  = rsrc_name;
899 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
900 	if (status != DDI_SUCCESS) {
901 		tavor_rsrc_fini(state, cleanup);
902 		/* Set "status" and "errormsg" and goto failure */
903 		TAVOR_TNF_FAIL(DDI_FAILURE, "UAR scratch table");
904 		goto rsrcinitp2_fail;
905 	}
906 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL13;
907 
908 	/*
909 	 * Initialize the resource pool for the SRQC table entries.  Notice
910 	 * that the number of SRQs is configurable.  The configured value must
911 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
912 	 * command) or the initialization will fail.  Note also that a certain
913 	 * number of SRQ contexts must be set aside for Tavor firmware use.
914 	 *
915 	 * Note: We only allocate these resources if SRQ is enabled in the
916 	 * config profile; see below.
917 	 */
918 	num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
919 	max = ((uint64_t)1 << state->ts_devlim.log_max_srq);
920 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_srq);
921 
922 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_SRQC];
923 	rsrc_pool->rsrc_type	  = TAVOR_SRQC;
924 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
925 	rsrc_pool->rsrc_pool_size = (TAVOR_SRQC_SIZE * num);
926 	rsrc_pool->rsrc_shift	  = TAVOR_SRQC_SIZE_SHIFT;
927 	rsrc_pool->rsrc_quantum	  = TAVOR_SRQC_SIZE;
928 	rsrc_pool->rsrc_align	  = (TAVOR_SRQC_SIZE * num);
929 	rsrc_pool->rsrc_state	  = state;
930 	rsrc_pool->rsrc_start	  = NULL;
931 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_SRQC_VMEM);
932 	entry_info.hwi_num	  = num;
933 	entry_info.hwi_max	  = max;
934 	entry_info.hwi_prealloc	  = num_prealloc;
935 	entry_info.hwi_rsrcpool	  = rsrc_pool;
936 	entry_info.hwi_rsrcname	  = rsrc_name;
937 
938 	/*
939 	 * SRQ support is configurable.  Only if SRQ is enabled (the default)
940 	 * do we actually try to configure these resources.  Otherwise, we
941 	 * simply set the cleanup level and continue on to the next resource
942 	 */
943 	if (state->ts_cfg_profile->cp_srq_enable != 0) {
944 		status = tavor_rsrc_hw_entries_init(state, &entry_info);
945 		if (status != DDI_SUCCESS) {
946 			tavor_rsrc_fini(state, cleanup);
947 			/* Set "status" and "errormsg" and goto failure */
948 			TAVOR_TNF_FAIL(DDI_FAILURE, "SRQC table");
949 			goto rsrcinitp2_fail;
950 		}
951 	}
952 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL14;
953 
954 	/*
955 	 * Initialize the resource pool for "In" mailboxes.  Notice that
956 	 * the number of "In" mailboxes, their size, and their location
957 	 * (DDR or system memory) is configurable.  By default, however,
958 	 * all "In" mailboxes are located in system memory only (because
959 	 * they are primarily written to and rarely read from)
960 	 */
961 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_inmbox);
962 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
963 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_IN_MBOX];
964 	rsrc_pool->rsrc_type	  = TAVOR_IN_MBOX;
965 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
966 	rsrc_pool->rsrc_pool_size = (size * num);
967 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
968 	rsrc_pool->rsrc_quantum	  = size;
969 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
970 	rsrc_pool->rsrc_state	  = state;
971 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INMBOX_VMEM);
972 	mbox_info.mbi_num	  = num;
973 	mbox_info.mbi_size	  = size;
974 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
975 	mbox_info.mbi_rsrcname	  = rsrc_name;
976 	status = tavor_rsrc_mbox_init(state, &mbox_info);
977 	if (status != DDI_SUCCESS) {
978 		tavor_rsrc_fini(state, cleanup);
979 		/* Set "status" and "errormsg" and goto failure */
980 		TAVOR_TNF_FAIL(DDI_FAILURE, "in mailboxes");
981 		goto rsrcinitp2_fail;
982 	}
983 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL15;
984 
985 	/*
986 	 * Initialize the Tavor "In" mailbox list.  This step actually uses
987 	 * the tavor_rsrc_alloc() for TAVOR_IN_MBOX to preallocate the
988 	 * "In" mailboxes, bind them for DMA access, and arrange them into
989 	 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
990 	 * for more details)
991 	 */
992 	status = tavor_inmbox_list_init(state);
993 	if (status != DDI_SUCCESS) {
994 		tavor_rsrc_fini(state, cleanup);
995 		/* Set "status" and "errormsg" and goto failure */
996 		TAVOR_TNF_FAIL(DDI_FAILURE, "in mailbox list");
997 		goto rsrcinitp2_fail;
998 	}
999 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL16;
1000 
1001 	/*
1002 	 * Initialize the resource pool for interrupt "In" mailboxes.  Notice
1003 	 * that the number of interrupt "In" mailboxes, their size, and their
1004 	 * location (DDR or system memory) is configurable.  By default,
1005 	 * however, all interrupt "In" mailboxes are located in system memory
1006 	 * only (because they are primarily written to and rarely read from)
1007 	 */
1008 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_inmbox);
1009 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
1010 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_INTR_IN_MBOX];
1011 	rsrc_pool->rsrc_type	  = TAVOR_INTR_IN_MBOX;
1012 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
1013 	rsrc_pool->rsrc_pool_size = (size * num);
1014 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
1015 	rsrc_pool->rsrc_quantum	  = size;
1016 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
1017 	rsrc_pool->rsrc_state	  = state;
1018 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INTR_INMBOX_VMEM);
1019 	mbox_info.mbi_num	  = num;
1020 	mbox_info.mbi_size	  = size;
1021 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
1022 	mbox_info.mbi_rsrcname	  = rsrc_name;
1023 	status = tavor_rsrc_mbox_init(state, &mbox_info);
1024 	if (status != DDI_SUCCESS) {
1025 		tavor_rsrc_fini(state, cleanup);
1026 		/* Set "status" and "errormsg" and goto failure */
1027 		TAVOR_TNF_FAIL(DDI_FAILURE, "in intr mailboxes");
1028 		goto rsrcinitp2_fail;
1029 	}
1030 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL17;
1031 
1032 	/*
1033 	 * Initialize the Tavor interrupt "In" mailbox list.  This step
1034 	 * actually uses the tavor_rsrc_alloc() for TAVOR_IN_MBOX to
1035 	 * preallocate the interrupt "In" mailboxes, bind them for DMA access,
1036 	 * and arrange them into an easily accessed fast-allocation mechanism
1037 	 * (see tavor_cmd.c for more details)
1038 	 */
1039 	status = tavor_intr_inmbox_list_init(state);
1040 	if (status != DDI_SUCCESS) {
1041 		tavor_rsrc_fini(state, cleanup);
1042 		/* Set "status" and "errormsg" and goto failure */
1043 		TAVOR_TNF_FAIL(DDI_FAILURE, "in intr mailbox list");
1044 		goto rsrcinitp2_fail;
1045 	}
1046 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL18;
1047 
1048 	/*
1049 	 * Initialize the Tavor command handling interfaces.  This step
1050 	 * sets up the outstanding command tracking mechanism for easy access
1051 	 * and fast allocation (see tavor_cmd.c for more details).
1052 	 */
1053 	status = tavor_outstanding_cmdlist_init(state);
1054 	if (status != DDI_SUCCESS) {
1055 		tavor_rsrc_fini(state, cleanup);
1056 		/* Set "status" and "errormsg" and goto failure */
1057 		TAVOR_TNF_FAIL(DDI_FAILURE, "outstanding cmd list");
1058 		goto rsrcinitp2_fail;
1059 	}
1060 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL19;
1061 
1062 	/*
1063 	 * Calculate (and validate) the size of Multicast Group (MCG) entries
1064 	 */
1065 	status = tavor_rsrc_mcg_entry_get_size(state, &mcg_size_shift);
1066 	if (status != DDI_SUCCESS) {
1067 		tavor_rsrc_fini(state, cleanup);
1068 		/* Set "status" and "errormsg" and goto failure */
1069 		TAVOR_TNF_FAIL(DDI_FAILURE, "failed get MCG size");
1070 		goto rsrcinitp2_fail;
1071 	}
1072 	mcg_size = TAVOR_MCGMEM_SZ(state);
1073 
1074 	/*
1075 	 * Initialize the resource pool for the MCG table entries.  Notice
1076 	 * that the number of MCGs is configurable.  The configured value must
1077 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
1078 	 * command) or the initialization will fail.  Note also that a certain
1079 	 * number of MCGs must be set aside for Tavor firmware use (they
1080 	 * correspond to the number of MCGs used by the internal hash
1081 	 * function.
1082 	 */
1083 	num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1084 	max = ((uint64_t)1 << state->ts_devlim.log_max_mcg);
1085 	num_prealloc = ((uint64_t)1 << cfgprof->cp_log_num_mcg_hash);
1086 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MCG];
1087 	rsrc_pool->rsrc_type	  = TAVOR_MCG;
1088 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
1089 	rsrc_pool->rsrc_pool_size = (mcg_size * num);
1090 	rsrc_pool->rsrc_shift	  = mcg_size_shift;
1091 	rsrc_pool->rsrc_quantum	  = mcg_size;
1092 	rsrc_pool->rsrc_align	  = mcg_size;
1093 	rsrc_pool->rsrc_state	  = state;
1094 	rsrc_pool->rsrc_start	  = NULL;
1095 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MCG_VMEM);
1096 	entry_info.hwi_num	  = num;
1097 	entry_info.hwi_max	  = max;
1098 	entry_info.hwi_prealloc	  = num_prealloc;
1099 	entry_info.hwi_rsrcpool	  = rsrc_pool;
1100 	entry_info.hwi_rsrcname	  = rsrc_name;
1101 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
1102 	if (status != DDI_SUCCESS) {
1103 		tavor_rsrc_fini(state, cleanup);
1104 		/* Set "status" and "errormsg" and goto failure */
1105 		TAVOR_TNF_FAIL(DDI_FAILURE, "MCG table");
1106 		goto rsrcinitp2_fail;
1107 	}
1108 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL20;
1109 
1110 	/*
1111 	 * Initialize the resource pool for the EQC table entries.  Notice
1112 	 * that the number of EQs is hardcoded.  The hardcoded value should
1113 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
1114 	 * command) or the initialization will fail.
1115 	 */
1116 	num = TAVOR_NUM_EQ;
1117 	max = ((uint64_t)1 << state->ts_devlim.log_max_eq);
1118 	num_prealloc = 0;
1119 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQC];
1120 	rsrc_pool->rsrc_type	  = TAVOR_EQC;
1121 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
1122 	rsrc_pool->rsrc_pool_size = (TAVOR_EQC_SIZE * num);
1123 	rsrc_pool->rsrc_shift	  = TAVOR_EQC_SIZE_SHIFT;
1124 	rsrc_pool->rsrc_quantum	  = TAVOR_EQC_SIZE;
1125 	rsrc_pool->rsrc_align	  = (TAVOR_EQC_SIZE * num);
1126 	rsrc_pool->rsrc_state	  = state;
1127 	rsrc_pool->rsrc_start	  = NULL;
1128 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_EQC_VMEM);
1129 	entry_info.hwi_num	  = num;
1130 	entry_info.hwi_max	  = max;
1131 	entry_info.hwi_prealloc	  = num_prealloc;
1132 	entry_info.hwi_rsrcpool	  = rsrc_pool;
1133 	entry_info.hwi_rsrcname	  = rsrc_name;
1134 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
1135 	if (status != DDI_SUCCESS) {
1136 		tavor_rsrc_fini(state, cleanup);
1137 		/* Set "status" and "errormsg" and goto failure */
1138 		TAVOR_TNF_FAIL(DDI_FAILURE, "EQC table");
1139 		goto rsrcinitp2_fail;
1140 	}
1141 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL21;
1142 
1143 	/*
1144 	 * Initialize the resource pools for all objects that exist in
1145 	 * system memory.  This includes PD handles, MR handle, EQ handles,
1146 	 * QP handles, etc.  These objects are almost entirely managed using
1147 	 * kmem_cache routines.  (See comment above for more detail)
1148 	 */
1149 
1150 	/*
1151 	 * Initialize the resource pool for the PD handles.  Notice
1152 	 * that the number of PDHDLs is configurable.  The configured value
1153 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1154 	 * command) or the initialization will fail.  Note also that the PD
1155 	 * handle has constructor and destructor methods associated with it.
1156 	 */
1157 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_PDHDL];
1158 	rsrc_pool->rsrc_type	 = TAVOR_PDHDL;
1159 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1160 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_pd_s);
1161 	rsrc_pool->rsrc_state	 = state;
1162 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_PDHDL_CACHE);
1163 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_pd);
1164 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_pd);
1165 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1166 	hdl_info.swi_constructor = tavor_rsrc_pdhdl_constructor;
1167 	hdl_info.swi_destructor	 = tavor_rsrc_pdhdl_destructor;
1168 	hdl_info.swi_rsrcname	 = rsrc_name;
1169 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
1170 	status = tavor_rsrc_pd_handles_init(state, &hdl_info);
1171 	if (status != DDI_SUCCESS) {
1172 		tavor_rsrc_fini(state, cleanup);
1173 		/* Set "status" and "errormsg" and goto failure */
1174 		TAVOR_TNF_FAIL(DDI_FAILURE, "PD handle");
1175 		goto rsrcinitp2_fail;
1176 	}
1177 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL22;
1178 
1179 	/*
1180 	 * Initialize the resource pool for the MR handles.  Notice
1181 	 * that the number of MRHDLs is configurable.  The configured value
1182 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1183 	 * command) or the initialization will fail.
1184 	 */
1185 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MRHDL];
1186 	rsrc_pool->rsrc_type	 = TAVOR_MRHDL;
1187 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1188 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_mr_s);
1189 	rsrc_pool->rsrc_state	 = state;
1190 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_MRHDL_CACHE);
1191 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
1192 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
1193 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1194 	hdl_info.swi_constructor = tavor_rsrc_mrhdl_constructor;
1195 	hdl_info.swi_destructor	 = tavor_rsrc_mrhdl_destructor;
1196 	hdl_info.swi_rsrcname	 = rsrc_name;
1197 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
1198 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1199 	if (status != DDI_SUCCESS) {
1200 		tavor_rsrc_fini(state, cleanup);
1201 		/* Set "status" and "errormsg" and goto failure */
1202 		TAVOR_TNF_FAIL(DDI_FAILURE, "MR handle");
1203 		goto rsrcinitp2_fail;
1204 	}
1205 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL23;
1206 
1207 	/*
1208 	 * Initialize the resource pool for the EQ handles.  Notice
1209 	 * that the number of EQHDLs is hardcoded.  The hardcoded value
1210 	 * should be less that the maximum value (obtained from the
1211 	 * QUERY_DEV_LIM command) or the initialization will fail.
1212 	 */
1213 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQHDL];
1214 	rsrc_pool->rsrc_type	 = TAVOR_EQHDL;
1215 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1216 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_eq_s);
1217 	rsrc_pool->rsrc_state	 = state;
1218 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_EQHDL_CACHE);
1219 	hdl_info.swi_num = TAVOR_NUM_EQ;
1220 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_eq);
1221 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1222 	hdl_info.swi_constructor = NULL;
1223 	hdl_info.swi_destructor	 = NULL;
1224 	hdl_info.swi_rsrcname	 = rsrc_name;
1225 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
1226 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1227 	if (status != DDI_SUCCESS) {
1228 		tavor_rsrc_fini(state, cleanup);
1229 		/* Set "status" and "errormsg" and goto failure */
1230 		TAVOR_TNF_FAIL(DDI_FAILURE, "EQ handle");
1231 		goto rsrcinitp2_fail;
1232 	}
1233 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL24;
1234 
1235 	/*
1236 	 * Initialize the resource pool for the CQ handles.  Notice
1237 	 * that the number of CQHDLs is configurable.  The configured value
1238 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1239 	 * command) or the initialization will fail.  Note also that the CQ
1240 	 * handle has constructor and destructor methods associated with it.
1241 	 */
1242 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_CQHDL];
1243 	rsrc_pool->rsrc_type	 = TAVOR_CQHDL;
1244 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1245 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_cq_s);
1246 	rsrc_pool->rsrc_state	 = state;
1247 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_CQHDL_CACHE);
1248 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
1249 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_cq);
1250 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1251 	hdl_info.swi_constructor = tavor_rsrc_cqhdl_constructor;
1252 	hdl_info.swi_destructor	 = tavor_rsrc_cqhdl_destructor;
1253 	hdl_info.swi_rsrcname	 = rsrc_name;
1254 	hdl_info.swi_flags	 = (TAVOR_SWHDL_KMEMCACHE_INIT |
1255 	    TAVOR_SWHDL_TABLE_INIT);
1256 	hdl_info.swi_prealloc_sz = sizeof (tavor_cqhdl_t);
1257 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1258 	if (status != DDI_SUCCESS) {
1259 		tavor_rsrc_fini(state, cleanup);
1260 		/* Set "status" and "errormsg" and goto failure */
1261 		TAVOR_TNF_FAIL(DDI_FAILURE, "CQ handle");
1262 		goto rsrcinitp2_fail;
1263 	}
1264 
1265 	/*
1266 	 * Save away the pointer to the central list of CQ handle pointers
1267 	 * This this is used as a mechanism to enable fast CQnumber-to-CQhandle
1268 	 * lookup during EQ event processing.  The table is a list of
1269 	 * tavor_cqhdl_t allocated by the above routine because of the
1270 	 * TAVOR_SWHDL_TABLE_INIT flag.  The table has as many tavor_cqhdl_t
1271 	 * as the number of CQs.
1272 	 */
1273 	state->ts_cqhdl = hdl_info.swi_table_ptr;
1274 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL25;
1275 
1276 	/*
1277 	 * Initialize the resource pool for the SRQ handles.  Notice
1278 	 * that the number of SRQHDLs is configurable.  The configured value
1279 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1280 	 * command) or the initialization will fail.  Note also that the SRQ
1281 	 * handle has constructor and destructor methods associated with it.
1282 	 *
1283 	 * Note: We only allocate these resources if SRQ is enabled in the
1284 	 * config profile; see below.
1285 	 */
1286 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_SRQHDL];
1287 	rsrc_pool->rsrc_type	 = TAVOR_SRQHDL;
1288 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1289 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_srq_s);
1290 	rsrc_pool->rsrc_state	 = state;
1291 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_SRQHDL_CACHE);
1292 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
1293 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_srq);
1294 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1295 	hdl_info.swi_constructor = tavor_rsrc_srqhdl_constructor;
1296 	hdl_info.swi_destructor	 = tavor_rsrc_srqhdl_destructor;
1297 	hdl_info.swi_rsrcname	 = rsrc_name;
1298 	hdl_info.swi_flags	 = (TAVOR_SWHDL_KMEMCACHE_INIT |
1299 	    TAVOR_SWHDL_TABLE_INIT);
1300 	hdl_info.swi_prealloc_sz = sizeof (tavor_srqhdl_t);
1301 
1302 	/*
1303 	 * SRQ support is configurable.  Only if SRQ is enabled (the default)
1304 	 * do we actually try to configure these resources.  Otherwise, we
1305 	 * simply set the cleanup level and continue on to the next resource
1306 	 */
1307 	if (state->ts_cfg_profile->cp_srq_enable != 0) {
1308 		status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1309 		if (status != DDI_SUCCESS) {
1310 			tavor_rsrc_fini(state, cleanup);
1311 			/* Set "status" and "errormsg" and goto failure */
1312 			TAVOR_TNF_FAIL(DDI_FAILURE, "SRQ handle");
1313 			goto rsrcinitp2_fail;
1314 		}
1315 
1316 		/*
1317 		 * Save away the pointer to the central list of SRQ handle
1318 		 * pointers This this is used as a mechanism to enable fast
1319 		 * SRQnumber-to-SRQhandle lookup.  The table is a list of
1320 		 * tavor_srqhdl_t allocated by the above routine because of the
1321 		 * TAVOR_SWHDL_TABLE_INIT flag.  The table has as many
1322 		 * tavor_srqhdl_t as the number of SRQs.
1323 		 */
1324 		state->ts_srqhdl = hdl_info.swi_table_ptr;
1325 	}
1326 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL26;
1327 
1328 	/*
1329 	 * Initialize the resource pool for the address handles.  Notice
1330 	 * that the number of AHHDLs is configurable.  The configured value
1331 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1332 	 * command) or the initialization will fail.
1333 	 */
1334 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_AHHDL];
1335 	rsrc_pool->rsrc_type	 = TAVOR_AHHDL;
1336 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1337 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_ah_s);
1338 	rsrc_pool->rsrc_state	 = state;
1339 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_AHHDL_CACHE);
1340 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_ah);
1341 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_av);
1342 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1343 	hdl_info.swi_constructor = tavor_rsrc_ahhdl_constructor;
1344 	hdl_info.swi_destructor	 = tavor_rsrc_ahhdl_destructor;
1345 	hdl_info.swi_rsrcname	 = rsrc_name;
1346 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
1347 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1348 	if (status != DDI_SUCCESS) {
1349 		tavor_rsrc_fini(state, cleanup);
1350 		/* Set "status" and "errormsg" and goto failure */
1351 		TAVOR_TNF_FAIL(DDI_FAILURE, "AH handle");
1352 		goto rsrcinitp2_fail;
1353 	}
1354 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL27;
1355 
1356 	/*
1357 	 * Initialize the resource pool for the QP handles.  Notice
1358 	 * that the number of QPHDLs is configurable.  The configured value
1359 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1360 	 * command) or the initialization will fail.  Note also that the QP
1361 	 * handle has constructor and destructor methods associated with it.
1362 	 */
1363 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_QPHDL];
1364 	rsrc_pool->rsrc_type	 = TAVOR_QPHDL;
1365 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1366 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_qp_s);
1367 	rsrc_pool->rsrc_state	 = state;
1368 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_QPHDL_CACHE);
1369 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
1370 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
1371 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1372 	hdl_info.swi_constructor = tavor_rsrc_qphdl_constructor;
1373 	hdl_info.swi_destructor	 = tavor_rsrc_qphdl_destructor;
1374 	hdl_info.swi_rsrcname	 = rsrc_name;
1375 	hdl_info.swi_flags	 = (TAVOR_SWHDL_KMEMCACHE_INIT |
1376 	    TAVOR_SWHDL_TABLE_INIT);
1377 	hdl_info.swi_prealloc_sz = sizeof (tavor_qphdl_t);
1378 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1379 	if (status != DDI_SUCCESS) {
1380 		tavor_rsrc_fini(state, cleanup);
1381 		/* Set "status" and "errormsg" and goto failure */
1382 		TAVOR_TNF_FAIL(DDI_FAILURE, "QP handle");
1383 		goto rsrcinitp2_fail;
1384 	}
1385 
1386 	/*
1387 	 * Save away the pointer to the central list of QP handle pointers
1388 	 * This this is used as a mechanism to enable fast QPnumber-to-QPhandle
1389 	 * lookup during CQ event processing.  The table is a list of
1390 	 * tavor_qphdl_t allocated by the above routine because of the
1391 	 * TAVOR_SWHDL_TABLE_INIT flag.  The table has as many tavor_qphdl_t
1392 	 * as the number of QPs.
1393 	 */
1394 	state->ts_qphdl = hdl_info.swi_table_ptr;
1395 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL28;
1396 
1397 	/*
1398 	 * Initialize the resource pool for the reference count handles.
1399 	 * Notice that the number of REFCNTs is configurable, but it's value
1400 	 * is set to the number of MPTs.  Since REFCNTs are used to support
1401 	 * shared memory regions, it is possible that we might require as
1402 	 * one REFCNT for every MPT.
1403 	 */
1404 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_REFCNT];
1405 	rsrc_pool->rsrc_type	 = TAVOR_REFCNT;
1406 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
1407 	rsrc_pool->rsrc_quantum	 = sizeof (tavor_sw_refcnt_t);
1408 	rsrc_pool->rsrc_state	 = state;
1409 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_REFCNT_CACHE);
1410 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
1411 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
1412 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1413 	hdl_info.swi_constructor = tavor_rsrc_refcnt_constructor;
1414 	hdl_info.swi_destructor	 = tavor_rsrc_refcnt_destructor;
1415 	hdl_info.swi_rsrcname	 = rsrc_name;
1416 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
1417 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1418 	if (status != DDI_SUCCESS) {
1419 		tavor_rsrc_fini(state, cleanup);
1420 		/* Set "status" and "errormsg" and goto failure */
1421 		TAVOR_TNF_FAIL(DDI_FAILURE, "reference count handle");
1422 		goto rsrcinitp2_fail;
1423 	}
1424 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL29;
1425 
1426 	/*
1427 	 * Initialize the resource pool for the MCG handles.  Notice that for
1428 	 * these MCG handles, we are allocating a table of structures (used to
1429 	 * keep track of the MCG entries that are being written to hardware
1430 	 * and to speed up multicast attach/detach operations).
1431 	 */
1432 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1433 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mcg);
1434 	hdl_info.swi_flags = TAVOR_SWHDL_TABLE_INIT;
1435 	hdl_info.swi_prealloc_sz = sizeof (struct tavor_sw_mcg_list_s);
1436 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1437 	if (status != DDI_SUCCESS) {
1438 		tavor_rsrc_fini(state, cleanup);
1439 		/* Set "status" and "errormsg" and goto failure */
1440 		TAVOR_TNF_FAIL(DDI_FAILURE, "MCG handle");
1441 		goto rsrcinitp2_fail;
1442 	}
1443 	state->ts_mcghdl = hdl_info.swi_table_ptr;
1444 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL30;
1445 
1446 	/*
1447 	 * Initialize the resource pools for all objects that exist in
1448 	 * UAR memory.  The only objects that are allocated from UAR memory
1449 	 * are the UAR pages which are used for holding Tavor hardware's
1450 	 * doorbell registers.
1451 	 */
1452 
1453 	/*
1454 	 * Initialize the resource pool for the UAR pages.  Notice
1455 	 * that the number of UARPGs is configurable.  The configured value
1456 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1457 	 * command) or the initialization will fail.  Note also that by
1458 	 * specifying the rsrc_start parameter in advance, we direct the
1459 	 * initialization routine not to attempt to allocated space from the
1460 	 * Tavor DDR vmem_arena.
1461 	 */
1462 	num  = ((uint64_t)1 << cfgprof->cp_log_num_uar);
1463 	max  = ((uint64_t)1 << (state->ts_devlim.log_max_uar_sz + 20 -
1464 	    PAGESHIFT));
1465 	num_prealloc = 0;
1466 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UARPG];
1467 	rsrc_pool->rsrc_type	  = TAVOR_UARPG;
1468 	rsrc_pool->rsrc_loc	  = TAVOR_IN_UAR;
1469 	rsrc_pool->rsrc_pool_size = (num << PAGESHIFT);
1470 	rsrc_pool->rsrc_shift	  = PAGESHIFT;
1471 	rsrc_pool->rsrc_quantum	  = PAGESIZE;
1472 	rsrc_pool->rsrc_align	  = PAGESIZE;
1473 	rsrc_pool->rsrc_state	  = state;
1474 	rsrc_pool->rsrc_start	  = (void *)state->ts_reg_uar_baseaddr;
1475 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_UAR_VMEM);
1476 	entry_info.hwi_num	  = num;
1477 	entry_info.hwi_max	  = max;
1478 	entry_info.hwi_prealloc	  = num_prealloc;
1479 	entry_info.hwi_rsrcpool	  = rsrc_pool;
1480 	entry_info.hwi_rsrcname	  = rsrc_name;
1481 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
1482 	if (status != DDI_SUCCESS) {
1483 		tavor_rsrc_fini(state, cleanup);
1484 		/* Set "status" and "errormsg" and goto failure */
1485 		TAVOR_TNF_FAIL(DDI_FAILURE, "UAR page table");
1486 		goto rsrcinitp2_fail;
1487 	}
1488 	cleanup = TAVOR_RSRC_CLEANUP_ALL;
1489 
1490 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
1491 	TAVOR_TNF_EXIT(tavor_rsrc_init_phase2);
1492 	return (DDI_SUCCESS);
1493 
1494 rsrcinitp2_fail:
1495 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
1496 	TNF_PROBE_1(tavor_rsrc_init_phase2_fail, TAVOR_TNF_ERROR, "",
1497 	    tnf_string, msg, errormsg);
1498 	TAVOR_TNF_EXIT(tavor_rsrc_init_phase2);
1499 	return (status);
1500 }
1501 
1502 
1503 /*
1504  * tavor_rsrc_fini()
1505  *    Context: Only called from attach() and/or detach() path contexts
1506  */
1507 void
1508 tavor_rsrc_fini(tavor_state_t *state, tavor_rsrc_cleanup_level_t clean)
1509 {
1510 	tavor_rsrc_sw_hdl_info_t	hdl_info;
1511 	tavor_rsrc_hw_entry_info_t	entry_info;
1512 	tavor_rsrc_mbox_info_t		mbox_info;
1513 	tavor_cfg_profile_t		*cfgprof;
1514 
1515 	TAVOR_TNF_ENTER(tavor_rsrc_fini);
1516 
1517 	ASSERT(state != NULL);
1518 
1519 	cfgprof = state->ts_cfg_profile;
1520 
1521 	switch (clean) {
1522 	/*
1523 	 * If we add more resources that need to be cleaned up here, we should
1524 	 * ensure that TAVOR_RSRC_CLEANUP_ALL is still the first entry (i.e.
1525 	 * corresponds to the last resource allocated).
1526 	 */
1527 	case TAVOR_RSRC_CLEANUP_ALL:
1528 		/* Cleanup the UAR page resource pool */
1529 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UARPG];
1530 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1531 		/* FALLTHROUGH */
1532 
1533 	case TAVOR_RSRC_CLEANUP_LEVEL30:
1534 		/* Cleanup the central MCG handle pointers list */
1535 		hdl_info.swi_rsrcpool  = NULL;
1536 		hdl_info.swi_table_ptr = state->ts_mcghdl;
1537 		hdl_info.swi_num =
1538 		    ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1539 		hdl_info.swi_prealloc_sz = sizeof (struct tavor_sw_mcg_list_s);
1540 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
1541 		/* FALLTHROUGH */
1542 
1543 	case TAVOR_RSRC_CLEANUP_LEVEL29:
1544 		/* Cleanup the reference count resource pool */
1545 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_REFCNT];
1546 		hdl_info.swi_table_ptr = NULL;
1547 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
1548 		/* FALLTHROUGH */
1549 
1550 	case TAVOR_RSRC_CLEANUP_LEVEL28:
1551 		/* Cleanup the QP handle resource pool */
1552 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_QPHDL];
1553 		hdl_info.swi_table_ptr = state->ts_qphdl;
1554 		hdl_info.swi_num =
1555 		    ((uint64_t)1 << cfgprof->cp_log_num_qp);
1556 		hdl_info.swi_prealloc_sz = sizeof (tavor_qphdl_t);
1557 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
1558 		/* FALLTHROUGH */
1559 
1560 	case TAVOR_RSRC_CLEANUP_LEVEL27:
1561 		/* Cleanup the address handle resource pool */
1562 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_AHHDL];
1563 		hdl_info.swi_table_ptr = NULL;
1564 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
1565 		/* FALLTHROUGH */
1566 
1567 	case TAVOR_RSRC_CLEANUP_LEVEL26:
1568 		/*
1569 		 * Cleanup the SRQ handle resource pool.
1570 		 *
1571 		 * Note: We only clean up if SRQ is enabled.  Otherwise we
1572 		 * simply fallthrough to the next resource cleanup.
1573 		 */
1574 		if (state->ts_cfg_profile->cp_srq_enable != 0) {
1575 			hdl_info.swi_rsrcpool  =
1576 			    &state->ts_rsrc_hdl[TAVOR_SRQHDL];
1577 			hdl_info.swi_table_ptr = state->ts_srqhdl;
1578 			hdl_info.swi_num =
1579 			    ((uint64_t)1 << cfgprof->cp_log_num_srq);
1580 			hdl_info.swi_prealloc_sz = sizeof (tavor_srqhdl_t);
1581 			tavor_rsrc_sw_handles_fini(state, &hdl_info);
1582 		}
1583 		/* FALLTHROUGH */
1584 
1585 	case TAVOR_RSRC_CLEANUP_LEVEL25:
1586 		/* Cleanup the CQ handle resource pool */
1587 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_CQHDL];
1588 		hdl_info.swi_table_ptr = state->ts_cqhdl;
1589 		hdl_info.swi_num =
1590 		    ((uint64_t)1 << cfgprof->cp_log_num_cq);
1591 		hdl_info.swi_prealloc_sz = sizeof (tavor_cqhdl_t);
1592 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
1593 		/* FALLTHROUGH */
1594 
1595 	case TAVOR_RSRC_CLEANUP_LEVEL24:
1596 		/* Cleanup the EQ handle resource pool */
1597 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_EQHDL];
1598 		hdl_info.swi_table_ptr = NULL;
1599 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
1600 		/* FALLTHROUGH */
1601 
1602 	case TAVOR_RSRC_CLEANUP_LEVEL23:
1603 		/* Cleanup the MR handle resource pool */
1604 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_MRHDL];
1605 		hdl_info.swi_table_ptr = NULL;
1606 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
1607 		/* FALLTHROUGH */
1608 
1609 	case TAVOR_RSRC_CLEANUP_LEVEL22:
1610 		/* Cleanup the PD handle resource pool */
1611 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_PDHDL];
1612 		hdl_info.swi_table_ptr = NULL;
1613 		tavor_rsrc_pd_handles_fini(state, &hdl_info);
1614 		/* FALLTHROUGH */
1615 
1616 	case TAVOR_RSRC_CLEANUP_LEVEL21:
1617 		/* Cleanup the EQC table resource pool */
1618 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_EQC];
1619 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1620 		/* FALLTHROUGH */
1621 
1622 	case TAVOR_RSRC_CLEANUP_LEVEL20:
1623 		/* Cleanup the MCG table resource pool */
1624 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MCG];
1625 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1626 		/* FALLTHROUGH */
1627 
1628 	case TAVOR_RSRC_CLEANUP_LEVEL19:
1629 		/* Cleanup the outstanding command list  */
1630 		tavor_outstanding_cmdlist_fini(state);
1631 		/* FALLTHROUGH */
1632 
1633 	case TAVOR_RSRC_CLEANUP_LEVEL18:
1634 		/* Cleanup the "In" mailbox list  */
1635 		tavor_intr_inmbox_list_fini(state);
1636 		/* FALLTHROUGH */
1637 
1638 	case TAVOR_RSRC_CLEANUP_LEVEL17:
1639 		/* Cleanup the interrupt "In" mailbox resource pool */
1640 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[
1641 		    TAVOR_INTR_IN_MBOX];
1642 		tavor_rsrc_mbox_fini(state, &mbox_info);
1643 		/* FALLTHROUGH */
1644 
1645 	case TAVOR_RSRC_CLEANUP_LEVEL16:
1646 		/* Cleanup the "In" mailbox list  */
1647 		tavor_inmbox_list_fini(state);
1648 		/* FALLTHROUGH */
1649 
1650 	case TAVOR_RSRC_CLEANUP_LEVEL15:
1651 		/* Cleanup the "In" mailbox resource pool */
1652 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_IN_MBOX];
1653 		tavor_rsrc_mbox_fini(state, &mbox_info);
1654 		/* FALLTHROUGH */
1655 
1656 	case TAVOR_RSRC_CLEANUP_LEVEL14:
1657 		/*
1658 		 * Cleanup the SRQC table resource pool.
1659 		 *
1660 		 * Note: We only clean up if SRQ is enabled.  Otherwise we
1661 		 * simply fallthrough to the next resource cleanup.
1662 		 */
1663 		if (state->ts_cfg_profile->cp_srq_enable != 0) {
1664 			entry_info.hwi_rsrcpool =
1665 			    &state->ts_rsrc_hdl[TAVOR_SRQC];
1666 			tavor_rsrc_hw_entries_fini(state, &entry_info);
1667 		}
1668 		/* FALLTHROUGH */
1669 
1670 	case TAVOR_RSRC_CLEANUP_LEVEL13:
1671 		/* Cleanup the UAR scratch table resource pool */
1672 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UAR_SCR];
1673 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1674 		/* FALLTHROUGH */
1675 
1676 	case TAVOR_RSRC_CLEANUP_LEVEL12:
1677 		/* Cleanup the UDAV table resource pool */
1678 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UDAV];
1679 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1680 		/* FALLTHROUGH */
1681 
1682 	case TAVOR_RSRC_CLEANUP_LEVEL11:
1683 		/* Cleanup the EQPC table resource pool */
1684 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_EQPC];
1685 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1686 		/* FALLTHROUGH */
1687 
1688 	case TAVOR_RSRC_CLEANUP_LEVEL10:
1689 		/* Cleanup the CQC table resource pool */
1690 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_CQC];
1691 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1692 		/* FALLTHROUGH */
1693 
1694 	case TAVOR_RSRC_CLEANUP_LEVEL9:
1695 		/* Cleanup the RDB table resource pool */
1696 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_RDB];
1697 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1698 		/* FALLTHROUGH */
1699 
1700 	case TAVOR_RSRC_CLEANUP_LEVEL8:
1701 		/* Cleanup the QPC table resource pool */
1702 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_QPC];
1703 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1704 		/* FALLTHROUGH */
1705 
1706 	case TAVOR_RSRC_CLEANUP_LEVEL7:
1707 		/* Cleanup the MTT table resource pool */
1708 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MTT];
1709 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1710 		/* FALLTHROUGH */
1711 
1712 	case TAVOR_RSRC_CLEANUP_LEVEL6:
1713 		/* Cleanup the MPT table resource pool */
1714 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MPT];
1715 		tavor_rsrc_hw_entries_fini(state, &entry_info);
1716 		/* FALLTHROUGH */
1717 
1718 	case TAVOR_RSRC_CLEANUP_LEVEL5:
1719 		/* Destroy the vmem arena for DDR memory */
1720 		vmem_destroy(state->ts_ddrvmem);
1721 		break;
1722 
1723 	/*
1724 	 * The cleanup below comes from the "Phase 1" initialization step.
1725 	 * (see tavor_rsrc_init_phase1() above)
1726 	 */
1727 	case TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE:
1728 		/* Cleanup the interrupt "Out" mailbox list  */
1729 		tavor_intr_outmbox_list_fini(state);
1730 		/* FALLTHROUGH */
1731 
1732 	case TAVOR_RSRC_CLEANUP_LEVEL3:
1733 		/* Cleanup the "Out" mailbox resource pool */
1734 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[
1735 		    TAVOR_INTR_OUT_MBOX];
1736 		tavor_rsrc_mbox_fini(state, &mbox_info);
1737 		/* FALLTHROUGH */
1738 
1739 	case TAVOR_RSRC_CLEANUP_LEVEL2:
1740 		/* Cleanup the "Out" mailbox list  */
1741 		tavor_outmbox_list_fini(state);
1742 		/* FALLTHROUGH */
1743 
1744 	case TAVOR_RSRC_CLEANUP_LEVEL1:
1745 		/* Cleanup the "Out" mailbox resource pool */
1746 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_OUT_MBOX];
1747 		tavor_rsrc_mbox_fini(state, &mbox_info);
1748 		/* FALLTHROUGH */
1749 
1750 	case TAVOR_RSRC_CLEANUP_LEVEL0:
1751 		/* Free the array of tavor_rsrc_pool_info_t's */
1752 		kmem_free(state->ts_rsrc_hdl, TAVOR_NUM_RESOURCES *
1753 		    sizeof (tavor_rsrc_pool_info_t));
1754 		kmem_cache_destroy(state->ts_rsrc_cache);
1755 		break;
1756 
1757 	default:
1758 		TAVOR_WARNING(state, "unexpected resource cleanup level");
1759 		TNF_PROBE_0(tavor_rsrc_fini_default_fail, TAVOR_TNF_ERROR, "");
1760 		TAVOR_TNF_EXIT(tavor_rsrc_fini);
1761 		return;
1762 	}
1763 
1764 	TAVOR_TNF_EXIT(tavor_rsrc_fini);
1765 }
1766 
1767 
1768 /*
1769  * tavor_rsrc_mbox_init()
1770  *    Context: Only called from attach() path context
1771  */
1772 static int
1773 tavor_rsrc_mbox_init(tavor_state_t *state, tavor_rsrc_mbox_info_t *info)
1774 {
1775 	tavor_rsrc_pool_info_t	*rsrc_pool;
1776 	tavor_rsrc_priv_mbox_t	*priv;
1777 	vmem_t			*vmp;
1778 	uint64_t		offset;
1779 	uint_t			dma_xfer_mode;
1780 
1781 	TAVOR_TNF_ENTER(tavor_rsrc_mbox_init);
1782 
1783 	ASSERT(state != NULL);
1784 	ASSERT(info != NULL);
1785 
1786 	rsrc_pool = info->mbi_rsrcpool;
1787 	ASSERT(rsrc_pool != NULL);
1788 
1789 	dma_xfer_mode = state->ts_cfg_profile->cp_streaming_consistent;
1790 
1791 	/* Allocate and initialize mailbox private structure */
1792 	priv = kmem_zalloc(sizeof (tavor_rsrc_priv_mbox_t), KM_SLEEP);
1793 	priv->pmb_dip		= state->ts_dip;
1794 	priv->pmb_acchdl	= state->ts_reg_ddrhdl;
1795 	priv->pmb_devaccattr	= state->ts_reg_accattr;
1796 	priv->pmb_xfer_mode	= dma_xfer_mode;
1797 
1798 	/*
1799 	 * Initialize many of the default DMA attributes.  Then set alignment
1800 	 * and scatter-gather restrictions specific for mailbox memory.
1801 	 */
1802 	tavor_dma_attr_init(&priv->pmb_dmaattr);
1803 	priv->pmb_dmaattr.dma_attr_align  = TAVOR_MBOX_ALIGN;
1804 	priv->pmb_dmaattr.dma_attr_sgllen = 1;
1805 
1806 	rsrc_pool->rsrc_private = priv;
1807 
1808 	/* Is object in DDR memory or system memory? */
1809 	if (rsrc_pool->rsrc_loc == TAVOR_IN_DDR) {
1810 		rsrc_pool->rsrc_ddr_offset = vmem_xalloc(state->ts_ddrvmem,
1811 		    rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_align,
1812 		    0, 0, NULL, NULL, VM_SLEEP);
1813 		if (rsrc_pool->rsrc_ddr_offset == NULL) {
1814 			/* Unable to alloc space for mailboxes */
1815 			kmem_free(priv, sizeof (tavor_rsrc_priv_mbox_t));
1816 			TNF_PROBE_0(tavor_rsrc_mbox_init_vma_fail,
1817 			    TAVOR_TNF_ERROR, "");
1818 			TAVOR_TNF_EXIT(tavor_rsrc_mbox_init);
1819 			return (DDI_FAILURE);
1820 		}
1821 
1822 		/* Calculate offset and starting point (in DDR) */
1823 		offset = ((uintptr_t)rsrc_pool->rsrc_ddr_offset -
1824 		    state->ts_ddr.ddr_baseaddr);
1825 		rsrc_pool->rsrc_start =
1826 		    (void *)(uintptr_t)((uintptr_t)state->ts_reg_ddr_baseaddr +
1827 		    offset);
1828 
1829 		/* Create new vmem arena for the mailboxes */
1830 		vmp = vmem_create(info->mbi_rsrcname,
1831 		    rsrc_pool->rsrc_ddr_offset, rsrc_pool->rsrc_pool_size,
1832 		    rsrc_pool->rsrc_quantum, NULL, NULL, NULL, 0, VM_SLEEP);
1833 		if (vmp == NULL) {
1834 			/* Unable to create vmem arena */
1835 			vmem_xfree(state->ts_ddrvmem,
1836 			    rsrc_pool->rsrc_ddr_offset,
1837 			    rsrc_pool->rsrc_pool_size);
1838 			kmem_free(priv, sizeof (tavor_rsrc_priv_mbox_t));
1839 			TNF_PROBE_0(tavor_rsrc_mbox_init_vmem_create_fail,
1840 			    TAVOR_TNF_ERROR, "");
1841 			TAVOR_TNF_EXIT(tavor_rsrc_mbox_init);
1842 			return (DDI_FAILURE);
1843 		}
1844 		rsrc_pool->rsrc_vmp = vmp;
1845 	} else {
1846 		rsrc_pool->rsrc_ddr_offset = NULL;
1847 		rsrc_pool->rsrc_start = NULL;
1848 		rsrc_pool->rsrc_vmp = NULL;
1849 	}
1850 
1851 	TAVOR_TNF_EXIT(tavor_rsrc_mbox_init);
1852 	return (DDI_SUCCESS);
1853 }
1854 
1855 
1856 /*
1857  * tavor_rsrc_mbox_fini()
1858  *    Context: Only called from attach() and/or detach() path contexts
1859  */
1860 static void
1861 tavor_rsrc_mbox_fini(tavor_state_t *state, tavor_rsrc_mbox_info_t *info)
1862 {
1863 	tavor_rsrc_pool_info_t	*rsrc_pool;
1864 
1865 	TAVOR_TNF_ENTER(tavor_rsrc_mbox_fini);
1866 
1867 	ASSERT(state != NULL);
1868 	ASSERT(info != NULL);
1869 
1870 	rsrc_pool = info->mbi_rsrcpool;
1871 	ASSERT(rsrc_pool != NULL);
1872 
1873 	/* If mailboxes are DDR memory, then destroy and free up vmem */
1874 	if (rsrc_pool->rsrc_loc == TAVOR_IN_DDR) {
1875 
1876 		/* Destroy the specially created mbox vmem arena */
1877 		vmem_destroy(rsrc_pool->rsrc_vmp);
1878 
1879 		/* Free up the region from the ddr_vmem arena */
1880 		vmem_xfree(state->ts_ddrvmem, rsrc_pool->rsrc_ddr_offset,
1881 		    rsrc_pool->rsrc_pool_size);
1882 	}
1883 
1884 	/* Free up the private struct */
1885 	kmem_free(rsrc_pool->rsrc_private, sizeof (tavor_rsrc_priv_mbox_t));
1886 
1887 	TAVOR_TNF_EXIT(tavor_rsrc_mbox_fini);
1888 }
1889 
1890 
1891 /*
1892  * tavor_rsrc_hw_entries_init()
1893  *    Context: Only called from attach() path context
1894  */
1895 static int
1896 tavor_rsrc_hw_entries_init(tavor_state_t *state,
1897     tavor_rsrc_hw_entry_info_t *info)
1898 {
1899 	tavor_rsrc_pool_info_t	*rsrc_pool;
1900 	tavor_rsrc_t		*rsvd_rsrc = NULL;
1901 	vmem_t			*vmp;
1902 	uint64_t		num_hwentry, max_hwentry, num_prealloc;
1903 	uint64_t		offset;
1904 	int			status;
1905 
1906 	TAVOR_TNF_ENTER(tavor_rsrc_hw_entries_init);
1907 
1908 	ASSERT(state != NULL);
1909 	ASSERT(info != NULL);
1910 
1911 	rsrc_pool	= info->hwi_rsrcpool;
1912 	ASSERT(rsrc_pool != NULL);
1913 	num_hwentry	= info->hwi_num;
1914 	max_hwentry	= info->hwi_max;
1915 	num_prealloc	= info->hwi_prealloc;
1916 
1917 	/* Make sure number of HW entries makes sense */
1918 	if (num_hwentry > max_hwentry) {
1919 		TNF_PROBE_2(tavor_rsrc_hw_entries_init_toomany_fail,
1920 		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of HW "
1921 		    "entries exceeds device maximum", tnf_uint, maxhw,
1922 		    max_hwentry);
1923 		TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
1924 		return (DDI_FAILURE);
1925 	}
1926 
1927 	/*
1928 	 * Determine if we need to allocate DDR space to set up the
1929 	 * "rsrc_start" pointer.  Not necessary if "rsrc_start" has already
1930 	 * been initialized (as is the case for the UAR page init).
1931 	 */
1932 	if (rsrc_pool->rsrc_start == NULL) {
1933 		/* Make sure HW entries table is aligned as specified */
1934 		rsrc_pool->rsrc_ddr_offset = vmem_xalloc(state->ts_ddrvmem,
1935 		    rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_align,
1936 		    0, 0, NULL, NULL, VM_NOSLEEP | VM_FIRSTFIT);
1937 		if (rsrc_pool->rsrc_ddr_offset == NULL) {
1938 			/* Unable to alloc space for aligned HW table */
1939 			TNF_PROBE_0(tavor_rsrc_hw_entry_table_vmxalloc_fail,
1940 			    TAVOR_TNF_ERROR, "");
1941 			TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
1942 			return (DDI_FAILURE);
1943 		}
1944 
1945 		/* Calculate offset and starting point (in DDR) */
1946 		offset = ((uintptr_t)rsrc_pool->rsrc_ddr_offset -
1947 		    state->ts_ddr.ddr_baseaddr);
1948 		rsrc_pool->rsrc_start =
1949 		    (void *)(uintptr_t)((uintptr_t)state->ts_reg_ddr_baseaddr +
1950 		    offset);
1951 	} else {
1952 		rsrc_pool->rsrc_ddr_offset = rsrc_pool->rsrc_start;
1953 	}
1954 
1955 	/*
1956 	 * Create new vmem arena for the HW entries table (if rsrc_quantum
1957 	 * is non-zero).  Otherwise if rsrc_quantum is zero, then these HW
1958 	 * entries are not going to be dynamically allocatable (i.e. they
1959 	 * won't be allocated/freed through tavor_rsrc_alloc/free).  This
1960 	 * latter option is used for EQPC and UARSCR resource which are, in
1961 	 * fact, managed by the Tavor hardware.
1962 	 */
1963 	if (rsrc_pool->rsrc_quantum != 0) {
1964 		vmp = vmem_create(info->hwi_rsrcname,
1965 		    rsrc_pool->rsrc_ddr_offset, rsrc_pool->rsrc_pool_size,
1966 		    rsrc_pool->rsrc_quantum, NULL, NULL, NULL, 0, VM_SLEEP);
1967 		if (vmp == NULL) {
1968 			/* Unable to create vmem arena */
1969 			if (rsrc_pool->rsrc_ddr_offset !=
1970 			    rsrc_pool->rsrc_start) {
1971 				vmem_xfree(state->ts_ddrvmem,
1972 				    rsrc_pool->rsrc_ddr_offset,
1973 				    rsrc_pool->rsrc_pool_size);
1974 			}
1975 			TNF_PROBE_0(tavor_rsrc_hw_entries_init_vmemcreate_fail,
1976 			    TAVOR_TNF_ERROR, "");
1977 			TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
1978 			return (DDI_FAILURE);
1979 		}
1980 		rsrc_pool->rsrc_vmp = vmp;
1981 	} else {
1982 		rsrc_pool->rsrc_vmp = NULL;
1983 	}
1984 
1985 	/* The first HW entries may be reserved by Tavor firmware */
1986 	if (num_prealloc != 0) {
1987 		status = tavor_rsrc_alloc(state, rsrc_pool->rsrc_type,
1988 		    num_prealloc, TAVOR_SLEEP, &rsvd_rsrc);
1989 		if (status != DDI_SUCCESS) {
1990 			/* Unable to preallocate the reserved HW entries */
1991 			if (rsrc_pool->rsrc_vmp != NULL) {
1992 				vmem_destroy(rsrc_pool->rsrc_vmp);
1993 			}
1994 			if (rsrc_pool->rsrc_ddr_offset !=
1995 			    rsrc_pool->rsrc_start) {
1996 				vmem_xfree(state->ts_ddrvmem,
1997 				    rsrc_pool->rsrc_ddr_offset,
1998 				    rsrc_pool->rsrc_pool_size);
1999 			}
2000 			TNF_PROBE_0(tavor_rsrc_hw_entries_init_pre_fail,
2001 			    TAVOR_TNF_ERROR, "");
2002 			TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
2003 			return (DDI_FAILURE);
2004 		}
2005 	}
2006 	rsrc_pool->rsrc_private = rsvd_rsrc;
2007 
2008 	TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
2009 	return (DDI_SUCCESS);
2010 }
2011 
2012 
2013 /*
2014  * tavor_rsrc_hw_entries_fini()
2015  *    Context: Only called from attach() and/or detach() path contexts
2016  */
2017 static void
2018 tavor_rsrc_hw_entries_fini(tavor_state_t *state,
2019     tavor_rsrc_hw_entry_info_t *info)
2020 {
2021 	tavor_rsrc_pool_info_t	*rsrc_pool;
2022 	tavor_rsrc_t		*rsvd_rsrc;
2023 
2024 	TAVOR_TNF_ENTER(tavor_rsrc_hw_entries_fini);
2025 
2026 	ASSERT(state != NULL);
2027 	ASSERT(info != NULL);
2028 
2029 	rsrc_pool = info->hwi_rsrcpool;
2030 	ASSERT(rsrc_pool != NULL);
2031 
2032 	/* Free up any "reserved" (i.e. preallocated) HW entries */
2033 	rsvd_rsrc = (tavor_rsrc_t *)rsrc_pool->rsrc_private;
2034 	if (rsvd_rsrc != NULL) {
2035 		tavor_rsrc_free(state, &rsvd_rsrc);
2036 	}
2037 
2038 	/*
2039 	 * If we've actually setup a vmem arena for the HW entries, then
2040 	 * destroy it now
2041 	 */
2042 	if (rsrc_pool->rsrc_vmp != NULL) {
2043 		vmem_destroy(rsrc_pool->rsrc_vmp);
2044 	}
2045 
2046 	/*
2047 	 * Determine if a region was allocated from the tavor_ddr_vmem
2048 	 * arena (and free it up if necessary)
2049 	 */
2050 	if (rsrc_pool->rsrc_ddr_offset != rsrc_pool->rsrc_start) {
2051 		vmem_xfree(state->ts_ddrvmem, rsrc_pool->rsrc_ddr_offset,
2052 		    rsrc_pool->rsrc_pool_size);
2053 	}
2054 
2055 	TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_fini);
2056 }
2057 
2058 
2059 /*
2060  * tavor_rsrc_sw_handles_init()
2061  *    Context: Only called from attach() path context
2062  */
2063 /* ARGSUSED */
2064 static int
2065 tavor_rsrc_sw_handles_init(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2066 {
2067 	tavor_rsrc_pool_info_t	*rsrc_pool;
2068 	uint64_t		num_swhdl, max_swhdl, prealloc_sz;
2069 
2070 	TAVOR_TNF_ENTER(tavor_rsrc_sw_handles_init);
2071 
2072 	ASSERT(state != NULL);
2073 	ASSERT(info != NULL);
2074 
2075 	rsrc_pool	= info->swi_rsrcpool;
2076 	ASSERT(rsrc_pool != NULL);
2077 	num_swhdl	= info->swi_num;
2078 	max_swhdl	= info->swi_max;
2079 	prealloc_sz	= info->swi_prealloc_sz;
2080 
2081 	/* Make sure number of SW handles makes sense */
2082 	if (num_swhdl > max_swhdl) {
2083 		TNF_PROBE_2(tavor_rsrc_sw_handles_init_toomany_fail,
2084 		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of SW "
2085 		    "handles exceeds maximum", tnf_uint, maxsw, max_swhdl);
2086 		TAVOR_TNF_EXIT(tavor_rsrc_sw_handles_init);
2087 		return (DDI_FAILURE);
2088 	}
2089 
2090 	/*
2091 	 * Depending on the flags parameter, create a kmem_cache for some
2092 	 * number of software handle structures.  Note: kmem_cache_create()
2093 	 * will SLEEP until successful.
2094 	 */
2095 	if (info->swi_flags & TAVOR_SWHDL_KMEMCACHE_INIT) {
2096 		rsrc_pool->rsrc_private = kmem_cache_create(
2097 		    info->swi_rsrcname, rsrc_pool->rsrc_quantum, 0,
2098 		    info->swi_constructor, info->swi_destructor, NULL,
2099 		    rsrc_pool->rsrc_state, NULL, 0);
2100 	}
2101 
2102 	/* Allocate the central list of SW handle pointers */
2103 	if (info->swi_flags & TAVOR_SWHDL_TABLE_INIT) {
2104 		info->swi_table_ptr = kmem_zalloc(num_swhdl * prealloc_sz,
2105 		    KM_SLEEP);
2106 	}
2107 
2108 	TAVOR_TNF_EXIT(tavor_rsrc_sw_handles_init);
2109 	return (DDI_SUCCESS);
2110 }
2111 
2112 
2113 /*
2114  * tavor_rsrc_sw_handles_fini()
2115  *    Context: Only called from attach() and/or detach() path contexts
2116  */
2117 /* ARGSUSED */
2118 static void
2119 tavor_rsrc_sw_handles_fini(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2120 {
2121 	tavor_rsrc_pool_info_t	*rsrc_pool;
2122 	uint64_t		num_swhdl, prealloc_sz;
2123 
2124 	TAVOR_TNF_ENTER(tavor_rsrc_sw_handles_fini);
2125 
2126 	ASSERT(state != NULL);
2127 	ASSERT(info != NULL);
2128 
2129 	rsrc_pool	= info->swi_rsrcpool;
2130 	num_swhdl	= info->swi_num;
2131 	prealloc_sz	= info->swi_prealloc_sz;
2132 
2133 	/*
2134 	 * If a "software handle" kmem_cache exists for this resource, then
2135 	 * destroy it now
2136 	 */
2137 	if (rsrc_pool != NULL) {
2138 		kmem_cache_destroy(rsrc_pool->rsrc_private);
2139 	}
2140 
2141 	/* Free up this central list of SW handle pointers */
2142 	if (info->swi_table_ptr != NULL) {
2143 		kmem_free(info->swi_table_ptr, num_swhdl * prealloc_sz);
2144 	}
2145 
2146 	TAVOR_TNF_EXIT(tavor_rsrc_sw_handles_fini);
2147 }
2148 
2149 
2150 /*
2151  * tavor_rsrc_pd_handles_init()
2152  *    Context: Only called from attach() path context
2153  */
2154 static int
2155 tavor_rsrc_pd_handles_init(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2156 {
2157 	tavor_rsrc_pool_info_t	*rsrc_pool;
2158 	vmem_t			*vmp;
2159 	char			vmem_name[TAVOR_RSRC_NAME_MAXLEN];
2160 	int			status;
2161 
2162 	TAVOR_TNF_ENTER(tavor_rsrc_pd_handles_init);
2163 
2164 	ASSERT(state != NULL);
2165 	ASSERT(info != NULL);
2166 
2167 	rsrc_pool = info->swi_rsrcpool;
2168 	ASSERT(rsrc_pool != NULL);
2169 
2170 	/* Initialize the resource pool for software handle table */
2171 	status = tavor_rsrc_sw_handles_init(state, info);
2172 	if (status != DDI_SUCCESS) {
2173 		TNF_PROBE_0(tavor_rsrc_pdhdl_alloc_fail, TAVOR_TNF_ERROR, "");
2174 		TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2175 		return (DDI_FAILURE);
2176 	}
2177 
2178 	/* Build vmem arena name from Tavor instance */
2179 	TAVOR_RSRC_NAME(vmem_name, TAVOR_PDHDL_VMEM);
2180 
2181 	/* Create new vmem arena for PD numbers */
2182 	vmp = vmem_create(vmem_name, (caddr_t)1, info->swi_num, 1, NULL,
2183 	    NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
2184 	if (vmp == NULL) {
2185 		/* Unable to create vmem arena */
2186 		info->swi_table_ptr = NULL;
2187 		tavor_rsrc_sw_handles_fini(state, info);
2188 		TNF_PROBE_0(tavor_rsrc_pd_handles_init_vmem_create_fail,
2189 		    TAVOR_TNF_ERROR, "");
2190 		TAVOR_TNF_EXIT(tavor_rsrc_pd_handles_init);
2191 		return (DDI_FAILURE);
2192 	}
2193 	rsrc_pool->rsrc_vmp = vmp;
2194 
2195 	TAVOR_TNF_EXIT(tavor_rsrc_pd_handles_init);
2196 	return (DDI_SUCCESS);
2197 }
2198 
2199 
2200 /*
2201  * tavor_rsrc_pd_handles_fini()
2202  *    Context: Only called from attach() and/or detach() path contexts
2203  */
2204 static void
2205 tavor_rsrc_pd_handles_fini(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2206 {
2207 	tavor_rsrc_pool_info_t	*rsrc_pool;
2208 
2209 	TAVOR_TNF_ENTER(tavor_rsrc_pd_handles_fini);
2210 
2211 	ASSERT(state != NULL);
2212 	ASSERT(info != NULL);
2213 
2214 	rsrc_pool = info->swi_rsrcpool;
2215 
2216 	/* Destroy the specially created UAR scratch table vmem arena */
2217 	vmem_destroy(rsrc_pool->rsrc_vmp);
2218 
2219 	/* Destroy the "tavor_sw_pd_t" kmem_cache */
2220 	tavor_rsrc_sw_handles_fini(state, info);
2221 
2222 	TAVOR_TNF_EXIT(tavor_rsrc_pd_handles_fini);
2223 }
2224 
2225 
2226 /*
2227  * tavor_rsrc_mbox_alloc()
2228  *    Context: Only called from attach() path context
2229  */
2230 static int
2231 tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t num,
2232     tavor_rsrc_t *hdl)
2233 {
2234 	tavor_rsrc_priv_mbox_t	*priv;
2235 	void			*addr;
2236 	caddr_t			kaddr;
2237 	uint64_t		offset;
2238 	size_t			real_len, temp_len;
2239 	int			status;
2240 
2241 	TAVOR_TNF_ENTER(tavor_rsrc_mbox_alloc);
2242 
2243 	ASSERT(pool_info != NULL);
2244 	ASSERT(hdl != NULL);
2245 
2246 	/* Get the private pointer for the mailboxes */
2247 	priv = pool_info->rsrc_private;
2248 	ASSERT(priv != NULL);
2249 
2250 	/*
2251 	 * Allocate a DMA handle for the mailbox.  This will be used for
2252 	 * two purposes (potentially).  First, it could be used below in
2253 	 * the call to ddi_dma_mem_alloc() - if the mailbox is to come from
2254 	 * system memory.  Second, it is definitely used later to bind
2255 	 * the mailbox for DMA access from/by the hardware.
2256 	 */
2257 	status = ddi_dma_alloc_handle(priv->pmb_dip, &priv->pmb_dmaattr,
2258 	    DDI_DMA_SLEEP, NULL, &hdl->tr_dmahdl);
2259 	if (status != DDI_SUCCESS) {
2260 		TNF_PROBE_1(tavor_rsrc_mbox_alloc_dmahdl_fail, TAVOR_TNF_ERROR,
2261 		    "", tnf_uint, status, status);
2262 		TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2263 		return (DDI_FAILURE);
2264 	}
2265 
2266 	/* Is mailbox in DDR memory or system memory? */
2267 	if (pool_info->rsrc_loc == TAVOR_IN_DDR) {
2268 		/* Use vmem_alloc() to get DDR address of mbox */
2269 		hdl->tr_len = (num * pool_info->rsrc_quantum);
2270 		addr = vmem_alloc(pool_info->rsrc_vmp, hdl->tr_len,
2271 		    VM_SLEEP);
2272 		if (addr == NULL) {
2273 			/* No more DDR available for mailbox entries */
2274 			ddi_dma_free_handle(&hdl->tr_dmahdl);
2275 			TNF_PROBE_0(tavor_rsrc_mbox_alloc_vma_fail,
2276 			    TAVOR_TNF_ERROR, "");
2277 			TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2278 			return (DDI_FAILURE);
2279 		}
2280 		hdl->tr_acchdl = priv->pmb_acchdl;
2281 
2282 		/* Calculate kernel virtual address (from the DDR offset) */
2283 		offset = ((uintptr_t)addr -
2284 		    (uintptr_t)pool_info->rsrc_ddr_offset);
2285 		hdl->tr_addr = (void *)(uintptr_t)(offset +
2286 		    (uintptr_t)pool_info->rsrc_start);
2287 
2288 	} else { /* TAVOR_IN_SYSMEM */
2289 
2290 		/* Use ddi_dma_mem_alloc() to get memory for mailbox */
2291 		temp_len = (num * pool_info->rsrc_quantum);
2292 		status = ddi_dma_mem_alloc(hdl->tr_dmahdl, temp_len,
2293 		    &priv->pmb_devaccattr, priv->pmb_xfer_mode, DDI_DMA_SLEEP,
2294 		    NULL, &kaddr, &real_len, &hdl->tr_acchdl);
2295 		if (status != DDI_SUCCESS) {
2296 			/* No more sys memory available for mailbox entries */
2297 			ddi_dma_free_handle(&hdl->tr_dmahdl);
2298 			TNF_PROBE_0(tavor_rsrc_mbox_alloc_dma_memalloc_fail,
2299 			    TAVOR_TNF_ERROR, "");
2300 			TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2301 			return (DDI_FAILURE);
2302 		}
2303 		hdl->tr_addr = (void *)kaddr;
2304 		hdl->tr_len  = real_len;
2305 	}
2306 
2307 	TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2308 	return (DDI_SUCCESS);
2309 }
2310 
2311 
2312 /*
2313  * tavor_rsrc_mbox_free()
2314  *    Context: Can be called from interrupt or base context.
2315  */
2316 static void
2317 tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2318 {
2319 	void		*addr;
2320 	uint64_t	offset;
2321 
2322 	TAVOR_TNF_ENTER(tavor_rsrc_mbox_free);
2323 
2324 	ASSERT(pool_info != NULL);
2325 	ASSERT(hdl != NULL);
2326 
2327 	/* Is mailbox in DDR memory or system memory? */
2328 	if (pool_info->rsrc_loc == TAVOR_IN_DDR) {
2329 
2330 		/* Calculate the allocated address (the mbox's DDR offset) */
2331 		offset = ((uintptr_t)hdl->tr_addr -
2332 		    (uintptr_t)pool_info->rsrc_start);
2333 		addr = (void *)(uintptr_t)(offset +
2334 		    (uintptr_t)pool_info->rsrc_ddr_offset);
2335 
2336 		/* Use vmem_free() to free up DDR memory for mailbox */
2337 		vmem_free(pool_info->rsrc_vmp, addr, hdl->tr_len);
2338 
2339 	} else { /* TAVOR_IN_SYSMEM */
2340 
2341 		/* Use ddi_dma_mem_free() to free up sys memory for mailbox */
2342 		ddi_dma_mem_free(&hdl->tr_acchdl);
2343 	}
2344 
2345 	/* Free the DMA handle for the mailbox */
2346 	ddi_dma_free_handle(&hdl->tr_dmahdl);
2347 
2348 	TAVOR_TNF_EXIT(tavor_rsrc_mbox_free);
2349 }
2350 
2351 
2352 /*
2353  * tavor_rsrc_hw_entry_alloc()
2354  *    Context: Can be called from interrupt or base context.
2355  */
2356 static int
2357 tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t num,
2358     uint_t num_align, ddi_acc_handle_t acc_handle, uint_t sleepflag,
2359     tavor_rsrc_t *hdl)
2360 {
2361 	void		*addr;
2362 	uint64_t	offset;
2363 	uint32_t	align;
2364 	int		flag;
2365 
2366 	TAVOR_TNF_ENTER(tavor_rsrc_hw_entry_alloc);
2367 
2368 	ASSERT(pool_info != NULL);
2369 	ASSERT(hdl != NULL);
2370 
2371 	/*
2372 	 * Tavor hardware entries (QPC, CQC, EQC, MPT, MTT, etc.) do not
2373 	 * use dma_handle (because they are in Tavor locally attached DDR
2374 	 * memory) and, generally, don't use the acc_handle (because the
2375 	 * entries are not directly accessed by software).  The exceptions
2376 	 * to this rule are the UARPG and UDAV entries.
2377 	 */
2378 
2379 	/*
2380 	 * Use vmem_xalloc() to get a properly aligned pointer (based on
2381 	 * the number requested) to the HW entry(ies).  This handles the
2382 	 * cases (for special QPCs and for RDB entries) where we need more
2383 	 * than one and need to ensure that they are properly aligned.
2384 	 */
2385 	flag = (sleepflag == TAVOR_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
2386 	hdl->tr_len = (num * pool_info->rsrc_quantum);
2387 	align	    = (num_align * pool_info->rsrc_quantum);
2388 	addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->tr_len,
2389 	    align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
2390 	if (addr == NULL) {
2391 		/* No more HW entries available */
2392 		TNF_PROBE_0(tavor_rsrc_hw_entry_alloc_vmxa_fail,
2393 		    TAVOR_TNF_ERROR, "");
2394 		TAVOR_TNF_EXIT(tavor_rsrc_hw_entry_alloc);
2395 		return (DDI_FAILURE);
2396 	}
2397 
2398 	/* If an access handle was provided, fill it in */
2399 	if (acc_handle != 0) {
2400 		hdl->tr_acchdl = acc_handle;
2401 	}
2402 
2403 	/* Calculate vaddr and HW table index (from the DDR offset) */
2404 	offset = ((uintptr_t)addr - (uintptr_t)pool_info->rsrc_ddr_offset);
2405 	hdl->tr_addr = (void *)(uintptr_t)(offset +
2406 	    (uintptr_t)pool_info->rsrc_start);
2407 	hdl->tr_indx = (offset >> pool_info->rsrc_shift);
2408 
2409 	TAVOR_TNF_EXIT(tavor_rsrc_hw_entry_alloc);
2410 	return (DDI_SUCCESS);
2411 }
2412 
2413 
2414 /*
2415  * tavor_rsrc_hw_entry_free()
2416  *    Context: Can be called from interrupt or base context.
2417  */
2418 static void
2419 tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2420 {
2421 	void		*addr;
2422 	uint64_t	offset;
2423 
2424 	TAVOR_TNF_ENTER(tavor_rsrc_hw_entry_free);
2425 
2426 	ASSERT(pool_info != NULL);
2427 	ASSERT(hdl != NULL);
2428 
2429 	/* Calculate the allocated address (the entry's DDR offset) */
2430 	offset = ((uintptr_t)hdl->tr_addr - (uintptr_t)pool_info->rsrc_start);
2431 	addr   = (void *)(uintptr_t)(offset +
2432 	    (uintptr_t)pool_info->rsrc_ddr_offset);
2433 
2434 	/* Use vmem_xfree() to free up the HW table entry */
2435 	vmem_xfree(pool_info->rsrc_vmp, addr, hdl->tr_len);
2436 
2437 	TAVOR_TNF_EXIT(tavor_rsrc_hw_entry_free);
2438 }
2439 
2440 
2441 /*
2442  * tavor_rsrc_swhdl_alloc()
2443  *    Context: Can be called from interrupt or base context.
2444  */
2445 static int
2446 tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t sleepflag,
2447     tavor_rsrc_t *hdl)
2448 {
2449 	void	*addr;
2450 	int	flag;
2451 
2452 	TAVOR_TNF_ENTER(tavor_rsrc_swhdl_alloc);
2453 
2454 	ASSERT(pool_info != NULL);
2455 	ASSERT(hdl != NULL);
2456 
2457 	/* Allocate the software handle structure */
2458 	flag = (sleepflag == TAVOR_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
2459 	addr = kmem_cache_alloc(pool_info->rsrc_private, flag);
2460 	if (addr == NULL) {
2461 		TNF_PROBE_0(tavor_rsrc_swhdl_alloc_kmca_fail, TAVOR_TNF_ERROR,
2462 		    "");
2463 		TAVOR_TNF_EXIT(tavor_rsrc_swhdl_alloc);
2464 		return (DDI_FAILURE);
2465 	}
2466 	hdl->tr_len  = pool_info->rsrc_quantum;
2467 	hdl->tr_addr = addr;
2468 
2469 	TAVOR_TNF_EXIT(tavor_rsrc_swhdl_alloc);
2470 	return (DDI_SUCCESS);
2471 }
2472 
2473 
2474 /*
2475  * tavor_rsrc_swhdl_free()
2476  *    Context: Can be called from interrupt or base context.
2477  */
2478 static void
2479 tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2480 {
2481 	TAVOR_TNF_ENTER(tavor_rsrc_swhdl_free);
2482 
2483 	ASSERT(pool_info != NULL);
2484 	ASSERT(hdl != NULL);
2485 
2486 	/* Free the software handle structure */
2487 	kmem_cache_free(pool_info->rsrc_private, hdl->tr_addr);
2488 
2489 	TAVOR_TNF_EXIT(tavor_rsrc_swhdl_free);
2490 }
2491 
2492 
2493 /*
2494  * tavor_rsrc_pdhdl_alloc()
2495  *    Context: Can be called from interrupt or base context.
2496  */
2497 static int
2498 tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t sleepflag,
2499     tavor_rsrc_t *hdl)
2500 {
2501 	tavor_pdhdl_t	addr;
2502 	void		*tmpaddr;
2503 	int		flag, status;
2504 
2505 	TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_alloc);
2506 
2507 	ASSERT(pool_info != NULL);
2508 	ASSERT(hdl != NULL);
2509 
2510 	/* Allocate the software handle */
2511 	status = tavor_rsrc_swhdl_alloc(pool_info, sleepflag, hdl);
2512 	if (status != DDI_SUCCESS) {
2513 		TNF_PROBE_0(tavor_rsrc_pdhdl_alloc_fail, TAVOR_TNF_ERROR, "");
2514 		TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2515 		return (DDI_FAILURE);
2516 	}
2517 	addr = (tavor_pdhdl_t)hdl->tr_addr;
2518 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr))
2519 
2520 	/* Allocate a PD number for the handle */
2521 	flag = (sleepflag == TAVOR_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
2522 	tmpaddr = vmem_alloc(pool_info->rsrc_vmp, 1, flag);
2523 	if (tmpaddr == NULL) {
2524 		/* No more PD number entries available */
2525 		tavor_rsrc_swhdl_free(pool_info, hdl);
2526 		TNF_PROBE_0(tavor_rsrc_pdhdl_alloc_vma_fail,
2527 		    TAVOR_TNF_ERROR, "");
2528 		TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2529 		return (DDI_FAILURE);
2530 	}
2531 	addr->pd_pdnum = (uint32_t)(uintptr_t)tmpaddr;
2532 	addr->pd_rsrcp = hdl;
2533 	hdl->tr_indx   = addr->pd_pdnum;
2534 
2535 	TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2536 	return (DDI_SUCCESS);
2537 }
2538 
2539 
2540 /*
2541  * tavor_rsrc_pdhdl_free()
2542  *    Context: Can be called from interrupt or base context.
2543  */
2544 static void
2545 tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2546 {
2547 	TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_free);
2548 
2549 	ASSERT(pool_info != NULL);
2550 	ASSERT(hdl != NULL);
2551 
2552 	/* Use vmem_free() to free up the PD number */
2553 	vmem_free(pool_info->rsrc_vmp, (void *)(uintptr_t)hdl->tr_indx, 1);
2554 
2555 	/* Free the software handle structure */
2556 	tavor_rsrc_swhdl_free(pool_info, hdl);
2557 
2558 	TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_free);
2559 }
2560 
2561 
2562 /*
2563  * tavor_rsrc_pdhdl_constructor()
2564  *    Context: Can be called from interrupt or base context.
2565  */
2566 /* ARGSUSED */
2567 static int
2568 tavor_rsrc_pdhdl_constructor(void *pd, void *priv, int flags)
2569 {
2570 	tavor_pdhdl_t	pdhdl;
2571 	tavor_state_t	*state;
2572 
2573 	TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_constructor);
2574 
2575 	pdhdl = (tavor_pdhdl_t)pd;
2576 	state = (tavor_state_t *)priv;
2577 
2578 	mutex_init(&pdhdl->pd_lock, NULL, MUTEX_DRIVER,
2579 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2580 
2581 	TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_constructor);
2582 	return (DDI_SUCCESS);
2583 }
2584 
2585 
2586 /*
2587  * tavor_rsrc_pdhdl_destructor()
2588  *    Context: Can be called from interrupt or base context.
2589  */
2590 /* ARGSUSED */
2591 static void
2592 tavor_rsrc_pdhdl_destructor(void *pd, void *priv)
2593 {
2594 	tavor_pdhdl_t	pdhdl;
2595 
2596 	TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_destructor);
2597 
2598 	pdhdl = (tavor_pdhdl_t)pd;
2599 
2600 	mutex_destroy(&pdhdl->pd_lock);
2601 
2602 	TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_destructor);
2603 }
2604 
2605 
2606 /*
2607  * tavor_rsrc_cqhdl_constructor()
2608  *    Context: Can be called from interrupt or base context.
2609  */
2610 /* ARGSUSED */
2611 static int
2612 tavor_rsrc_cqhdl_constructor(void *cq, void *priv, int flags)
2613 {
2614 	tavor_cqhdl_t	cqhdl;
2615 	tavor_state_t	*state;
2616 
2617 	TAVOR_TNF_ENTER(tavor_rsrc_cqhdl_constructor);
2618 
2619 	cqhdl = (tavor_cqhdl_t)cq;
2620 	state = (tavor_state_t *)priv;
2621 
2622 	mutex_init(&cqhdl->cq_lock, NULL, MUTEX_DRIVER,
2623 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2624 	mutex_init(&cqhdl->cq_wrid_wqhdr_lock, NULL, MUTEX_DRIVER,
2625 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2626 
2627 	TAVOR_TNF_EXIT(tavor_rsrc_cqhdl_constructor);
2628 	return (DDI_SUCCESS);
2629 }
2630 
2631 
2632 /*
2633  * tavor_rsrc_cqhdl_destructor()
2634  *    Context: Can be called from interrupt or base context.
2635  */
2636 /* ARGSUSED */
2637 static void
2638 tavor_rsrc_cqhdl_destructor(void *cq, void *priv)
2639 {
2640 	tavor_cqhdl_t	cqhdl;
2641 
2642 	TAVOR_TNF_ENTER(tavor_rsrc_cqhdl_destructor);
2643 
2644 	cqhdl = (tavor_cqhdl_t)cq;
2645 
2646 	mutex_destroy(&cqhdl->cq_wrid_wqhdr_lock);
2647 	mutex_destroy(&cqhdl->cq_lock);
2648 
2649 	TAVOR_TNF_EXIT(tavor_rsrc_cqhdl_destructor);
2650 }
2651 
2652 
2653 /*
2654  * tavor_rsrc_qphdl_constructor()
2655  *    Context: Can be called from interrupt or base context.
2656  */
2657 /* ARGSUSED */
2658 static int
2659 tavor_rsrc_qphdl_constructor(void *qp, void *priv, int flags)
2660 {
2661 	tavor_qphdl_t	qphdl;
2662 	tavor_state_t	*state;
2663 
2664 	TAVOR_TNF_ENTER(tavor_rsrc_qphdl_constructor);
2665 
2666 	qphdl = (tavor_qphdl_t)qp;
2667 	state = (tavor_state_t *)priv;
2668 
2669 	mutex_init(&qphdl->qp_lock, NULL, MUTEX_DRIVER,
2670 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2671 
2672 	TAVOR_TNF_EXIT(tavor_rsrc_qphdl_constructor);
2673 	return (DDI_SUCCESS);
2674 }
2675 
2676 
2677 /*
2678  * tavor_rsrc_qphdl_destructor()
2679  *    Context: Can be called from interrupt or base context.
2680  */
2681 /* ARGSUSED */
2682 static void
2683 tavor_rsrc_qphdl_destructor(void *qp, void *priv)
2684 {
2685 	tavor_qphdl_t	qphdl;
2686 
2687 	TAVOR_TNF_ENTER(tavor_rsrc_qphdl_destructor);
2688 
2689 	qphdl = (tavor_qphdl_t)qp;
2690 
2691 	mutex_destroy(&qphdl->qp_lock);
2692 
2693 	TAVOR_TNF_ENTER(tavor_rsrc_qphdl_destructor);
2694 }
2695 
2696 
2697 /*
2698  * tavor_rsrc_srqhdl_constructor()
2699  *    Context: Can be called from interrupt or base context.
2700  */
2701 /* ARGSUSED */
2702 static int
2703 tavor_rsrc_srqhdl_constructor(void *srq, void *priv, int flags)
2704 {
2705 	tavor_srqhdl_t	srqhdl;
2706 	tavor_state_t	*state;
2707 
2708 	TAVOR_TNF_ENTER(tavor_rsrc_srqhdl_constructor);
2709 
2710 	srqhdl = (tavor_srqhdl_t)srq;
2711 	state = (tavor_state_t *)priv;
2712 
2713 	mutex_init(&srqhdl->srq_lock, NULL, MUTEX_DRIVER,
2714 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2715 
2716 	TAVOR_TNF_EXIT(tavor_rsrc_srqhdl_constructor);
2717 	return (DDI_SUCCESS);
2718 }
2719 
2720 
2721 /*
2722  * tavor_rsrc_srqhdl_destructor()
2723  *    Context: Can be called from interrupt or base context.
2724  */
2725 /* ARGSUSED */
2726 static void
2727 tavor_rsrc_srqhdl_destructor(void *srq, void *priv)
2728 {
2729 	tavor_srqhdl_t	srqhdl;
2730 
2731 	TAVOR_TNF_ENTER(tavor_rsrc_srqhdl_destructor);
2732 
2733 	srqhdl = (tavor_srqhdl_t)srq;
2734 
2735 	mutex_destroy(&srqhdl->srq_lock);
2736 
2737 	TAVOR_TNF_EXIT(tavor_rsrc_srqhdl_destructor);
2738 }
2739 
2740 
2741 /*
2742  * tavor_rsrc_refcnt_constructor()
2743  *    Context: Can be called from interrupt or base context.
2744  */
2745 /* ARGSUSED */
2746 static int
2747 tavor_rsrc_refcnt_constructor(void *rc, void *priv, int flags)
2748 {
2749 	tavor_sw_refcnt_t	*refcnt;
2750 	tavor_state_t		*state;
2751 
2752 	TAVOR_TNF_ENTER(tavor_rsrc_refcnt_constructor);
2753 
2754 	refcnt = (tavor_sw_refcnt_t *)rc;
2755 	state  = (tavor_state_t *)priv;
2756 
2757 	mutex_init(&refcnt->swrc_lock, NULL, MUTEX_DRIVER,
2758 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2759 
2760 	TAVOR_TNF_EXIT(tavor_rsrc_refcnt_constructor);
2761 	return (DDI_SUCCESS);
2762 }
2763 
2764 
2765 /*
2766  * tavor_rsrc_refcnt_destructor()
2767  *    Context: Can be called from interrupt or base context.
2768  */
2769 /* ARGSUSED */
2770 static void
2771 tavor_rsrc_refcnt_destructor(void *rc, void *priv)
2772 {
2773 	tavor_sw_refcnt_t	*refcnt;
2774 
2775 	TAVOR_TNF_ENTER(tavor_rsrc_refcnt_destructor);
2776 
2777 	refcnt = (tavor_sw_refcnt_t *)rc;
2778 
2779 	mutex_destroy(&refcnt->swrc_lock);
2780 
2781 	TAVOR_TNF_ENTER(tavor_rsrc_refcnt_destructor);
2782 }
2783 
2784 
2785 /*
2786  * tavor_rsrc_ahhdl_constructor()
2787  *    Context: Can be called from interrupt or base context.
2788  */
2789 /* ARGSUSED */
2790 static int
2791 tavor_rsrc_ahhdl_constructor(void *ah, void *priv, int flags)
2792 {
2793 	tavor_ahhdl_t	ahhdl;
2794 	tavor_state_t	*state;
2795 
2796 	TAVOR_TNF_ENTER(tavor_rsrc_ahhdl_constructor);
2797 
2798 	ahhdl = (tavor_ahhdl_t)ah;
2799 	state = (tavor_state_t *)priv;
2800 
2801 	mutex_init(&ahhdl->ah_lock, NULL, MUTEX_DRIVER,
2802 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2803 
2804 	TAVOR_TNF_EXIT(tavor_rsrc_ahhdl_constructor);
2805 	return (DDI_SUCCESS);
2806 }
2807 
2808 
2809 /*
2810  * tavor_rsrc_ahhdl_destructor()
2811  *    Context: Can be called from interrupt or base context.
2812  */
2813 /* ARGSUSED */
2814 static void
2815 tavor_rsrc_ahhdl_destructor(void *ah, void *priv)
2816 {
2817 	tavor_ahhdl_t	ahhdl;
2818 
2819 	TAVOR_TNF_ENTER(tavor_rsrc_ahhdl_destructor);
2820 
2821 	ahhdl = (tavor_ahhdl_t)ah;
2822 
2823 	mutex_destroy(&ahhdl->ah_lock);
2824 
2825 	TAVOR_TNF_ENTER(tavor_rsrc_ahhdl_destructor);
2826 }
2827 
2828 
2829 /*
2830  * tavor_rsrc_mrhdl_constructor()
2831  *    Context: Can be called from interrupt or base context.
2832  */
2833 /* ARGSUSED */
2834 static int
2835 tavor_rsrc_mrhdl_constructor(void *mr, void *priv, int flags)
2836 {
2837 	tavor_mrhdl_t	mrhdl;
2838 	tavor_state_t	*state;
2839 
2840 	TAVOR_TNF_ENTER(tavor_rsrc_mrhdl_constructor);
2841 
2842 	mrhdl = (tavor_mrhdl_t)mr;
2843 	state = (tavor_state_t *)priv;
2844 
2845 	mutex_init(&mrhdl->mr_lock, NULL, MUTEX_DRIVER,
2846 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2847 
2848 	TAVOR_TNF_EXIT(tavor_rsrc_mrhdl_constructor);
2849 	return (DDI_SUCCESS);
2850 }
2851 
2852 
2853 /*
2854  * tavor_rsrc_mrhdl_destructor()
2855  *    Context: Can be called from interrupt or base context.
2856  */
2857 /* ARGSUSED */
2858 static void
2859 tavor_rsrc_mrhdl_destructor(void *mr, void *priv)
2860 {
2861 	tavor_mrhdl_t	mrhdl;
2862 
2863 	TAVOR_TNF_ENTER(tavor_rsrc_mrhdl_destructor);
2864 
2865 	mrhdl = (tavor_mrhdl_t)mr;
2866 
2867 	mutex_destroy(&mrhdl->mr_lock);
2868 
2869 	TAVOR_TNF_ENTER(tavor_rsrc_mrhdl_destructor);
2870 }
2871 
2872 
2873 /*
2874  * tavor_rsrc_mcg_entry_get_size()
2875  */
2876 static int
2877 tavor_rsrc_mcg_entry_get_size(tavor_state_t *state, uint_t *mcg_size_shift)
2878 {
2879 	uint_t	num_qp_per_mcg, max_qp_per_mcg, log2;
2880 
2881 	TAVOR_TNF_ENTER(tavor_rsrc_mcg_entry_get_size);
2882 
2883 	/*
2884 	 * Round the configured number of QP per MCG to next larger
2885 	 * power-of-2 size and update.
2886 	 */
2887 	num_qp_per_mcg = state->ts_cfg_profile->cp_num_qp_per_mcg + 8;
2888 	log2 = highbit(num_qp_per_mcg);
2889 	if (ISP2(num_qp_per_mcg)) {
2890 		log2 = log2 - 1;
2891 	}
2892 	state->ts_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
2893 
2894 	/* Now make sure number of QP per MCG makes sense */
2895 	num_qp_per_mcg = state->ts_cfg_profile->cp_num_qp_per_mcg;
2896 	max_qp_per_mcg = (1 << state->ts_devlim.log_max_qp_mcg);
2897 	if (num_qp_per_mcg > max_qp_per_mcg) {
2898 		TNF_PROBE_1(tavor_rsrc_mcg_getsz_toomany_qppermcg_fail,
2899 		    TAVOR_TNF_ERROR, "", tnf_uint, maxqpmcg, max_qp_per_mcg);
2900 		TAVOR_TNF_EXIT(tavor_rsrc_mcg_entry_get_size);
2901 		return (DDI_FAILURE);
2902 	}
2903 
2904 	/* Return the (shift) size of an individual MCG HW entry */
2905 	*mcg_size_shift = log2 + 2;
2906 
2907 	TAVOR_TNF_EXIT(tavor_rsrc_mcg_entry_get_size);
2908 	return (DDI_SUCCESS);
2909 }
2910