xref: /illumos-gate/usr/src/uts/common/io/ib/adapters/tavor/tavor_rsrc.c (revision 2570281cf351044b6936651ce26dbe1f801dcbd8)
19e39c5baSBill Taylor /*
29e39c5baSBill Taylor  * CDDL HEADER START
39e39c5baSBill Taylor  *
49e39c5baSBill Taylor  * The contents of this file are subject to the terms of the
59e39c5baSBill Taylor  * Common Development and Distribution License (the "License").
69e39c5baSBill Taylor  * You may not use this file except in compliance with the License.
79e39c5baSBill Taylor  *
89e39c5baSBill Taylor  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e39c5baSBill Taylor  * or http://www.opensolaris.org/os/licensing.
109e39c5baSBill Taylor  * See the License for the specific language governing permissions
119e39c5baSBill Taylor  * and limitations under the License.
129e39c5baSBill Taylor  *
139e39c5baSBill Taylor  * When distributing Covered Code, include this CDDL HEADER in each
149e39c5baSBill Taylor  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e39c5baSBill Taylor  * If applicable, add the following below this CDDL HEADER, with the
169e39c5baSBill Taylor  * fields enclosed by brackets "[]" replaced with your own identifying
179e39c5baSBill Taylor  * information: Portions Copyright [yyyy] [name of copyright owner]
189e39c5baSBill Taylor  *
199e39c5baSBill Taylor  * CDDL HEADER END
209e39c5baSBill Taylor  */
219e39c5baSBill Taylor 
229e39c5baSBill Taylor /*
239e39c5baSBill Taylor  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
249e39c5baSBill Taylor  * Use is subject to license terms.
259e39c5baSBill Taylor  */
269e39c5baSBill Taylor 
279e39c5baSBill Taylor /*
289e39c5baSBill Taylor  * tavor_rsrc.c
299e39c5baSBill Taylor  *    Tavor Resource Management Routines
309e39c5baSBill Taylor  *
319e39c5baSBill Taylor  *    Implements all the routines necessary for setup, teardown, and
329e39c5baSBill Taylor  *    alloc/free of all Tavor resources, including those that are managed
339e39c5baSBill Taylor  *    by Tavor hardware or which live in Tavor's direct attached DDR memory.
349e39c5baSBill Taylor  */
359e39c5baSBill Taylor 
36de710d24SJosef 'Jeff' Sipek #include <sys/sysmacros.h>
379e39c5baSBill Taylor #include <sys/types.h>
389e39c5baSBill Taylor #include <sys/conf.h>
399e39c5baSBill Taylor #include <sys/ddi.h>
409e39c5baSBill Taylor #include <sys/sunddi.h>
419e39c5baSBill Taylor #include <sys/modctl.h>
429e39c5baSBill Taylor #include <sys/vmem.h>
439e39c5baSBill Taylor #include <sys/bitmap.h>
449e39c5baSBill Taylor 
459e39c5baSBill Taylor #include <sys/ib/adapters/tavor/tavor.h>
469e39c5baSBill Taylor 
479e39c5baSBill Taylor /*
489e39c5baSBill Taylor  * The following routines are used for initializing and destroying
499e39c5baSBill Taylor  * the resource pools used by the Tavor resource allocation routines.
509e39c5baSBill Taylor  * They consist of four classes of object:
519e39c5baSBill Taylor  *
529e39c5baSBill Taylor  * Mailboxes:  The "In" and "Out" mailbox types are used by the Tavor
539e39c5baSBill Taylor  *    command interface routines.  Mailboxes are used to pass information
549e39c5baSBill Taylor  *    back and forth to the Tavor firmware.  Either type of mailbox may
559e39c5baSBill Taylor  *    be allocated from Tavor's direct attached DDR memory or from system
569e39c5baSBill Taylor  *    memory (although currently all "In" mailboxes are in DDR and all "out"
579e39c5baSBill Taylor  *    mailboxes come from system memory.
589e39c5baSBill Taylor  *
599e39c5baSBill Taylor  * HW entry objects:  These objects represent resources required by the Tavor
609e39c5baSBill Taylor  *    hardware.  These objects include things like Queue Pair contexts (QPC),
619e39c5baSBill Taylor  *    Completion Queue contexts (CQC), Event Queue contexts (EQC), RDB (for
629e39c5baSBill Taylor  *    supporting RDMA Read/Atomic), Multicast Group entries (MCG), Memory
639e39c5baSBill Taylor  *    Protection Table entries (MPT), Memory Translation Table entries (MTT).
649e39c5baSBill Taylor  *
659e39c5baSBill Taylor  *    What these objects all have in common is that they are each required
669e39c5baSBill Taylor  *    to come from DDR memory, they are always allocated from tables, and
679e39c5baSBill Taylor  *    they are not to be directly accessed (read or written) by driver
689e39c5baSBill Taylor  *    software.
699e39c5baSBill Taylor  *    One notable exceptions to this rule are the Extended QP contexts (EQPC),
709e39c5baSBill Taylor  *    and the UAR scratch area (UAR_SCR), both of which are not directly
719e39c5baSBill Taylor  *    accessible through the Tavor resource allocation routines, but both
729e39c5baSBill Taylor  *    of which are also required to reside in DDR memory and are not to be
739e39c5baSBill Taylor  *    manipulated by driver software (they are privately managed by Tavor
749e39c5baSBill Taylor  *    hardware).
759e39c5baSBill Taylor  *    The other notable exceptions are the UAR pages (UAR_PG) which are
769e39c5baSBill Taylor  *    allocated from the UAR address space rather than DDR, and the UD
779e39c5baSBill Taylor  *    address vectors (UDAV) which are similar to the common object types
789e39c5baSBill Taylor  *    with the major difference being that UDAVs _are_ directly read and
799e39c5baSBill Taylor  *    written by driver software.
809e39c5baSBill Taylor  *
819e39c5baSBill Taylor  * SW handle objects: These objects represent resources required by Tavor
829e39c5baSBill Taylor  *    driver software.  They are primarily software tracking structures,
839e39c5baSBill Taylor  *    which are allocated from system memory (using kmem_cache).  Several of
849e39c5baSBill Taylor  *    the objects have both a "constructor" and "destructor" method
859e39c5baSBill Taylor  *    associated with them (see below).
869e39c5baSBill Taylor  *
879e39c5baSBill Taylor  * Protection Domain (PD) handle objects:  These objects are very much like
889e39c5baSBill Taylor  *    a SW handle object with the notable difference that all PD handle
899e39c5baSBill Taylor  *    objects have an actual Protection Domain number (PD) associated with
909e39c5baSBill Taylor  *    them (and the PD number is allocated/managed through a separate
919e39c5baSBill Taylor  *    vmem_arena specifically set aside for this purpose.
929e39c5baSBill Taylor  */
939e39c5baSBill Taylor 
949e39c5baSBill Taylor static int tavor_rsrc_mbox_init(tavor_state_t *state,
959e39c5baSBill Taylor     tavor_rsrc_mbox_info_t *info);
969e39c5baSBill Taylor static void tavor_rsrc_mbox_fini(tavor_state_t *state,
979e39c5baSBill Taylor     tavor_rsrc_mbox_info_t *info);
989e39c5baSBill Taylor 
999e39c5baSBill Taylor static int tavor_rsrc_hw_entries_init(tavor_state_t *state,
1009e39c5baSBill Taylor     tavor_rsrc_hw_entry_info_t *info);
1019e39c5baSBill Taylor static void tavor_rsrc_hw_entries_fini(tavor_state_t *state,
1029e39c5baSBill Taylor     tavor_rsrc_hw_entry_info_t *info);
1039e39c5baSBill Taylor 
1049e39c5baSBill Taylor static int tavor_rsrc_sw_handles_init(tavor_state_t *state,
1059e39c5baSBill Taylor     tavor_rsrc_sw_hdl_info_t *info);
1069e39c5baSBill Taylor static void tavor_rsrc_sw_handles_fini(tavor_state_t *state,
1079e39c5baSBill Taylor     tavor_rsrc_sw_hdl_info_t *info);
1089e39c5baSBill Taylor 
1099e39c5baSBill Taylor static int tavor_rsrc_pd_handles_init(tavor_state_t *state,
1109e39c5baSBill Taylor     tavor_rsrc_sw_hdl_info_t *info);
1119e39c5baSBill Taylor static void tavor_rsrc_pd_handles_fini(tavor_state_t *state,
1129e39c5baSBill Taylor     tavor_rsrc_sw_hdl_info_t *info);
1139e39c5baSBill Taylor 
1149e39c5baSBill Taylor /*
1159e39c5baSBill Taylor  * The following routines are used for allocating and freeing the specific
1169e39c5baSBill Taylor  * types of objects described above from their associated resource pools.
1179e39c5baSBill Taylor  */
1189e39c5baSBill Taylor static int tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t *pool_info,
1199e39c5baSBill Taylor     uint_t num, tavor_rsrc_t *hdl);
1209e39c5baSBill Taylor static void tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t *pool_info,
1219e39c5baSBill Taylor     tavor_rsrc_t *hdl);
1229e39c5baSBill Taylor 
1239e39c5baSBill Taylor static int tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t *pool_info,
1249e39c5baSBill Taylor     uint_t num, uint_t num_align, ddi_acc_handle_t acc_handle,
1259e39c5baSBill Taylor     uint_t sleepflag, tavor_rsrc_t *hdl);
1269e39c5baSBill Taylor static void tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t *pool_info,
1279e39c5baSBill Taylor     tavor_rsrc_t *hdl);
1289e39c5baSBill Taylor 
1299e39c5baSBill Taylor static int tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t *pool_info,
1309e39c5baSBill Taylor     uint_t sleepflag, tavor_rsrc_t *hdl);
1319e39c5baSBill Taylor static void tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t *pool_info,
1329e39c5baSBill Taylor     tavor_rsrc_t *hdl);
1339e39c5baSBill Taylor 
1349e39c5baSBill Taylor static int tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t *pool_info,
1359e39c5baSBill Taylor     uint_t sleepflag, tavor_rsrc_t *hdl);
1369e39c5baSBill Taylor static void tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t *pool_info,
1379e39c5baSBill Taylor     tavor_rsrc_t *hdl);
1389e39c5baSBill Taylor 
1399e39c5baSBill Taylor /*
1409e39c5baSBill Taylor  * The following routines are the constructors and destructors for several
1419e39c5baSBill Taylor  * of the SW handle type objects.  For certain types of SW handles objects
1429e39c5baSBill Taylor  * (all of which are implemented using kmem_cache), we need to do some
1439e39c5baSBill Taylor  * special field initialization (specifically, mutex_init/destroy).  These
1449e39c5baSBill Taylor  * routines enable that init and teardown.
1459e39c5baSBill Taylor  */
1469e39c5baSBill Taylor static int tavor_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
1479e39c5baSBill Taylor static void tavor_rsrc_pdhdl_destructor(void *pd, void *state);
1489e39c5baSBill Taylor static int tavor_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
1499e39c5baSBill Taylor static void tavor_rsrc_cqhdl_destructor(void *cq, void *state);
1509e39c5baSBill Taylor static int tavor_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
1519e39c5baSBill Taylor static void tavor_rsrc_qphdl_destructor(void *cq, void *state);
1529e39c5baSBill Taylor static int tavor_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
1539e39c5baSBill Taylor static void tavor_rsrc_srqhdl_destructor(void *srq, void *state);
1549e39c5baSBill Taylor static int tavor_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
1559e39c5baSBill Taylor static void tavor_rsrc_refcnt_destructor(void *rc, void *state);
1569e39c5baSBill Taylor static int tavor_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
1579e39c5baSBill Taylor static void tavor_rsrc_ahhdl_destructor(void *ah, void *state);
1589e39c5baSBill Taylor static int tavor_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
1599e39c5baSBill Taylor static void tavor_rsrc_mrhdl_destructor(void *mr, void *state);
1609e39c5baSBill Taylor 
1619e39c5baSBill Taylor /*
1629e39c5baSBill Taylor  * Special routine to calculate and return the size of a MCG object based
1639e39c5baSBill Taylor  * on current driver configuration (specifically, the number of QP per MCG
1649e39c5baSBill Taylor  * that has been configured.
1659e39c5baSBill Taylor  */
1669e39c5baSBill Taylor static int tavor_rsrc_mcg_entry_get_size(tavor_state_t *state,
1679e39c5baSBill Taylor     uint_t *mcg_size_shift);
1689e39c5baSBill Taylor 
1699e39c5baSBill Taylor 
1709e39c5baSBill Taylor /*
1719e39c5baSBill Taylor  * tavor_rsrc_alloc()
1729e39c5baSBill Taylor  *
1739e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
1749e39c5baSBill Taylor  *    The "sleepflag" parameter is used by all object allocators to
1759e39c5baSBill Taylor  *    determine whether to SLEEP for resources or not.
1769e39c5baSBill Taylor  */
1779e39c5baSBill Taylor int
tavor_rsrc_alloc(tavor_state_t * state,tavor_rsrc_type_t rsrc,uint_t num,uint_t sleepflag,tavor_rsrc_t ** hdl)1789e39c5baSBill Taylor tavor_rsrc_alloc(tavor_state_t *state, tavor_rsrc_type_t rsrc, uint_t num,
1799e39c5baSBill Taylor     uint_t sleepflag, tavor_rsrc_t **hdl)
1809e39c5baSBill Taylor {
1819e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
1829e39c5baSBill Taylor 	tavor_rsrc_t		*tmp_rsrc_hdl;
1839e39c5baSBill Taylor 	int			flag, status = DDI_FAILURE;
1849e39c5baSBill Taylor 
1859e39c5baSBill Taylor 	ASSERT(state != NULL);
1869e39c5baSBill Taylor 	ASSERT(hdl != NULL);
1879e39c5baSBill Taylor 
1889e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[rsrc];
1899e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
1909e39c5baSBill Taylor 
1919e39c5baSBill Taylor 	/*
1929e39c5baSBill Taylor 	 * Allocate space for the object used to track the resource handle
1939e39c5baSBill Taylor 	 */
1949e39c5baSBill Taylor 	flag = (sleepflag == TAVOR_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
1959e39c5baSBill Taylor 	tmp_rsrc_hdl = (tavor_rsrc_t *)kmem_cache_alloc(state->ts_rsrc_cache,
1969e39c5baSBill Taylor 	    flag);
1979e39c5baSBill Taylor 	if (tmp_rsrc_hdl == NULL) {
1989e39c5baSBill Taylor 		return (DDI_FAILURE);
1999e39c5baSBill Taylor 	}
2009e39c5baSBill Taylor 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
2019e39c5baSBill Taylor 
2029e39c5baSBill Taylor 	/*
2039e39c5baSBill Taylor 	 * Set rsrc_hdl type.  This is later used by the tavor_rsrc_free call
2049e39c5baSBill Taylor 	 * to know what type of resource is being freed.
2059e39c5baSBill Taylor 	 */
2069e39c5baSBill Taylor 	tmp_rsrc_hdl->rsrc_type = rsrc;
2079e39c5baSBill Taylor 
2089e39c5baSBill Taylor 	/*
2099e39c5baSBill Taylor 	 * Depending on resource type, call the appropriate alloc routine
2109e39c5baSBill Taylor 	 */
2119e39c5baSBill Taylor 	switch (rsrc_pool->rsrc_type) {
2129e39c5baSBill Taylor 	case TAVOR_IN_MBOX:
2139e39c5baSBill Taylor 	case TAVOR_OUT_MBOX:
2149e39c5baSBill Taylor 	case TAVOR_INTR_IN_MBOX:
2159e39c5baSBill Taylor 	case TAVOR_INTR_OUT_MBOX:
2169e39c5baSBill Taylor 		status = tavor_rsrc_mbox_alloc(rsrc_pool, num, tmp_rsrc_hdl);
2179e39c5baSBill Taylor 		break;
2189e39c5baSBill Taylor 
2199e39c5baSBill Taylor 	case TAVOR_QPC:
2209e39c5baSBill Taylor 	case TAVOR_CQC:
2219e39c5baSBill Taylor 	case TAVOR_SRQC:
2229e39c5baSBill Taylor 	case TAVOR_EQC:
2239e39c5baSBill Taylor 	case TAVOR_RDB:
2249e39c5baSBill Taylor 		/*
2259e39c5baSBill Taylor 		 * Because these objects are NOT accessed by Tavor driver
2269e39c5baSBill Taylor 		 * software, we set the acc_handle parameter to zero.  But
2279e39c5baSBill Taylor 		 * if they are allocated in multiples, we specify here that
2289e39c5baSBill Taylor 		 * they must be aligned on a more restrictive boundary.
2299e39c5baSBill Taylor 		 */
2309e39c5baSBill Taylor 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, num, 0,
2319e39c5baSBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2329e39c5baSBill Taylor 		break;
2339e39c5baSBill Taylor 
2349e39c5baSBill Taylor 	case TAVOR_MPT:
2359e39c5baSBill Taylor 		/*
2369e39c5baSBill Taylor 		 * Because these MPT objects are sometimes accessed by Tavor
2379e39c5baSBill Taylor 		 * driver software (FMR), we set the acc_handle parameter.  But
2389e39c5baSBill Taylor 		 * if they are allocated in multiples, we specify here that
2399e39c5baSBill Taylor 		 * they must be aligned on a more restrictive boundary.
2409e39c5baSBill Taylor 		 */
2419e39c5baSBill Taylor 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, num,
2429e39c5baSBill Taylor 		    state->ts_reg_ddrhdl, sleepflag, tmp_rsrc_hdl);
2439e39c5baSBill Taylor 		break;
2449e39c5baSBill Taylor 
2459e39c5baSBill Taylor 	case TAVOR_MCG:
2469e39c5baSBill Taylor 		/*
2479e39c5baSBill Taylor 		 * Tavor MCG entries are also NOT accessed by Tavor driver
2489e39c5baSBill Taylor 		 * software, but because MCG entries do not have the same
2499e39c5baSBill Taylor 		 * alignnment restrictions we loosen the constraint here.
2509e39c5baSBill Taylor 		 */
2519e39c5baSBill Taylor 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1, 0,
2529e39c5baSBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2539e39c5baSBill Taylor 		break;
2549e39c5baSBill Taylor 
2559e39c5baSBill Taylor 	case TAVOR_MTT:
2569e39c5baSBill Taylor 	case TAVOR_UDAV:
2579e39c5baSBill Taylor 		/*
2589e39c5baSBill Taylor 		 * Because MTT segments are among the few HW resources that
2599e39c5baSBill Taylor 		 * may be allocated in odd numbers, we specify a less
2609e39c5baSBill Taylor 		 * restrictive alignment than for the above resources.
2619e39c5baSBill Taylor 		 *
2629e39c5baSBill Taylor 		 * Also because both UDAV and MTT segment objects are read
2639e39c5baSBill Taylor 		 * and/or written by Tavor driver software, we set the
2649e39c5baSBill Taylor 		 * acc_handle parameter to point to the ddi_acc_handle_t for
2659e39c5baSBill Taylor 		 * the Tavor DDR memory.
2669e39c5baSBill Taylor 		 */
2679e39c5baSBill Taylor 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
2689e39c5baSBill Taylor 		    state->ts_reg_ddrhdl, sleepflag, tmp_rsrc_hdl);
2699e39c5baSBill Taylor 		break;
2709e39c5baSBill Taylor 
2719e39c5baSBill Taylor 	case TAVOR_UARPG:
2729e39c5baSBill Taylor 		/*
2739e39c5baSBill Taylor 		 * Because UAR pages are written by Tavor driver software (for
2749e39c5baSBill Taylor 		 * doorbells), we set the acc_handle parameter to point to
2759e39c5baSBill Taylor 		 * the ddi_acc_handle_t for the Tavor UAR memory.
2769e39c5baSBill Taylor 		 */
2779e39c5baSBill Taylor 		status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
2789e39c5baSBill Taylor 		    state->ts_reg_uarhdl, sleepflag, tmp_rsrc_hdl);
2799e39c5baSBill Taylor 		break;
2809e39c5baSBill Taylor 
2819e39c5baSBill Taylor 	case TAVOR_MRHDL:
2829e39c5baSBill Taylor 	case TAVOR_EQHDL:
2839e39c5baSBill Taylor 	case TAVOR_CQHDL:
2849e39c5baSBill Taylor 	case TAVOR_SRQHDL:
2859e39c5baSBill Taylor 	case TAVOR_AHHDL:
2869e39c5baSBill Taylor 	case TAVOR_QPHDL:
2879e39c5baSBill Taylor 	case TAVOR_REFCNT:
2889e39c5baSBill Taylor 		status = tavor_rsrc_swhdl_alloc(rsrc_pool, sleepflag,
2899e39c5baSBill Taylor 		    tmp_rsrc_hdl);
2909e39c5baSBill Taylor 		break;
2919e39c5baSBill Taylor 
2929e39c5baSBill Taylor 	case TAVOR_PDHDL:
2939e39c5baSBill Taylor 		status = tavor_rsrc_pdhdl_alloc(rsrc_pool, sleepflag,
2949e39c5baSBill Taylor 		    tmp_rsrc_hdl);
2959e39c5baSBill Taylor 		break;
2969e39c5baSBill Taylor 
2979e39c5baSBill Taylor 	default:
2989e39c5baSBill Taylor 		TAVOR_WARNING(state, "unexpected resource type in alloc");
2999e39c5baSBill Taylor 		break;
3009e39c5baSBill Taylor 	}
3019e39c5baSBill Taylor 
3029e39c5baSBill Taylor 	/*
3039e39c5baSBill Taylor 	 * If the resource allocation failed, then free the special resource
3049e39c5baSBill Taylor 	 * tracking structure and return failure.  Otherwise return the
3059e39c5baSBill Taylor 	 * handle for the resource tracking structure.
3069e39c5baSBill Taylor 	 */
3079e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
3089e39c5baSBill Taylor 		kmem_cache_free(state->ts_rsrc_cache, tmp_rsrc_hdl);
3099e39c5baSBill Taylor 		tmp_rsrc_hdl = NULL;
3109e39c5baSBill Taylor 		return (DDI_FAILURE);
3119e39c5baSBill Taylor 	} else {
3129e39c5baSBill Taylor 		*hdl = tmp_rsrc_hdl;
3139e39c5baSBill Taylor 		return (DDI_SUCCESS);
3149e39c5baSBill Taylor 	}
3159e39c5baSBill Taylor }
3169e39c5baSBill Taylor 
3179e39c5baSBill Taylor 
3189e39c5baSBill Taylor /*
3199e39c5baSBill Taylor  * tavor_rsrc_free()
3209e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
3219e39c5baSBill Taylor  */
3229e39c5baSBill Taylor void
tavor_rsrc_free(tavor_state_t * state,tavor_rsrc_t ** hdl)3239e39c5baSBill Taylor tavor_rsrc_free(tavor_state_t *state, tavor_rsrc_t **hdl)
3249e39c5baSBill Taylor {
3259e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
3269e39c5baSBill Taylor 
3279e39c5baSBill Taylor 	ASSERT(state != NULL);
3289e39c5baSBill Taylor 	ASSERT(hdl != NULL);
3299e39c5baSBill Taylor 
3309e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[(*hdl)->rsrc_type];
3319e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
3329e39c5baSBill Taylor 
3339e39c5baSBill Taylor 	/*
3349e39c5baSBill Taylor 	 * Depending on resource type, call the appropriate free routine
3359e39c5baSBill Taylor 	 */
3369e39c5baSBill Taylor 	switch (rsrc_pool->rsrc_type) {
3379e39c5baSBill Taylor 	case TAVOR_IN_MBOX:
3389e39c5baSBill Taylor 	case TAVOR_OUT_MBOX:
3399e39c5baSBill Taylor 	case TAVOR_INTR_IN_MBOX:
3409e39c5baSBill Taylor 	case TAVOR_INTR_OUT_MBOX:
3419e39c5baSBill Taylor 		tavor_rsrc_mbox_free(rsrc_pool, *hdl);
3429e39c5baSBill Taylor 		break;
3439e39c5baSBill Taylor 
3449e39c5baSBill Taylor 	case TAVOR_QPC:
3459e39c5baSBill Taylor 	case TAVOR_CQC:
3469e39c5baSBill Taylor 	case TAVOR_SRQC:
3479e39c5baSBill Taylor 	case TAVOR_EQC:
3489e39c5baSBill Taylor 	case TAVOR_RDB:
3499e39c5baSBill Taylor 	case TAVOR_MCG:
3509e39c5baSBill Taylor 	case TAVOR_MPT:
3519e39c5baSBill Taylor 	case TAVOR_MTT:
3529e39c5baSBill Taylor 	case TAVOR_UDAV:
3539e39c5baSBill Taylor 	case TAVOR_UARPG:
3549e39c5baSBill Taylor 		tavor_rsrc_hw_entry_free(rsrc_pool, *hdl);
3559e39c5baSBill Taylor 		break;
3569e39c5baSBill Taylor 
3579e39c5baSBill Taylor 	case TAVOR_MRHDL:
3589e39c5baSBill Taylor 	case TAVOR_EQHDL:
3599e39c5baSBill Taylor 	case TAVOR_CQHDL:
3609e39c5baSBill Taylor 	case TAVOR_SRQHDL:
3619e39c5baSBill Taylor 	case TAVOR_AHHDL:
3629e39c5baSBill Taylor 	case TAVOR_QPHDL:
3639e39c5baSBill Taylor 	case TAVOR_REFCNT:
3649e39c5baSBill Taylor 		tavor_rsrc_swhdl_free(rsrc_pool, *hdl);
3659e39c5baSBill Taylor 		break;
3669e39c5baSBill Taylor 
3679e39c5baSBill Taylor 	case TAVOR_PDHDL:
3689e39c5baSBill Taylor 		tavor_rsrc_pdhdl_free(rsrc_pool, *hdl);
3699e39c5baSBill Taylor 		break;
3709e39c5baSBill Taylor 
3719e39c5baSBill Taylor 	default:
3729e39c5baSBill Taylor 		TAVOR_WARNING(state, "unexpected resource type in free");
3739e39c5baSBill Taylor 		break;
3749e39c5baSBill Taylor 	}
3759e39c5baSBill Taylor 
3769e39c5baSBill Taylor 	/*
3779e39c5baSBill Taylor 	 * Free the special resource tracking structure, set the handle to
3789e39c5baSBill Taylor 	 * NULL, and return.
3799e39c5baSBill Taylor 	 */
3809e39c5baSBill Taylor 	kmem_cache_free(state->ts_rsrc_cache, *hdl);
3819e39c5baSBill Taylor 	*hdl = NULL;
3829e39c5baSBill Taylor }
3839e39c5baSBill Taylor 
3849e39c5baSBill Taylor 
3859e39c5baSBill Taylor /*
3869e39c5baSBill Taylor  * tavor_rsrc_init_phase1()
3879e39c5baSBill Taylor  *
3889e39c5baSBill Taylor  *    Completes the first phase of Tavor resource/configuration init.
3899e39c5baSBill Taylor  *    This involves creating the kmem_cache for the "tavor_rsrc_t"
3909e39c5baSBill Taylor  *    structs, allocating the space for the resource pool handles,
3919e39c5baSBill Taylor  *    and setting up the "Out" mailboxes.
3929e39c5baSBill Taylor  *
3939e39c5baSBill Taylor  *    When this function completes, the Tavor driver is ready to
3949e39c5baSBill Taylor  *    post the following commands which return information only in the
3959e39c5baSBill Taylor  *    "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
3969e39c5baSBill Taylor  *    If any of these commands are to be posted at this time, they must be
3979e39c5baSBill Taylor  *    done so only when "spinning" (as the outstanding command list and
3989e39c5baSBill Taylor  *    EQ setup code has not yet run)
3999e39c5baSBill Taylor  *
4009e39c5baSBill Taylor  *    Context: Only called from attach() path context
4019e39c5baSBill Taylor  */
4029e39c5baSBill Taylor int
tavor_rsrc_init_phase1(tavor_state_t * state)4039e39c5baSBill Taylor tavor_rsrc_init_phase1(tavor_state_t *state)
4049e39c5baSBill Taylor {
4059e39c5baSBill Taylor 	tavor_rsrc_pool_info_t		*rsrc_pool;
4069e39c5baSBill Taylor 	tavor_rsrc_mbox_info_t 		mbox_info;
4079e39c5baSBill Taylor 	tavor_rsrc_cleanup_level_t	cleanup;
4089e39c5baSBill Taylor 	tavor_cfg_profile_t		*cfgprof;
4099e39c5baSBill Taylor 	uint64_t			num, size;
4109e39c5baSBill Taylor 	int				status;
411*2570281cSToomas Soome 	char				*rsrc_name;
4129e39c5baSBill Taylor 
4139e39c5baSBill Taylor 	ASSERT(state != NULL);
4149e39c5baSBill Taylor 
4159e39c5baSBill Taylor 	/* This is where Phase 1 of resource initialization begins */
4169e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL0;
4179e39c5baSBill Taylor 
4189e39c5baSBill Taylor 	/* Build kmem cache name from Tavor instance */
4199e39c5baSBill Taylor 	rsrc_name = (char *)kmem_zalloc(TAVOR_RSRC_NAME_MAXLEN, KM_SLEEP);
4209e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_RSRC_CACHE);
4219e39c5baSBill Taylor 
4229e39c5baSBill Taylor 	/*
4239e39c5baSBill Taylor 	 * Create the kmem_cache for "tavor_rsrc_t" structures
4249e39c5baSBill Taylor 	 * (kmem_cache_create will SLEEP until successful)
4259e39c5baSBill Taylor 	 */
4269e39c5baSBill Taylor 	state->ts_rsrc_cache = kmem_cache_create(rsrc_name,
4279e39c5baSBill Taylor 	    sizeof (tavor_rsrc_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
4289e39c5baSBill Taylor 
4299e39c5baSBill Taylor 	/*
4309e39c5baSBill Taylor 	 * Allocate an array of tavor_rsrc_pool_info_t's (used in all
4319e39c5baSBill Taylor 	 * subsequent resource allocations)
4329e39c5baSBill Taylor 	 */
4339e39c5baSBill Taylor 	state->ts_rsrc_hdl = kmem_zalloc(TAVOR_NUM_RESOURCES *
4349e39c5baSBill Taylor 	    sizeof (tavor_rsrc_pool_info_t), KM_SLEEP);
4359e39c5baSBill Taylor 
4369e39c5baSBill Taylor 	cfgprof = state->ts_cfg_profile;
4379e39c5baSBill Taylor 
4389e39c5baSBill Taylor 	/*
4399e39c5baSBill Taylor 	 * Initialize the resource pool for "Out" mailboxes.  Notice that
4409e39c5baSBill Taylor 	 * the number of "Out" mailboxes, their size, and their location
4419e39c5baSBill Taylor 	 * (DDR or system memory) is configurable.  By default, however,
4429e39c5baSBill Taylor 	 * all "Out" mailboxes are located in system memory only (because
4439e39c5baSBill Taylor 	 * they are primarily read from and never written to)
4449e39c5baSBill Taylor 	 */
4459e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_outmbox);
4469e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
4479e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_OUT_MBOX];
4489e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_OUT_MBOX;
4499e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_SYSMEM;
4509e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
4519e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
4529e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = size;
4539e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
4549e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
4559e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_OUTMBOX_VMEM);
4569e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
4579e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
4589e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
4599e39c5baSBill Taylor 	mbox_info.mbi_rsrcname	  = rsrc_name;
4609e39c5baSBill Taylor 	status = tavor_rsrc_mbox_init(state, &mbox_info);
4619e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
4629e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
4639e39c5baSBill Taylor 		goto rsrcinitp1_fail;
4649e39c5baSBill Taylor 	}
4659e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL1;
4669e39c5baSBill Taylor 
4679e39c5baSBill Taylor 	/*
4689e39c5baSBill Taylor 	 * Initialize the Tavor "Out" mailbox list.  This step actually uses
4699e39c5baSBill Taylor 	 * the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
4709e39c5baSBill Taylor 	 * "Out" mailboxes, bind them for DMA access, and arrange them into
4719e39c5baSBill Taylor 	 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
4729e39c5baSBill Taylor 	 * for more details)
4739e39c5baSBill Taylor 	 */
4749e39c5baSBill Taylor 	status = tavor_outmbox_list_init(state);
4759e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
4769e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
4779e39c5baSBill Taylor 		goto rsrcinitp1_fail;
4789e39c5baSBill Taylor 	}
4799e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL2;
4809e39c5baSBill Taylor 
4819e39c5baSBill Taylor 	/*
4829e39c5baSBill Taylor 	 * Initialize the resource pool for interrupt "Out" mailboxes.  Notice
4839e39c5baSBill Taylor 	 * that the number of interrupt "Out" mailboxes, their size, and their
4849e39c5baSBill Taylor 	 * location (DDR or system memory) is configurable.  By default,
4859e39c5baSBill Taylor 	 * however, all interrupt "Out" mailboxes are located in system memory
4869e39c5baSBill Taylor 	 * only (because they are primarily read from and never written to)
4879e39c5baSBill Taylor 	 */
4889e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_outmbox);
4899e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
4909e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_INTR_OUT_MBOX];
4919e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_INTR_OUT_MBOX;
4929e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_SYSMEM;
4939e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
4949e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
4959e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = size;
4969e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
4979e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
4989e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INTR_OUTMBOX_VMEM);
4999e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
5009e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
5019e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
5029e39c5baSBill Taylor 	mbox_info.mbi_rsrcname	  = rsrc_name;
5039e39c5baSBill Taylor 	status = tavor_rsrc_mbox_init(state, &mbox_info);
5049e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
5059e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
5069e39c5baSBill Taylor 		goto rsrcinitp1_fail;
5079e39c5baSBill Taylor 	}
5089e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL3;
5099e39c5baSBill Taylor 
5109e39c5baSBill Taylor 	/*
5119e39c5baSBill Taylor 	 * Initialize the Tavor "Out" mailbox list.  This step actually uses
5129e39c5baSBill Taylor 	 * the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
5139e39c5baSBill Taylor 	 * "Out" mailboxes, bind them for DMA access, and arrange them into
5149e39c5baSBill Taylor 	 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
5159e39c5baSBill Taylor 	 * for more details)
5169e39c5baSBill Taylor 	 */
5179e39c5baSBill Taylor 	status = tavor_intr_outmbox_list_init(state);
5189e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
5199e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
5209e39c5baSBill Taylor 		goto rsrcinitp1_fail;
5219e39c5baSBill Taylor 	}
5229e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE;
5239e39c5baSBill Taylor 
5249e39c5baSBill Taylor 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
5259e39c5baSBill Taylor 	return (DDI_SUCCESS);
5269e39c5baSBill Taylor 
5279e39c5baSBill Taylor rsrcinitp1_fail:
5289e39c5baSBill Taylor 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
5299e39c5baSBill Taylor 	return (status);
5309e39c5baSBill Taylor }
5319e39c5baSBill Taylor 
5329e39c5baSBill Taylor 
5339e39c5baSBill Taylor /*
5349e39c5baSBill Taylor  * tavor_rsrc_init_phase2()
5359e39c5baSBill Taylor  *    Context: Only called from attach() path context
5369e39c5baSBill Taylor  */
5379e39c5baSBill Taylor int
tavor_rsrc_init_phase2(tavor_state_t * state)5389e39c5baSBill Taylor tavor_rsrc_init_phase2(tavor_state_t *state)
5399e39c5baSBill Taylor {
5409e39c5baSBill Taylor 	tavor_rsrc_sw_hdl_info_t	hdl_info;
5419e39c5baSBill Taylor 	tavor_rsrc_hw_entry_info_t	entry_info;
5429e39c5baSBill Taylor 	tavor_rsrc_mbox_info_t		mbox_info;
5439e39c5baSBill Taylor 	tavor_rsrc_pool_info_t		*rsrc_pool;
5449e39c5baSBill Taylor 	tavor_rsrc_cleanup_level_t	cleanup;
5459e39c5baSBill Taylor 	tavor_cfg_profile_t		*cfgprof;
5469e39c5baSBill Taylor 	uint64_t			num, max, size, num_prealloc;
5479e39c5baSBill Taylor 	uint64_t			ddr_size, fw_size;
5489e39c5baSBill Taylor 	uint_t				mcg_size, mcg_size_shift;
5499e39c5baSBill Taylor 	uint_t				uarscr_size, mttsegment_sz;
5509e39c5baSBill Taylor 	int				status;
551*2570281cSToomas Soome 	char				*rsrc_name;
5529e39c5baSBill Taylor 
5539e39c5baSBill Taylor 	ASSERT(state != NULL);
5549e39c5baSBill Taylor 
5559e39c5baSBill Taylor 	/* Phase 2 initialization begins where Phase 1 left off */
5569e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE;
5579e39c5baSBill Taylor 
5589e39c5baSBill Taylor 	/*
5599e39c5baSBill Taylor 	 * Calculate the extent of the DDR size and portion of which that
5609e39c5baSBill Taylor 	 * is already reserved for Tavor firmware.  (Note: this information
5619e39c5baSBill Taylor 	 * is available because the QUERY_DDR and QUERY_FW commands have
5629e39c5baSBill Taylor 	 * been posted to Tavor firmware prior to calling this routine)
5639e39c5baSBill Taylor 	 */
5649e39c5baSBill Taylor 	ddr_size = state->ts_ddr.ddr_endaddr - state->ts_ddr.ddr_baseaddr + 1;
5659e39c5baSBill Taylor 	fw_size  = state->ts_fw.fw_endaddr - state->ts_fw.fw_baseaddr + 1;
5669e39c5baSBill Taylor 
5679e39c5baSBill Taylor 	/* Build the DDR vmem arena name from Tavor instance */
5689e39c5baSBill Taylor 	rsrc_name = (char *)kmem_zalloc(TAVOR_RSRC_NAME_MAXLEN, KM_SLEEP);
5699e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_VMEM);
5709e39c5baSBill Taylor 
5719e39c5baSBill Taylor 	/*
5729e39c5baSBill Taylor 	 * Do a vmem_create for the entire DDR range (not including the
5739e39c5baSBill Taylor 	 * portion consumed by Tavor firmware).  This creates the vmem arena
5749e39c5baSBill Taylor 	 * from which all other DDR objects (specifically, tables of HW
5759e39c5baSBill Taylor 	 * entries) will be allocated.
5769e39c5baSBill Taylor 	 */
5779e39c5baSBill Taylor 	state->ts_ddrvmem = vmem_create(rsrc_name,
5789e39c5baSBill Taylor 	    (void *)(uintptr_t)state->ts_ddr.ddr_baseaddr, (ddr_size - fw_size),
5799e39c5baSBill Taylor 	    sizeof (uint64_t), NULL, NULL, NULL, 0, VM_SLEEP);
5809e39c5baSBill Taylor 	if (state->ts_ddrvmem == NULL) {
5819e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
5829e39c5baSBill Taylor 		goto rsrcinitp2_fail;
5839e39c5baSBill Taylor 	}
5849e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL5;
5859e39c5baSBill Taylor 
5869e39c5baSBill Taylor 	/*
5879e39c5baSBill Taylor 	 * Initialize the resource pools for all objects that exist in
5889e39c5baSBill Taylor 	 * Tavor DDR memory.  This includes ("In") mailboxes, context tables
5899e39c5baSBill Taylor 	 * (QPC, CQC, EQC, etc...), and other miscellaneous HW objects.
5909e39c5baSBill Taylor 	 */
5919e39c5baSBill Taylor 	cfgprof = state->ts_cfg_profile;
5929e39c5baSBill Taylor 
5939e39c5baSBill Taylor 	/*
5949e39c5baSBill Taylor 	 * Initialize the resource pool for the MPT table entries.  Notice
5959e39c5baSBill Taylor 	 * that the number of MPTs is configurable.  The configured value must
5969e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
5979e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that a certain
5989e39c5baSBill Taylor 	 * number of MPTs must be set aside for Tavor firmware use.
5999e39c5baSBill Taylor 	 */
6009e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
6019e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
6029e39c5baSBill Taylor 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_mpt);
6039e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MPT];
6049e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_MPT;
6059e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
6069e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_MPT_SIZE * num);
6079e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_MPT_SIZE_SHIFT;
6089e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = TAVOR_MPT_SIZE;
6099e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (TAVOR_MPT_SIZE * num);
6109e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
6119e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
6129e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MPT_VMEM);
6139e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
6149e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
6159e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
6169e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
6179e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
6189e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
6199e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
6209e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
6219e39c5baSBill Taylor 		goto rsrcinitp2_fail;
6229e39c5baSBill Taylor 	}
6239e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL6;
6249e39c5baSBill Taylor 
6259e39c5baSBill Taylor 	/*
6269e39c5baSBill Taylor 	 * Initialize the resource pool for the MTT table entries.  Notice
6279e39c5baSBill Taylor 	 * that the number of MTTs is configurable.  The configured value must
6289e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
6299e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that a certain
6309e39c5baSBill Taylor 	 * number of MTT segments must be set aside for Tavor firmware use.
6319e39c5baSBill Taylor 	 */
6329e39c5baSBill Taylor 	mttsegment_sz = (TAVOR_MTTSEG_SIZE << TAVOR_MTT_SIZE_SHIFT);
6339e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_mttseg);
6349e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_mttseg);
6359e39c5baSBill Taylor 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_mttseg);
6369e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MTT];
6379e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_MTT;
6389e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
6399e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_MTT_SIZE * num);
6409e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_MTT_SIZE_SHIFT;
6419e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = mttsegment_sz;
6429e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (TAVOR_MTT_SIZE * num);
6439e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
6449e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
6459e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MTT_VMEM);
6469e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
6479e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
6489e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
6499e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
6509e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
6519e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
6529e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
6539e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
6549e39c5baSBill Taylor 		goto rsrcinitp2_fail;
6559e39c5baSBill Taylor 	}
6569e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL7;
6579e39c5baSBill Taylor 
6589e39c5baSBill Taylor 	/*
6599e39c5baSBill Taylor 	 * Initialize the resource pool for the QPC table entries.  Notice
6609e39c5baSBill Taylor 	 * that the number of QPs is configurable.  The configured value must
6619e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
6629e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that a certain
6639e39c5baSBill Taylor 	 * number of QP contexts must be set aside for Tavor firmware use.
6649e39c5baSBill Taylor 	 */
6659e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
6669e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
6679e39c5baSBill Taylor 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_qp);
6689e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_QPC];
6699e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_QPC;
6709e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
6719e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_QPC_SIZE * num);
6729e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_QPC_SIZE_SHIFT;
6739e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = TAVOR_QPC_SIZE;
6749e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (TAVOR_QPC_SIZE * num);
6759e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
6769e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
6779e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_QPC_VMEM);
6789e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
6799e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
6809e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
6819e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
6829e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
6839e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
6849e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
6859e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
6869e39c5baSBill Taylor 		goto rsrcinitp2_fail;
6879e39c5baSBill Taylor 	}
6889e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL8;
6899e39c5baSBill Taylor 
6909e39c5baSBill Taylor 	/*
6919e39c5baSBill Taylor 	 * Initialize the resource pool for the RDB table entries.  Notice
6929e39c5baSBill Taylor 	 * that the number of RDBs is configurable.  The configured value must
6939e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
6949e39c5baSBill Taylor 	 * command) or the initialization will fail.
6959e39c5baSBill Taylor 	 */
6969e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_rdb);
6979e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_ra_glob);
6989e39c5baSBill Taylor 	num_prealloc = 0;
6999e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_RDB];
7009e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_RDB;
7019e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
7029e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_RDB_SIZE * num);
7039e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_RDB_SIZE_SHIFT;
7049e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = TAVOR_RDB_SIZE;
7059e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (TAVOR_RDB_SIZE * num);
7069e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
7079e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
7089e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_RDB_VMEM);
7099e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
7109e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
7119e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
7129e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
7139e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
7149e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
7159e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7169e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
7179e39c5baSBill Taylor 		goto rsrcinitp2_fail;
7189e39c5baSBill Taylor 	}
7199e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL9;
7209e39c5baSBill Taylor 
7219e39c5baSBill Taylor 	/*
7229e39c5baSBill Taylor 	 * Initialize the resource pool for the CQC table entries.  Notice
7239e39c5baSBill Taylor 	 * that the number of CQs is configurable.  The configured value must
7249e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
7259e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that a certain
7269e39c5baSBill Taylor 	 * number of CQ contexts must be set aside for Tavor firmware use.
7279e39c5baSBill Taylor 	 */
7289e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
7299e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_cq);
7309e39c5baSBill Taylor 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_cq);
7319e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_CQC];
7329e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_CQC;
7339e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
7349e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_CQC_SIZE * num);
7359e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_CQC_SIZE_SHIFT;
7369e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = TAVOR_CQC_SIZE;
7379e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (TAVOR_CQC_SIZE * num);
7389e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
7399e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
7409e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_CQC_VMEM);
7419e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
7429e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
7439e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
7449e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
7459e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
7469e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
7479e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7489e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
7499e39c5baSBill Taylor 		goto rsrcinitp2_fail;
7509e39c5baSBill Taylor 	}
7519e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL10;
7529e39c5baSBill Taylor 
7539e39c5baSBill Taylor 	/*
7549e39c5baSBill Taylor 	 * Initialize the resource pool for the Extended QPC table entries.
7559e39c5baSBill Taylor 	 * Notice that the number of EQPCs must be the same as the number
7569e39c5baSBill Taylor 	 * of QP contexts.  So the initialization is constructed in a
7579e39c5baSBill Taylor 	 * similar way as above (for TAVOR_QPC).  One notable difference
7589e39c5baSBill Taylor 	 * here, however, is that by setting the rsrc_quantum field to
7599e39c5baSBill Taylor 	 * zero (indicating a zero-sized object) we indicate that the
7609e39c5baSBill Taylor 	 * object is not allocatable.  The EQPC table is, in fact, managed
7619e39c5baSBill Taylor 	 * internally by the hardware and it is, therefore, unnecessary to
7629e39c5baSBill Taylor 	 * initialize an additional vmem_arena for this type of object.
7639e39c5baSBill Taylor 	 */
7649e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
7659e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
7669e39c5baSBill Taylor 	num_prealloc = 0;
7679e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQPC];
7689e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_EQPC;
7699e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
7709e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_EQPC_SIZE * num);
7719e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = 0;
7729e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = 0;
7739e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = TAVOR_EQPC_SIZE;
7749e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
7759e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
7769e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_EQPC_VMEM);
7779e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
7789e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
7799e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
7809e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
7819e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
7829e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
7839e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7849e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
7859e39c5baSBill Taylor 		goto rsrcinitp2_fail;
7869e39c5baSBill Taylor 	}
7879e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL11;
7889e39c5baSBill Taylor 
7899e39c5baSBill Taylor 	/*
7909e39c5baSBill Taylor 	 * Initialize the resource pool for the UD address vector table
7919e39c5baSBill Taylor 	 * entries.  Notice that the number of UDAVs is configurable.  The
7929e39c5baSBill Taylor 	 * configured value must be less that the maximum value (obtained
7939e39c5baSBill Taylor 	 * from the QUERY_DEV_LIM command) or the initialization will fail.
7949e39c5baSBill Taylor 	 */
7959e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_ah);
7969e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_av);
7979e39c5baSBill Taylor 	num_prealloc = 0;
7989e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UDAV];
7999e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_UDAV;
8009e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
8019e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_UDAV_SIZE * num);
8029e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_UDAV_SIZE_SHIFT;
8039e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = TAVOR_UDAV_SIZE;
8049e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = TAVOR_UDAV_SIZE;
8059e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
8069e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
8079e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_UDAV_VMEM);
8089e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
8099e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
8109e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
8119e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
8129e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
8139e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
8149e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
8159e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
8169e39c5baSBill Taylor 		goto rsrcinitp2_fail;
8179e39c5baSBill Taylor 	}
8189e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL12;
8199e39c5baSBill Taylor 
8209e39c5baSBill Taylor 	/*
8219e39c5baSBill Taylor 	 * Initialize the resource pool for the UAR scratch table entries.
8229e39c5baSBill Taylor 	 * Notice that the number of UARSCRs is configurable.  The configured
8239e39c5baSBill Taylor 	 * value must be less that the maximum value (obtained from the
8249e39c5baSBill Taylor 	 * QUERY_DEV_LIM command) or the initialization will fail.
8259e39c5baSBill Taylor 	 * Like the EQPCs above, UARSCR objects are not allocatable.  The
8269e39c5baSBill Taylor 	 * UARSCR table is also managed internally by the hardware and it
8279e39c5baSBill Taylor 	 * is, therefore, unnecessary to initialize an additional vmem_arena
8289e39c5baSBill Taylor 	 * for this type of object.  We indicate this by setting the
8299e39c5baSBill Taylor 	 * rsrc_quantum field to zero (indicating a zero-sized object).
8309e39c5baSBill Taylor 	 */
8319e39c5baSBill Taylor 	uarscr_size = state->ts_devlim.uarscr_entry_sz;
8329e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_uar);
8339e39c5baSBill Taylor 	max = ((uint64_t)1 << (state->ts_devlim.log_max_uar_sz + 20 -
8349e39c5baSBill Taylor 	    PAGESHIFT));
8359e39c5baSBill Taylor 	num_prealloc = 0;
8369e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UAR_SCR];
8379e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_UAR_SCR;
8389e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
8399e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (uarscr_size * num);
8409e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = 0;
8419e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = 0;
8429e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = uarscr_size;
8439e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
8449e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
8459e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_UARSCR_VMEM);
8469e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
8479e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
8489e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
8499e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
8509e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
8519e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
8529e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
8539e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
8549e39c5baSBill Taylor 		goto rsrcinitp2_fail;
8559e39c5baSBill Taylor 	}
8569e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL13;
8579e39c5baSBill Taylor 
8589e39c5baSBill Taylor 	/*
8599e39c5baSBill Taylor 	 * Initialize the resource pool for the SRQC table entries.  Notice
8609e39c5baSBill Taylor 	 * that the number of SRQs is configurable.  The configured value must
8619e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
8629e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that a certain
8639e39c5baSBill Taylor 	 * number of SRQ contexts must be set aside for Tavor firmware use.
8649e39c5baSBill Taylor 	 *
8659e39c5baSBill Taylor 	 * Note: We only allocate these resources if SRQ is enabled in the
8669e39c5baSBill Taylor 	 * config profile; see below.
8679e39c5baSBill Taylor 	 */
8689e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
8699e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_srq);
8709e39c5baSBill Taylor 	num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_srq);
8719e39c5baSBill Taylor 
8729e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_SRQC];
8739e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_SRQC;
8749e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
8759e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_SRQC_SIZE * num);
8769e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_SRQC_SIZE_SHIFT;
8779e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = TAVOR_SRQC_SIZE;
8789e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (TAVOR_SRQC_SIZE * num);
8799e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
8809e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
8819e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_SRQC_VMEM);
8829e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
8839e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
8849e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
8859e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
8869e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
8879e39c5baSBill Taylor 
8889e39c5baSBill Taylor 	/*
8899e39c5baSBill Taylor 	 * SRQ support is configurable.  Only if SRQ is enabled (the default)
8909e39c5baSBill Taylor 	 * do we actually try to configure these resources.  Otherwise, we
8919e39c5baSBill Taylor 	 * simply set the cleanup level and continue on to the next resource
8929e39c5baSBill Taylor 	 */
8939e39c5baSBill Taylor 	if (state->ts_cfg_profile->cp_srq_enable != 0) {
8949e39c5baSBill Taylor 		status = tavor_rsrc_hw_entries_init(state, &entry_info);
8959e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
8969e39c5baSBill Taylor 			tavor_rsrc_fini(state, cleanup);
8979e39c5baSBill Taylor 			goto rsrcinitp2_fail;
8989e39c5baSBill Taylor 		}
8999e39c5baSBill Taylor 	}
9009e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL14;
9019e39c5baSBill Taylor 
9029e39c5baSBill Taylor 	/*
9039e39c5baSBill Taylor 	 * Initialize the resource pool for "In" mailboxes.  Notice that
9049e39c5baSBill Taylor 	 * the number of "In" mailboxes, their size, and their location
9059e39c5baSBill Taylor 	 * (DDR or system memory) is configurable.  By default, however,
9069e39c5baSBill Taylor 	 * all "In" mailboxes are located in system memory only (because
9079e39c5baSBill Taylor 	 * they are primarily written to and rarely read from)
9089e39c5baSBill Taylor 	 */
9099e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_inmbox);
9109e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
9119e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_IN_MBOX];
9129e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_IN_MBOX;
9139e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
9149e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
9159e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
9169e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = size;
9179e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
9189e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
9199e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INMBOX_VMEM);
9209e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
9219e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
9229e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
9239e39c5baSBill Taylor 	mbox_info.mbi_rsrcname	  = rsrc_name;
9249e39c5baSBill Taylor 	status = tavor_rsrc_mbox_init(state, &mbox_info);
9259e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9269e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
9279e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9289e39c5baSBill Taylor 	}
9299e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL15;
9309e39c5baSBill Taylor 
9319e39c5baSBill Taylor 	/*
9329e39c5baSBill Taylor 	 * Initialize the Tavor "In" mailbox list.  This step actually uses
9339e39c5baSBill Taylor 	 * the tavor_rsrc_alloc() for TAVOR_IN_MBOX to preallocate the
9349e39c5baSBill Taylor 	 * "In" mailboxes, bind them for DMA access, and arrange them into
9359e39c5baSBill Taylor 	 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
9369e39c5baSBill Taylor 	 * for more details)
9379e39c5baSBill Taylor 	 */
9389e39c5baSBill Taylor 	status = tavor_inmbox_list_init(state);
9399e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9409e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
9419e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9429e39c5baSBill Taylor 	}
9439e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL16;
9449e39c5baSBill Taylor 
9459e39c5baSBill Taylor 	/*
9469e39c5baSBill Taylor 	 * Initialize the resource pool for interrupt "In" mailboxes.  Notice
9479e39c5baSBill Taylor 	 * that the number of interrupt "In" mailboxes, their size, and their
9489e39c5baSBill Taylor 	 * location (DDR or system memory) is configurable.  By default,
9499e39c5baSBill Taylor 	 * however, all interrupt "In" mailboxes are located in system memory
9509e39c5baSBill Taylor 	 * only (because they are primarily written to and rarely read from)
9519e39c5baSBill Taylor 	 */
9529e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_inmbox);
9539e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
9549e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_INTR_IN_MBOX];
9559e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_INTR_IN_MBOX;
9569e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
9579e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
9589e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
9599e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = size;
9609e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = TAVOR_MBOX_ALIGN;
9619e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
9629e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INTR_INMBOX_VMEM);
9639e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
9649e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
9659e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
9669e39c5baSBill Taylor 	mbox_info.mbi_rsrcname	  = rsrc_name;
9679e39c5baSBill Taylor 	status = tavor_rsrc_mbox_init(state, &mbox_info);
9689e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9699e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
9709e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9719e39c5baSBill Taylor 	}
9729e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL17;
9739e39c5baSBill Taylor 
9749e39c5baSBill Taylor 	/*
9759e39c5baSBill Taylor 	 * Initialize the Tavor interrupt "In" mailbox list.  This step
9769e39c5baSBill Taylor 	 * actually uses the tavor_rsrc_alloc() for TAVOR_IN_MBOX to
9779e39c5baSBill Taylor 	 * preallocate the interrupt "In" mailboxes, bind them for DMA access,
9789e39c5baSBill Taylor 	 * and arrange them into an easily accessed fast-allocation mechanism
9799e39c5baSBill Taylor 	 * (see tavor_cmd.c for more details)
9809e39c5baSBill Taylor 	 */
9819e39c5baSBill Taylor 	status = tavor_intr_inmbox_list_init(state);
9829e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9839e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
9849e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9859e39c5baSBill Taylor 	}
9869e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL18;
9879e39c5baSBill Taylor 
9889e39c5baSBill Taylor 	/*
9899e39c5baSBill Taylor 	 * Initialize the Tavor command handling interfaces.  This step
9909e39c5baSBill Taylor 	 * sets up the outstanding command tracking mechanism for easy access
9919e39c5baSBill Taylor 	 * and fast allocation (see tavor_cmd.c for more details).
9929e39c5baSBill Taylor 	 */
9939e39c5baSBill Taylor 	status = tavor_outstanding_cmdlist_init(state);
9949e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9959e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
9969e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9979e39c5baSBill Taylor 	}
9989e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL19;
9999e39c5baSBill Taylor 
10009e39c5baSBill Taylor 	/*
10019e39c5baSBill Taylor 	 * Calculate (and validate) the size of Multicast Group (MCG) entries
10029e39c5baSBill Taylor 	 */
10039e39c5baSBill Taylor 	status = tavor_rsrc_mcg_entry_get_size(state, &mcg_size_shift);
10049e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
10059e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
10069e39c5baSBill Taylor 		goto rsrcinitp2_fail;
10079e39c5baSBill Taylor 	}
10089e39c5baSBill Taylor 	mcg_size = TAVOR_MCGMEM_SZ(state);
10099e39c5baSBill Taylor 
10109e39c5baSBill Taylor 	/*
10119e39c5baSBill Taylor 	 * Initialize the resource pool for the MCG table entries.  Notice
10129e39c5baSBill Taylor 	 * that the number of MCGs is configurable.  The configured value must
10139e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
10149e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that a certain
10159e39c5baSBill Taylor 	 * number of MCGs must be set aside for Tavor firmware use (they
10169e39c5baSBill Taylor 	 * correspond to the number of MCGs used by the internal hash
10179e39c5baSBill Taylor 	 * function.
10189e39c5baSBill Taylor 	 */
10199e39c5baSBill Taylor 	num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
10209e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_mcg);
10219e39c5baSBill Taylor 	num_prealloc = ((uint64_t)1 << cfgprof->cp_log_num_mcg_hash);
10229e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MCG];
10239e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_MCG;
10249e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
10259e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (mcg_size * num);
10269e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = mcg_size_shift;
10279e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = mcg_size;
10289e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = mcg_size;
10299e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
10309e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
10319e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MCG_VMEM);
10329e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
10339e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
10349e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
10359e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
10369e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
10379e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
10389e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
10399e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
10409e39c5baSBill Taylor 		goto rsrcinitp2_fail;
10419e39c5baSBill Taylor 	}
10429e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL20;
10439e39c5baSBill Taylor 
10449e39c5baSBill Taylor 	/*
10459e39c5baSBill Taylor 	 * Initialize the resource pool for the EQC table entries.  Notice
10469e39c5baSBill Taylor 	 * that the number of EQs is hardcoded.  The hardcoded value should
10479e39c5baSBill Taylor 	 * be less that the maximum value (obtained from the QUERY_DEV_LIM
10489e39c5baSBill Taylor 	 * command) or the initialization will fail.
10499e39c5baSBill Taylor 	 */
10509e39c5baSBill Taylor 	num = TAVOR_NUM_EQ;
10519e39c5baSBill Taylor 	max = ((uint64_t)1 << state->ts_devlim.log_max_eq);
10529e39c5baSBill Taylor 	num_prealloc = 0;
10539e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQC];
10549e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_EQC;
10559e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_DDR;
10569e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (TAVOR_EQC_SIZE * num);
10579e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = TAVOR_EQC_SIZE_SHIFT;
10589e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = TAVOR_EQC_SIZE;
10599e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (TAVOR_EQC_SIZE * num);
10609e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
10619e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = NULL;
10629e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_EQC_VMEM);
10639e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
10649e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
10659e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
10669e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
10679e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
10689e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
10699e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
10709e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
10719e39c5baSBill Taylor 		goto rsrcinitp2_fail;
10729e39c5baSBill Taylor 	}
10739e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL21;
10749e39c5baSBill Taylor 
10759e39c5baSBill Taylor 	/*
10769e39c5baSBill Taylor 	 * Initialize the resource pools for all objects that exist in
10779e39c5baSBill Taylor 	 * system memory.  This includes PD handles, MR handle, EQ handles,
10789e39c5baSBill Taylor 	 * QP handles, etc.  These objects are almost entirely managed using
10799e39c5baSBill Taylor 	 * kmem_cache routines.  (See comment above for more detail)
10809e39c5baSBill Taylor 	 */
10819e39c5baSBill Taylor 
10829e39c5baSBill Taylor 	/*
10839e39c5baSBill Taylor 	 * Initialize the resource pool for the PD handles.  Notice
10849e39c5baSBill Taylor 	 * that the number of PDHDLs is configurable.  The configured value
10859e39c5baSBill Taylor 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
10869e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that the PD
10879e39c5baSBill Taylor 	 * handle has constructor and destructor methods associated with it.
10889e39c5baSBill Taylor 	 */
10899e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_PDHDL];
10909e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_PDHDL;
10919e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
10929e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_pd_s);
10939e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
10949e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_PDHDL_CACHE);
10959e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_pd);
10969e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_pd);
10979e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
10989e39c5baSBill Taylor 	hdl_info.swi_constructor = tavor_rsrc_pdhdl_constructor;
10999e39c5baSBill Taylor 	hdl_info.swi_destructor	 = tavor_rsrc_pdhdl_destructor;
11009e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
11019e39c5baSBill Taylor 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
11029e39c5baSBill Taylor 	status = tavor_rsrc_pd_handles_init(state, &hdl_info);
11039e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
11049e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
11059e39c5baSBill Taylor 		goto rsrcinitp2_fail;
11069e39c5baSBill Taylor 	}
11079e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL22;
11089e39c5baSBill Taylor 
11099e39c5baSBill Taylor 	/*
11109e39c5baSBill Taylor 	 * Initialize the resource pool for the MR handles.  Notice
11119e39c5baSBill Taylor 	 * that the number of MRHDLs is configurable.  The configured value
11129e39c5baSBill Taylor 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
11139e39c5baSBill Taylor 	 * command) or the initialization will fail.
11149e39c5baSBill Taylor 	 */
11159e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MRHDL];
11169e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_MRHDL;
11179e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
11189e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_mr_s);
11199e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
11209e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_MRHDL_CACHE);
11219e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
11229e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
11239e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
11249e39c5baSBill Taylor 	hdl_info.swi_constructor = tavor_rsrc_mrhdl_constructor;
11259e39c5baSBill Taylor 	hdl_info.swi_destructor	 = tavor_rsrc_mrhdl_destructor;
11269e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
11279e39c5baSBill Taylor 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
11289e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
11299e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
11309e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
11319e39c5baSBill Taylor 		goto rsrcinitp2_fail;
11329e39c5baSBill Taylor 	}
11339e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL23;
11349e39c5baSBill Taylor 
11359e39c5baSBill Taylor 	/*
11369e39c5baSBill Taylor 	 * Initialize the resource pool for the EQ handles.  Notice
11379e39c5baSBill Taylor 	 * that the number of EQHDLs is hardcoded.  The hardcoded value
11389e39c5baSBill Taylor 	 * should be less that the maximum value (obtained from the
11399e39c5baSBill Taylor 	 * QUERY_DEV_LIM command) or the initialization will fail.
11409e39c5baSBill Taylor 	 */
11419e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQHDL];
11429e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_EQHDL;
11439e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
11449e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_eq_s);
11459e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
11469e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_EQHDL_CACHE);
11479e39c5baSBill Taylor 	hdl_info.swi_num = TAVOR_NUM_EQ;
11489e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_eq);
11499e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
11509e39c5baSBill Taylor 	hdl_info.swi_constructor = NULL;
11519e39c5baSBill Taylor 	hdl_info.swi_destructor	 = NULL;
11529e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
11539e39c5baSBill Taylor 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
11549e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
11559e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
11569e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
11579e39c5baSBill Taylor 		goto rsrcinitp2_fail;
11589e39c5baSBill Taylor 	}
11599e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL24;
11609e39c5baSBill Taylor 
11619e39c5baSBill Taylor 	/*
11629e39c5baSBill Taylor 	 * Initialize the resource pool for the CQ handles.  Notice
11639e39c5baSBill Taylor 	 * that the number of CQHDLs is configurable.  The configured value
11649e39c5baSBill Taylor 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
11659e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that the CQ
11669e39c5baSBill Taylor 	 * handle has constructor and destructor methods associated with it.
11679e39c5baSBill Taylor 	 */
11689e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_CQHDL];
11699e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_CQHDL;
11709e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
11719e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_cq_s);
11729e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
11739e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_CQHDL_CACHE);
11749e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
11759e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_cq);
11769e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
11779e39c5baSBill Taylor 	hdl_info.swi_constructor = tavor_rsrc_cqhdl_constructor;
11789e39c5baSBill Taylor 	hdl_info.swi_destructor	 = tavor_rsrc_cqhdl_destructor;
11799e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
11809e39c5baSBill Taylor 	hdl_info.swi_flags	 = (TAVOR_SWHDL_KMEMCACHE_INIT |
11819e39c5baSBill Taylor 	    TAVOR_SWHDL_TABLE_INIT);
11829e39c5baSBill Taylor 	hdl_info.swi_prealloc_sz = sizeof (tavor_cqhdl_t);
11839e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
11849e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
11859e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
11869e39c5baSBill Taylor 		goto rsrcinitp2_fail;
11879e39c5baSBill Taylor 	}
11889e39c5baSBill Taylor 
11899e39c5baSBill Taylor 	/*
11909e39c5baSBill Taylor 	 * Save away the pointer to the central list of CQ handle pointers
11919e39c5baSBill Taylor 	 * This this is used as a mechanism to enable fast CQnumber-to-CQhandle
11929e39c5baSBill Taylor 	 * lookup during EQ event processing.  The table is a list of
11939e39c5baSBill Taylor 	 * tavor_cqhdl_t allocated by the above routine because of the
11949e39c5baSBill Taylor 	 * TAVOR_SWHDL_TABLE_INIT flag.  The table has as many tavor_cqhdl_t
11959e39c5baSBill Taylor 	 * as the number of CQs.
11969e39c5baSBill Taylor 	 */
11979e39c5baSBill Taylor 	state->ts_cqhdl = hdl_info.swi_table_ptr;
11989e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL25;
11999e39c5baSBill Taylor 
12009e39c5baSBill Taylor 	/*
12019e39c5baSBill Taylor 	 * Initialize the resource pool for the SRQ handles.  Notice
12029e39c5baSBill Taylor 	 * that the number of SRQHDLs is configurable.  The configured value
12039e39c5baSBill Taylor 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
12049e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that the SRQ
12059e39c5baSBill Taylor 	 * handle has constructor and destructor methods associated with it.
12069e39c5baSBill Taylor 	 *
12079e39c5baSBill Taylor 	 * Note: We only allocate these resources if SRQ is enabled in the
12089e39c5baSBill Taylor 	 * config profile; see below.
12099e39c5baSBill Taylor 	 */
12109e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_SRQHDL];
12119e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_SRQHDL;
12129e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
12139e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_srq_s);
12149e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
12159e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_SRQHDL_CACHE);
12169e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
12179e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_srq);
12189e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
12199e39c5baSBill Taylor 	hdl_info.swi_constructor = tavor_rsrc_srqhdl_constructor;
12209e39c5baSBill Taylor 	hdl_info.swi_destructor	 = tavor_rsrc_srqhdl_destructor;
12219e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
12229e39c5baSBill Taylor 	hdl_info.swi_flags	 = (TAVOR_SWHDL_KMEMCACHE_INIT |
12239e39c5baSBill Taylor 	    TAVOR_SWHDL_TABLE_INIT);
12249e39c5baSBill Taylor 	hdl_info.swi_prealloc_sz = sizeof (tavor_srqhdl_t);
12259e39c5baSBill Taylor 
12269e39c5baSBill Taylor 	/*
12279e39c5baSBill Taylor 	 * SRQ support is configurable.  Only if SRQ is enabled (the default)
12289e39c5baSBill Taylor 	 * do we actually try to configure these resources.  Otherwise, we
12299e39c5baSBill Taylor 	 * simply set the cleanup level and continue on to the next resource
12309e39c5baSBill Taylor 	 */
12319e39c5baSBill Taylor 	if (state->ts_cfg_profile->cp_srq_enable != 0) {
12329e39c5baSBill Taylor 		status = tavor_rsrc_sw_handles_init(state, &hdl_info);
12339e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
12349e39c5baSBill Taylor 			tavor_rsrc_fini(state, cleanup);
12359e39c5baSBill Taylor 			goto rsrcinitp2_fail;
12369e39c5baSBill Taylor 		}
12379e39c5baSBill Taylor 
12389e39c5baSBill Taylor 		/*
12399e39c5baSBill Taylor 		 * Save away the pointer to the central list of SRQ handle
12409e39c5baSBill Taylor 		 * pointers This this is used as a mechanism to enable fast
12419e39c5baSBill Taylor 		 * SRQnumber-to-SRQhandle lookup.  The table is a list of
12429e39c5baSBill Taylor 		 * tavor_srqhdl_t allocated by the above routine because of the
12439e39c5baSBill Taylor 		 * TAVOR_SWHDL_TABLE_INIT flag.  The table has as many
12449e39c5baSBill Taylor 		 * tavor_srqhdl_t as the number of SRQs.
12459e39c5baSBill Taylor 		 */
12469e39c5baSBill Taylor 		state->ts_srqhdl = hdl_info.swi_table_ptr;
12479e39c5baSBill Taylor 	}
12489e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL26;
12499e39c5baSBill Taylor 
12509e39c5baSBill Taylor 	/*
12519e39c5baSBill Taylor 	 * Initialize the resource pool for the address handles.  Notice
12529e39c5baSBill Taylor 	 * that the number of AHHDLs is configurable.  The configured value
12539e39c5baSBill Taylor 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
12549e39c5baSBill Taylor 	 * command) or the initialization will fail.
12559e39c5baSBill Taylor 	 */
12569e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_AHHDL];
12579e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_AHHDL;
12589e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
12599e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_ah_s);
12609e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
12619e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_AHHDL_CACHE);
12629e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_ah);
12639e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_av);
12649e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
12659e39c5baSBill Taylor 	hdl_info.swi_constructor = tavor_rsrc_ahhdl_constructor;
12669e39c5baSBill Taylor 	hdl_info.swi_destructor	 = tavor_rsrc_ahhdl_destructor;
12679e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
12689e39c5baSBill Taylor 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
12699e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
12709e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
12719e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
12729e39c5baSBill Taylor 		goto rsrcinitp2_fail;
12739e39c5baSBill Taylor 	}
12749e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL27;
12759e39c5baSBill Taylor 
12769e39c5baSBill Taylor 	/*
12779e39c5baSBill Taylor 	 * Initialize the resource pool for the QP handles.  Notice
12789e39c5baSBill Taylor 	 * that the number of QPHDLs is configurable.  The configured value
12799e39c5baSBill Taylor 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
12809e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that the QP
12819e39c5baSBill Taylor 	 * handle has constructor and destructor methods associated with it.
12829e39c5baSBill Taylor 	 */
12839e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_QPHDL];
12849e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_QPHDL;
12859e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
12869e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct tavor_sw_qp_s);
12879e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
12889e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_QPHDL_CACHE);
12899e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
12909e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
12919e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
12929e39c5baSBill Taylor 	hdl_info.swi_constructor = tavor_rsrc_qphdl_constructor;
12939e39c5baSBill Taylor 	hdl_info.swi_destructor	 = tavor_rsrc_qphdl_destructor;
12949e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
12959e39c5baSBill Taylor 	hdl_info.swi_flags	 = (TAVOR_SWHDL_KMEMCACHE_INIT |
12969e39c5baSBill Taylor 	    TAVOR_SWHDL_TABLE_INIT);
12979e39c5baSBill Taylor 	hdl_info.swi_prealloc_sz = sizeof (tavor_qphdl_t);
12989e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
12999e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
13009e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
13019e39c5baSBill Taylor 		goto rsrcinitp2_fail;
13029e39c5baSBill Taylor 	}
13039e39c5baSBill Taylor 
13049e39c5baSBill Taylor 	/*
13059e39c5baSBill Taylor 	 * Save away the pointer to the central list of QP handle pointers
13069e39c5baSBill Taylor 	 * This this is used as a mechanism to enable fast QPnumber-to-QPhandle
13079e39c5baSBill Taylor 	 * lookup during CQ event processing.  The table is a list of
13089e39c5baSBill Taylor 	 * tavor_qphdl_t allocated by the above routine because of the
13099e39c5baSBill Taylor 	 * TAVOR_SWHDL_TABLE_INIT flag.  The table has as many tavor_qphdl_t
13109e39c5baSBill Taylor 	 * as the number of QPs.
13119e39c5baSBill Taylor 	 */
13129e39c5baSBill Taylor 	state->ts_qphdl = hdl_info.swi_table_ptr;
13139e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL28;
13149e39c5baSBill Taylor 
13159e39c5baSBill Taylor 	/*
13169e39c5baSBill Taylor 	 * Initialize the resource pool for the reference count handles.
13179e39c5baSBill Taylor 	 * Notice that the number of REFCNTs is configurable, but it's value
13189e39c5baSBill Taylor 	 * is set to the number of MPTs.  Since REFCNTs are used to support
13199e39c5baSBill Taylor 	 * shared memory regions, it is possible that we might require as
13209e39c5baSBill Taylor 	 * one REFCNT for every MPT.
13219e39c5baSBill Taylor 	 */
13229e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_REFCNT];
13239e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = TAVOR_REFCNT;
13249e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = TAVOR_IN_SYSMEM;
13259e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (tavor_sw_refcnt_t);
13269e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
13279e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_REFCNT_CACHE);
13289e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
13299e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
13309e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
13319e39c5baSBill Taylor 	hdl_info.swi_constructor = tavor_rsrc_refcnt_constructor;
13329e39c5baSBill Taylor 	hdl_info.swi_destructor	 = tavor_rsrc_refcnt_destructor;
13339e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
13349e39c5baSBill Taylor 	hdl_info.swi_flags	 = TAVOR_SWHDL_KMEMCACHE_INIT;
13359e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
13369e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
13379e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
13389e39c5baSBill Taylor 		goto rsrcinitp2_fail;
13399e39c5baSBill Taylor 	}
13409e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL29;
13419e39c5baSBill Taylor 
13429e39c5baSBill Taylor 	/*
13439e39c5baSBill Taylor 	 * Initialize the resource pool for the MCG handles.  Notice that for
13449e39c5baSBill Taylor 	 * these MCG handles, we are allocating a table of structures (used to
13459e39c5baSBill Taylor 	 * keep track of the MCG entries that are being written to hardware
13469e39c5baSBill Taylor 	 * and to speed up multicast attach/detach operations).
13479e39c5baSBill Taylor 	 */
13489e39c5baSBill Taylor 	hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
13499e39c5baSBill Taylor 	hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mcg);
13509e39c5baSBill Taylor 	hdl_info.swi_flags = TAVOR_SWHDL_TABLE_INIT;
13519e39c5baSBill Taylor 	hdl_info.swi_prealloc_sz = sizeof (struct tavor_sw_mcg_list_s);
13529e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, &hdl_info);
13539e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
13549e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
13559e39c5baSBill Taylor 		goto rsrcinitp2_fail;
13569e39c5baSBill Taylor 	}
13579e39c5baSBill Taylor 	state->ts_mcghdl = hdl_info.swi_table_ptr;
13589e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_LEVEL30;
13599e39c5baSBill Taylor 
13609e39c5baSBill Taylor 	/*
13619e39c5baSBill Taylor 	 * Initialize the resource pools for all objects that exist in
13629e39c5baSBill Taylor 	 * UAR memory.  The only objects that are allocated from UAR memory
13639e39c5baSBill Taylor 	 * are the UAR pages which are used for holding Tavor hardware's
13649e39c5baSBill Taylor 	 * doorbell registers.
13659e39c5baSBill Taylor 	 */
13669e39c5baSBill Taylor 
13679e39c5baSBill Taylor 	/*
13689e39c5baSBill Taylor 	 * Initialize the resource pool for the UAR pages.  Notice
13699e39c5baSBill Taylor 	 * that the number of UARPGs is configurable.  The configured value
13709e39c5baSBill Taylor 	 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
13719e39c5baSBill Taylor 	 * command) or the initialization will fail.  Note also that by
13729e39c5baSBill Taylor 	 * specifying the rsrc_start parameter in advance, we direct the
13739e39c5baSBill Taylor 	 * initialization routine not to attempt to allocated space from the
13749e39c5baSBill Taylor 	 * Tavor DDR vmem_arena.
13759e39c5baSBill Taylor 	 */
13769e39c5baSBill Taylor 	num  = ((uint64_t)1 << cfgprof->cp_log_num_uar);
13779e39c5baSBill Taylor 	max  = ((uint64_t)1 << (state->ts_devlim.log_max_uar_sz + 20 -
13789e39c5baSBill Taylor 	    PAGESHIFT));
13799e39c5baSBill Taylor 	num_prealloc = 0;
13809e39c5baSBill Taylor 	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UARPG];
13819e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = TAVOR_UARPG;
13829e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = TAVOR_IN_UAR;
13839e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (num << PAGESHIFT);
13849e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = PAGESHIFT;
13859e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = PAGESIZE;
13869e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = PAGESIZE;
13879e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
13889e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = (void *)state->ts_reg_uar_baseaddr;
13899e39c5baSBill Taylor 	TAVOR_RSRC_NAME(rsrc_name, TAVOR_UAR_VMEM);
13909e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
13919e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
13929e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
13939e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
13949e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
13959e39c5baSBill Taylor 	status = tavor_rsrc_hw_entries_init(state, &entry_info);
13969e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
13979e39c5baSBill Taylor 		tavor_rsrc_fini(state, cleanup);
13989e39c5baSBill Taylor 		goto rsrcinitp2_fail;
13999e39c5baSBill Taylor 	}
14009e39c5baSBill Taylor 	cleanup = TAVOR_RSRC_CLEANUP_ALL;
14019e39c5baSBill Taylor 
14029e39c5baSBill Taylor 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
14039e39c5baSBill Taylor 	return (DDI_SUCCESS);
14049e39c5baSBill Taylor 
14059e39c5baSBill Taylor rsrcinitp2_fail:
14069e39c5baSBill Taylor 	kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
14079e39c5baSBill Taylor 	return (status);
14089e39c5baSBill Taylor }
14099e39c5baSBill Taylor 
14109e39c5baSBill Taylor 
14119e39c5baSBill Taylor /*
14129e39c5baSBill Taylor  * tavor_rsrc_fini()
14139e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
14149e39c5baSBill Taylor  */
14159e39c5baSBill Taylor void
tavor_rsrc_fini(tavor_state_t * state,tavor_rsrc_cleanup_level_t clean)14169e39c5baSBill Taylor tavor_rsrc_fini(tavor_state_t *state, tavor_rsrc_cleanup_level_t clean)
14179e39c5baSBill Taylor {
14189e39c5baSBill Taylor 	tavor_rsrc_sw_hdl_info_t	hdl_info;
14199e39c5baSBill Taylor 	tavor_rsrc_hw_entry_info_t	entry_info;
14209e39c5baSBill Taylor 	tavor_rsrc_mbox_info_t		mbox_info;
14219e39c5baSBill Taylor 	tavor_cfg_profile_t		*cfgprof;
14229e39c5baSBill Taylor 
14239e39c5baSBill Taylor 	ASSERT(state != NULL);
14249e39c5baSBill Taylor 
14259e39c5baSBill Taylor 	cfgprof = state->ts_cfg_profile;
14269e39c5baSBill Taylor 
14279e39c5baSBill Taylor 	switch (clean) {
14289e39c5baSBill Taylor 	/*
14299e39c5baSBill Taylor 	 * If we add more resources that need to be cleaned up here, we should
14309e39c5baSBill Taylor 	 * ensure that TAVOR_RSRC_CLEANUP_ALL is still the first entry (i.e.
14319e39c5baSBill Taylor 	 * corresponds to the last resource allocated).
14329e39c5baSBill Taylor 	 */
14339e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_ALL:
14349e39c5baSBill Taylor 		/* Cleanup the UAR page resource pool */
14359e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UARPG];
14369e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
14379e39c5baSBill Taylor 		/* FALLTHROUGH */
14389e39c5baSBill Taylor 
14399e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL30:
14409e39c5baSBill Taylor 		/* Cleanup the central MCG handle pointers list */
14419e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = NULL;
14429e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->ts_mcghdl;
14439e39c5baSBill Taylor 		hdl_info.swi_num =
14449e39c5baSBill Taylor 		    ((uint64_t)1 << cfgprof->cp_log_num_mcg);
14459e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (struct tavor_sw_mcg_list_s);
14469e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
14479e39c5baSBill Taylor 		/* FALLTHROUGH */
14489e39c5baSBill Taylor 
14499e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL29:
14509e39c5baSBill Taylor 		/* Cleanup the reference count resource pool */
14519e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_REFCNT];
14529e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
14539e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
14549e39c5baSBill Taylor 		/* FALLTHROUGH */
14559e39c5baSBill Taylor 
14569e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL28:
14579e39c5baSBill Taylor 		/* Cleanup the QP handle resource pool */
14589e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_QPHDL];
14599e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->ts_qphdl;
14609e39c5baSBill Taylor 		hdl_info.swi_num =
14619e39c5baSBill Taylor 		    ((uint64_t)1 << cfgprof->cp_log_num_qp);
14629e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (tavor_qphdl_t);
14639e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
14649e39c5baSBill Taylor 		/* FALLTHROUGH */
14659e39c5baSBill Taylor 
14669e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL27:
14679e39c5baSBill Taylor 		/* Cleanup the address handle resource pool */
14689e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_AHHDL];
14699e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
14709e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
14719e39c5baSBill Taylor 		/* FALLTHROUGH */
14729e39c5baSBill Taylor 
14739e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL26:
14749e39c5baSBill Taylor 		/*
14759e39c5baSBill Taylor 		 * Cleanup the SRQ handle resource pool.
14769e39c5baSBill Taylor 		 *
14779e39c5baSBill Taylor 		 * Note: We only clean up if SRQ is enabled.  Otherwise we
14789e39c5baSBill Taylor 		 * simply fallthrough to the next resource cleanup.
14799e39c5baSBill Taylor 		 */
14809e39c5baSBill Taylor 		if (state->ts_cfg_profile->cp_srq_enable != 0) {
14819e39c5baSBill Taylor 			hdl_info.swi_rsrcpool  =
14829e39c5baSBill Taylor 			    &state->ts_rsrc_hdl[TAVOR_SRQHDL];
14839e39c5baSBill Taylor 			hdl_info.swi_table_ptr = state->ts_srqhdl;
14849e39c5baSBill Taylor 			hdl_info.swi_num =
14859e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_srq);
14869e39c5baSBill Taylor 			hdl_info.swi_prealloc_sz = sizeof (tavor_srqhdl_t);
14879e39c5baSBill Taylor 			tavor_rsrc_sw_handles_fini(state, &hdl_info);
14889e39c5baSBill Taylor 		}
14899e39c5baSBill Taylor 		/* FALLTHROUGH */
14909e39c5baSBill Taylor 
14919e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL25:
14929e39c5baSBill Taylor 		/* Cleanup the CQ handle resource pool */
14939e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_CQHDL];
14949e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->ts_cqhdl;
14959e39c5baSBill Taylor 		hdl_info.swi_num =
14969e39c5baSBill Taylor 		    ((uint64_t)1 << cfgprof->cp_log_num_cq);
14979e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (tavor_cqhdl_t);
14989e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
14999e39c5baSBill Taylor 		/* FALLTHROUGH */
15009e39c5baSBill Taylor 
15019e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL24:
15029e39c5baSBill Taylor 		/* Cleanup the EQ handle resource pool */
15039e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_EQHDL];
15049e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
15059e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
15069e39c5baSBill Taylor 		/* FALLTHROUGH */
15079e39c5baSBill Taylor 
15089e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL23:
15099e39c5baSBill Taylor 		/* Cleanup the MR handle resource pool */
15109e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_MRHDL];
15119e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
15129e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, &hdl_info);
15139e39c5baSBill Taylor 		/* FALLTHROUGH */
15149e39c5baSBill Taylor 
15159e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL22:
15169e39c5baSBill Taylor 		/* Cleanup the PD handle resource pool */
15179e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->ts_rsrc_hdl[TAVOR_PDHDL];
15189e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
15199e39c5baSBill Taylor 		tavor_rsrc_pd_handles_fini(state, &hdl_info);
15209e39c5baSBill Taylor 		/* FALLTHROUGH */
15219e39c5baSBill Taylor 
15229e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL21:
15239e39c5baSBill Taylor 		/* Cleanup the EQC table resource pool */
15249e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_EQC];
15259e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
15269e39c5baSBill Taylor 		/* FALLTHROUGH */
15279e39c5baSBill Taylor 
15289e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL20:
15299e39c5baSBill Taylor 		/* Cleanup the MCG table resource pool */
15309e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MCG];
15319e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
15329e39c5baSBill Taylor 		/* FALLTHROUGH */
15339e39c5baSBill Taylor 
15349e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL19:
15359e39c5baSBill Taylor 		/* Cleanup the outstanding command list  */
15369e39c5baSBill Taylor 		tavor_outstanding_cmdlist_fini(state);
15379e39c5baSBill Taylor 		/* FALLTHROUGH */
15389e39c5baSBill Taylor 
15399e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL18:
15409e39c5baSBill Taylor 		/* Cleanup the "In" mailbox list  */
15419e39c5baSBill Taylor 		tavor_intr_inmbox_list_fini(state);
15429e39c5baSBill Taylor 		/* FALLTHROUGH */
15439e39c5baSBill Taylor 
15449e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL17:
15459e39c5baSBill Taylor 		/* Cleanup the interrupt "In" mailbox resource pool */
15469e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[
15479e39c5baSBill Taylor 		    TAVOR_INTR_IN_MBOX];
15489e39c5baSBill Taylor 		tavor_rsrc_mbox_fini(state, &mbox_info);
15499e39c5baSBill Taylor 		/* FALLTHROUGH */
15509e39c5baSBill Taylor 
15519e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL16:
15529e39c5baSBill Taylor 		/* Cleanup the "In" mailbox list  */
15539e39c5baSBill Taylor 		tavor_inmbox_list_fini(state);
15549e39c5baSBill Taylor 		/* FALLTHROUGH */
15559e39c5baSBill Taylor 
15569e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL15:
15579e39c5baSBill Taylor 		/* Cleanup the "In" mailbox resource pool */
15589e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_IN_MBOX];
15599e39c5baSBill Taylor 		tavor_rsrc_mbox_fini(state, &mbox_info);
15609e39c5baSBill Taylor 		/* FALLTHROUGH */
15619e39c5baSBill Taylor 
15629e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL14:
15639e39c5baSBill Taylor 		/*
15649e39c5baSBill Taylor 		 * Cleanup the SRQC table resource pool.
15659e39c5baSBill Taylor 		 *
15669e39c5baSBill Taylor 		 * Note: We only clean up if SRQ is enabled.  Otherwise we
15679e39c5baSBill Taylor 		 * simply fallthrough to the next resource cleanup.
15689e39c5baSBill Taylor 		 */
15699e39c5baSBill Taylor 		if (state->ts_cfg_profile->cp_srq_enable != 0) {
15709e39c5baSBill Taylor 			entry_info.hwi_rsrcpool =
15719e39c5baSBill Taylor 			    &state->ts_rsrc_hdl[TAVOR_SRQC];
15729e39c5baSBill Taylor 			tavor_rsrc_hw_entries_fini(state, &entry_info);
15739e39c5baSBill Taylor 		}
15749e39c5baSBill Taylor 		/* FALLTHROUGH */
15759e39c5baSBill Taylor 
15769e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL13:
15779e39c5baSBill Taylor 		/* Cleanup the UAR scratch table resource pool */
15789e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UAR_SCR];
15799e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
15809e39c5baSBill Taylor 		/* FALLTHROUGH */
15819e39c5baSBill Taylor 
15829e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL12:
15839e39c5baSBill Taylor 		/* Cleanup the UDAV table resource pool */
15849e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UDAV];
15859e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
15869e39c5baSBill Taylor 		/* FALLTHROUGH */
15879e39c5baSBill Taylor 
15889e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL11:
15899e39c5baSBill Taylor 		/* Cleanup the EQPC table resource pool */
15909e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_EQPC];
15919e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
15929e39c5baSBill Taylor 		/* FALLTHROUGH */
15939e39c5baSBill Taylor 
15949e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL10:
15959e39c5baSBill Taylor 		/* Cleanup the CQC table resource pool */
15969e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_CQC];
15979e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
15989e39c5baSBill Taylor 		/* FALLTHROUGH */
15999e39c5baSBill Taylor 
16009e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL9:
16019e39c5baSBill Taylor 		/* Cleanup the RDB table resource pool */
16029e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_RDB];
16039e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
16049e39c5baSBill Taylor 		/* FALLTHROUGH */
16059e39c5baSBill Taylor 
16069e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL8:
16079e39c5baSBill Taylor 		/* Cleanup the QPC table resource pool */
16089e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_QPC];
16099e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
16109e39c5baSBill Taylor 		/* FALLTHROUGH */
16119e39c5baSBill Taylor 
16129e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL7:
16139e39c5baSBill Taylor 		/* Cleanup the MTT table resource pool */
16149e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MTT];
16159e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
16169e39c5baSBill Taylor 		/* FALLTHROUGH */
16179e39c5baSBill Taylor 
16189e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL6:
16199e39c5baSBill Taylor 		/* Cleanup the MPT table resource pool */
16209e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MPT];
16219e39c5baSBill Taylor 		tavor_rsrc_hw_entries_fini(state, &entry_info);
16229e39c5baSBill Taylor 		/* FALLTHROUGH */
16239e39c5baSBill Taylor 
16249e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL5:
16259e39c5baSBill Taylor 		/* Destroy the vmem arena for DDR memory */
16269e39c5baSBill Taylor 		vmem_destroy(state->ts_ddrvmem);
16279e39c5baSBill Taylor 		break;
16289e39c5baSBill Taylor 
16299e39c5baSBill Taylor 	/*
16309e39c5baSBill Taylor 	 * The cleanup below comes from the "Phase 1" initialization step.
16319e39c5baSBill Taylor 	 * (see tavor_rsrc_init_phase1() above)
16329e39c5baSBill Taylor 	 */
16339e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE:
16349e39c5baSBill Taylor 		/* Cleanup the interrupt "Out" mailbox list  */
16359e39c5baSBill Taylor 		tavor_intr_outmbox_list_fini(state);
16369e39c5baSBill Taylor 		/* FALLTHROUGH */
16379e39c5baSBill Taylor 
16389e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL3:
16399e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox resource pool */
16409e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[
16419e39c5baSBill Taylor 		    TAVOR_INTR_OUT_MBOX];
16429e39c5baSBill Taylor 		tavor_rsrc_mbox_fini(state, &mbox_info);
16439e39c5baSBill Taylor 		/* FALLTHROUGH */
16449e39c5baSBill Taylor 
16459e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL2:
16469e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox list  */
16479e39c5baSBill Taylor 		tavor_outmbox_list_fini(state);
16489e39c5baSBill Taylor 		/* FALLTHROUGH */
16499e39c5baSBill Taylor 
16509e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL1:
16519e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox resource pool */
16529e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_OUT_MBOX];
16539e39c5baSBill Taylor 		tavor_rsrc_mbox_fini(state, &mbox_info);
16549e39c5baSBill Taylor 		/* FALLTHROUGH */
16559e39c5baSBill Taylor 
16569e39c5baSBill Taylor 	case TAVOR_RSRC_CLEANUP_LEVEL0:
16579e39c5baSBill Taylor 		/* Free the array of tavor_rsrc_pool_info_t's */
16589e39c5baSBill Taylor 		kmem_free(state->ts_rsrc_hdl, TAVOR_NUM_RESOURCES *
16599e39c5baSBill Taylor 		    sizeof (tavor_rsrc_pool_info_t));
16609e39c5baSBill Taylor 		kmem_cache_destroy(state->ts_rsrc_cache);
16619e39c5baSBill Taylor 		break;
16629e39c5baSBill Taylor 
16639e39c5baSBill Taylor 	default:
16649e39c5baSBill Taylor 		TAVOR_WARNING(state, "unexpected resource cleanup level");
16659e39c5baSBill Taylor 	}
16669e39c5baSBill Taylor }
16679e39c5baSBill Taylor 
16689e39c5baSBill Taylor 
16699e39c5baSBill Taylor /*
16709e39c5baSBill Taylor  * tavor_rsrc_mbox_init()
16719e39c5baSBill Taylor  *    Context: Only called from attach() path context
16729e39c5baSBill Taylor  */
16739e39c5baSBill Taylor static int
tavor_rsrc_mbox_init(tavor_state_t * state,tavor_rsrc_mbox_info_t * info)16749e39c5baSBill Taylor tavor_rsrc_mbox_init(tavor_state_t *state, tavor_rsrc_mbox_info_t *info)
16759e39c5baSBill Taylor {
16769e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
16779e39c5baSBill Taylor 	tavor_rsrc_priv_mbox_t	*priv;
16789e39c5baSBill Taylor 	vmem_t			*vmp;
16799e39c5baSBill Taylor 	uint64_t		offset;
16809e39c5baSBill Taylor 	uint_t			dma_xfer_mode;
16819e39c5baSBill Taylor 
16829e39c5baSBill Taylor 	ASSERT(state != NULL);
16839e39c5baSBill Taylor 	ASSERT(info != NULL);
16849e39c5baSBill Taylor 
16859e39c5baSBill Taylor 	rsrc_pool = info->mbi_rsrcpool;
16869e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
16879e39c5baSBill Taylor 
16889e39c5baSBill Taylor 	dma_xfer_mode = state->ts_cfg_profile->cp_streaming_consistent;
16899e39c5baSBill Taylor 
16909e39c5baSBill Taylor 	/* Allocate and initialize mailbox private structure */
16919e39c5baSBill Taylor 	priv = kmem_zalloc(sizeof (tavor_rsrc_priv_mbox_t), KM_SLEEP);
16929e39c5baSBill Taylor 	priv->pmb_dip		= state->ts_dip;
16939e39c5baSBill Taylor 	priv->pmb_acchdl	= state->ts_reg_ddrhdl;
16949e39c5baSBill Taylor 	priv->pmb_devaccattr	= state->ts_reg_accattr;
16959e39c5baSBill Taylor 	priv->pmb_xfer_mode	= dma_xfer_mode;
16969e39c5baSBill Taylor 
16979e39c5baSBill Taylor 	/*
16989e39c5baSBill Taylor 	 * Initialize many of the default DMA attributes.  Then set alignment
16999e39c5baSBill Taylor 	 * and scatter-gather restrictions specific for mailbox memory.
17009e39c5baSBill Taylor 	 */
17019e39c5baSBill Taylor 	tavor_dma_attr_init(&priv->pmb_dmaattr);
17029e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_align  = TAVOR_MBOX_ALIGN;
17039e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_sgllen = 1;
17049e39c5baSBill Taylor 
17059e39c5baSBill Taylor 	rsrc_pool->rsrc_private = priv;
17069e39c5baSBill Taylor 
17079e39c5baSBill Taylor 	/* Is object in DDR memory or system memory? */
17089e39c5baSBill Taylor 	if (rsrc_pool->rsrc_loc == TAVOR_IN_DDR) {
17099e39c5baSBill Taylor 		rsrc_pool->rsrc_ddr_offset = vmem_xalloc(state->ts_ddrvmem,
17109e39c5baSBill Taylor 		    rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_align,
17119e39c5baSBill Taylor 		    0, 0, NULL, NULL, VM_SLEEP);
17129e39c5baSBill Taylor 		if (rsrc_pool->rsrc_ddr_offset == NULL) {
17139e39c5baSBill Taylor 			/* Unable to alloc space for mailboxes */
17149e39c5baSBill Taylor 			kmem_free(priv, sizeof (tavor_rsrc_priv_mbox_t));
17159e39c5baSBill Taylor 			return (DDI_FAILURE);
17169e39c5baSBill Taylor 		}
17179e39c5baSBill Taylor 
17189e39c5baSBill Taylor 		/* Calculate offset and starting point (in DDR) */
17199e39c5baSBill Taylor 		offset = ((uintptr_t)rsrc_pool->rsrc_ddr_offset -
17209e39c5baSBill Taylor 		    state->ts_ddr.ddr_baseaddr);
17219e39c5baSBill Taylor 		rsrc_pool->rsrc_start =
17229e39c5baSBill Taylor 		    (void *)(uintptr_t)((uintptr_t)state->ts_reg_ddr_baseaddr +
17239e39c5baSBill Taylor 		    offset);
17249e39c5baSBill Taylor 
17259e39c5baSBill Taylor 		/* Create new vmem arena for the mailboxes */
17269e39c5baSBill Taylor 		vmp = vmem_create(info->mbi_rsrcname,
17279e39c5baSBill Taylor 		    rsrc_pool->rsrc_ddr_offset, rsrc_pool->rsrc_pool_size,
17289e39c5baSBill Taylor 		    rsrc_pool->rsrc_quantum, NULL, NULL, NULL, 0, VM_SLEEP);
17299e39c5baSBill Taylor 		if (vmp == NULL) {
17309e39c5baSBill Taylor 			/* Unable to create vmem arena */
17319e39c5baSBill Taylor 			vmem_xfree(state->ts_ddrvmem,
17329e39c5baSBill Taylor 			    rsrc_pool->rsrc_ddr_offset,
17339e39c5baSBill Taylor 			    rsrc_pool->rsrc_pool_size);
17349e39c5baSBill Taylor 			kmem_free(priv, sizeof (tavor_rsrc_priv_mbox_t));
17359e39c5baSBill Taylor 			return (DDI_FAILURE);
17369e39c5baSBill Taylor 		}
17379e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = vmp;
17389e39c5baSBill Taylor 	} else {
17399e39c5baSBill Taylor 		rsrc_pool->rsrc_ddr_offset = NULL;
17409e39c5baSBill Taylor 		rsrc_pool->rsrc_start = NULL;
17419e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = NULL;
17429e39c5baSBill Taylor 	}
17439e39c5baSBill Taylor 
17449e39c5baSBill Taylor 	return (DDI_SUCCESS);
17459e39c5baSBill Taylor }
17469e39c5baSBill Taylor 
17479e39c5baSBill Taylor 
17489e39c5baSBill Taylor /*
17499e39c5baSBill Taylor  * tavor_rsrc_mbox_fini()
17509e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
17519e39c5baSBill Taylor  */
17529e39c5baSBill Taylor static void
tavor_rsrc_mbox_fini(tavor_state_t * state,tavor_rsrc_mbox_info_t * info)17539e39c5baSBill Taylor tavor_rsrc_mbox_fini(tavor_state_t *state, tavor_rsrc_mbox_info_t *info)
17549e39c5baSBill Taylor {
17559e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
17569e39c5baSBill Taylor 
17579e39c5baSBill Taylor 	ASSERT(state != NULL);
17589e39c5baSBill Taylor 	ASSERT(info != NULL);
17599e39c5baSBill Taylor 
17609e39c5baSBill Taylor 	rsrc_pool = info->mbi_rsrcpool;
17619e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
17629e39c5baSBill Taylor 
17639e39c5baSBill Taylor 	/* If mailboxes are DDR memory, then destroy and free up vmem */
17649e39c5baSBill Taylor 	if (rsrc_pool->rsrc_loc == TAVOR_IN_DDR) {
17659e39c5baSBill Taylor 
17669e39c5baSBill Taylor 		/* Destroy the specially created mbox vmem arena */
17679e39c5baSBill Taylor 		vmem_destroy(rsrc_pool->rsrc_vmp);
17689e39c5baSBill Taylor 
17699e39c5baSBill Taylor 		/* Free up the region from the ddr_vmem arena */
17709e39c5baSBill Taylor 		vmem_xfree(state->ts_ddrvmem, rsrc_pool->rsrc_ddr_offset,
17719e39c5baSBill Taylor 		    rsrc_pool->rsrc_pool_size);
17729e39c5baSBill Taylor 	}
17739e39c5baSBill Taylor 
17749e39c5baSBill Taylor 	/* Free up the private struct */
17759e39c5baSBill Taylor 	kmem_free(rsrc_pool->rsrc_private, sizeof (tavor_rsrc_priv_mbox_t));
17769e39c5baSBill Taylor }
17779e39c5baSBill Taylor 
17789e39c5baSBill Taylor 
17799e39c5baSBill Taylor /*
17809e39c5baSBill Taylor  * tavor_rsrc_hw_entries_init()
17819e39c5baSBill Taylor  *    Context: Only called from attach() path context
17829e39c5baSBill Taylor  */
17839e39c5baSBill Taylor static int
tavor_rsrc_hw_entries_init(tavor_state_t * state,tavor_rsrc_hw_entry_info_t * info)17849e39c5baSBill Taylor tavor_rsrc_hw_entries_init(tavor_state_t *state,
17859e39c5baSBill Taylor     tavor_rsrc_hw_entry_info_t *info)
17869e39c5baSBill Taylor {
17879e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
17889e39c5baSBill Taylor 	tavor_rsrc_t		*rsvd_rsrc = NULL;
17899e39c5baSBill Taylor 	vmem_t			*vmp;
17909e39c5baSBill Taylor 	uint64_t		num_hwentry, max_hwentry, num_prealloc;
17919e39c5baSBill Taylor 	uint64_t		offset;
17929e39c5baSBill Taylor 	int			status;
17939e39c5baSBill Taylor 
17949e39c5baSBill Taylor 	ASSERT(state != NULL);
17959e39c5baSBill Taylor 	ASSERT(info != NULL);
17969e39c5baSBill Taylor 
17979e39c5baSBill Taylor 	rsrc_pool	= info->hwi_rsrcpool;
17989e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
17999e39c5baSBill Taylor 	num_hwentry	= info->hwi_num;
18009e39c5baSBill Taylor 	max_hwentry	= info->hwi_max;
18019e39c5baSBill Taylor 	num_prealloc	= info->hwi_prealloc;
18029e39c5baSBill Taylor 
18039e39c5baSBill Taylor 	/* Make sure number of HW entries makes sense */
18049e39c5baSBill Taylor 	if (num_hwentry > max_hwentry) {
18059e39c5baSBill Taylor 		return (DDI_FAILURE);
18069e39c5baSBill Taylor 	}
18079e39c5baSBill Taylor 
18089e39c5baSBill Taylor 	/*
18099e39c5baSBill Taylor 	 * Determine if we need to allocate DDR space to set up the
18109e39c5baSBill Taylor 	 * "rsrc_start" pointer.  Not necessary if "rsrc_start" has already
18119e39c5baSBill Taylor 	 * been initialized (as is the case for the UAR page init).
18129e39c5baSBill Taylor 	 */
18139e39c5baSBill Taylor 	if (rsrc_pool->rsrc_start == NULL) {
18149e39c5baSBill Taylor 		/* Make sure HW entries table is aligned as specified */
18159e39c5baSBill Taylor 		rsrc_pool->rsrc_ddr_offset = vmem_xalloc(state->ts_ddrvmem,
18169e39c5baSBill Taylor 		    rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_align,
18179e39c5baSBill Taylor 		    0, 0, NULL, NULL, VM_NOSLEEP | VM_FIRSTFIT);
18189e39c5baSBill Taylor 		if (rsrc_pool->rsrc_ddr_offset == NULL) {
18199e39c5baSBill Taylor 			/* Unable to alloc space for aligned HW table */
18209e39c5baSBill Taylor 			return (DDI_FAILURE);
18219e39c5baSBill Taylor 		}
18229e39c5baSBill Taylor 
18239e39c5baSBill Taylor 		/* Calculate offset and starting point (in DDR) */
18249e39c5baSBill Taylor 		offset = ((uintptr_t)rsrc_pool->rsrc_ddr_offset -
18259e39c5baSBill Taylor 		    state->ts_ddr.ddr_baseaddr);
18269e39c5baSBill Taylor 		rsrc_pool->rsrc_start =
18279e39c5baSBill Taylor 		    (void *)(uintptr_t)((uintptr_t)state->ts_reg_ddr_baseaddr +
18289e39c5baSBill Taylor 		    offset);
18299e39c5baSBill Taylor 	} else {
18309e39c5baSBill Taylor 		rsrc_pool->rsrc_ddr_offset = rsrc_pool->rsrc_start;
18319e39c5baSBill Taylor 	}
18329e39c5baSBill Taylor 
18339e39c5baSBill Taylor 	/*
18349e39c5baSBill Taylor 	 * Create new vmem arena for the HW entries table (if rsrc_quantum
18359e39c5baSBill Taylor 	 * is non-zero).  Otherwise if rsrc_quantum is zero, then these HW
18369e39c5baSBill Taylor 	 * entries are not going to be dynamically allocatable (i.e. they
18379e39c5baSBill Taylor 	 * won't be allocated/freed through tavor_rsrc_alloc/free).  This
18389e39c5baSBill Taylor 	 * latter option is used for EQPC and UARSCR resource which are, in
18399e39c5baSBill Taylor 	 * fact, managed by the Tavor hardware.
18409e39c5baSBill Taylor 	 */
18419e39c5baSBill Taylor 	if (rsrc_pool->rsrc_quantum != 0) {
18429e39c5baSBill Taylor 		vmp = vmem_create(info->hwi_rsrcname,
18439e39c5baSBill Taylor 		    rsrc_pool->rsrc_ddr_offset, rsrc_pool->rsrc_pool_size,
18449e39c5baSBill Taylor 		    rsrc_pool->rsrc_quantum, NULL, NULL, NULL, 0, VM_SLEEP);
18459e39c5baSBill Taylor 		if (vmp == NULL) {
18469e39c5baSBill Taylor 			/* Unable to create vmem arena */
18479e39c5baSBill Taylor 			if (rsrc_pool->rsrc_ddr_offset !=
18489e39c5baSBill Taylor 			    rsrc_pool->rsrc_start) {
18499e39c5baSBill Taylor 				vmem_xfree(state->ts_ddrvmem,
18509e39c5baSBill Taylor 				    rsrc_pool->rsrc_ddr_offset,
18519e39c5baSBill Taylor 				    rsrc_pool->rsrc_pool_size);
18529e39c5baSBill Taylor 			}
18539e39c5baSBill Taylor 			return (DDI_FAILURE);
18549e39c5baSBill Taylor 		}
18559e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = vmp;
18569e39c5baSBill Taylor 	} else {
18579e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = NULL;
18589e39c5baSBill Taylor 	}
18599e39c5baSBill Taylor 
18609e39c5baSBill Taylor 	/* The first HW entries may be reserved by Tavor firmware */
18619e39c5baSBill Taylor 	if (num_prealloc != 0) {
18629e39c5baSBill Taylor 		status = tavor_rsrc_alloc(state, rsrc_pool->rsrc_type,
18639e39c5baSBill Taylor 		    num_prealloc, TAVOR_SLEEP, &rsvd_rsrc);
18649e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
18659e39c5baSBill Taylor 			/* Unable to preallocate the reserved HW entries */
18669e39c5baSBill Taylor 			if (rsrc_pool->rsrc_vmp != NULL) {
18679e39c5baSBill Taylor 				vmem_destroy(rsrc_pool->rsrc_vmp);
18689e39c5baSBill Taylor 			}
18699e39c5baSBill Taylor 			if (rsrc_pool->rsrc_ddr_offset !=
18709e39c5baSBill Taylor 			    rsrc_pool->rsrc_start) {
18719e39c5baSBill Taylor 				vmem_xfree(state->ts_ddrvmem,
18729e39c5baSBill Taylor 				    rsrc_pool->rsrc_ddr_offset,
18739e39c5baSBill Taylor 				    rsrc_pool->rsrc_pool_size);
18749e39c5baSBill Taylor 			}
18759e39c5baSBill Taylor 			return (DDI_FAILURE);
18769e39c5baSBill Taylor 		}
18779e39c5baSBill Taylor 	}
18789e39c5baSBill Taylor 	rsrc_pool->rsrc_private = rsvd_rsrc;
18799e39c5baSBill Taylor 
18809e39c5baSBill Taylor 	return (DDI_SUCCESS);
18819e39c5baSBill Taylor }
18829e39c5baSBill Taylor 
18839e39c5baSBill Taylor 
18849e39c5baSBill Taylor /*
18859e39c5baSBill Taylor  * tavor_rsrc_hw_entries_fini()
18869e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
18879e39c5baSBill Taylor  */
18889e39c5baSBill Taylor static void
tavor_rsrc_hw_entries_fini(tavor_state_t * state,tavor_rsrc_hw_entry_info_t * info)18899e39c5baSBill Taylor tavor_rsrc_hw_entries_fini(tavor_state_t *state,
18909e39c5baSBill Taylor     tavor_rsrc_hw_entry_info_t *info)
18919e39c5baSBill Taylor {
18929e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
18939e39c5baSBill Taylor 	tavor_rsrc_t		*rsvd_rsrc;
18949e39c5baSBill Taylor 
18959e39c5baSBill Taylor 	ASSERT(state != NULL);
18969e39c5baSBill Taylor 	ASSERT(info != NULL);
18979e39c5baSBill Taylor 
18989e39c5baSBill Taylor 	rsrc_pool = info->hwi_rsrcpool;
18999e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
19009e39c5baSBill Taylor 
19019e39c5baSBill Taylor 	/* Free up any "reserved" (i.e. preallocated) HW entries */
19029e39c5baSBill Taylor 	rsvd_rsrc = (tavor_rsrc_t *)rsrc_pool->rsrc_private;
19039e39c5baSBill Taylor 	if (rsvd_rsrc != NULL) {
19049e39c5baSBill Taylor 		tavor_rsrc_free(state, &rsvd_rsrc);
19059e39c5baSBill Taylor 	}
19069e39c5baSBill Taylor 
19079e39c5baSBill Taylor 	/*
19089e39c5baSBill Taylor 	 * If we've actually setup a vmem arena for the HW entries, then
19099e39c5baSBill Taylor 	 * destroy it now
19109e39c5baSBill Taylor 	 */
19119e39c5baSBill Taylor 	if (rsrc_pool->rsrc_vmp != NULL) {
19129e39c5baSBill Taylor 		vmem_destroy(rsrc_pool->rsrc_vmp);
19139e39c5baSBill Taylor 	}
19149e39c5baSBill Taylor 
19159e39c5baSBill Taylor 	/*
19169e39c5baSBill Taylor 	 * Determine if a region was allocated from the tavor_ddr_vmem
19179e39c5baSBill Taylor 	 * arena (and free it up if necessary)
19189e39c5baSBill Taylor 	 */
19199e39c5baSBill Taylor 	if (rsrc_pool->rsrc_ddr_offset != rsrc_pool->rsrc_start) {
19209e39c5baSBill Taylor 		vmem_xfree(state->ts_ddrvmem, rsrc_pool->rsrc_ddr_offset,
19219e39c5baSBill Taylor 		    rsrc_pool->rsrc_pool_size);
19229e39c5baSBill Taylor 	}
19239e39c5baSBill Taylor }
19249e39c5baSBill Taylor 
19259e39c5baSBill Taylor 
19269e39c5baSBill Taylor /*
19279e39c5baSBill Taylor  * tavor_rsrc_sw_handles_init()
19289e39c5baSBill Taylor  *    Context: Only called from attach() path context
19299e39c5baSBill Taylor  */
19309e39c5baSBill Taylor /* ARGSUSED */
19319e39c5baSBill Taylor static int
tavor_rsrc_sw_handles_init(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)19329e39c5baSBill Taylor tavor_rsrc_sw_handles_init(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
19339e39c5baSBill Taylor {
19349e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
19359e39c5baSBill Taylor 	uint64_t		num_swhdl, max_swhdl, prealloc_sz;
19369e39c5baSBill Taylor 
19379e39c5baSBill Taylor 	ASSERT(state != NULL);
19389e39c5baSBill Taylor 	ASSERT(info != NULL);
19399e39c5baSBill Taylor 
19409e39c5baSBill Taylor 	rsrc_pool	= info->swi_rsrcpool;
19419e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
19429e39c5baSBill Taylor 	num_swhdl	= info->swi_num;
19439e39c5baSBill Taylor 	max_swhdl	= info->swi_max;
19449e39c5baSBill Taylor 	prealloc_sz	= info->swi_prealloc_sz;
19459e39c5baSBill Taylor 
19469e39c5baSBill Taylor 	/* Make sure number of SW handles makes sense */
19479e39c5baSBill Taylor 	if (num_swhdl > max_swhdl) {
19489e39c5baSBill Taylor 		return (DDI_FAILURE);
19499e39c5baSBill Taylor 	}
19509e39c5baSBill Taylor 
19519e39c5baSBill Taylor 	/*
19529e39c5baSBill Taylor 	 * Depending on the flags parameter, create a kmem_cache for some
19539e39c5baSBill Taylor 	 * number of software handle structures.  Note: kmem_cache_create()
19549e39c5baSBill Taylor 	 * will SLEEP until successful.
19559e39c5baSBill Taylor 	 */
19569e39c5baSBill Taylor 	if (info->swi_flags & TAVOR_SWHDL_KMEMCACHE_INIT) {
19579e39c5baSBill Taylor 		rsrc_pool->rsrc_private = kmem_cache_create(
19589e39c5baSBill Taylor 		    info->swi_rsrcname, rsrc_pool->rsrc_quantum, 0,
19599e39c5baSBill Taylor 		    info->swi_constructor, info->swi_destructor, NULL,
19609e39c5baSBill Taylor 		    rsrc_pool->rsrc_state, NULL, 0);
19619e39c5baSBill Taylor 	}
19629e39c5baSBill Taylor 
19639e39c5baSBill Taylor 	/* Allocate the central list of SW handle pointers */
19649e39c5baSBill Taylor 	if (info->swi_flags & TAVOR_SWHDL_TABLE_INIT) {
19659e39c5baSBill Taylor 		info->swi_table_ptr = kmem_zalloc(num_swhdl * prealloc_sz,
19669e39c5baSBill Taylor 		    KM_SLEEP);
19679e39c5baSBill Taylor 	}
19689e39c5baSBill Taylor 
19699e39c5baSBill Taylor 	return (DDI_SUCCESS);
19709e39c5baSBill Taylor }
19719e39c5baSBill Taylor 
19729e39c5baSBill Taylor 
19739e39c5baSBill Taylor /*
19749e39c5baSBill Taylor  * tavor_rsrc_sw_handles_fini()
19759e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
19769e39c5baSBill Taylor  */
19779e39c5baSBill Taylor /* ARGSUSED */
19789e39c5baSBill Taylor static void
tavor_rsrc_sw_handles_fini(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)19799e39c5baSBill Taylor tavor_rsrc_sw_handles_fini(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
19809e39c5baSBill Taylor {
19819e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
19829e39c5baSBill Taylor 	uint64_t		num_swhdl, prealloc_sz;
19839e39c5baSBill Taylor 
19849e39c5baSBill Taylor 	ASSERT(state != NULL);
19859e39c5baSBill Taylor 	ASSERT(info != NULL);
19869e39c5baSBill Taylor 
19879e39c5baSBill Taylor 	rsrc_pool	= info->swi_rsrcpool;
19889e39c5baSBill Taylor 	num_swhdl	= info->swi_num;
19899e39c5baSBill Taylor 	prealloc_sz	= info->swi_prealloc_sz;
19909e39c5baSBill Taylor 
19919e39c5baSBill Taylor 	/*
19929e39c5baSBill Taylor 	 * If a "software handle" kmem_cache exists for this resource, then
19939e39c5baSBill Taylor 	 * destroy it now
19949e39c5baSBill Taylor 	 */
19959e39c5baSBill Taylor 	if (rsrc_pool != NULL) {
19969e39c5baSBill Taylor 		kmem_cache_destroy(rsrc_pool->rsrc_private);
19979e39c5baSBill Taylor 	}
19989e39c5baSBill Taylor 
19999e39c5baSBill Taylor 	/* Free up this central list of SW handle pointers */
20009e39c5baSBill Taylor 	if (info->swi_table_ptr != NULL) {
20019e39c5baSBill Taylor 		kmem_free(info->swi_table_ptr, num_swhdl * prealloc_sz);
20029e39c5baSBill Taylor 	}
20039e39c5baSBill Taylor }
20049e39c5baSBill Taylor 
20059e39c5baSBill Taylor 
20069e39c5baSBill Taylor /*
20079e39c5baSBill Taylor  * tavor_rsrc_pd_handles_init()
20089e39c5baSBill Taylor  *    Context: Only called from attach() path context
20099e39c5baSBill Taylor  */
20109e39c5baSBill Taylor static int
tavor_rsrc_pd_handles_init(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)20119e39c5baSBill Taylor tavor_rsrc_pd_handles_init(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
20129e39c5baSBill Taylor {
20139e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
20149e39c5baSBill Taylor 	vmem_t			*vmp;
20159e39c5baSBill Taylor 	char			vmem_name[TAVOR_RSRC_NAME_MAXLEN];
20169e39c5baSBill Taylor 	int			status;
20179e39c5baSBill Taylor 
20189e39c5baSBill Taylor 	ASSERT(state != NULL);
20199e39c5baSBill Taylor 	ASSERT(info != NULL);
20209e39c5baSBill Taylor 
20219e39c5baSBill Taylor 	rsrc_pool = info->swi_rsrcpool;
20229e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
20239e39c5baSBill Taylor 
20249e39c5baSBill Taylor 	/* Initialize the resource pool for software handle table */
20259e39c5baSBill Taylor 	status = tavor_rsrc_sw_handles_init(state, info);
20269e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
20279e39c5baSBill Taylor 		return (DDI_FAILURE);
20289e39c5baSBill Taylor 	}
20299e39c5baSBill Taylor 
20309e39c5baSBill Taylor 	/* Build vmem arena name from Tavor instance */
20319e39c5baSBill Taylor 	TAVOR_RSRC_NAME(vmem_name, TAVOR_PDHDL_VMEM);
20329e39c5baSBill Taylor 
20339e39c5baSBill Taylor 	/* Create new vmem arena for PD numbers */
20349e39c5baSBill Taylor 	vmp = vmem_create(vmem_name, (caddr_t)1, info->swi_num, 1, NULL,
20359e39c5baSBill Taylor 	    NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
20369e39c5baSBill Taylor 	if (vmp == NULL) {
20379e39c5baSBill Taylor 		/* Unable to create vmem arena */
20389e39c5baSBill Taylor 		info->swi_table_ptr = NULL;
20399e39c5baSBill Taylor 		tavor_rsrc_sw_handles_fini(state, info);
20409e39c5baSBill Taylor 		return (DDI_FAILURE);
20419e39c5baSBill Taylor 	}
20429e39c5baSBill Taylor 	rsrc_pool->rsrc_vmp = vmp;
20439e39c5baSBill Taylor 
20449e39c5baSBill Taylor 	return (DDI_SUCCESS);
20459e39c5baSBill Taylor }
20469e39c5baSBill Taylor 
20479e39c5baSBill Taylor 
20489e39c5baSBill Taylor /*
20499e39c5baSBill Taylor  * tavor_rsrc_pd_handles_fini()
20509e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
20519e39c5baSBill Taylor  */
20529e39c5baSBill Taylor static void
tavor_rsrc_pd_handles_fini(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)20539e39c5baSBill Taylor tavor_rsrc_pd_handles_fini(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
20549e39c5baSBill Taylor {
20559e39c5baSBill Taylor 	tavor_rsrc_pool_info_t	*rsrc_pool;
20569e39c5baSBill Taylor 
20579e39c5baSBill Taylor 	ASSERT(state != NULL);
20589e39c5baSBill Taylor 	ASSERT(info != NULL);
20599e39c5baSBill Taylor 
20609e39c5baSBill Taylor 	rsrc_pool = info->swi_rsrcpool;
20619e39c5baSBill Taylor 
20629e39c5baSBill Taylor 	/* Destroy the specially created UAR scratch table vmem arena */
20639e39c5baSBill Taylor 	vmem_destroy(rsrc_pool->rsrc_vmp);
20649e39c5baSBill Taylor 
20659e39c5baSBill Taylor 	/* Destroy the "tavor_sw_pd_t" kmem_cache */
20669e39c5baSBill Taylor 	tavor_rsrc_sw_handles_fini(state, info);
20679e39c5baSBill Taylor }
20689e39c5baSBill Taylor 
20699e39c5baSBill Taylor 
20709e39c5baSBill Taylor /*
20719e39c5baSBill Taylor  * tavor_rsrc_mbox_alloc()
20729e39c5baSBill Taylor  *    Context: Only called from attach() path context
20739e39c5baSBill Taylor  */
20749e39c5baSBill Taylor static int
tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t num,tavor_rsrc_t * hdl)20759e39c5baSBill Taylor tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t num,
20769e39c5baSBill Taylor     tavor_rsrc_t *hdl)
20779e39c5baSBill Taylor {
20789e39c5baSBill Taylor 	tavor_rsrc_priv_mbox_t	*priv;
20799e39c5baSBill Taylor 	void			*addr;
20809e39c5baSBill Taylor 	caddr_t			kaddr;
20819e39c5baSBill Taylor 	uint64_t		offset;
20829e39c5baSBill Taylor 	size_t			real_len, temp_len;
20839e39c5baSBill Taylor 	int			status;
20849e39c5baSBill Taylor 
20859e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
20869e39c5baSBill Taylor 	ASSERT(hdl != NULL);
20879e39c5baSBill Taylor 
20889e39c5baSBill Taylor 	/* Get the private pointer for the mailboxes */
20899e39c5baSBill Taylor 	priv = pool_info->rsrc_private;
20909e39c5baSBill Taylor 	ASSERT(priv != NULL);
20919e39c5baSBill Taylor 
20929e39c5baSBill Taylor 	/*
20939e39c5baSBill Taylor 	 * Allocate a DMA handle for the mailbox.  This will be used for
20949e39c5baSBill Taylor 	 * two purposes (potentially).  First, it could be used below in
20959e39c5baSBill Taylor 	 * the call to ddi_dma_mem_alloc() - if the mailbox is to come from
20969e39c5baSBill Taylor 	 * system memory.  Second, it is definitely used later to bind
20979e39c5baSBill Taylor 	 * the mailbox for DMA access from/by the hardware.
20989e39c5baSBill Taylor 	 */
20999e39c5baSBill Taylor 	status = ddi_dma_alloc_handle(priv->pmb_dip, &priv->pmb_dmaattr,
21009e39c5baSBill Taylor 	    DDI_DMA_SLEEP, NULL, &hdl->tr_dmahdl);
21019e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
21029e39c5baSBill Taylor 		return (DDI_FAILURE);
21039e39c5baSBill Taylor 	}
21049e39c5baSBill Taylor 
21059e39c5baSBill Taylor 	/* Is mailbox in DDR memory or system memory? */
21069e39c5baSBill Taylor 	if (pool_info->rsrc_loc == TAVOR_IN_DDR) {
21079e39c5baSBill Taylor 		/* Use vmem_alloc() to get DDR address of mbox */
21089e39c5baSBill Taylor 		hdl->tr_len = (num * pool_info->rsrc_quantum);
21099e39c5baSBill Taylor 		addr = vmem_alloc(pool_info->rsrc_vmp, hdl->tr_len,
21109e39c5baSBill Taylor 		    VM_SLEEP);
21119e39c5baSBill Taylor 		if (addr == NULL) {
21129e39c5baSBill Taylor 			/* No more DDR available for mailbox entries */
21139e39c5baSBill Taylor 			ddi_dma_free_handle(&hdl->tr_dmahdl);
21149e39c5baSBill Taylor 			return (DDI_FAILURE);
21159e39c5baSBill Taylor 		}
21169e39c5baSBill Taylor 		hdl->tr_acchdl = priv->pmb_acchdl;
21179e39c5baSBill Taylor 
21189e39c5baSBill Taylor 		/* Calculate kernel virtual address (from the DDR offset) */
21199e39c5baSBill Taylor 		offset = ((uintptr_t)addr -
21209e39c5baSBill Taylor 		    (uintptr_t)pool_info->rsrc_ddr_offset);
21219e39c5baSBill Taylor 		hdl->tr_addr = (void *)(uintptr_t)(offset +
21229e39c5baSBill Taylor 		    (uintptr_t)pool_info->rsrc_start);
21239e39c5baSBill Taylor 
21249e39c5baSBill Taylor 	} else { /* TAVOR_IN_SYSMEM */
21259e39c5baSBill Taylor 
21269e39c5baSBill Taylor 		/* Use ddi_dma_mem_alloc() to get memory for mailbox */
21279e39c5baSBill Taylor 		temp_len = (num * pool_info->rsrc_quantum);
21289e39c5baSBill Taylor 		status = ddi_dma_mem_alloc(hdl->tr_dmahdl, temp_len,
21299e39c5baSBill Taylor 		    &priv->pmb_devaccattr, priv->pmb_xfer_mode, DDI_DMA_SLEEP,
21309e39c5baSBill Taylor 		    NULL, &kaddr, &real_len, &hdl->tr_acchdl);
21319e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
21329e39c5baSBill Taylor 			/* No more sys memory available for mailbox entries */
21339e39c5baSBill Taylor 			ddi_dma_free_handle(&hdl->tr_dmahdl);
21349e39c5baSBill Taylor 			return (DDI_FAILURE);
21359e39c5baSBill Taylor 		}
21369e39c5baSBill Taylor 		hdl->tr_addr = (void *)kaddr;
21379e39c5baSBill Taylor 		hdl->tr_len  = real_len;
21389e39c5baSBill Taylor 	}
21399e39c5baSBill Taylor 
21409e39c5baSBill Taylor 	return (DDI_SUCCESS);
21419e39c5baSBill Taylor }
21429e39c5baSBill Taylor 
21439e39c5baSBill Taylor 
21449e39c5baSBill Taylor /*
21459e39c5baSBill Taylor  * tavor_rsrc_mbox_free()
21469e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
21479e39c5baSBill Taylor  */
21489e39c5baSBill Taylor static void
tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)21499e39c5baSBill Taylor tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
21509e39c5baSBill Taylor {
21519e39c5baSBill Taylor 	void		*addr;
21529e39c5baSBill Taylor 	uint64_t	offset;
21539e39c5baSBill Taylor 
21549e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
21559e39c5baSBill Taylor 	ASSERT(hdl != NULL);
21569e39c5baSBill Taylor 
21579e39c5baSBill Taylor 	/* Is mailbox in DDR memory or system memory? */
21589e39c5baSBill Taylor 	if (pool_info->rsrc_loc == TAVOR_IN_DDR) {
21599e39c5baSBill Taylor 
21609e39c5baSBill Taylor 		/* Calculate the allocated address (the mbox's DDR offset) */
21619e39c5baSBill Taylor 		offset = ((uintptr_t)hdl->tr_addr -
21629e39c5baSBill Taylor 		    (uintptr_t)pool_info->rsrc_start);
21639e39c5baSBill Taylor 		addr = (void *)(uintptr_t)(offset +
21649e39c5baSBill Taylor 		    (uintptr_t)pool_info->rsrc_ddr_offset);
21659e39c5baSBill Taylor 
21669e39c5baSBill Taylor 		/* Use vmem_free() to free up DDR memory for mailbox */
21679e39c5baSBill Taylor 		vmem_free(pool_info->rsrc_vmp, addr, hdl->tr_len);
21689e39c5baSBill Taylor 
21699e39c5baSBill Taylor 	} else { /* TAVOR_IN_SYSMEM */
21709e39c5baSBill Taylor 
21719e39c5baSBill Taylor 		/* Use ddi_dma_mem_free() to free up sys memory for mailbox */
21729e39c5baSBill Taylor 		ddi_dma_mem_free(&hdl->tr_acchdl);
21739e39c5baSBill Taylor 	}
21749e39c5baSBill Taylor 
21759e39c5baSBill Taylor 	/* Free the DMA handle for the mailbox */
21769e39c5baSBill Taylor 	ddi_dma_free_handle(&hdl->tr_dmahdl);
21779e39c5baSBill Taylor }
21789e39c5baSBill Taylor 
21799e39c5baSBill Taylor 
21809e39c5baSBill Taylor /*
21819e39c5baSBill Taylor  * tavor_rsrc_hw_entry_alloc()
21829e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
21839e39c5baSBill Taylor  */
21849e39c5baSBill Taylor static int
tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t num,uint_t num_align,ddi_acc_handle_t acc_handle,uint_t sleepflag,tavor_rsrc_t * hdl)21859e39c5baSBill Taylor tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t num,
21869e39c5baSBill Taylor     uint_t num_align, ddi_acc_handle_t acc_handle, uint_t sleepflag,
21879e39c5baSBill Taylor     tavor_rsrc_t *hdl)
21889e39c5baSBill Taylor {
21899e39c5baSBill Taylor 	void		*addr;
21909e39c5baSBill Taylor 	uint64_t	offset;
21919e39c5baSBill Taylor 	uint32_t	align;
21929e39c5baSBill Taylor 	int		flag;
21939e39c5baSBill Taylor 
21949e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
21959e39c5baSBill Taylor 	ASSERT(hdl != NULL);
21969e39c5baSBill Taylor 
21979e39c5baSBill Taylor 	/*
21989e39c5baSBill Taylor 	 * Tavor hardware entries (QPC, CQC, EQC, MPT, MTT, etc.) do not
21999e39c5baSBill Taylor 	 * use dma_handle (because they are in Tavor locally attached DDR
22009e39c5baSBill Taylor 	 * memory) and, generally, don't use the acc_handle (because the
22019e39c5baSBill Taylor 	 * entries are not directly accessed by software).  The exceptions
22029e39c5baSBill Taylor 	 * to this rule are the UARPG and UDAV entries.
22039e39c5baSBill Taylor 	 */
22049e39c5baSBill Taylor 
22059e39c5baSBill Taylor 	/*
22069e39c5baSBill Taylor 	 * Use vmem_xalloc() to get a properly aligned pointer (based on
22079e39c5baSBill Taylor 	 * the number requested) to the HW entry(ies).  This handles the
22089e39c5baSBill Taylor 	 * cases (for special QPCs and for RDB entries) where we need more
22099e39c5baSBill Taylor 	 * than one and need to ensure that they are properly aligned.
22109e39c5baSBill Taylor 	 */
22119e39c5baSBill Taylor 	flag = (sleepflag == TAVOR_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
22129e39c5baSBill Taylor 	hdl->tr_len = (num * pool_info->rsrc_quantum);
22139e39c5baSBill Taylor 	align	    = (num_align * pool_info->rsrc_quantum);
22149e39c5baSBill Taylor 	addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->tr_len,
22159e39c5baSBill Taylor 	    align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
22169e39c5baSBill Taylor 	if (addr == NULL) {
22179e39c5baSBill Taylor 		/* No more HW entries available */
22189e39c5baSBill Taylor 		return (DDI_FAILURE);
22199e39c5baSBill Taylor 	}
22209e39c5baSBill Taylor 
22219e39c5baSBill Taylor 	/* If an access handle was provided, fill it in */
22229e39c5baSBill Taylor 	if (acc_handle != 0) {
22239e39c5baSBill Taylor 		hdl->tr_acchdl = acc_handle;
22249e39c5baSBill Taylor 	}
22259e39c5baSBill Taylor 
22269e39c5baSBill Taylor 	/* Calculate vaddr and HW table index (from the DDR offset) */
22279e39c5baSBill Taylor 	offset = ((uintptr_t)addr - (uintptr_t)pool_info->rsrc_ddr_offset);
22289e39c5baSBill Taylor 	hdl->tr_addr = (void *)(uintptr_t)(offset +
22299e39c5baSBill Taylor 	    (uintptr_t)pool_info->rsrc_start);
22309e39c5baSBill Taylor 	hdl->tr_indx = (offset >> pool_info->rsrc_shift);
22319e39c5baSBill Taylor 
22329e39c5baSBill Taylor 	return (DDI_SUCCESS);
22339e39c5baSBill Taylor }
22349e39c5baSBill Taylor 
22359e39c5baSBill Taylor 
22369e39c5baSBill Taylor /*
22379e39c5baSBill Taylor  * tavor_rsrc_hw_entry_free()
22389e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22399e39c5baSBill Taylor  */
22409e39c5baSBill Taylor static void
tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)22419e39c5baSBill Taylor tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
22429e39c5baSBill Taylor {
22439e39c5baSBill Taylor 	void		*addr;
22449e39c5baSBill Taylor 	uint64_t	offset;
22459e39c5baSBill Taylor 
22469e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
22479e39c5baSBill Taylor 	ASSERT(hdl != NULL);
22489e39c5baSBill Taylor 
22499e39c5baSBill Taylor 	/* Calculate the allocated address (the entry's DDR offset) */
22509e39c5baSBill Taylor 	offset = ((uintptr_t)hdl->tr_addr - (uintptr_t)pool_info->rsrc_start);
22519e39c5baSBill Taylor 	addr   = (void *)(uintptr_t)(offset +
22529e39c5baSBill Taylor 	    (uintptr_t)pool_info->rsrc_ddr_offset);
22539e39c5baSBill Taylor 
22549e39c5baSBill Taylor 	/* Use vmem_xfree() to free up the HW table entry */
22559e39c5baSBill Taylor 	vmem_xfree(pool_info->rsrc_vmp, addr, hdl->tr_len);
22569e39c5baSBill Taylor }
22579e39c5baSBill Taylor 
22589e39c5baSBill Taylor 
22599e39c5baSBill Taylor /*
22609e39c5baSBill Taylor  * tavor_rsrc_swhdl_alloc()
22619e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22629e39c5baSBill Taylor  */
22639e39c5baSBill Taylor static int
tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t sleepflag,tavor_rsrc_t * hdl)22649e39c5baSBill Taylor tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t sleepflag,
22659e39c5baSBill Taylor     tavor_rsrc_t *hdl)
22669e39c5baSBill Taylor {
22679e39c5baSBill Taylor 	void	*addr;
22689e39c5baSBill Taylor 	int	flag;
22699e39c5baSBill Taylor 
22709e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
22719e39c5baSBill Taylor 	ASSERT(hdl != NULL);
22729e39c5baSBill Taylor 
22739e39c5baSBill Taylor 	/* Allocate the software handle structure */
22749e39c5baSBill Taylor 	flag = (sleepflag == TAVOR_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
22759e39c5baSBill Taylor 	addr = kmem_cache_alloc(pool_info->rsrc_private, flag);
22769e39c5baSBill Taylor 	if (addr == NULL) {
22779e39c5baSBill Taylor 		return (DDI_FAILURE);
22789e39c5baSBill Taylor 	}
22799e39c5baSBill Taylor 	hdl->tr_len  = pool_info->rsrc_quantum;
22809e39c5baSBill Taylor 	hdl->tr_addr = addr;
22819e39c5baSBill Taylor 
22829e39c5baSBill Taylor 	return (DDI_SUCCESS);
22839e39c5baSBill Taylor }
22849e39c5baSBill Taylor 
22859e39c5baSBill Taylor 
22869e39c5baSBill Taylor /*
22879e39c5baSBill Taylor  * tavor_rsrc_swhdl_free()
22889e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22899e39c5baSBill Taylor  */
22909e39c5baSBill Taylor static void
tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)22919e39c5baSBill Taylor tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
22929e39c5baSBill Taylor {
22939e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
22949e39c5baSBill Taylor 	ASSERT(hdl != NULL);
22959e39c5baSBill Taylor 
22969e39c5baSBill Taylor 	/* Free the software handle structure */
22979e39c5baSBill Taylor 	kmem_cache_free(pool_info->rsrc_private, hdl->tr_addr);
22989e39c5baSBill Taylor }
22999e39c5baSBill Taylor 
23009e39c5baSBill Taylor 
23019e39c5baSBill Taylor /*
23029e39c5baSBill Taylor  * tavor_rsrc_pdhdl_alloc()
23039e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23049e39c5baSBill Taylor  */
23059e39c5baSBill Taylor static int
tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t sleepflag,tavor_rsrc_t * hdl)23069e39c5baSBill Taylor tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t sleepflag,
23079e39c5baSBill Taylor     tavor_rsrc_t *hdl)
23089e39c5baSBill Taylor {
23099e39c5baSBill Taylor 	tavor_pdhdl_t	addr;
23109e39c5baSBill Taylor 	void		*tmpaddr;
23119e39c5baSBill Taylor 	int		flag, status;
23129e39c5baSBill Taylor 
23139e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
23149e39c5baSBill Taylor 	ASSERT(hdl != NULL);
23159e39c5baSBill Taylor 
23169e39c5baSBill Taylor 	/* Allocate the software handle */
23179e39c5baSBill Taylor 	status = tavor_rsrc_swhdl_alloc(pool_info, sleepflag, hdl);
23189e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
23199e39c5baSBill Taylor 		return (DDI_FAILURE);
23209e39c5baSBill Taylor 	}
23219e39c5baSBill Taylor 	addr = (tavor_pdhdl_t)hdl->tr_addr;
23229e39c5baSBill Taylor 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr))
23239e39c5baSBill Taylor 
23249e39c5baSBill Taylor 	/* Allocate a PD number for the handle */
23259e39c5baSBill Taylor 	flag = (sleepflag == TAVOR_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
23269e39c5baSBill Taylor 	tmpaddr = vmem_alloc(pool_info->rsrc_vmp, 1, flag);
23279e39c5baSBill Taylor 	if (tmpaddr == NULL) {
23289e39c5baSBill Taylor 		/* No more PD number entries available */
23299e39c5baSBill Taylor 		tavor_rsrc_swhdl_free(pool_info, hdl);
23309e39c5baSBill Taylor 		return (DDI_FAILURE);
23319e39c5baSBill Taylor 	}
23329e39c5baSBill Taylor 	addr->pd_pdnum = (uint32_t)(uintptr_t)tmpaddr;
23339e39c5baSBill Taylor 	addr->pd_rsrcp = hdl;
23349e39c5baSBill Taylor 	hdl->tr_indx   = addr->pd_pdnum;
23359e39c5baSBill Taylor 
23369e39c5baSBill Taylor 	return (DDI_SUCCESS);
23379e39c5baSBill Taylor }
23389e39c5baSBill Taylor 
23399e39c5baSBill Taylor 
23409e39c5baSBill Taylor /*
23419e39c5baSBill Taylor  * tavor_rsrc_pdhdl_free()
23429e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23439e39c5baSBill Taylor  */
23449e39c5baSBill Taylor static void
tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)23459e39c5baSBill Taylor tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
23469e39c5baSBill Taylor {
23479e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
23489e39c5baSBill Taylor 	ASSERT(hdl != NULL);
23499e39c5baSBill Taylor 
23509e39c5baSBill Taylor 	/* Use vmem_free() to free up the PD number */
23519e39c5baSBill Taylor 	vmem_free(pool_info->rsrc_vmp, (void *)(uintptr_t)hdl->tr_indx, 1);
23529e39c5baSBill Taylor 
23539e39c5baSBill Taylor 	/* Free the software handle structure */
23549e39c5baSBill Taylor 	tavor_rsrc_swhdl_free(pool_info, hdl);
23559e39c5baSBill Taylor }
23569e39c5baSBill Taylor 
23579e39c5baSBill Taylor 
23589e39c5baSBill Taylor /*
23599e39c5baSBill Taylor  * tavor_rsrc_pdhdl_constructor()
23609e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23619e39c5baSBill Taylor  */
23629e39c5baSBill Taylor /* ARGSUSED */
23639e39c5baSBill Taylor static int
tavor_rsrc_pdhdl_constructor(void * pd,void * priv,int flags)23649e39c5baSBill Taylor tavor_rsrc_pdhdl_constructor(void *pd, void *priv, int flags)
23659e39c5baSBill Taylor {
23669e39c5baSBill Taylor 	tavor_pdhdl_t	pdhdl;
23679e39c5baSBill Taylor 	tavor_state_t	*state;
23689e39c5baSBill Taylor 
23699e39c5baSBill Taylor 	pdhdl = (tavor_pdhdl_t)pd;
23709e39c5baSBill Taylor 	state = (tavor_state_t *)priv;
23719e39c5baSBill Taylor 
23729e39c5baSBill Taylor 	mutex_init(&pdhdl->pd_lock, NULL, MUTEX_DRIVER,
23739e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
23749e39c5baSBill Taylor 
23759e39c5baSBill Taylor 	return (DDI_SUCCESS);
23769e39c5baSBill Taylor }
23779e39c5baSBill Taylor 
23789e39c5baSBill Taylor 
23799e39c5baSBill Taylor /*
23809e39c5baSBill Taylor  * tavor_rsrc_pdhdl_destructor()
23819e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23829e39c5baSBill Taylor  */
23839e39c5baSBill Taylor /* ARGSUSED */
23849e39c5baSBill Taylor static void
tavor_rsrc_pdhdl_destructor(void * pd,void * priv)23859e39c5baSBill Taylor tavor_rsrc_pdhdl_destructor(void *pd, void *priv)
23869e39c5baSBill Taylor {
23879e39c5baSBill Taylor 	tavor_pdhdl_t	pdhdl;
23889e39c5baSBill Taylor 
23899e39c5baSBill Taylor 	pdhdl = (tavor_pdhdl_t)pd;
23909e39c5baSBill Taylor 
23919e39c5baSBill Taylor 	mutex_destroy(&pdhdl->pd_lock);
23929e39c5baSBill Taylor }
23939e39c5baSBill Taylor 
23949e39c5baSBill Taylor 
23959e39c5baSBill Taylor /*
23969e39c5baSBill Taylor  * tavor_rsrc_cqhdl_constructor()
23979e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23989e39c5baSBill Taylor  */
23999e39c5baSBill Taylor /* ARGSUSED */
24009e39c5baSBill Taylor static int
tavor_rsrc_cqhdl_constructor(void * cq,void * priv,int flags)24019e39c5baSBill Taylor tavor_rsrc_cqhdl_constructor(void *cq, void *priv, int flags)
24029e39c5baSBill Taylor {
24039e39c5baSBill Taylor 	tavor_cqhdl_t	cqhdl;
24049e39c5baSBill Taylor 	tavor_state_t	*state;
24059e39c5baSBill Taylor 
24069e39c5baSBill Taylor 	cqhdl = (tavor_cqhdl_t)cq;
24079e39c5baSBill Taylor 	state = (tavor_state_t *)priv;
24089e39c5baSBill Taylor 
24099e39c5baSBill Taylor 	mutex_init(&cqhdl->cq_lock, NULL, MUTEX_DRIVER,
24109e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
24119e39c5baSBill Taylor 	mutex_init(&cqhdl->cq_wrid_wqhdr_lock, NULL, MUTEX_DRIVER,
24129e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
24139e39c5baSBill Taylor 
24149e39c5baSBill Taylor 	return (DDI_SUCCESS);
24159e39c5baSBill Taylor }
24169e39c5baSBill Taylor 
24179e39c5baSBill Taylor 
24189e39c5baSBill Taylor /*
24199e39c5baSBill Taylor  * tavor_rsrc_cqhdl_destructor()
24209e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24219e39c5baSBill Taylor  */
24229e39c5baSBill Taylor /* ARGSUSED */
24239e39c5baSBill Taylor static void
tavor_rsrc_cqhdl_destructor(void * cq,void * priv)24249e39c5baSBill Taylor tavor_rsrc_cqhdl_destructor(void *cq, void *priv)
24259e39c5baSBill Taylor {
24269e39c5baSBill Taylor 	tavor_cqhdl_t	cqhdl;
24279e39c5baSBill Taylor 
24289e39c5baSBill Taylor 	cqhdl = (tavor_cqhdl_t)cq;
24299e39c5baSBill Taylor 
24309e39c5baSBill Taylor 	mutex_destroy(&cqhdl->cq_wrid_wqhdr_lock);
24319e39c5baSBill Taylor 	mutex_destroy(&cqhdl->cq_lock);
24329e39c5baSBill Taylor }
24339e39c5baSBill Taylor 
24349e39c5baSBill Taylor 
24359e39c5baSBill Taylor /*
24369e39c5baSBill Taylor  * tavor_rsrc_qphdl_constructor()
24379e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24389e39c5baSBill Taylor  */
24399e39c5baSBill Taylor /* ARGSUSED */
24409e39c5baSBill Taylor static int
tavor_rsrc_qphdl_constructor(void * qp,void * priv,int flags)24419e39c5baSBill Taylor tavor_rsrc_qphdl_constructor(void *qp, void *priv, int flags)
24429e39c5baSBill Taylor {
24439e39c5baSBill Taylor 	tavor_qphdl_t	qphdl;
24449e39c5baSBill Taylor 	tavor_state_t	*state;
24459e39c5baSBill Taylor 
24469e39c5baSBill Taylor 	qphdl = (tavor_qphdl_t)qp;
24479e39c5baSBill Taylor 	state = (tavor_state_t *)priv;
24489e39c5baSBill Taylor 
24499e39c5baSBill Taylor 	mutex_init(&qphdl->qp_lock, NULL, MUTEX_DRIVER,
24509e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
24519e39c5baSBill Taylor 
24529e39c5baSBill Taylor 	return (DDI_SUCCESS);
24539e39c5baSBill Taylor }
24549e39c5baSBill Taylor 
24559e39c5baSBill Taylor 
24569e39c5baSBill Taylor /*
24579e39c5baSBill Taylor  * tavor_rsrc_qphdl_destructor()
24589e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24599e39c5baSBill Taylor  */
24609e39c5baSBill Taylor /* ARGSUSED */
24619e39c5baSBill Taylor static void
tavor_rsrc_qphdl_destructor(void * qp,void * priv)24629e39c5baSBill Taylor tavor_rsrc_qphdl_destructor(void *qp, void *priv)
24639e39c5baSBill Taylor {
24649e39c5baSBill Taylor 	tavor_qphdl_t	qphdl;
24659e39c5baSBill Taylor 
24669e39c5baSBill Taylor 	qphdl = (tavor_qphdl_t)qp;
24679e39c5baSBill Taylor 
24689e39c5baSBill Taylor 	mutex_destroy(&qphdl->qp_lock);
24699e39c5baSBill Taylor }
24709e39c5baSBill Taylor 
24719e39c5baSBill Taylor 
24729e39c5baSBill Taylor /*
24739e39c5baSBill Taylor  * tavor_rsrc_srqhdl_constructor()
24749e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24759e39c5baSBill Taylor  */
24769e39c5baSBill Taylor /* ARGSUSED */
24779e39c5baSBill Taylor static int
tavor_rsrc_srqhdl_constructor(void * srq,void * priv,int flags)24789e39c5baSBill Taylor tavor_rsrc_srqhdl_constructor(void *srq, void *priv, int flags)
24799e39c5baSBill Taylor {
24809e39c5baSBill Taylor 	tavor_srqhdl_t	srqhdl;
24819e39c5baSBill Taylor 	tavor_state_t	*state;
24829e39c5baSBill Taylor 
24839e39c5baSBill Taylor 	srqhdl = (tavor_srqhdl_t)srq;
24849e39c5baSBill Taylor 	state = (tavor_state_t *)priv;
24859e39c5baSBill Taylor 
24869e39c5baSBill Taylor 	mutex_init(&srqhdl->srq_lock, NULL, MUTEX_DRIVER,
24879e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
24889e39c5baSBill Taylor 
24899e39c5baSBill Taylor 	return (DDI_SUCCESS);
24909e39c5baSBill Taylor }
24919e39c5baSBill Taylor 
24929e39c5baSBill Taylor 
24939e39c5baSBill Taylor /*
24949e39c5baSBill Taylor  * tavor_rsrc_srqhdl_destructor()
24959e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24969e39c5baSBill Taylor  */
24979e39c5baSBill Taylor /* ARGSUSED */
24989e39c5baSBill Taylor static void
tavor_rsrc_srqhdl_destructor(void * srq,void * priv)24999e39c5baSBill Taylor tavor_rsrc_srqhdl_destructor(void *srq, void *priv)
25009e39c5baSBill Taylor {
25019e39c5baSBill Taylor 	tavor_srqhdl_t	srqhdl;
25029e39c5baSBill Taylor 
25039e39c5baSBill Taylor 	srqhdl = (tavor_srqhdl_t)srq;
25049e39c5baSBill Taylor 
25059e39c5baSBill Taylor 	mutex_destroy(&srqhdl->srq_lock);
25069e39c5baSBill Taylor }
25079e39c5baSBill Taylor 
25089e39c5baSBill Taylor 
25099e39c5baSBill Taylor /*
25109e39c5baSBill Taylor  * tavor_rsrc_refcnt_constructor()
25119e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25129e39c5baSBill Taylor  */
25139e39c5baSBill Taylor /* ARGSUSED */
25149e39c5baSBill Taylor static int
tavor_rsrc_refcnt_constructor(void * rc,void * priv,int flags)25159e39c5baSBill Taylor tavor_rsrc_refcnt_constructor(void *rc, void *priv, int flags)
25169e39c5baSBill Taylor {
25179e39c5baSBill Taylor 	tavor_sw_refcnt_t	*refcnt;
25189e39c5baSBill Taylor 	tavor_state_t		*state;
25199e39c5baSBill Taylor 
25209e39c5baSBill Taylor 	refcnt = (tavor_sw_refcnt_t *)rc;
25219e39c5baSBill Taylor 	state  = (tavor_state_t *)priv;
25229e39c5baSBill Taylor 
25239e39c5baSBill Taylor 	mutex_init(&refcnt->swrc_lock, NULL, MUTEX_DRIVER,
25249e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
25259e39c5baSBill Taylor 
25269e39c5baSBill Taylor 	return (DDI_SUCCESS);
25279e39c5baSBill Taylor }
25289e39c5baSBill Taylor 
25299e39c5baSBill Taylor 
25309e39c5baSBill Taylor /*
25319e39c5baSBill Taylor  * tavor_rsrc_refcnt_destructor()
25329e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25339e39c5baSBill Taylor  */
25349e39c5baSBill Taylor /* ARGSUSED */
25359e39c5baSBill Taylor static void
tavor_rsrc_refcnt_destructor(void * rc,void * priv)25369e39c5baSBill Taylor tavor_rsrc_refcnt_destructor(void *rc, void *priv)
25379e39c5baSBill Taylor {
25389e39c5baSBill Taylor 	tavor_sw_refcnt_t	*refcnt;
25399e39c5baSBill Taylor 
25409e39c5baSBill Taylor 	refcnt = (tavor_sw_refcnt_t *)rc;
25419e39c5baSBill Taylor 
25429e39c5baSBill Taylor 	mutex_destroy(&refcnt->swrc_lock);
25439e39c5baSBill Taylor }
25449e39c5baSBill Taylor 
25459e39c5baSBill Taylor 
25469e39c5baSBill Taylor /*
25479e39c5baSBill Taylor  * tavor_rsrc_ahhdl_constructor()
25489e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25499e39c5baSBill Taylor  */
25509e39c5baSBill Taylor /* ARGSUSED */
25519e39c5baSBill Taylor static int
tavor_rsrc_ahhdl_constructor(void * ah,void * priv,int flags)25529e39c5baSBill Taylor tavor_rsrc_ahhdl_constructor(void *ah, void *priv, int flags)
25539e39c5baSBill Taylor {
25549e39c5baSBill Taylor 	tavor_ahhdl_t	ahhdl;
25559e39c5baSBill Taylor 	tavor_state_t	*state;
25569e39c5baSBill Taylor 
25579e39c5baSBill Taylor 	ahhdl = (tavor_ahhdl_t)ah;
25589e39c5baSBill Taylor 	state = (tavor_state_t *)priv;
25599e39c5baSBill Taylor 
25609e39c5baSBill Taylor 	mutex_init(&ahhdl->ah_lock, NULL, MUTEX_DRIVER,
25619e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
25629e39c5baSBill Taylor 
25639e39c5baSBill Taylor 	return (DDI_SUCCESS);
25649e39c5baSBill Taylor }
25659e39c5baSBill Taylor 
25669e39c5baSBill Taylor 
25679e39c5baSBill Taylor /*
25689e39c5baSBill Taylor  * tavor_rsrc_ahhdl_destructor()
25699e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25709e39c5baSBill Taylor  */
25719e39c5baSBill Taylor /* ARGSUSED */
25729e39c5baSBill Taylor static void
tavor_rsrc_ahhdl_destructor(void * ah,void * priv)25739e39c5baSBill Taylor tavor_rsrc_ahhdl_destructor(void *ah, void *priv)
25749e39c5baSBill Taylor {
25759e39c5baSBill Taylor 	tavor_ahhdl_t	ahhdl;
25769e39c5baSBill Taylor 
25779e39c5baSBill Taylor 	ahhdl = (tavor_ahhdl_t)ah;
25789e39c5baSBill Taylor 
25799e39c5baSBill Taylor 	mutex_destroy(&ahhdl->ah_lock);
25809e39c5baSBill Taylor }
25819e39c5baSBill Taylor 
25829e39c5baSBill Taylor 
25839e39c5baSBill Taylor /*
25849e39c5baSBill Taylor  * tavor_rsrc_mrhdl_constructor()
25859e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25869e39c5baSBill Taylor  */
25879e39c5baSBill Taylor /* ARGSUSED */
25889e39c5baSBill Taylor static int
tavor_rsrc_mrhdl_constructor(void * mr,void * priv,int flags)25899e39c5baSBill Taylor tavor_rsrc_mrhdl_constructor(void *mr, void *priv, int flags)
25909e39c5baSBill Taylor {
25919e39c5baSBill Taylor 	tavor_mrhdl_t	mrhdl;
25929e39c5baSBill Taylor 	tavor_state_t	*state;
25939e39c5baSBill Taylor 
25949e39c5baSBill Taylor 	mrhdl = (tavor_mrhdl_t)mr;
25959e39c5baSBill Taylor 	state = (tavor_state_t *)priv;
25969e39c5baSBill Taylor 
25979e39c5baSBill Taylor 	mutex_init(&mrhdl->mr_lock, NULL, MUTEX_DRIVER,
25989e39c5baSBill Taylor 	    DDI_INTR_PRI(state->ts_intrmsi_pri));
25999e39c5baSBill Taylor 
26009e39c5baSBill Taylor 	return (DDI_SUCCESS);
26019e39c5baSBill Taylor }
26029e39c5baSBill Taylor 
26039e39c5baSBill Taylor 
26049e39c5baSBill Taylor /*
26059e39c5baSBill Taylor  * tavor_rsrc_mrhdl_destructor()
26069e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
26079e39c5baSBill Taylor  */
26089e39c5baSBill Taylor /* ARGSUSED */
26099e39c5baSBill Taylor static void
tavor_rsrc_mrhdl_destructor(void * mr,void * priv)26109e39c5baSBill Taylor tavor_rsrc_mrhdl_destructor(void *mr, void *priv)
26119e39c5baSBill Taylor {
26129e39c5baSBill Taylor 	tavor_mrhdl_t	mrhdl;
26139e39c5baSBill Taylor 
26149e39c5baSBill Taylor 	mrhdl = (tavor_mrhdl_t)mr;
26159e39c5baSBill Taylor 
26169e39c5baSBill Taylor 	mutex_destroy(&mrhdl->mr_lock);
26179e39c5baSBill Taylor }
26189e39c5baSBill Taylor 
26199e39c5baSBill Taylor 
26209e39c5baSBill Taylor /*
26219e39c5baSBill Taylor  * tavor_rsrc_mcg_entry_get_size()
26229e39c5baSBill Taylor  */
26239e39c5baSBill Taylor static int
tavor_rsrc_mcg_entry_get_size(tavor_state_t * state,uint_t * mcg_size_shift)26249e39c5baSBill Taylor tavor_rsrc_mcg_entry_get_size(tavor_state_t *state, uint_t *mcg_size_shift)
26259e39c5baSBill Taylor {
26269e39c5baSBill Taylor 	uint_t	num_qp_per_mcg, max_qp_per_mcg, log2;
26279e39c5baSBill Taylor 
26289e39c5baSBill Taylor 	/*
26299e39c5baSBill Taylor 	 * Round the configured number of QP per MCG to next larger
26309e39c5baSBill Taylor 	 * power-of-2 size and update.
26319e39c5baSBill Taylor 	 */
26329e39c5baSBill Taylor 	num_qp_per_mcg = state->ts_cfg_profile->cp_num_qp_per_mcg + 8;
26339e39c5baSBill Taylor 	log2 = highbit(num_qp_per_mcg);
2634de710d24SJosef 'Jeff' Sipek 	if (ISP2(num_qp_per_mcg)) {
26359e39c5baSBill Taylor 		log2 = log2 - 1;
26369e39c5baSBill Taylor 	}
26379e39c5baSBill Taylor 	state->ts_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
26389e39c5baSBill Taylor 
26399e39c5baSBill Taylor 	/* Now make sure number of QP per MCG makes sense */
26409e39c5baSBill Taylor 	num_qp_per_mcg = state->ts_cfg_profile->cp_num_qp_per_mcg;
26419e39c5baSBill Taylor 	max_qp_per_mcg = (1 << state->ts_devlim.log_max_qp_mcg);
26429e39c5baSBill Taylor 	if (num_qp_per_mcg > max_qp_per_mcg) {
26439e39c5baSBill Taylor 		return (DDI_FAILURE);
26449e39c5baSBill Taylor 	}
26459e39c5baSBill Taylor 
26469e39c5baSBill Taylor 	/* Return the (shift) size of an individual MCG HW entry */
26479e39c5baSBill Taylor 	*mcg_size_shift = log2 + 2;
26489e39c5baSBill Taylor 
26499e39c5baSBill Taylor 	return (DDI_SUCCESS);
26509e39c5baSBill Taylor }
2651