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 /*
23*c7facc54SBill Taylor  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
249e39c5baSBill Taylor  * Use is subject to license terms.
259e39c5baSBill Taylor  */
269e39c5baSBill Taylor 
279e39c5baSBill Taylor /*
289e39c5baSBill Taylor  * hermon_rsrc.c
299e39c5baSBill Taylor  *    Hermon Resource Management Routines
309e39c5baSBill Taylor  *
319e39c5baSBill Taylor  *    Implements all the routines necessary for setup, teardown, and
329e39c5baSBill Taylor  *    alloc/free of all Hermon resources, including those that are managed
339e39c5baSBill Taylor  *    by Hermon hardware or which live in Hermon's direct attached DDR memory.
349e39c5baSBill Taylor  */
359e39c5baSBill Taylor 
369e39c5baSBill Taylor #include <sys/types.h>
379e39c5baSBill Taylor #include <sys/conf.h>
389e39c5baSBill Taylor #include <sys/ddi.h>
399e39c5baSBill Taylor #include <sys/sunddi.h>
409e39c5baSBill Taylor #include <sys/modctl.h>
419e39c5baSBill Taylor #include <sys/vmem.h>
429e39c5baSBill Taylor #include <sys/bitmap.h>
439e39c5baSBill Taylor 
449e39c5baSBill Taylor #include <sys/ib/adapters/hermon/hermon.h>
459e39c5baSBill Taylor 
469e39c5baSBill Taylor int hermon_rsrc_verbose = 0;
479e39c5baSBill Taylor 
489e39c5baSBill Taylor /*
499e39c5baSBill Taylor  * The following routines are used for initializing and destroying
509e39c5baSBill Taylor  * the resource pools used by the Hermon resource allocation routines.
519e39c5baSBill Taylor  * They consist of four classes of object:
529e39c5baSBill Taylor  *
539e39c5baSBill Taylor  * Mailboxes:  The "In" and "Out" mailbox types are used by the Hermon
549e39c5baSBill Taylor  *    command interface routines.  Mailboxes are used to pass information
559e39c5baSBill Taylor  *    back and forth to the Hermon firmware.  Either type of mailbox may
569e39c5baSBill Taylor  *    be allocated from Hermon's direct attached DDR memory or from system
579e39c5baSBill Taylor  *    memory (although currently all "In" mailboxes are in DDR and all "out"
589e39c5baSBill Taylor  *    mailboxes come from system memory.
599e39c5baSBill Taylor  *
609e39c5baSBill Taylor  * HW entry objects:  These objects represent resources required by the Hermon
619e39c5baSBill Taylor  *    hardware.  These objects include things like Queue Pair contexts (QPC),
629e39c5baSBill Taylor  *    Completion Queue contexts (CQC), Event Queue contexts (EQC), RDB (for
639e39c5baSBill Taylor  *    supporting RDMA Read/Atomic), Multicast Group entries (MCG), Memory
649e39c5baSBill Taylor  *    Protection Table entries (MPT), Memory Translation Table entries (MTT).
659e39c5baSBill Taylor  *
669e39c5baSBill Taylor  *    What these objects all have in common is that they are each required
679e39c5baSBill Taylor  *    to come from ICM memory, they are always allocated from tables, and
689e39c5baSBill Taylor  *    they are not to be directly accessed (read or written) by driver
699e39c5baSBill Taylor  *    software (Mellanox FMR access to MPT is an exception).
709e39c5baSBill Taylor  *    The other notable exceptions are the UAR pages (UAR_PG) which are
719e39c5baSBill Taylor  *    allocated from the UAR address space rather than DDR, and the UD
729e39c5baSBill Taylor  *    address vectors (UDAV) which are similar to the common object types
739e39c5baSBill Taylor  *    with the major difference being that UDAVs _are_ directly read and
749e39c5baSBill Taylor  *    written by driver software.
759e39c5baSBill Taylor  *
769e39c5baSBill Taylor  * SW handle objects: These objects represent resources required by Hermon
779e39c5baSBill Taylor  *    driver software.  They are primarily software tracking structures,
789e39c5baSBill Taylor  *    which are allocated from system memory (using kmem_cache).  Several of
799e39c5baSBill Taylor  *    the objects have both a "constructor" and "destructor" method
809e39c5baSBill Taylor  *    associated with them (see below).
819e39c5baSBill Taylor  *
829e39c5baSBill Taylor  * Protection Domain (PD) handle objects:  These objects are very much like
839e39c5baSBill Taylor  *    a SW handle object with the notable difference that all PD handle
849e39c5baSBill Taylor  *    objects have an actual Protection Domain number (PD) associated with
859e39c5baSBill Taylor  *    them (and the PD number is allocated/managed through a separate
869e39c5baSBill Taylor  *    vmem_arena specifically set aside for this purpose.
879e39c5baSBill Taylor  */
889e39c5baSBill Taylor 
899e39c5baSBill Taylor static int hermon_rsrc_mbox_init(hermon_state_t *state,
909e39c5baSBill Taylor     hermon_rsrc_mbox_info_t *info);
919e39c5baSBill Taylor static void hermon_rsrc_mbox_fini(hermon_state_t *state,
929e39c5baSBill Taylor     hermon_rsrc_mbox_info_t *info);
939e39c5baSBill Taylor 
949e39c5baSBill Taylor static int hermon_rsrc_sw_handles_init(hermon_state_t *state,
959e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info);
969e39c5baSBill Taylor static void hermon_rsrc_sw_handles_fini(hermon_state_t *state,
979e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info);
989e39c5baSBill Taylor 
999e39c5baSBill Taylor static int hermon_rsrc_pd_handles_init(hermon_state_t *state,
1009e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info);
1019e39c5baSBill Taylor static void hermon_rsrc_pd_handles_fini(hermon_state_t *state,
1029e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info);
1039e39c5baSBill Taylor 
1049e39c5baSBill Taylor /*
1059e39c5baSBill Taylor  * The following routines are used for allocating and freeing the specific
1069e39c5baSBill Taylor  * types of objects described above from their associated resource pools.
1079e39c5baSBill Taylor  */
1089e39c5baSBill Taylor static int hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info,
1099e39c5baSBill Taylor     uint_t num, hermon_rsrc_t *hdl);
1109e39c5baSBill Taylor static void hermon_rsrc_mbox_free(hermon_rsrc_pool_info_t *pool_info,
1119e39c5baSBill Taylor     hermon_rsrc_t *hdl);
1129e39c5baSBill Taylor 
1139e39c5baSBill Taylor static int hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info,
1149e39c5baSBill Taylor     uint_t num, uint_t num_align, ddi_acc_handle_t acc_handle,
1159e39c5baSBill Taylor     uint_t sleepflag, hermon_rsrc_t *hdl);
1169e39c5baSBill Taylor static void hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
1179e39c5baSBill Taylor     hermon_rsrc_t *hdl);
1189e39c5baSBill Taylor 
1199e39c5baSBill Taylor static int hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info,
1209e39c5baSBill Taylor     uint_t num, hermon_rsrc_t *hdl);
1219e39c5baSBill Taylor static int hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
1229e39c5baSBill Taylor     hermon_rsrc_t *hdl);
1239e39c5baSBill Taylor 
1249e39c5baSBill Taylor static int hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
1259e39c5baSBill Taylor     uint_t sleepflag, hermon_rsrc_t *hdl);
1269e39c5baSBill Taylor static void hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info,
1279e39c5baSBill Taylor     hermon_rsrc_t *hdl);
1289e39c5baSBill Taylor 
1299e39c5baSBill Taylor static int hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
1309e39c5baSBill Taylor     uint_t sleepflag, hermon_rsrc_t *hdl);
1319e39c5baSBill Taylor static void hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t *pool_info,
1329e39c5baSBill Taylor     hermon_rsrc_t *hdl);
1339e39c5baSBill Taylor 
1349e39c5baSBill Taylor /*
1359e39c5baSBill Taylor  * The following routines are the constructors and destructors for several
1369e39c5baSBill Taylor  * of the SW handle type objects.  For certain types of SW handles objects
1379e39c5baSBill Taylor  * (all of which are implemented using kmem_cache), we need to do some
1389e39c5baSBill Taylor  * special field initialization (specifically, mutex_init/destroy).  These
1399e39c5baSBill Taylor  * routines enable that init and teardown.
1409e39c5baSBill Taylor  */
1419e39c5baSBill Taylor static int hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
1429e39c5baSBill Taylor static void hermon_rsrc_pdhdl_destructor(void *pd, void *state);
1439e39c5baSBill Taylor static int hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
1449e39c5baSBill Taylor static void hermon_rsrc_cqhdl_destructor(void *cq, void *state);
1459e39c5baSBill Taylor static int hermon_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
1469e39c5baSBill Taylor static void hermon_rsrc_qphdl_destructor(void *cq, void *state);
1479e39c5baSBill Taylor static int hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
1489e39c5baSBill Taylor static void hermon_rsrc_srqhdl_destructor(void *srq, void *state);
1499e39c5baSBill Taylor static int hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
1509e39c5baSBill Taylor static void hermon_rsrc_refcnt_destructor(void *rc, void *state);
1519e39c5baSBill Taylor static int hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
1529e39c5baSBill Taylor static void hermon_rsrc_ahhdl_destructor(void *ah, void *state);
1539e39c5baSBill Taylor static int hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
1549e39c5baSBill Taylor static void hermon_rsrc_mrhdl_destructor(void *mr, void *state);
1559e39c5baSBill Taylor 
1569e39c5baSBill Taylor /*
1579e39c5baSBill Taylor  * Special routine to calculate and return the size of a MCG object based
1589e39c5baSBill Taylor  * on current driver configuration (specifically, the number of QP per MCG
1599e39c5baSBill Taylor  * that has been configured.
1609e39c5baSBill Taylor  */
1619e39c5baSBill Taylor static int hermon_rsrc_mcg_entry_get_size(hermon_state_t *state,
1629e39c5baSBill Taylor     uint_t *mcg_size_shift);
1639e39c5baSBill Taylor 
1649e39c5baSBill Taylor 
1659e39c5baSBill Taylor /*
1669e39c5baSBill Taylor  * hermon_rsrc_alloc()
1679e39c5baSBill Taylor  *
1689e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
1699e39c5baSBill Taylor  *    The "sleepflag" parameter is used by all object allocators to
1709e39c5baSBill Taylor  *    determine whether to SLEEP for resources or not.
1719e39c5baSBill Taylor  */
1729e39c5baSBill Taylor int
1739e39c5baSBill Taylor hermon_rsrc_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num,
1749e39c5baSBill Taylor     uint_t sleepflag, hermon_rsrc_t **hdl)
1759e39c5baSBill Taylor {
1769e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
1779e39c5baSBill Taylor 	hermon_rsrc_t		*tmp_rsrc_hdl;
1789e39c5baSBill Taylor 	int			flag, status = DDI_FAILURE;
1799e39c5baSBill Taylor 
1809e39c5baSBill Taylor 	ASSERT(state != NULL);
1819e39c5baSBill Taylor 	ASSERT(hdl != NULL);
1829e39c5baSBill Taylor 
1839e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[rsrc];
1849e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
1859e39c5baSBill Taylor 
1869e39c5baSBill Taylor 	/*
1879e39c5baSBill Taylor 	 * Allocate space for the object used to track the resource handle
1889e39c5baSBill Taylor 	 */
1899e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
1909e39c5baSBill Taylor 	tmp_rsrc_hdl = (hermon_rsrc_t *)kmem_cache_alloc(state->hs_rsrc_cache,
1919e39c5baSBill Taylor 	    flag);
1929e39c5baSBill Taylor 	if (tmp_rsrc_hdl == NULL) {
1939e39c5baSBill Taylor 		return (DDI_FAILURE);
1949e39c5baSBill Taylor 	}
1959e39c5baSBill Taylor 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
1969e39c5baSBill Taylor 
1979e39c5baSBill Taylor 	/*
1989e39c5baSBill Taylor 	 * Set rsrc_hdl type.  This is later used by the hermon_rsrc_free call
1999e39c5baSBill Taylor 	 * to know what type of resource is being freed.
2009e39c5baSBill Taylor 	 */
2019e39c5baSBill Taylor 	tmp_rsrc_hdl->rsrc_type = rsrc;
2029e39c5baSBill Taylor 
2039e39c5baSBill Taylor 	/*
2049e39c5baSBill Taylor 	 * Depending on resource type, call the appropriate alloc routine
2059e39c5baSBill Taylor 	 */
2069e39c5baSBill Taylor 	switch (rsrc_pool->rsrc_type) {
2079e39c5baSBill Taylor 	case HERMON_IN_MBOX:
2089e39c5baSBill Taylor 	case HERMON_OUT_MBOX:
2099e39c5baSBill Taylor 	case HERMON_INTR_IN_MBOX:
2109e39c5baSBill Taylor 	case HERMON_INTR_OUT_MBOX:
2119e39c5baSBill Taylor 		status = hermon_rsrc_mbox_alloc(rsrc_pool, num, tmp_rsrc_hdl);
2129e39c5baSBill Taylor 		break;
2139e39c5baSBill Taylor 
2149e39c5baSBill Taylor 	case HERMON_QPC:
215*c7facc54SBill Taylor 		/* Allocate "num" contiguous/aligned QPCs for RSS */
216*c7facc54SBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, num,
217*c7facc54SBill Taylor 		    0, sleepflag, tmp_rsrc_hdl);
218*c7facc54SBill Taylor 		break;
219*c7facc54SBill Taylor 
2209e39c5baSBill Taylor 	case HERMON_CQC:
2219e39c5baSBill Taylor 	case HERMON_SRQC:
2229e39c5baSBill Taylor 	case HERMON_EQC:
2239e39c5baSBill Taylor 		/*
2249e39c5baSBill Taylor 		 * Because these objects are NOT accessed by Hermon driver
2259e39c5baSBill Taylor 		 * software, we set the acc_handle parameter to zero.
2269e39c5baSBill Taylor 		 */
2279e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, 1, 0,
2289e39c5baSBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2299e39c5baSBill Taylor 		break;
2309e39c5baSBill Taylor 
2319e39c5baSBill Taylor 	case HERMON_DMPT:
2329e39c5baSBill Taylor 		/*
2339e39c5baSBill Taylor 		 * Because these objects are sometimes accessed by Hermon
2349e39c5baSBill Taylor 		 * driver software (FMR for MPTs), we need the acc_handle
2359e39c5baSBill Taylor 		 * to be set.  The ICM-aware code will set it for all
2369e39c5baSBill Taylor 		 * ICM backed resources.
2379e39c5baSBill Taylor 		 * But if they are allocated in multiples, we specify here that
2389e39c5baSBill Taylor 		 * they must be aligned on a more restrictive boundary.
2399e39c5baSBill Taylor 		 */
2409e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, num,
2419e39c5baSBill Taylor 		    0, sleepflag, tmp_rsrc_hdl);
2429e39c5baSBill Taylor 		break;
2439e39c5baSBill Taylor 
2449e39c5baSBill Taylor 	case HERMON_MCG:
2459e39c5baSBill Taylor 		/*
2469e39c5baSBill Taylor 		 * Hermon MCG entries are also NOT accessed by Hermon driver
2479e39c5baSBill Taylor 		 * software, but because MCG entries do not have the same
2489e39c5baSBill Taylor 		 * alignnment restrictions we loosen the constraint here.
2499e39c5baSBill Taylor 		 */
2509e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, 1, 0,
2519e39c5baSBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2529e39c5baSBill Taylor 		break;
2539e39c5baSBill Taylor 
2549e39c5baSBill Taylor 	case HERMON_MTT:
2559e39c5baSBill Taylor 		/*
2569e39c5baSBill Taylor 		 * Because MTT objects are among the few HW resources that
2579e39c5baSBill Taylor 		 * may be allocated in odd numbers, we specify a less
2589e39c5baSBill Taylor 		 * restrictive alignment than for the above resources.
2599e39c5baSBill Taylor 		 */
2609e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
2619e39c5baSBill Taylor 		    0, sleepflag, tmp_rsrc_hdl);
2629e39c5baSBill Taylor 		break;
2639e39c5baSBill Taylor 
2649e39c5baSBill Taylor 	case HERMON_UARPG:
2659e39c5baSBill Taylor 		/*
2669e39c5baSBill Taylor 		 * Because UAR pages are written by Hermon driver software (for
2679e39c5baSBill Taylor 		 * doorbells), we set the acc_handle parameter to point to
2689e39c5baSBill Taylor 		 * the ddi_acc_handle_t for the Hermon UAR memory.
2699e39c5baSBill Taylor 		 */
2709e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
2719e39c5baSBill Taylor 		    hermon_rsrc_alloc_uarhdl(state), sleepflag, tmp_rsrc_hdl);
2729e39c5baSBill Taylor 		break;
2739e39c5baSBill Taylor 
2749e39c5baSBill Taylor 	case HERMON_MRHDL:
2759e39c5baSBill Taylor 	case HERMON_EQHDL:
2769e39c5baSBill Taylor 	case HERMON_CQHDL:
2779e39c5baSBill Taylor 	case HERMON_SRQHDL:
2789e39c5baSBill Taylor 	case HERMON_AHHDL:
2799e39c5baSBill Taylor 	case HERMON_QPHDL:
2809e39c5baSBill Taylor 	case HERMON_REFCNT:
2819e39c5baSBill Taylor 		status = hermon_rsrc_swhdl_alloc(rsrc_pool, sleepflag,
2829e39c5baSBill Taylor 		    tmp_rsrc_hdl);
2839e39c5baSBill Taylor 		break;
2849e39c5baSBill Taylor 
2859e39c5baSBill Taylor 	case HERMON_PDHDL:
2869e39c5baSBill Taylor 		status = hermon_rsrc_pdhdl_alloc(rsrc_pool, sleepflag,
2879e39c5baSBill Taylor 		    tmp_rsrc_hdl);
2889e39c5baSBill Taylor 		break;
2899e39c5baSBill Taylor 
2909e39c5baSBill Taylor 	case HERMON_RDB:	/* handled during HERMON_QPC */
2919e39c5baSBill Taylor 	case HERMON_ALTC:	/* handled during HERMON_QPC */
2929e39c5baSBill Taylor 	case HERMON_AUXC:	/* handled during HERMON_QPC */
2939e39c5baSBill Taylor 	case HERMON_CMPT_QPC:	/* handled during HERMON_QPC */
2949e39c5baSBill Taylor 	case HERMON_CMPT_SRQC:	/* handled during HERMON_SRQC */
2959e39c5baSBill Taylor 	case HERMON_CMPT_CQC:	/* handled during HERMON_CPC */
2969e39c5baSBill Taylor 	case HERMON_CMPT_EQC:	/* handled during HERMON_EPC */
2979e39c5baSBill Taylor 	default:
2989e39c5baSBill Taylor 		HERMON_WARNING(state, "unexpected resource type in alloc ");
2999e39c5baSBill Taylor 		cmn_err(CE_WARN, "Resource type %x \n", rsrc_pool->rsrc_type);
3009e39c5baSBill Taylor 		break;
3019e39c5baSBill Taylor 	}
3029e39c5baSBill Taylor 
3039e39c5baSBill Taylor 	/*
3049e39c5baSBill Taylor 	 * If the resource allocation failed, then free the special resource
3059e39c5baSBill Taylor 	 * tracking structure and return failure.  Otherwise return the
3069e39c5baSBill Taylor 	 * handle for the resource tracking structure.
3079e39c5baSBill Taylor 	 */
3089e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
3099e39c5baSBill Taylor 		kmem_cache_free(state->hs_rsrc_cache, tmp_rsrc_hdl);
3109e39c5baSBill Taylor 		tmp_rsrc_hdl = NULL;
3119e39c5baSBill Taylor 		return (DDI_FAILURE);
3129e39c5baSBill Taylor 	} else {
3139e39c5baSBill Taylor 		*hdl = tmp_rsrc_hdl;
3149e39c5baSBill Taylor 		return (DDI_SUCCESS);
3159e39c5baSBill Taylor 	}
3169e39c5baSBill Taylor }
3179e39c5baSBill Taylor 
3189e39c5baSBill Taylor 
3199e39c5baSBill Taylor /*
3209e39c5baSBill Taylor  * hermon_rsrc_free()
3219e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
3229e39c5baSBill Taylor  */
3239e39c5baSBill Taylor void
3249e39c5baSBill Taylor hermon_rsrc_free(hermon_state_t *state, hermon_rsrc_t **hdl)
3259e39c5baSBill Taylor {
3269e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
3279e39c5baSBill Taylor 
3289e39c5baSBill Taylor 	ASSERT(state != NULL);
3299e39c5baSBill Taylor 	ASSERT(hdl != NULL);
3309e39c5baSBill Taylor 
3319e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[(*hdl)->rsrc_type];
3329e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
3339e39c5baSBill Taylor 
3349e39c5baSBill Taylor 	/*
3359e39c5baSBill Taylor 	 * Depending on resource type, call the appropriate free routine
3369e39c5baSBill Taylor 	 */
3379e39c5baSBill Taylor 	switch (rsrc_pool->rsrc_type) {
3389e39c5baSBill Taylor 	case HERMON_IN_MBOX:
3399e39c5baSBill Taylor 	case HERMON_OUT_MBOX:
3409e39c5baSBill Taylor 	case HERMON_INTR_IN_MBOX:
3419e39c5baSBill Taylor 	case HERMON_INTR_OUT_MBOX:
3429e39c5baSBill Taylor 		hermon_rsrc_mbox_free(rsrc_pool, *hdl);
3439e39c5baSBill Taylor 		break;
3449e39c5baSBill Taylor 
3459e39c5baSBill Taylor 	case HERMON_QPC:
3469e39c5baSBill Taylor 	case HERMON_CQC:
3479e39c5baSBill Taylor 	case HERMON_SRQC:
3489e39c5baSBill Taylor 	case HERMON_EQC:
3499e39c5baSBill Taylor 	case HERMON_DMPT:
3509e39c5baSBill Taylor 	case HERMON_MCG:
3519e39c5baSBill Taylor 	case HERMON_MTT:
3529e39c5baSBill Taylor 	case HERMON_UARPG:
3539e39c5baSBill Taylor 		hermon_rsrc_hw_entry_free(rsrc_pool, *hdl);
3549e39c5baSBill Taylor 		break;
3559e39c5baSBill Taylor 
3569e39c5baSBill Taylor 	case HERMON_MRHDL:
3579e39c5baSBill Taylor 	case HERMON_EQHDL:
3589e39c5baSBill Taylor 	case HERMON_CQHDL:
3599e39c5baSBill Taylor 	case HERMON_SRQHDL:
3609e39c5baSBill Taylor 	case HERMON_AHHDL:
3619e39c5baSBill Taylor 	case HERMON_QPHDL:
3629e39c5baSBill Taylor 	case HERMON_REFCNT:
3639e39c5baSBill Taylor 		hermon_rsrc_swhdl_free(rsrc_pool, *hdl);
3649e39c5baSBill Taylor 		break;
3659e39c5baSBill Taylor 
3669e39c5baSBill Taylor 	case HERMON_PDHDL:
3679e39c5baSBill Taylor 		hermon_rsrc_pdhdl_free(rsrc_pool, *hdl);
3689e39c5baSBill Taylor 		break;
3699e39c5baSBill Taylor 
3709e39c5baSBill Taylor 	case HERMON_RDB:
3719e39c5baSBill Taylor 	case HERMON_ALTC:
3729e39c5baSBill Taylor 	case HERMON_AUXC:
3739e39c5baSBill Taylor 	case HERMON_CMPT_QPC:
3749e39c5baSBill Taylor 	case HERMON_CMPT_SRQC:
3759e39c5baSBill Taylor 	case HERMON_CMPT_CQC:
3769e39c5baSBill Taylor 	case HERMON_CMPT_EQC:
3779e39c5baSBill Taylor 	default:
3789e39c5baSBill Taylor 		HERMON_WARNING(state, "unexpected resource type in free");
3799e39c5baSBill Taylor 		break;
3809e39c5baSBill Taylor 	}
3819e39c5baSBill Taylor 
3829e39c5baSBill Taylor 	/*
3839e39c5baSBill Taylor 	 * Free the special resource tracking structure, set the handle to
3849e39c5baSBill Taylor 	 * NULL, and return.
3859e39c5baSBill Taylor 	 */
3869e39c5baSBill Taylor 	kmem_cache_free(state->hs_rsrc_cache, *hdl);
3879e39c5baSBill Taylor 	*hdl = NULL;
3889e39c5baSBill Taylor }
3899e39c5baSBill Taylor 
3909e39c5baSBill Taylor 
3919e39c5baSBill Taylor /*
3929e39c5baSBill Taylor  * hermon_rsrc_init_phase1()
3939e39c5baSBill Taylor  *
3949e39c5baSBill Taylor  *    Completes the first phase of Hermon resource/configuration init.
3959e39c5baSBill Taylor  *    This involves creating the kmem_cache for the "hermon_rsrc_t"
3969e39c5baSBill Taylor  *    structs, allocating the space for the resource pool handles,
3979e39c5baSBill Taylor  *    and setting up the "Out" mailboxes.
3989e39c5baSBill Taylor  *
3999e39c5baSBill Taylor  *    When this function completes, the Hermon driver is ready to
4009e39c5baSBill Taylor  *    post the following commands which return information only in the
4019e39c5baSBill Taylor  *    "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
4029e39c5baSBill Taylor  *    If any of these commands are to be posted at this time, they must be
4039e39c5baSBill Taylor  *    done so only when "spinning" (as the outstanding command list and
4049e39c5baSBill Taylor  *    EQ setup code has not yet run)
4059e39c5baSBill Taylor  *
4069e39c5baSBill Taylor  *    Context: Only called from attach() path context
4079e39c5baSBill Taylor  */
4089e39c5baSBill Taylor int
4099e39c5baSBill Taylor hermon_rsrc_init_phase1(hermon_state_t *state)
4109e39c5baSBill Taylor {
4119e39c5baSBill Taylor 	hermon_rsrc_pool_info_t		*rsrc_pool;
4129e39c5baSBill Taylor 	hermon_rsrc_mbox_info_t 		mbox_info;
4139e39c5baSBill Taylor 	hermon_rsrc_cleanup_level_t	cleanup;
4149e39c5baSBill Taylor 	hermon_cfg_profile_t		*cfgprof;
4159e39c5baSBill Taylor 	uint64_t			num, size;
4169e39c5baSBill Taylor 	int				status;
4179e39c5baSBill Taylor 	char				*rsrc_name;
4189e39c5baSBill Taylor 
4199e39c5baSBill Taylor 	ASSERT(state != NULL);
4209e39c5baSBill Taylor 
4219e39c5baSBill Taylor 	/* This is where Phase 1 of resource initialization begins */
4229e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL0;
4239e39c5baSBill Taylor 
4249e39c5baSBill Taylor 	/* Build kmem cache name from Hermon instance */
4259e39c5baSBill Taylor 	rsrc_name = (char *)kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
4269e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_RSRC_CACHE);
4279e39c5baSBill Taylor 
4289e39c5baSBill Taylor 	/*
4299e39c5baSBill Taylor 	 * Create the kmem_cache for "hermon_rsrc_t" structures
4309e39c5baSBill Taylor 	 * (kmem_cache_create will SLEEP until successful)
4319e39c5baSBill Taylor 	 */
4329e39c5baSBill Taylor 	state->hs_rsrc_cache = kmem_cache_create(rsrc_name,
4339e39c5baSBill Taylor 	    sizeof (hermon_rsrc_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
4349e39c5baSBill Taylor 
4359e39c5baSBill Taylor 	/*
4369e39c5baSBill Taylor 	 * Allocate an array of hermon_rsrc_pool_info_t's (used in all
4379e39c5baSBill Taylor 	 * subsequent resource allocations)
4389e39c5baSBill Taylor 	 */
4399e39c5baSBill Taylor 	state->hs_rsrc_hdl = kmem_zalloc(HERMON_NUM_RESOURCES *
4409e39c5baSBill Taylor 	    sizeof (hermon_rsrc_pool_info_t), KM_SLEEP);
4419e39c5baSBill Taylor 
4429e39c5baSBill Taylor 	/* Pull in the configuration profile */
4439e39c5baSBill Taylor 	cfgprof = state->hs_cfg_profile;
4449e39c5baSBill Taylor 
4459e39c5baSBill Taylor 	/* Initialize the resource pool for "out" mailboxes */
4469e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_outmbox);
4479e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
4489e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
4499e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = HERMON_OUT_MBOX;
4509e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
4519e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
4529e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
4539e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
4549e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
4559e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
4569e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
4579e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
4589e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
4599e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
4609e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
4619e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
4629e39c5baSBill Taylor 		status = DDI_FAILURE;
4639e39c5baSBill Taylor 		goto rsrcinitp1_fail;
4649e39c5baSBill Taylor 	}
4659e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL1;
4669e39c5baSBill Taylor 
4679e39c5baSBill Taylor 	/* Initialize the mailbox list */
4689e39c5baSBill Taylor 	status = hermon_outmbox_list_init(state);
4699e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
4709e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
4719e39c5baSBill Taylor 		status = DDI_FAILURE;
4729e39c5baSBill Taylor 		goto rsrcinitp1_fail;
4739e39c5baSBill Taylor 	}
4749e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL2;
4759e39c5baSBill Taylor 
4769e39c5baSBill Taylor 	/* Initialize the resource pool for "interrupt out" mailboxes */
4779e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_outmbox);
4789e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
4799e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
4809e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = HERMON_INTR_OUT_MBOX;
4819e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
4829e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
4839e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
4849e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
4859e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
4869e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
4879e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
4889e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
4899e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
4909e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
4919e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
4929e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
4939e39c5baSBill Taylor 		status = DDI_FAILURE;
4949e39c5baSBill Taylor 		goto rsrcinitp1_fail;
4959e39c5baSBill Taylor 	}
4969e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL3;
4979e39c5baSBill Taylor 
4989e39c5baSBill Taylor 	/* Initialize the mailbox list */
4999e39c5baSBill Taylor 	status = hermon_intr_outmbox_list_init(state);
5009e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
5019e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
5029e39c5baSBill Taylor 		status = DDI_FAILURE;
5039e39c5baSBill Taylor 		goto rsrcinitp1_fail;
5049e39c5baSBill Taylor 	}
5059e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL4;
5069e39c5baSBill Taylor 
5079e39c5baSBill Taylor 	/* Initialize the resource pool for "in" mailboxes */
5089e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_inmbox);
5099e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
5109e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
5119e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = HERMON_IN_MBOX;
5129e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
5139e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
5149e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
5159e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
5169e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
5179e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
5189e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
5199e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
5209e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
5219e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
5229e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
5239e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
5249e39c5baSBill Taylor 		status = DDI_FAILURE;
5259e39c5baSBill Taylor 		goto rsrcinitp1_fail;
5269e39c5baSBill Taylor 	}
5279e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL5;
5289e39c5baSBill Taylor 
5299e39c5baSBill Taylor 	/* Initialize the mailbox list */
5309e39c5baSBill Taylor 	status = hermon_inmbox_list_init(state);
5319e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
5329e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
5339e39c5baSBill Taylor 		status = DDI_FAILURE;
5349e39c5baSBill Taylor 		goto rsrcinitp1_fail;
5359e39c5baSBill Taylor 	}
5369e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL6;
5379e39c5baSBill Taylor 
5389e39c5baSBill Taylor 	/* Initialize the resource pool for "interrupt in" mailboxes */
5399e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_inmbox);
5409e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
5419e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
5429e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = HERMON_INTR_IN_MBOX;
5439e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
5449e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
5459e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
5469e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
5479e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
5489e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
5499e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
5509e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
5519e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
5529e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
5539e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
5549e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
5559e39c5baSBill Taylor 		status = DDI_FAILURE;
5569e39c5baSBill Taylor 		goto rsrcinitp1_fail;
5579e39c5baSBill Taylor 	}
5589e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL7;
5599e39c5baSBill Taylor 
5609e39c5baSBill Taylor 	/* Initialize the mailbox list */
5619e39c5baSBill Taylor 	status = hermon_intr_inmbox_list_init(state);
5629e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
5639e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
5649e39c5baSBill Taylor 		status = DDI_FAILURE;
5659e39c5baSBill Taylor 		goto rsrcinitp1_fail;
5669e39c5baSBill Taylor 	}
5679e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
5689e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
5699e39c5baSBill Taylor 	return (DDI_SUCCESS);
5709e39c5baSBill Taylor 
5719e39c5baSBill Taylor rsrcinitp1_fail:
5729e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
5739e39c5baSBill Taylor 	return (status);
5749e39c5baSBill Taylor }
5759e39c5baSBill Taylor 
5769e39c5baSBill Taylor 
5779e39c5baSBill Taylor /*
5789e39c5baSBill Taylor  * hermon_rsrc_init_phase2()
5799e39c5baSBill Taylor  *    Context: Only called from attach() path context
5809e39c5baSBill Taylor  */
5819e39c5baSBill Taylor int
5829e39c5baSBill Taylor hermon_rsrc_init_phase2(hermon_state_t *state)
5839e39c5baSBill Taylor {
5849e39c5baSBill Taylor 	hermon_rsrc_sw_hdl_info_t	hdl_info;
5859e39c5baSBill Taylor 	hermon_rsrc_hw_entry_info_t	entry_info;
5869e39c5baSBill Taylor 	hermon_rsrc_pool_info_t		*rsrc_pool;
5879e39c5baSBill Taylor 	hermon_rsrc_cleanup_level_t	cleanup, ncleanup;
5889e39c5baSBill Taylor 	hermon_cfg_profile_t		*cfgprof;
5899e39c5baSBill Taylor 	hermon_hw_querydevlim_t		*devlim;
5909e39c5baSBill Taylor 	uint64_t			num, max, num_prealloc;
5919e39c5baSBill Taylor 	uint_t				mcg_size, mcg_size_shift;
5929e39c5baSBill Taylor 	int				i, status;
5939e39c5baSBill Taylor 	char				*rsrc_name;
5949e39c5baSBill Taylor 
5959e39c5baSBill Taylor 	ASSERT(state != NULL);
5969e39c5baSBill Taylor 
5979e39c5baSBill Taylor 	/* Phase 2 initialization begins where Phase 1 left off */
5989e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
5999e39c5baSBill Taylor 
6009e39c5baSBill Taylor 	/* Allocate the ICM resource name space */
6019e39c5baSBill Taylor 
6029e39c5baSBill Taylor 	/* Build the ICM vmem arena names from Hermon instance */
6039e39c5baSBill Taylor 	rsrc_name = (char *)kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
6049e39c5baSBill Taylor 
6059e39c5baSBill Taylor 	/*
6069e39c5baSBill Taylor 	 * Initialize the resource pools for all objects that exist in
6079e39c5baSBill Taylor 	 * context memory (ICM). The ICM consists of context tables, each
6089e39c5baSBill Taylor 	 * type of resource (QP, CQ, EQ, etc) having it's own context table
6099e39c5baSBill Taylor 	 * (QPC, CQC, EQC, etc...).
6109e39c5baSBill Taylor 	 */
6119e39c5baSBill Taylor 	cfgprof = state->hs_cfg_profile;
6129e39c5baSBill Taylor 	devlim	= &state->hs_devlim;
6139e39c5baSBill Taylor 
6149e39c5baSBill Taylor 	/*
6159e39c5baSBill Taylor 	 * Initialize the resource pools for each of the driver resources.
6169e39c5baSBill Taylor 	 * With a few exceptions, these resources fall into the two cateogories
6179e39c5baSBill Taylor 	 * of either hw_entries or sw_entries.
6189e39c5baSBill Taylor 	 */
6199e39c5baSBill Taylor 
6209e39c5baSBill Taylor 	/*
6219e39c5baSBill Taylor 	 * Initialize the resource pools for ICM (hardware) types first.
6229e39c5baSBill Taylor 	 * These resources are managed through vmem arenas, which are
6239e39c5baSBill Taylor 	 * created via the rsrc pool initialization routine. Note that,
6249e39c5baSBill Taylor 	 * due to further calculations, the MCG resource pool is
6259e39c5baSBill Taylor 	 * initialized seperately.
6269e39c5baSBill Taylor 	 */
6279e39c5baSBill Taylor 	for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
6289e39c5baSBill Taylor 
6299e39c5baSBill Taylor 		rsrc_pool = &state->hs_rsrc_hdl[i];
6309e39c5baSBill Taylor 		rsrc_pool->rsrc_type = i;
6319e39c5baSBill Taylor 
6329e39c5baSBill Taylor 		/* Set the resource-specific attributes */
6339e39c5baSBill Taylor 		switch (i) {
6349e39c5baSBill Taylor 		case HERMON_MTT:
6359e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_mtt);
6369e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_mtt);
6379e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_MTT_VMEM);
6389e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL9;
6399e39c5baSBill Taylor 			break;
6409e39c5baSBill Taylor 
6419e39c5baSBill Taylor 		case HERMON_DMPT:
6429e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_dmpt);
6439e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_dmpt);
6449e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_DMPT_VMEM);
6459e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL10;
6469e39c5baSBill Taylor 			break;
6479e39c5baSBill Taylor 
6489e39c5baSBill Taylor 		case HERMON_QPC:
6499e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_qp);
6509e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_qp);
6519e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_QPC_VMEM);
6529e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL11;
6539e39c5baSBill Taylor 			break;
6549e39c5baSBill Taylor 
6559e39c5baSBill Taylor 		case HERMON_CQC:
6569e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_cq);
6579e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_cq);
6589e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_CQC_VMEM);
6599e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL13;
6609e39c5baSBill Taylor 			break;
6619e39c5baSBill Taylor 
6629e39c5baSBill Taylor 		case HERMON_SRQC:
6639e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_srq);
6649e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_srq);
6659e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_SRQC_VMEM);
6669e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL16;
6679e39c5baSBill Taylor 			break;
6689e39c5baSBill Taylor 
6699e39c5baSBill Taylor 		case HERMON_EQC:
6709e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_eq);
6719e39c5baSBill Taylor 			num_prealloc = devlim->num_rsvd_eq;
6729e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_EQC_VMEM);
6739e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL18;
6749e39c5baSBill Taylor 			break;
6759e39c5baSBill Taylor 
6769e39c5baSBill Taylor 		case HERMON_MCG:	/* handled below */
6779e39c5baSBill Taylor 		case HERMON_AUXC:
6789e39c5baSBill Taylor 		case HERMON_ALTC:
6799e39c5baSBill Taylor 		case HERMON_RDB:
6809e39c5baSBill Taylor 		case HERMON_CMPT_QPC:
6819e39c5baSBill Taylor 		case HERMON_CMPT_SRQC:
6829e39c5baSBill Taylor 		case HERMON_CMPT_CQC:
6839e39c5baSBill Taylor 		case HERMON_CMPT_EQC:
6849e39c5baSBill Taylor 		default:
6859e39c5baSBill Taylor 			/* We don't need to initialize this rsrc here. */
6869e39c5baSBill Taylor 			continue;
6879e39c5baSBill Taylor 		}
6889e39c5baSBill Taylor 
6899e39c5baSBill Taylor 		/* Set the common values for all resource pools */
6909e39c5baSBill Taylor 		rsrc_pool->rsrc_state	  = state;
6919e39c5baSBill Taylor 		rsrc_pool->rsrc_loc	  = HERMON_IN_ICM;
6929e39c5baSBill Taylor 		rsrc_pool->rsrc_pool_size = state->hs_icm[i].table_size;
6939e39c5baSBill Taylor 		rsrc_pool->rsrc_align	  = state->hs_icm[i].table_size;
6949e39c5baSBill Taylor 		rsrc_pool->rsrc_shift	  = state->hs_icm[i].log_object_size;
6959e39c5baSBill Taylor 		rsrc_pool->rsrc_quantum	  = state->hs_icm[i].object_size;
6969e39c5baSBill Taylor 
6979e39c5baSBill Taylor 		/* Now, initialize the entry_info and call the init routine */
6989e39c5baSBill Taylor 		entry_info.hwi_num	  = state->hs_icm[i].num_entries;
6999e39c5baSBill Taylor 		entry_info.hwi_max	  = max;
7009e39c5baSBill Taylor 		entry_info.hwi_prealloc	  = num_prealloc;
7019e39c5baSBill Taylor 		entry_info.hwi_rsrcpool	  = rsrc_pool;
7029e39c5baSBill Taylor 		entry_info.hwi_rsrcname	  = rsrc_name;
7039e39c5baSBill Taylor 		status = hermon_rsrc_hw_entries_init(state, &entry_info);
7049e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
7059e39c5baSBill Taylor 			hermon_rsrc_fini(state, cleanup);
7069e39c5baSBill Taylor 			status = DDI_FAILURE;
7079e39c5baSBill Taylor 			goto rsrcinitp2_fail;
7089e39c5baSBill Taylor 		}
7099e39c5baSBill Taylor 		cleanup = ncleanup;
7109e39c5baSBill Taylor 	}
7119e39c5baSBill Taylor 
7129e39c5baSBill Taylor 	/*
7139e39c5baSBill Taylor 	 * Initialize the Multicast Group (MCG) entries. First, calculate
7149e39c5baSBill Taylor 	 * (and validate) the size of the MCGs.
7159e39c5baSBill Taylor 	 */
7169e39c5baSBill Taylor 	status = hermon_rsrc_mcg_entry_get_size(state, &mcg_size_shift);
7179e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7189e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7199e39c5baSBill Taylor 		status = DDI_FAILURE;
7209e39c5baSBill Taylor 		goto rsrcinitp2_fail;
7219e39c5baSBill Taylor 	}
7229e39c5baSBill Taylor 	mcg_size = HERMON_MCGMEM_SZ(state);
7239e39c5baSBill Taylor 
7249e39c5baSBill Taylor 	/*
7259e39c5baSBill Taylor 	 * Initialize the resource pool for the MCG table entries.  Notice
7269e39c5baSBill Taylor 	 * that the number of MCGs is configurable. Note also that a certain
7279e39c5baSBill Taylor 	 * number of MCGs must be set aside for Hermon firmware use (they
7289e39c5baSBill Taylor 	 * correspond to the number of MCGs used by the internal hash
7299e39c5baSBill Taylor 	 * function).
7309e39c5baSBill Taylor 	 */
7319e39c5baSBill Taylor 	num			  = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
7329e39c5baSBill Taylor 	max			  = ((uint64_t)1 << devlim->log_max_mcg);
7339e39c5baSBill Taylor 	num_prealloc	  = ((uint64_t)1 << cfgprof->cp_log_num_mcg_hash);
7349e39c5baSBill Taylor 	rsrc_pool		  = &state->hs_rsrc_hdl[HERMON_MCG];
7359e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = HERMON_MCG;
7369e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_ICM;
7379e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (mcg_size * num);
7389e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = mcg_size_shift;
7399e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = mcg_size;
7409e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (mcg_size * num);
7419e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
7429e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_MCG_VMEM);
7439e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
7449e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
7459e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
7469e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
7479e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
7489e39c5baSBill Taylor 	status = hermon_rsrc_hw_entries_init(state, &entry_info);
7499e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7509e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7519e39c5baSBill Taylor 		status = DDI_FAILURE;
7529e39c5baSBill Taylor 		goto rsrcinitp2_fail;
7539e39c5baSBill Taylor 	}
7549e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL19;
7559e39c5baSBill Taylor 
7569e39c5baSBill Taylor 	/*
7579e39c5baSBill Taylor 	 * Initialize the full range of ICM for the AUXC resource.
7589e39c5baSBill Taylor 	 * This is done because its size is so small, about 1 byte per QP.
7599e39c5baSBill Taylor 	 */
7609e39c5baSBill Taylor 
7619e39c5baSBill Taylor 	/*
7629e39c5baSBill Taylor 	 * Initialize the Hermon command handling interfaces.  This step
7639e39c5baSBill Taylor 	 * sets up the outstanding command tracking mechanism for easy access
7649e39c5baSBill Taylor 	 * and fast allocation (see hermon_cmd.c for more details).
7659e39c5baSBill Taylor 	 */
7669e39c5baSBill Taylor 	status = hermon_outstanding_cmdlist_init(state);
7679e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7689e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7699e39c5baSBill Taylor 		status = DDI_FAILURE;
7709e39c5baSBill Taylor 		goto rsrcinitp2_fail;
7719e39c5baSBill Taylor 	}
7729e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL20;
7739e39c5baSBill Taylor 
7749e39c5baSBill Taylor 	/* Initialize the resource pool and vmem arena for the PD handles */
7759e39c5baSBill Taylor 	rsrc_pool		 = &state->hs_rsrc_hdl[HERMON_PDHDL];
7769e39c5baSBill Taylor 	rsrc_pool->rsrc_type	 = HERMON_PDHDL;
7779e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = HERMON_IN_SYSMEM;
7789e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct hermon_sw_pd_s);
7799e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
7809e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_PDHDL_CACHE);
7819e39c5baSBill Taylor 	hdl_info.swi_num	 = ((uint64_t)1 << cfgprof->cp_log_num_pd);
7829e39c5baSBill Taylor 	hdl_info.swi_max	 = ((uint64_t)1 << devlim->log_max_pd);
7839e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
7849e39c5baSBill Taylor 	hdl_info.swi_constructor = hermon_rsrc_pdhdl_constructor;
7859e39c5baSBill Taylor 	hdl_info.swi_destructor	 = hermon_rsrc_pdhdl_destructor;
7869e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
7879e39c5baSBill Taylor 	hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
7889e39c5baSBill Taylor 	status = hermon_rsrc_pd_handles_init(state, &hdl_info);
7899e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7909e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7919e39c5baSBill Taylor 		status = DDI_FAILURE;
7929e39c5baSBill Taylor 		goto rsrcinitp2_fail;
7939e39c5baSBill Taylor 	}
7949e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL21;
7959e39c5baSBill Taylor 
7969e39c5baSBill Taylor 	/*
7979e39c5baSBill Taylor 	 * Initialize the resource pools for the rest of the software handles.
7989e39c5baSBill Taylor 	 * This includes MR handles, EQ handles, QP handles, etc.  These
7999e39c5baSBill Taylor 	 * objects are almost entirely managed using kmem_cache routines,
8009e39c5baSBill Taylor 	 * and do not utilize a vmem arena.
8019e39c5baSBill Taylor 	 */
8029e39c5baSBill Taylor 	for (i = HERMON_NUM_ICM_RESOURCES; i < HERMON_NUM_RESOURCES; i++) {
8039e39c5baSBill Taylor 		rsrc_pool = &state->hs_rsrc_hdl[i];
8049e39c5baSBill Taylor 
8059e39c5baSBill Taylor 		/* Set the resource-specific attributes */
8069e39c5baSBill Taylor 		switch (i) {
8079e39c5baSBill Taylor 		case HERMON_MRHDL:
8089e39c5baSBill Taylor 			rsrc_pool->rsrc_type    = HERMON_MRHDL;
8099e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
8109e39c5baSBill Taylor 			    sizeof (struct hermon_sw_mr_s);
8119e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_MRHDL_CACHE);
8129e39c5baSBill Taylor 			hdl_info.swi_num =
8139e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
8149e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_cmpt);
8159e39c5baSBill Taylor 			hdl_info.swi_max =
8169e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
8179e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_cmpt);
8189e39c5baSBill Taylor 			hdl_info.swi_constructor =
8199e39c5baSBill Taylor 			    hermon_rsrc_mrhdl_constructor;
8209e39c5baSBill Taylor 			hdl_info.swi_destructor	 = hermon_rsrc_mrhdl_destructor;
8219e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
8229e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL22;
8239e39c5baSBill Taylor 			break;
8249e39c5baSBill Taylor 
8259e39c5baSBill Taylor 		case HERMON_EQHDL:
8269e39c5baSBill Taylor 			rsrc_pool->rsrc_type    = HERMON_EQHDL;
8279e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
8289e39c5baSBill Taylor 			    sizeof (struct hermon_sw_eq_s);
8299e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_EQHDL_CACHE);
8309e39c5baSBill Taylor 			hdl_info.swi_num = HERMON_NUM_EQ;
8319e39c5baSBill Taylor 			hdl_info.swi_max = ((uint64_t)1 << devlim->log_max_eq);
8329e39c5baSBill Taylor 			hdl_info.swi_constructor = NULL;
8339e39c5baSBill Taylor 			hdl_info.swi_destructor	 = NULL;
8349e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
8359e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL23;
8369e39c5baSBill Taylor 			break;
8379e39c5baSBill Taylor 
8389e39c5baSBill Taylor 		case HERMON_CQHDL:
8399e39c5baSBill Taylor 			rsrc_pool->rsrc_type    = HERMON_CQHDL;
8409e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
8419e39c5baSBill Taylor 			    sizeof (struct hermon_sw_cq_s);
8429e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_CQHDL_CACHE);
8439e39c5baSBill Taylor 			hdl_info.swi_num =
8449e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_cq;
8459e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_cq;
8469e39c5baSBill Taylor 			hdl_info.swi_constructor =
8479e39c5baSBill Taylor 			    hermon_rsrc_cqhdl_constructor;
8489e39c5baSBill Taylor 			hdl_info.swi_destructor	 = hermon_rsrc_cqhdl_destructor;
8499e39c5baSBill Taylor 			hdl_info.swi_flags = (HERMON_SWHDL_KMEMCACHE_INIT |
8509e39c5baSBill Taylor 			    HERMON_SWHDL_TABLE_INIT);
8519e39c5baSBill Taylor 			hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
8529e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL24;
8539e39c5baSBill Taylor 			break;
8549e39c5baSBill Taylor 
8559e39c5baSBill Taylor 		case HERMON_SRQHDL:
8569e39c5baSBill Taylor 			rsrc_pool->rsrc_type    = HERMON_SRQHDL;
8579e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
8589e39c5baSBill Taylor 			    sizeof (struct hermon_sw_srq_s);
8599e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_SRQHDL_CACHE);
8609e39c5baSBill Taylor 			hdl_info.swi_num =
8619e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_srq;
8629e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_srq;
8639e39c5baSBill Taylor 			hdl_info.swi_constructor =
8649e39c5baSBill Taylor 			    hermon_rsrc_srqhdl_constructor;
8659e39c5baSBill Taylor 			hdl_info.swi_destructor = hermon_rsrc_srqhdl_destructor;
8669e39c5baSBill Taylor 			hdl_info.swi_flags = (HERMON_SWHDL_KMEMCACHE_INIT |
8679e39c5baSBill Taylor 			    HERMON_SWHDL_TABLE_INIT);
8689e39c5baSBill Taylor 			hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
8699e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL25;
8709e39c5baSBill Taylor 			break;
8719e39c5baSBill Taylor 
8729e39c5baSBill Taylor 		case HERMON_AHHDL:
8739e39c5baSBill Taylor 			rsrc_pool->rsrc_type	= HERMON_AHHDL;
8749e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum	=
8759e39c5baSBill Taylor 			    sizeof (struct hermon_sw_ah_s);
8769e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_AHHDL_CACHE);
8779e39c5baSBill Taylor 			hdl_info.swi_num =
8789e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_ah;
8799e39c5baSBill Taylor 			hdl_info.swi_max = HERMON_NUM_AH;
8809e39c5baSBill Taylor 			hdl_info.swi_constructor =
8819e39c5baSBill Taylor 			    hermon_rsrc_ahhdl_constructor;
8829e39c5baSBill Taylor 			hdl_info.swi_destructor	 = hermon_rsrc_ahhdl_destructor;
8839e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
8849e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL26;
8859e39c5baSBill Taylor 			break;
8869e39c5baSBill Taylor 
8879e39c5baSBill Taylor 		case HERMON_QPHDL:
8889e39c5baSBill Taylor 			rsrc_pool->rsrc_type    = HERMON_QPHDL;
8899e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
8909e39c5baSBill Taylor 			    sizeof (struct hermon_sw_qp_s);
8919e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_QPHDL_CACHE);
8929e39c5baSBill Taylor 			hdl_info.swi_num =
8939e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_qp;
8949e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_qp;
8959e39c5baSBill Taylor 			hdl_info.swi_constructor =
8969e39c5baSBill Taylor 			    hermon_rsrc_qphdl_constructor;
8979e39c5baSBill Taylor 			hdl_info.swi_destructor	= hermon_rsrc_qphdl_destructor;
8989e39c5baSBill Taylor 			hdl_info.swi_flags = (HERMON_SWHDL_KMEMCACHE_INIT |
8999e39c5baSBill Taylor 			    HERMON_SWHDL_TABLE_INIT);
9009e39c5baSBill Taylor 			hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
9019e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL27;
9029e39c5baSBill Taylor 			break;
9039e39c5baSBill Taylor 
9049e39c5baSBill Taylor 		case HERMON_REFCNT:
9059e39c5baSBill Taylor 			rsrc_pool->rsrc_type	 = HERMON_REFCNT;
9069e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum	 = sizeof (hermon_sw_refcnt_t);
9079e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_REFCNT_CACHE);
9089e39c5baSBill Taylor 			hdl_info.swi_num =
9099e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_dmpt;
9109e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_dmpt;
9119e39c5baSBill Taylor 			hdl_info.swi_constructor =
9129e39c5baSBill Taylor 			    hermon_rsrc_refcnt_constructor;
9139e39c5baSBill Taylor 			hdl_info.swi_destructor = hermon_rsrc_refcnt_destructor;
9149e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
9159e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL28;
9169e39c5baSBill Taylor 			break;
9179e39c5baSBill Taylor 
9189e39c5baSBill Taylor 		default:
9199e39c5baSBill Taylor 			continue;
9209e39c5baSBill Taylor 		}
9219e39c5baSBill Taylor 
9229e39c5baSBill Taylor 		/* Set the common values and call the init routine */
9239e39c5baSBill Taylor 		rsrc_pool->rsrc_loc	 = HERMON_IN_SYSMEM;
9249e39c5baSBill Taylor 		rsrc_pool->rsrc_state    = state;
9259e39c5baSBill Taylor 		hdl_info.swi_rsrcpool    = rsrc_pool;
9269e39c5baSBill Taylor 		hdl_info.swi_rsrcname    = rsrc_name;
9279e39c5baSBill Taylor 		status = hermon_rsrc_sw_handles_init(state, &hdl_info);
9289e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
9299e39c5baSBill Taylor 			hermon_rsrc_fini(state, cleanup);
9309e39c5baSBill Taylor 			status = DDI_FAILURE;
9319e39c5baSBill Taylor 			goto rsrcinitp2_fail;
9329e39c5baSBill Taylor 		}
9339e39c5baSBill Taylor 		cleanup = ncleanup;
9349e39c5baSBill Taylor 
9359e39c5baSBill Taylor 		/*
9369e39c5baSBill Taylor 		 * For table entries, save away a pointer to the central list
9379e39c5baSBill Taylor 		 * of handle pointers. These are used to enable fast lookup
9389e39c5baSBill Taylor 		 * of the resources during event processing.
9399e39c5baSBill Taylor 		 */
9409e39c5baSBill Taylor 		switch (i) {
9419e39c5baSBill Taylor 		case HERMON_CQHDL:
9429e39c5baSBill Taylor 			state->hs_cqhdl = hdl_info.swi_table_ptr;
9439e39c5baSBill Taylor 			break;
9449e39c5baSBill Taylor 		case HERMON_QPHDL:
9459e39c5baSBill Taylor 			state->hs_qphdl = hdl_info.swi_table_ptr;
9469e39c5baSBill Taylor 			break;
9479e39c5baSBill Taylor 		case HERMON_SRQHDL:
9489e39c5baSBill Taylor 			state->hs_srqhdl = hdl_info.swi_table_ptr;
9499e39c5baSBill Taylor 			break;
9509e39c5baSBill Taylor 		default:
9519e39c5baSBill Taylor 			break;
9529e39c5baSBill Taylor 		}
9539e39c5baSBill Taylor 	}
9549e39c5baSBill Taylor 
9559e39c5baSBill Taylor 	/*
9569e39c5baSBill Taylor 	 * Initialize a resource pool for the MCG handles.  Notice that for
9579e39c5baSBill Taylor 	 * these MCG handles, we are allocating a table of structures (used to
9589e39c5baSBill Taylor 	 * keep track of the MCG entries that are being written to hardware
9599e39c5baSBill Taylor 	 * and to speed up multicast attach/detach operations).
9609e39c5baSBill Taylor 	 */
9619e39c5baSBill Taylor 	hdl_info.swi_num	 = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
9629e39c5baSBill Taylor 	hdl_info.swi_max	 = ((uint64_t)1 << devlim->log_max_mcg);
9639e39c5baSBill Taylor 	hdl_info.swi_flags	 = HERMON_SWHDL_TABLE_INIT;
9649e39c5baSBill Taylor 	hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
9659e39c5baSBill Taylor 	status = hermon_rsrc_sw_handles_init(state, &hdl_info);
9669e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9679e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
9689e39c5baSBill Taylor 		status = DDI_FAILURE;
9699e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9709e39c5baSBill Taylor 	}
9719e39c5baSBill Taylor 	state->hs_mcghdl = hdl_info.swi_table_ptr;
9729e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL29;
9739e39c5baSBill Taylor 
9749e39c5baSBill Taylor 	/*
9759e39c5baSBill Taylor 	 * Last, initialize the resource pool for the UAR pages, which contain
9769e39c5baSBill Taylor 	 * the hardware's doorbell registers. Each process supported in User
9779e39c5baSBill Taylor 	 * Mode is assigned a UAR page. Also coming from this pool are the
9789e39c5baSBill Taylor 	 * kernel-assigned UAR page, and any hardware-reserved pages. Note
9799e39c5baSBill Taylor 	 * that the number of UAR pages is configurable, the value must be less
9809e39c5baSBill Taylor 	 * than the maximum value (obtained from the QUERY_DEV_LIM command) or
9819e39c5baSBill Taylor 	 * the initialization will fail.  Note also that we assign the base
9829e39c5baSBill Taylor 	 * address of the UAR BAR to the rsrc_start parameter.
9839e39c5baSBill Taylor 	 */
9849e39c5baSBill Taylor 	num			  = ((uint64_t)1 << cfgprof->cp_log_num_uar);
9859e39c5baSBill Taylor 	max			  = num;
9869e39c5baSBill Taylor 	num_prealloc		  = max(devlim->num_rsvd_uar, 128);
9879e39c5baSBill Taylor 	rsrc_pool		  = &state->hs_rsrc_hdl[HERMON_UARPG];
9889e39c5baSBill Taylor 	rsrc_pool->rsrc_type	  = HERMON_UARPG;
9899e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_UAR;
9909e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (num << PAGESHIFT);
9919e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = PAGESHIFT;
9929e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)PAGESIZE;
9939e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = PAGESIZE;
9949e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
9959e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = (void *)state->hs_reg_uar_baseaddr;
9969e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_UAR_PAGE_VMEM_ATTCH);
9979e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
9989e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
9999e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
10009e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
10019e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
10029e39c5baSBill Taylor 	status = hermon_rsrc_hw_entries_init(state, &entry_info);
10039e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
10049e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
10059e39c5baSBill Taylor 		status = DDI_FAILURE;
10069e39c5baSBill Taylor 		goto rsrcinitp2_fail;
10079e39c5baSBill Taylor 	}
10089e39c5baSBill Taylor 
10099e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_ALL;
10109e39c5baSBill Taylor 
10119e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
10129e39c5baSBill Taylor 	return (DDI_SUCCESS);
10139e39c5baSBill Taylor 
10149e39c5baSBill Taylor rsrcinitp2_fail:
10159e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
10169e39c5baSBill Taylor 	return (status);
10179e39c5baSBill Taylor }
10189e39c5baSBill Taylor 
10199e39c5baSBill Taylor 
10209e39c5baSBill Taylor /*
10219e39c5baSBill Taylor  * hermon_rsrc_fini()
10229e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
10239e39c5baSBill Taylor  */
10249e39c5baSBill Taylor void
10259e39c5baSBill Taylor hermon_rsrc_fini(hermon_state_t *state, hermon_rsrc_cleanup_level_t clean)
10269e39c5baSBill Taylor {
10279e39c5baSBill Taylor 	hermon_rsrc_sw_hdl_info_t	hdl_info;
10289e39c5baSBill Taylor 	hermon_rsrc_hw_entry_info_t	entry_info;
10299e39c5baSBill Taylor 	hermon_rsrc_mbox_info_t		mbox_info;
10309e39c5baSBill Taylor 	hermon_cfg_profile_t		*cfgprof;
10319e39c5baSBill Taylor 
10329e39c5baSBill Taylor 	ASSERT(state != NULL);
10339e39c5baSBill Taylor 
10349e39c5baSBill Taylor 	cfgprof = state->hs_cfg_profile;
10359e39c5baSBill Taylor 
10369e39c5baSBill Taylor 	/*
10379e39c5baSBill Taylor 	 * If init code above is shortened up (see comments), then we
10389e39c5baSBill Taylor 	 * need to establish how to safely and simply clean up from any
10399e39c5baSBill Taylor 	 * given failure point. Flags, maybe...
10409e39c5baSBill Taylor 	 */
10419e39c5baSBill Taylor 
10429e39c5baSBill Taylor 	switch (clean) {
10439e39c5baSBill Taylor 	/*
10449e39c5baSBill Taylor 	 * If we add more resources that need to be cleaned up here, we should
10459e39c5baSBill Taylor 	 * ensure that HERMON_RSRC_CLEANUP_ALL is still the first entry (i.e.
10469e39c5baSBill Taylor 	 * corresponds to the last resource allocated).
10479e39c5baSBill Taylor 	 */
10489e39c5baSBill Taylor 
10499e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_ALL:
10509e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL31:
10519e39c5baSBill Taylor 		/* Cleanup the UAR page resource pool, first the dbr pages */
10529e39c5baSBill Taylor 		if (state->hs_kern_dbr) {
10539e39c5baSBill Taylor 			hermon_dbr_kern_free(state);
10549e39c5baSBill Taylor 			state->hs_kern_dbr = NULL;
10559e39c5baSBill Taylor 		}
10569e39c5baSBill Taylor 
10579e39c5baSBill Taylor 		/* NS then, the pool itself */
10589e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_UARPG];
10599e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
10609e39c5baSBill Taylor 
10619e39c5baSBill Taylor 		/* FALLTHROUGH */
10629e39c5baSBill Taylor 
10639e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL30:
10649e39c5baSBill Taylor 		/* Cleanup the central MCG handle pointers list */
10659e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = NULL;
10669e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->hs_mcghdl;
10679e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
10689e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
10699e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
10709e39c5baSBill Taylor 		/* FALLTHROUGH */
10719e39c5baSBill Taylor 
10729e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL29:
10739e39c5baSBill Taylor 		/* Cleanup the reference count resource pool */
10749e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_REFCNT];
10759e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
10769e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
10779e39c5baSBill Taylor 		/* FALLTHROUGH */
10789e39c5baSBill Taylor 
10799e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL28:
10809e39c5baSBill Taylor 		/* Cleanup the QP handle resource pool */
10819e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_QPHDL];
10829e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->hs_qphdl;
10839e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
10849e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
10859e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
10869e39c5baSBill Taylor 		/* FALLTHROUGH */
10879e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL27:
10889e39c5baSBill Taylor 		/* Cleanup the address handle resrouce pool */
10899e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_AHHDL];
10909e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
10919e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
10929e39c5baSBill Taylor 		/* FALLTHROUGH */
10939e39c5baSBill Taylor 
10949e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL26:
10959e39c5baSBill Taylor 		/* Cleanup the SRQ handle resource pool. */
10969e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_SRQHDL];
10979e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->hs_srqhdl;
10989e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
10999e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
11009e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
11019e39c5baSBill Taylor 		/* FALLTHROUGH */
11029e39c5baSBill Taylor 
11039e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL25:
11049e39c5baSBill Taylor 		/* Cleanup the CQ handle resource pool */
11059e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_CQHDL];
11069e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->hs_cqhdl;
11079e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
11089e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
11099e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
11109e39c5baSBill Taylor 		/* FALLTHROUGH */
11119e39c5baSBill Taylor 
11129e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL24:
11139e39c5baSBill Taylor 		/* Cleanup the EQ handle resource pool */
11149e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_EQHDL];
11159e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
11169e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
11179e39c5baSBill Taylor 		/* FALLTHROUGH */
11189e39c5baSBill Taylor 
11199e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL23:
11209e39c5baSBill Taylor 		/* Cleanup the MR handle resource pool */
11219e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_MRHDL];
11229e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
11239e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
11249e39c5baSBill Taylor 		/* FALLTHROUGH */
11259e39c5baSBill Taylor 
11269e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL22:
11279e39c5baSBill Taylor 		/* Cleanup the PD handle resource pool */
11289e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_PDHDL];
11299e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
11309e39c5baSBill Taylor 		hermon_rsrc_pd_handles_fini(state, &hdl_info);
11319e39c5baSBill Taylor 		/* FALLTHROUGH */
11329e39c5baSBill Taylor 
11339e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL21:
11349e39c5baSBill Taylor 		/* Currently unused - FALLTHROUGH */
11359e39c5baSBill Taylor 
11369e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL20:
11379e39c5baSBill Taylor 		/* Cleanup the outstanding command list  */
11389e39c5baSBill Taylor 		hermon_outstanding_cmdlist_fini(state);
11399e39c5baSBill Taylor 		/* FALLTHROUGH */
11409e39c5baSBill Taylor 
11419e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL19:
11429e39c5baSBill Taylor 		/* Cleanup the EQC table resource pool */
11439e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_EQC];
11449e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11459e39c5baSBill Taylor 		/* FALLTHROUGH */
11469e39c5baSBill Taylor 
11479e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL18:
11489e39c5baSBill Taylor 		/* Cleanup the MCG table resource pool */
11499e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MCG];
11509e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11519e39c5baSBill Taylor 		/* FALLTHROUGH */
11529e39c5baSBill Taylor 
11539e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL17:
11549e39c5baSBill Taylor 		/* Currently Unused - fallthrough */
11559e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL16:
11569e39c5baSBill Taylor 		/* Cleanup the SRQC table resource pool */
11579e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_SRQC];
11589e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11599e39c5baSBill Taylor 		/* FALLTHROUGH */
11609e39c5baSBill Taylor 
11619e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL15:
11629e39c5baSBill Taylor 		/* Cleanup the AUXC table resource pool */
11639e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_AUXC];
11649e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11659e39c5baSBill Taylor 		/* FALLTHROUGH */
11669e39c5baSBill Taylor 
11679e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL14:
11689e39c5baSBill Taylor 		/* Cleanup the ALTCF table resource pool */
11699e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_ALTC];
11709e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11719e39c5baSBill Taylor 		/* FALLTHROUGH */
11729e39c5baSBill Taylor 
11739e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL13:
11749e39c5baSBill Taylor 		/* Cleanup the CQC table resource pool */
11759e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CQC];
11769e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11779e39c5baSBill Taylor 		/* FALLTHROUGH */
11789e39c5baSBill Taylor 
11799e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL12:
11809e39c5baSBill Taylor 		/* Cleanup the RDB table resource pool */
11819e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_RDB];
11829e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11839e39c5baSBill Taylor 		/* FALLTHROUGH */
11849e39c5baSBill Taylor 
11859e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL11:
11869e39c5baSBill Taylor 		/* Cleanup the QPC table resource pool */
11879e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_QPC];
11889e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11899e39c5baSBill Taylor 		/* FALLTHROUGH */
11909e39c5baSBill Taylor 
11919e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10EQ:
11929e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
11939e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_EQC];
11949e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
11959e39c5baSBill Taylor 		/* FALLTHROUGH */
11969e39c5baSBill Taylor 
11979e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10CQ:
11989e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
11999e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_CQC];
12009e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
12019e39c5baSBill Taylor 		/* FALLTHROUGH */
12029e39c5baSBill Taylor 
12039e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10SRQ:
12049e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
12059e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_SRQC];
12069e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
12079e39c5baSBill Taylor 		/* FALLTHROUGH */
12089e39c5baSBill Taylor 
12099e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10QP:
12109e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
12119e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_QPC];
12129e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
12139e39c5baSBill Taylor 		/* FALLTHROUGH */
12149e39c5baSBill Taylor 
12159e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10:
12169e39c5baSBill Taylor 		/* Cleanup the dMPT table resource pool */
12179e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_DMPT];
12189e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
12199e39c5baSBill Taylor 		/* FALLTHROUGH */
12209e39c5baSBill Taylor 
12219e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL9:
12229e39c5baSBill Taylor 		/* Cleanup the MTT table resource pool */
12239e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MTT];
12249e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
12259e39c5baSBill Taylor 		break;
12269e39c5baSBill Taylor 
12279e39c5baSBill Taylor 	/*
12289e39c5baSBill Taylor 	 * The cleanup below comes from the "Phase 1" initialization step.
12299e39c5baSBill Taylor 	 * (see hermon_rsrc_init_phase1() above)
12309e39c5baSBill Taylor 	 */
12319e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_PHASE1_COMPLETE:
12329e39c5baSBill Taylor 		/* Cleanup the "In" mailbox list  */
12339e39c5baSBill Taylor 		hermon_intr_inmbox_list_fini(state);
12349e39c5baSBill Taylor 		/* FALLTHROUGH */
12359e39c5baSBill Taylor 
12369e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL7:
12379e39c5baSBill Taylor 		/* Cleanup the interrupt "In" mailbox resource pool */
12389e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool =
12399e39c5baSBill Taylor 		    &state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
12409e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
12419e39c5baSBill Taylor 		/* FALLTHROUGH */
12429e39c5baSBill Taylor 
12439e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL6:
12449e39c5baSBill Taylor 		/* Cleanup the "In" mailbox list  */
12459e39c5baSBill Taylor 		hermon_inmbox_list_fini(state);
12469e39c5baSBill Taylor 		/* FALLTHROUGH */
12479e39c5baSBill Taylor 
12489e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL5:
12499e39c5baSBill Taylor 		/* Cleanup the "In" mailbox resource pool */
12509e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
12519e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
12529e39c5baSBill Taylor 		/* FALLTHROUGH */
12539e39c5baSBill Taylor 
12549e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL4:
12559e39c5baSBill Taylor 		/* Cleanup the interrupt "Out" mailbox list  */
12569e39c5baSBill Taylor 		hermon_intr_outmbox_list_fini(state);
12579e39c5baSBill Taylor 		/* FALLTHROUGH */
12589e39c5baSBill Taylor 
12599e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL3:
12609e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox resource pool */
12619e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool =
12629e39c5baSBill Taylor 		    &state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
12639e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
12649e39c5baSBill Taylor 		/* FALLTHROUGH */
12659e39c5baSBill Taylor 
12669e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL2:
12679e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox list  */
12689e39c5baSBill Taylor 		hermon_outmbox_list_fini(state);
12699e39c5baSBill Taylor 		/* FALLTHROUGH */
12709e39c5baSBill Taylor 
12719e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL1:
12729e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox resource pool */
12739e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
12749e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
12759e39c5baSBill Taylor 		/* FALLTHROUGH */
12769e39c5baSBill Taylor 
12779e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL0:
12789e39c5baSBill Taylor 		/* Free the array of hermon_rsrc_pool_info_t's */
12799e39c5baSBill Taylor 
12809e39c5baSBill Taylor 		kmem_free(state->hs_rsrc_hdl, HERMON_NUM_RESOURCES *
12819e39c5baSBill Taylor 		    sizeof (hermon_rsrc_pool_info_t));
12829e39c5baSBill Taylor 
12839e39c5baSBill Taylor 		kmem_cache_destroy(state->hs_rsrc_cache);
12849e39c5baSBill Taylor 		break;
12859e39c5baSBill Taylor 
12869e39c5baSBill Taylor 	default:
12879e39c5baSBill Taylor 		HERMON_WARNING(state, "unexpected resource cleanup level");
12889e39c5baSBill Taylor 		break;
12899e39c5baSBill Taylor 	}
12909e39c5baSBill Taylor }
12919e39c5baSBill Taylor 
12929e39c5baSBill Taylor 
12939e39c5baSBill Taylor /*
12949e39c5baSBill Taylor  * hermon_rsrc_mbox_init()
12959e39c5baSBill Taylor  *    Context: Only called from attach() path context
12969e39c5baSBill Taylor  */
12979e39c5baSBill Taylor static int
12989e39c5baSBill Taylor hermon_rsrc_mbox_init(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
12999e39c5baSBill Taylor {
13009e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
13019e39c5baSBill Taylor 	hermon_rsrc_priv_mbox_t	*priv;
13029e39c5baSBill Taylor 
13039e39c5baSBill Taylor 	ASSERT(state != NULL);
13049e39c5baSBill Taylor 	ASSERT(info != NULL);
13059e39c5baSBill Taylor 
13069e39c5baSBill Taylor 	rsrc_pool = info->mbi_rsrcpool;
13079e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
13089e39c5baSBill Taylor 
13099e39c5baSBill Taylor 	/* Allocate and initialize mailbox private structure */
13109e39c5baSBill Taylor 	priv = kmem_zalloc(sizeof (hermon_rsrc_priv_mbox_t), KM_SLEEP);
13119e39c5baSBill Taylor 	priv->pmb_dip		= state->hs_dip;
13129e39c5baSBill Taylor 	priv->pmb_devaccattr	= state->hs_reg_accattr;
13139e39c5baSBill Taylor 	priv->pmb_xfer_mode	= DDI_DMA_CONSISTENT;
13149e39c5baSBill Taylor 
13159e39c5baSBill Taylor 	/*
13169e39c5baSBill Taylor 	 * Initialize many of the default DMA attributes.  Then set alignment
13179e39c5baSBill Taylor 	 * and scatter-gather restrictions specific for mailbox memory.
13189e39c5baSBill Taylor 	 */
13199e39c5baSBill Taylor 	hermon_dma_attr_init(state, &priv->pmb_dmaattr);
13209e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_align  = HERMON_MBOX_ALIGN;
13219e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_sgllen = 1;
13229e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_flags = 0;
13239e39c5baSBill Taylor 	rsrc_pool->rsrc_private = priv;
13249e39c5baSBill Taylor 
13259e39c5baSBill Taylor 	ASSERT(rsrc_pool->rsrc_loc == HERMON_IN_SYSMEM);
13269e39c5baSBill Taylor 
13279e39c5baSBill Taylor 	rsrc_pool->rsrc_start = NULL;
13289e39c5baSBill Taylor 	rsrc_pool->rsrc_vmp = NULL;
13299e39c5baSBill Taylor 
13309e39c5baSBill Taylor 	return (DDI_SUCCESS);
13319e39c5baSBill Taylor }
13329e39c5baSBill Taylor 
13339e39c5baSBill Taylor 
13349e39c5baSBill Taylor /*
13359e39c5baSBill Taylor  * hermon_rsrc_mbox_fini()
13369e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
13379e39c5baSBill Taylor  */
13389e39c5baSBill Taylor /* ARGSUSED */
13399e39c5baSBill Taylor static void
13409e39c5baSBill Taylor hermon_rsrc_mbox_fini(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
13419e39c5baSBill Taylor {
13429e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
13439e39c5baSBill Taylor 
13449e39c5baSBill Taylor 	ASSERT(state != NULL);
13459e39c5baSBill Taylor 	ASSERT(info != NULL);
13469e39c5baSBill Taylor 
13479e39c5baSBill Taylor 	rsrc_pool = info->mbi_rsrcpool;
13489e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
13499e39c5baSBill Taylor 
13509e39c5baSBill Taylor 	/* Free up the private struct */
13519e39c5baSBill Taylor 	kmem_free(rsrc_pool->rsrc_private, sizeof (hermon_rsrc_priv_mbox_t));
13529e39c5baSBill Taylor }
13539e39c5baSBill Taylor 
13549e39c5baSBill Taylor 
13559e39c5baSBill Taylor /*
13569e39c5baSBill Taylor  * hermon_rsrc_hw_entries_init()
13579e39c5baSBill Taylor  *    Context: Only called from attach() path context
13589e39c5baSBill Taylor  */
13599e39c5baSBill Taylor int
13609e39c5baSBill Taylor hermon_rsrc_hw_entries_init(hermon_state_t *state,
13619e39c5baSBill Taylor     hermon_rsrc_hw_entry_info_t *info)
13629e39c5baSBill Taylor {
13639e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
13649e39c5baSBill Taylor 	hermon_rsrc_t		*rsvd_rsrc = NULL;
13659e39c5baSBill Taylor 	vmem_t			*vmp;
13669e39c5baSBill Taylor 	uint64_t		num_hwentry, max_hwentry, num_prealloc;
13679e39c5baSBill Taylor 	int			status;
13689e39c5baSBill Taylor 
13699e39c5baSBill Taylor 	ASSERT(state != NULL);
13709e39c5baSBill Taylor 	ASSERT(info != NULL);
13719e39c5baSBill Taylor 
13729e39c5baSBill Taylor 	rsrc_pool	= info->hwi_rsrcpool;
13739e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
13749e39c5baSBill Taylor 	num_hwentry	= info->hwi_num;
13759e39c5baSBill Taylor 	max_hwentry	= info->hwi_max;
13769e39c5baSBill Taylor 	num_prealloc	= info->hwi_prealloc;
13779e39c5baSBill Taylor 
13789e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
13799e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init: "
13809e39c5baSBill Taylor 		    "rsrc_type (0x%x) num (%llx) max (0x%llx) prealloc "
13819e39c5baSBill Taylor 		    "(0x%llx)", rsrc_pool->rsrc_type, (longlong_t)num_hwentry,
13829e39c5baSBill Taylor 		    (longlong_t)max_hwentry, (longlong_t)num_prealloc);
13839e39c5baSBill Taylor 	}
13849e39c5baSBill Taylor 
13859e39c5baSBill Taylor 	/* Make sure number of HW entries makes sense */
13869e39c5baSBill Taylor 	if (num_hwentry > max_hwentry) {
13879e39c5baSBill Taylor 		return (DDI_FAILURE);
13889e39c5baSBill Taylor 	}
13899e39c5baSBill Taylor 
13909e39c5baSBill Taylor 	/* Set this pool's rsrc_start from the initial ICM allocation */
13919e39c5baSBill Taylor 	if (rsrc_pool->rsrc_start == 0) {
1392*c7facc54SBill Taylor 
1393*c7facc54SBill Taylor 		/* use a ROUND value that works on both 32 and 64-bit kernels */
1394*c7facc54SBill Taylor 		rsrc_pool->rsrc_start = (void *)(uintptr_t)0x10000000;
13959e39c5baSBill Taylor 
13969e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
13979e39c5baSBill Taylor 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
13989e39c5baSBill Taylor 			    " rsrc_type (0x%x) rsrc_start set (0x%lx)",
13999e39c5baSBill Taylor 			    rsrc_pool->rsrc_type, rsrc_pool->rsrc_start);
14009e39c5baSBill Taylor 		}
14019e39c5baSBill Taylor 	}
14029e39c5baSBill Taylor 
14039e39c5baSBill Taylor 	/*
14049e39c5baSBill Taylor 	 * Create new vmem arena for the HW entries table if rsrc_quantum
14059e39c5baSBill Taylor 	 * is non-zero.  Otherwise if rsrc_quantum is zero, then these HW
14069e39c5baSBill Taylor 	 * entries are not going to be dynamically allocatable (i.e. they
14079e39c5baSBill Taylor 	 * won't be allocated/freed through hermon_rsrc_alloc/free).  This
14089e39c5baSBill Taylor 	 * latter option is used for both ALTC and CMPT resources which
14099e39c5baSBill Taylor 	 * are managed by hardware.
14109e39c5baSBill Taylor 	 */
14119e39c5baSBill Taylor 	if (rsrc_pool->rsrc_quantum != 0) {
14129e39c5baSBill Taylor 		vmp = vmem_create(info->hwi_rsrcname,
14139e39c5baSBill Taylor 		    (void *)(uintptr_t)rsrc_pool->rsrc_start,
14149e39c5baSBill Taylor 		    rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_quantum,
14159e39c5baSBill Taylor 		    NULL, NULL, NULL, 0, VM_SLEEP);
14169e39c5baSBill Taylor 		if (vmp == NULL) {
14179e39c5baSBill Taylor 			/* failed to create vmem arena */
14189e39c5baSBill Taylor 			return (DDI_FAILURE);
14199e39c5baSBill Taylor 		}
14209e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = vmp;
14219e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
14229e39c5baSBill Taylor 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
14239e39c5baSBill Taylor 			    " rsrc_type (0x%x) created vmem arena for rsrc",
14249e39c5baSBill Taylor 			    rsrc_pool->rsrc_type);
14259e39c5baSBill Taylor 		}
14269e39c5baSBill Taylor 	} else {
14279e39c5baSBill Taylor 		/* we do not require a vmem arena */
14289e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = NULL;
14299e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
14309e39c5baSBill Taylor 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
14319e39c5baSBill Taylor 			    " rsrc_type (0x%x) vmem arena not required",
14329e39c5baSBill Taylor 			    rsrc_pool->rsrc_type);
14339e39c5baSBill Taylor 		}
14349e39c5baSBill Taylor 	}
14359e39c5baSBill Taylor 
14369e39c5baSBill Taylor 	/* Allocate hardware reserved resources, if any */
14379e39c5baSBill Taylor 	if (num_prealloc != 0) {
14389e39c5baSBill Taylor 		status = hermon_rsrc_alloc(state, rsrc_pool->rsrc_type,
14399e39c5baSBill Taylor 		    num_prealloc, HERMON_SLEEP, &rsvd_rsrc);
14409e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
14419e39c5baSBill Taylor 			/* unable to preallocate the reserved entries */
14429e39c5baSBill Taylor 			if (rsrc_pool->rsrc_vmp != NULL) {
14439e39c5baSBill Taylor 				vmem_destroy(rsrc_pool->rsrc_vmp);
14449e39c5baSBill Taylor 			}
14459e39c5baSBill Taylor 			return (DDI_FAILURE);
14469e39c5baSBill Taylor 		}
14479e39c5baSBill Taylor 	}
14489e39c5baSBill Taylor 	rsrc_pool->rsrc_private = rsvd_rsrc;
14499e39c5baSBill Taylor 
14509e39c5baSBill Taylor 	return (DDI_SUCCESS);
14519e39c5baSBill Taylor }
14529e39c5baSBill Taylor 
14539e39c5baSBill Taylor 
14549e39c5baSBill Taylor /*
14559e39c5baSBill Taylor  * hermon_rsrc_hw_entries_fini()
14569e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
14579e39c5baSBill Taylor  */
14589e39c5baSBill Taylor void
14599e39c5baSBill Taylor hermon_rsrc_hw_entries_fini(hermon_state_t *state,
14609e39c5baSBill Taylor     hermon_rsrc_hw_entry_info_t *info)
14619e39c5baSBill Taylor {
14629e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
14639e39c5baSBill Taylor 	hermon_rsrc_t		*rsvd_rsrc;
14649e39c5baSBill Taylor 
14659e39c5baSBill Taylor 	ASSERT(state != NULL);
14669e39c5baSBill Taylor 	ASSERT(info != NULL);
14679e39c5baSBill Taylor 
14689e39c5baSBill Taylor 	rsrc_pool = info->hwi_rsrcpool;
14699e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
14709e39c5baSBill Taylor 
14719e39c5baSBill Taylor 	/* Free up any "reserved" (i.e. preallocated) HW entries */
14729e39c5baSBill Taylor 	rsvd_rsrc = (hermon_rsrc_t *)rsrc_pool->rsrc_private;
14739e39c5baSBill Taylor 	if (rsvd_rsrc != NULL) {
14749e39c5baSBill Taylor 		hermon_rsrc_free(state, &rsvd_rsrc);
14759e39c5baSBill Taylor 	}
14769e39c5baSBill Taylor 
14779e39c5baSBill Taylor 	/*
14789e39c5baSBill Taylor 	 * If we've actually setup a vmem arena for the HW entries, then
14799e39c5baSBill Taylor 	 * destroy it now
14809e39c5baSBill Taylor 	 */
14819e39c5baSBill Taylor 	if (rsrc_pool->rsrc_vmp != NULL) {
14829e39c5baSBill Taylor 		vmem_destroy(rsrc_pool->rsrc_vmp);
14839e39c5baSBill Taylor 	}
14849e39c5baSBill Taylor }
14859e39c5baSBill Taylor 
14869e39c5baSBill Taylor 
14879e39c5baSBill Taylor /*
14889e39c5baSBill Taylor  * hermon_rsrc_sw_handles_init()
14899e39c5baSBill Taylor  *    Context: Only called from attach() path context
14909e39c5baSBill Taylor  */
14919e39c5baSBill Taylor /* ARGSUSED */
14929e39c5baSBill Taylor static int
14939e39c5baSBill Taylor hermon_rsrc_sw_handles_init(hermon_state_t *state,
14949e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
14959e39c5baSBill Taylor {
14969e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
14979e39c5baSBill Taylor 	uint64_t		num_swhdl, max_swhdl, prealloc_sz;
14989e39c5baSBill Taylor 
14999e39c5baSBill Taylor 	ASSERT(state != NULL);
15009e39c5baSBill Taylor 	ASSERT(info != NULL);
15019e39c5baSBill Taylor 
15029e39c5baSBill Taylor 	rsrc_pool	= info->swi_rsrcpool;
15039e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
15049e39c5baSBill Taylor 	num_swhdl	= info->swi_num;
15059e39c5baSBill Taylor 	max_swhdl	= info->swi_max;
15069e39c5baSBill Taylor 	prealloc_sz	= info->swi_prealloc_sz;
15079e39c5baSBill Taylor 
15089e39c5baSBill Taylor 
15099e39c5baSBill Taylor 	/* Make sure number of SW handles makes sense */
15109e39c5baSBill Taylor 	if (num_swhdl > max_swhdl) {
15119e39c5baSBill Taylor 		return (DDI_FAILURE);
15129e39c5baSBill Taylor 	}
15139e39c5baSBill Taylor 
15149e39c5baSBill Taylor 	/*
15159e39c5baSBill Taylor 	 * Depending on the flags parameter, create a kmem_cache for some
15169e39c5baSBill Taylor 	 * number of software handle structures.  Note: kmem_cache_create()
15179e39c5baSBill Taylor 	 * will SLEEP until successful.
15189e39c5baSBill Taylor 	 */
15199e39c5baSBill Taylor 	if (info->swi_flags & HERMON_SWHDL_KMEMCACHE_INIT) {
15209e39c5baSBill Taylor 		rsrc_pool->rsrc_private = kmem_cache_create(
15219e39c5baSBill Taylor 		    info->swi_rsrcname, rsrc_pool->rsrc_quantum, 0,
15229e39c5baSBill Taylor 		    info->swi_constructor, info->swi_destructor, NULL,
15239e39c5baSBill Taylor 		    rsrc_pool->rsrc_state, NULL, 0);
15249e39c5baSBill Taylor 	}
15259e39c5baSBill Taylor 
15269e39c5baSBill Taylor 
15279e39c5baSBill Taylor 	/* Allocate the central list of SW handle pointers */
15289e39c5baSBill Taylor 	if (info->swi_flags & HERMON_SWHDL_TABLE_INIT) {
15299e39c5baSBill Taylor 		info->swi_table_ptr = kmem_zalloc(num_swhdl * prealloc_sz,
15309e39c5baSBill Taylor 		    KM_SLEEP);
15319e39c5baSBill Taylor 	}
15329e39c5baSBill Taylor 
15339e39c5baSBill Taylor 	return (DDI_SUCCESS);
15349e39c5baSBill Taylor }
15359e39c5baSBill Taylor 
15369e39c5baSBill Taylor 
15379e39c5baSBill Taylor /*
15389e39c5baSBill Taylor  * hermon_rsrc_sw_handles_fini()
15399e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
15409e39c5baSBill Taylor  */
15419e39c5baSBill Taylor /* ARGSUSED */
15429e39c5baSBill Taylor static void
15439e39c5baSBill Taylor hermon_rsrc_sw_handles_fini(hermon_state_t *state,
15449e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
15459e39c5baSBill Taylor {
15469e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
15479e39c5baSBill Taylor 	uint64_t		num_swhdl, prealloc_sz;
15489e39c5baSBill Taylor 
15499e39c5baSBill Taylor 	ASSERT(state != NULL);
15509e39c5baSBill Taylor 	ASSERT(info != NULL);
15519e39c5baSBill Taylor 
15529e39c5baSBill Taylor 	rsrc_pool	= info->swi_rsrcpool;
15539e39c5baSBill Taylor 	num_swhdl	= info->swi_num;
15549e39c5baSBill Taylor 	prealloc_sz	= info->swi_prealloc_sz;
15559e39c5baSBill Taylor 
15569e39c5baSBill Taylor 	/*
15579e39c5baSBill Taylor 	 * If a "software handle" kmem_cache exists for this resource, then
15589e39c5baSBill Taylor 	 * destroy it now
15599e39c5baSBill Taylor 	 */
15609e39c5baSBill Taylor 	if (rsrc_pool != NULL) {
15619e39c5baSBill Taylor 		kmem_cache_destroy(rsrc_pool->rsrc_private);
15629e39c5baSBill Taylor 	}
15639e39c5baSBill Taylor 
15649e39c5baSBill Taylor 	/* Free up this central list of SW handle pointers */
15659e39c5baSBill Taylor 	if (info->swi_table_ptr != NULL) {
15669e39c5baSBill Taylor 		kmem_free(info->swi_table_ptr, num_swhdl * prealloc_sz);
15679e39c5baSBill Taylor 	}
15689e39c5baSBill Taylor }
15699e39c5baSBill Taylor 
15709e39c5baSBill Taylor 
15719e39c5baSBill Taylor /*
15729e39c5baSBill Taylor  * hermon_rsrc_pd_handles_init()
15739e39c5baSBill Taylor  *    Context: Only called from attach() path context
15749e39c5baSBill Taylor  */
15759e39c5baSBill Taylor static int
15769e39c5baSBill Taylor hermon_rsrc_pd_handles_init(hermon_state_t *state,
15779e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
15789e39c5baSBill Taylor {
15799e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
15809e39c5baSBill Taylor 	vmem_t			*vmp;
15819e39c5baSBill Taylor 	char			vmem_name[HERMON_RSRC_NAME_MAXLEN];
15829e39c5baSBill Taylor 	int			status;
15839e39c5baSBill Taylor 
15849e39c5baSBill Taylor 	ASSERT(state != NULL);
15859e39c5baSBill Taylor 	ASSERT(info != NULL);
15869e39c5baSBill Taylor 
15879e39c5baSBill Taylor 	rsrc_pool = info->swi_rsrcpool;
15889e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
15899e39c5baSBill Taylor 
15909e39c5baSBill Taylor 	/* Initialize the resource pool for software handle table */
15919e39c5baSBill Taylor 	status = hermon_rsrc_sw_handles_init(state, info);
15929e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
15939e39c5baSBill Taylor 		return (DDI_FAILURE);
15949e39c5baSBill Taylor 	}
15959e39c5baSBill Taylor 
15969e39c5baSBill Taylor 	/* Build vmem arena name from Hermon instance */
15979e39c5baSBill Taylor 	HERMON_RSRC_NAME(vmem_name, HERMON_PDHDL_VMEM);
15989e39c5baSBill Taylor 
15999e39c5baSBill Taylor 	/* Create new vmem arena for PD numbers */
16009e39c5baSBill Taylor 	vmp = vmem_create(vmem_name, (caddr_t)1, info->swi_num, 1, NULL,
16019e39c5baSBill Taylor 	    NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
16029e39c5baSBill Taylor 	if (vmp == NULL) {
16039e39c5baSBill Taylor 		/* Unable to create vmem arena */
16049e39c5baSBill Taylor 		info->swi_table_ptr = NULL;
16059e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, info);
16069e39c5baSBill Taylor 		return (DDI_FAILURE);
16079e39c5baSBill Taylor 	}
16089e39c5baSBill Taylor 	rsrc_pool->rsrc_vmp = vmp;
16099e39c5baSBill Taylor 
16109e39c5baSBill Taylor 	return (DDI_SUCCESS);
16119e39c5baSBill Taylor }
16129e39c5baSBill Taylor 
16139e39c5baSBill Taylor 
16149e39c5baSBill Taylor /*
16159e39c5baSBill Taylor  * hermon_rsrc_pd_handles_fini()
16169e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
16179e39c5baSBill Taylor  */
16189e39c5baSBill Taylor static void
16199e39c5baSBill Taylor hermon_rsrc_pd_handles_fini(hermon_state_t *state,
16209e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
16219e39c5baSBill Taylor {
16229e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
16239e39c5baSBill Taylor 
16249e39c5baSBill Taylor 	ASSERT(state != NULL);
16259e39c5baSBill Taylor 	ASSERT(info != NULL);
16269e39c5baSBill Taylor 
16279e39c5baSBill Taylor 	rsrc_pool = info->swi_rsrcpool;
16289e39c5baSBill Taylor 
16299e39c5baSBill Taylor 	/* Destroy the specially created UAR scratch table vmem arena */
16309e39c5baSBill Taylor 	vmem_destroy(rsrc_pool->rsrc_vmp);
16319e39c5baSBill Taylor 
16329e39c5baSBill Taylor 	/* Destroy the "hermon_sw_pd_t" kmem_cache */
16339e39c5baSBill Taylor 	hermon_rsrc_sw_handles_fini(state, info);
16349e39c5baSBill Taylor }
16359e39c5baSBill Taylor 
16369e39c5baSBill Taylor 
16379e39c5baSBill Taylor /*
16389e39c5baSBill Taylor  * hermon_rsrc_mbox_alloc()
16399e39c5baSBill Taylor  *    Context: Only called from attach() path context
16409e39c5baSBill Taylor  */
16419e39c5baSBill Taylor static int
16429e39c5baSBill Taylor hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
16439e39c5baSBill Taylor     hermon_rsrc_t *hdl)
16449e39c5baSBill Taylor {
16459e39c5baSBill Taylor 	hermon_rsrc_priv_mbox_t	*priv;
16469e39c5baSBill Taylor 	caddr_t			kaddr;
16479e39c5baSBill Taylor 	size_t			real_len, temp_len;
16489e39c5baSBill Taylor 	int			status;
16499e39c5baSBill Taylor 
16509e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
16519e39c5baSBill Taylor 	ASSERT(hdl != NULL);
16529e39c5baSBill Taylor 
16539e39c5baSBill Taylor 	/* Get the private pointer for the mailboxes */
16549e39c5baSBill Taylor 	priv = pool_info->rsrc_private;
16559e39c5baSBill Taylor 	ASSERT(priv != NULL);
16569e39c5baSBill Taylor 
16579e39c5baSBill Taylor 	/* Allocate a DMA handle for the mailbox */
16589e39c5baSBill Taylor 	status = ddi_dma_alloc_handle(priv->pmb_dip, &priv->pmb_dmaattr,
16599e39c5baSBill Taylor 	    DDI_DMA_SLEEP, NULL, &hdl->hr_dmahdl);
16609e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
16619e39c5baSBill Taylor 		return (DDI_FAILURE);
16629e39c5baSBill Taylor 	}
16639e39c5baSBill Taylor 
16649e39c5baSBill Taylor 	/* Allocate memory for the mailbox */
16659e39c5baSBill Taylor 	temp_len = (num * pool_info->rsrc_quantum);
16669e39c5baSBill Taylor 	status = ddi_dma_mem_alloc(hdl->hr_dmahdl, temp_len,
16679e39c5baSBill Taylor 	    &priv->pmb_devaccattr, priv->pmb_xfer_mode, DDI_DMA_SLEEP,
16689e39c5baSBill Taylor 	    NULL, &kaddr, &real_len, &hdl->hr_acchdl);
16699e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
16709e39c5baSBill Taylor 		/* No more memory available for mailbox entries */
16719e39c5baSBill Taylor 		ddi_dma_free_handle(&hdl->hr_dmahdl);
16729e39c5baSBill Taylor 		return (DDI_FAILURE);
16739e39c5baSBill Taylor 	}
16749e39c5baSBill Taylor 
16759e39c5baSBill Taylor 	hdl->hr_addr = (void *)kaddr;
16769e39c5baSBill Taylor 	hdl->hr_len  = (uint32_t)real_len;
16779e39c5baSBill Taylor 
16789e39c5baSBill Taylor 	return (DDI_SUCCESS);
16799e39c5baSBill Taylor }
16809e39c5baSBill Taylor 
16819e39c5baSBill Taylor 
16829e39c5baSBill Taylor /*
16839e39c5baSBill Taylor  * hermon_rsrc_mbox_free()
16849e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
16859e39c5baSBill Taylor  */
16869e39c5baSBill Taylor static void
16879e39c5baSBill Taylor hermon_rsrc_mbox_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
16889e39c5baSBill Taylor {
16899e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
16909e39c5baSBill Taylor 	ASSERT(hdl != NULL);
16919e39c5baSBill Taylor 
16929e39c5baSBill Taylor 	/* Use ddi_dma_mem_free() to free up sys memory for mailbox */
16939e39c5baSBill Taylor 	ddi_dma_mem_free(&hdl->hr_acchdl);
16949e39c5baSBill Taylor 
16959e39c5baSBill Taylor 	/* Free the DMA handle for the mailbox */
16969e39c5baSBill Taylor 	ddi_dma_free_handle(&hdl->hr_dmahdl);
16979e39c5baSBill Taylor }
16989e39c5baSBill Taylor 
16999e39c5baSBill Taylor 
17009e39c5baSBill Taylor /*
17019e39c5baSBill Taylor  * hermon_rsrc_hw_entry_alloc()
17029e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
17039e39c5baSBill Taylor  */
17049e39c5baSBill Taylor static int
17059e39c5baSBill Taylor hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
17069e39c5baSBill Taylor     uint_t num_align, ddi_acc_handle_t acc_handle, uint_t sleepflag,
17079e39c5baSBill Taylor     hermon_rsrc_t *hdl)
17089e39c5baSBill Taylor {
17099e39c5baSBill Taylor 	void			*addr;
17109e39c5baSBill Taylor 	uint64_t		offset;
17119e39c5baSBill Taylor 	uint32_t		align;
17129e39c5baSBill Taylor 	int			status;
17139e39c5baSBill Taylor 	int			flag;
17149e39c5baSBill Taylor 
17159e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
17169e39c5baSBill Taylor 	ASSERT(hdl != NULL);
17179e39c5baSBill Taylor 
17189e39c5baSBill Taylor 	/*
17199e39c5baSBill Taylor 	 * Hermon hardware entries (QPC, CQC, EQC, MPT, etc.) do not
17209e39c5baSBill Taylor 	 * generally use the acc_handle (because the entries are not
17219e39c5baSBill Taylor 	 * directly accessed by software).  The exception to this rule
17229e39c5baSBill Taylor 	 * are the MTT entries.
17239e39c5baSBill Taylor 	 */
17249e39c5baSBill Taylor 
17259e39c5baSBill Taylor 	/*
17269e39c5baSBill Taylor 	 * Use vmem_xalloc() to get a properly aligned pointer (based on
17279e39c5baSBill Taylor 	 * the number requested) to the HW entry(ies).  This handles the
17289e39c5baSBill Taylor 	 * cases (for special QPCs and for RDB entries) where we need more
17299e39c5baSBill Taylor 	 * than one and need to ensure that they are properly aligned.
17309e39c5baSBill Taylor 	 */
17319e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
17329e39c5baSBill Taylor 	hdl->hr_len = (num * pool_info->rsrc_quantum);
17339e39c5baSBill Taylor 	align = (num_align * pool_info->rsrc_quantum);
17349e39c5baSBill Taylor 
17359e39c5baSBill Taylor 	addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->hr_len,
17369e39c5baSBill Taylor 	    align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
17379e39c5baSBill Taylor 
17389e39c5baSBill Taylor 	if (addr == NULL) {
17399e39c5baSBill Taylor 		/* No more HW entries available */
17409e39c5baSBill Taylor 		return (DDI_FAILURE);
17419e39c5baSBill Taylor 	}
17429e39c5baSBill Taylor 
17439e39c5baSBill Taylor 	hdl->hr_acchdl = acc_handle;
17449e39c5baSBill Taylor 
17459e39c5baSBill Taylor 	/* Calculate vaddr and HW table index */
17469e39c5baSBill Taylor 	offset = (uintptr_t)addr - (uintptr_t)pool_info->rsrc_start;
17479e39c5baSBill Taylor 	hdl->hr_addr = addr;
17489e39c5baSBill Taylor 	hdl->hr_indx = offset >> pool_info->rsrc_shift;
17499e39c5baSBill Taylor 
17509e39c5baSBill Taylor 	if (pool_info->rsrc_loc == HERMON_IN_ICM) {
17519e39c5baSBill Taylor 		/* confirm ICM is mapped, and allocate if necessary */
17529e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_icm_confirm(pool_info, num, hdl);
17539e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
17549e39c5baSBill Taylor 			return (DDI_FAILURE);
17559e39c5baSBill Taylor 		}
1756*c7facc54SBill Taylor 		hdl->hr_addr = NULL;
17579e39c5baSBill Taylor 	}
17589e39c5baSBill Taylor 
17599e39c5baSBill Taylor 	return (DDI_SUCCESS);
17609e39c5baSBill Taylor }
17619e39c5baSBill Taylor 
17629e39c5baSBill Taylor 
17639e39c5baSBill Taylor 
17649e39c5baSBill Taylor /*
17659e39c5baSBill Taylor  * hermon_rsrc_hw_entry_free()
17669e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
17679e39c5baSBill Taylor  */
17689e39c5baSBill Taylor static void
17699e39c5baSBill Taylor hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
17709e39c5baSBill Taylor     hermon_rsrc_t *hdl)
17719e39c5baSBill Taylor {
17729e39c5baSBill Taylor 	void			*addr;
17739e39c5baSBill Taylor 	uint64_t		offset;
17749e39c5baSBill Taylor 	int			status;
17759e39c5baSBill Taylor 
17769e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
17779e39c5baSBill Taylor 	ASSERT(hdl != NULL);
17789e39c5baSBill Taylor 
17799e39c5baSBill Taylor 	/* Calculate the allocated address */
17809e39c5baSBill Taylor 	offset = hdl->hr_indx << pool_info->rsrc_shift;
17819e39c5baSBill Taylor 	addr = (void *)(uintptr_t)(offset + (uintptr_t)pool_info->rsrc_start);
17829e39c5baSBill Taylor 
17839e39c5baSBill Taylor 	/* Use vmem_xfree() to free up the HW table entry */
17849e39c5baSBill Taylor 	vmem_xfree(pool_info->rsrc_vmp, addr, hdl->hr_len);
17859e39c5baSBill Taylor 
17869e39c5baSBill Taylor 	if (pool_info->rsrc_loc == HERMON_IN_ICM) {
17879e39c5baSBill Taylor 		/* free ICM references, and free ICM if required */
17889e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_icm_free(pool_info, hdl);
17899e39c5baSBill Taylor 		if (status != DDI_SUCCESS)
17909e39c5baSBill Taylor 			HERMON_WARNING(pool_info->rsrc_state,
17919e39c5baSBill Taylor 			    "failure in hw_entry_free");
17929e39c5baSBill Taylor 	}
17939e39c5baSBill Taylor }
17949e39c5baSBill Taylor 
17959e39c5baSBill Taylor /*
17969e39c5baSBill Taylor  * hermon_rsrc_hw_entry_icm_confirm()
17979e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
17989e39c5baSBill Taylor  */
17999e39c5baSBill Taylor static int
18009e39c5baSBill Taylor hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info, uint_t num,
18019e39c5baSBill Taylor     hermon_rsrc_t *hdl)
18029e39c5baSBill Taylor {
18039e39c5baSBill Taylor 	hermon_state_t		*state;
18049e39c5baSBill Taylor 	hermon_icm_table_t	*icm_table;
18059e39c5baSBill Taylor 	uint8_t			*bitmap;
18069e39c5baSBill Taylor 	hermon_dma_info_t	*dma_info;
18079e39c5baSBill Taylor 	hermon_rsrc_type_t	type;
18089e39c5baSBill Taylor 	uint32_t		rindx, span_offset;
18099e39c5baSBill Taylor 	uint32_t		span_avail;
18109e39c5baSBill Taylor 	int			num_backed;
18119e39c5baSBill Taylor 	int			status;
18129e39c5baSBill Taylor 	uint32_t		index1, index2;
18139e39c5baSBill Taylor 
18149e39c5baSBill Taylor 	/*
18159e39c5baSBill Taylor 	 * Utility routine responsible for ensuring that there is memory
18169e39c5baSBill Taylor 	 * backing the ICM resources allocated via hermon_rsrc_hw_entry_alloc().
18179e39c5baSBill Taylor 	 * Confirm existing ICM mapping(s) or allocate ICM memory for the
18189e39c5baSBill Taylor 	 * given hardware resources being allocated, and increment the
18199e39c5baSBill Taylor 	 * ICM DMA structure(s) reference count.
18209e39c5baSBill Taylor 	 *
18219e39c5baSBill Taylor 	 * We may be allocating more objects than can fit in a single span,
18229e39c5baSBill Taylor 	 * or more than will fit in the remaining contiguous memory (from
18239e39c5baSBill Taylor 	 * the offset indicated by hdl->ar_indx) in the span in question.
18249e39c5baSBill Taylor 	 * In either of these cases, we'll be breaking up our allocation
18259e39c5baSBill Taylor 	 * into multiple spans.
18269e39c5baSBill Taylor 	 */
18279e39c5baSBill Taylor 	state = pool_info->rsrc_state;
18289e39c5baSBill Taylor 	type  = pool_info->rsrc_type;
18299e39c5baSBill Taylor 	icm_table = &state->hs_icm[type];
18309e39c5baSBill Taylor 
18319e39c5baSBill Taylor 	rindx = hdl->hr_indx;
18329e39c5baSBill Taylor 	hermon_index(index1, index2, rindx, icm_table, span_offset);
18339e39c5baSBill Taylor 
18349e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
18359e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_confirm: "
18369e39c5baSBill Taylor 		    "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x): ",
18379e39c5baSBill Taylor 		    type, num, hdl->hr_len, index1, index2);
18389e39c5baSBill Taylor 	}
18399e39c5baSBill Taylor 
18409e39c5baSBill Taylor 	mutex_enter(&icm_table->icm_table_lock);
18419e39c5baSBill Taylor 	hermon_bitmap(bitmap, dma_info, icm_table, index1);
18429e39c5baSBill Taylor 	while (num) {
18439e39c5baSBill Taylor #ifndef __lock_lint
18449e39c5baSBill Taylor 		while (icm_table->icm_busy) {
18459e39c5baSBill Taylor 			cv_wait(&icm_table->icm_table_cv,
18469e39c5baSBill Taylor 			    &icm_table->icm_table_lock);
18479e39c5baSBill Taylor 		}
18489e39c5baSBill Taylor #endif
18499e39c5baSBill Taylor 		if (!HERMON_BMAP_BIT_ISSET(bitmap, index2)) {
18509e39c5baSBill Taylor 			/* Allocate ICM for this span */
18519e39c5baSBill Taylor 			icm_table->icm_busy = 1;
18529e39c5baSBill Taylor 			mutex_exit(&icm_table->icm_table_lock);
18539e39c5baSBill Taylor 			status = hermon_icm_alloc(state, type, index1, index2);
18549e39c5baSBill Taylor 			mutex_enter(&icm_table->icm_table_lock);
18559e39c5baSBill Taylor 			icm_table->icm_busy = 0;
18569e39c5baSBill Taylor 			cv_broadcast(&icm_table->icm_table_cv);
18579e39c5baSBill Taylor 			if (status != DDI_SUCCESS) {
18589e39c5baSBill Taylor 				goto fail_alloc;
18599e39c5baSBill Taylor 			}
18609e39c5baSBill Taylor 			if (hermon_rsrc_verbose) {
18619e39c5baSBill Taylor 				IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
18629e39c5baSBill Taylor 				    "hw_entry_icm_confirm: ALLOCATED ICM: "
18639e39c5baSBill Taylor 				    "type (0x%x) index (0x%x, 0x%x)",
18649e39c5baSBill Taylor 				    type, index1, index2);
18659e39c5baSBill Taylor 			}
18669e39c5baSBill Taylor 		}
18679e39c5baSBill Taylor 
18689e39c5baSBill Taylor 		/*
18699e39c5baSBill Taylor 		 * Mellanox FMR accesses the MPT directly.  We set the
18709e39c5baSBill Taylor 		 * access handle here only for this case
18719e39c5baSBill Taylor 		 */
18729e39c5baSBill Taylor 		if (type == HERMON_DMPT)
18739e39c5baSBill Taylor 			hdl->hr_acchdl = dma_info[index2].acc_hdl;
18749e39c5baSBill Taylor 
18759e39c5baSBill Taylor 		/*
18769e39c5baSBill Taylor 		 * We need to increment the refcnt of this span by the
18779e39c5baSBill Taylor 		 * number of objects in this resource allocation that are
18789e39c5baSBill Taylor 		 * backed by this span. Given that the rsrc allocation is
18799e39c5baSBill Taylor 		 * contiguous, this value will be the number of objects in
18809e39c5baSBill Taylor 		 * the span from 'span_offset' onward, either up to a max
18819e39c5baSBill Taylor 		 * of the total number of objects, or the end of the span.
18829e39c5baSBill Taylor 		 * So, determine the number of objects that can be backed
18839e39c5baSBill Taylor 		 * by this span ('span_avail'), then determine the number
18849e39c5baSBill Taylor 		 * of backed resources.
18859e39c5baSBill Taylor 		 */
18869e39c5baSBill Taylor 		span_avail = icm_table->span - span_offset;
18879e39c5baSBill Taylor 		if (num > span_avail) {
18889e39c5baSBill Taylor 			num_backed = span_avail;
18899e39c5baSBill Taylor 		} else {
18909e39c5baSBill Taylor 			num_backed = num;
18919e39c5baSBill Taylor 		}
18929e39c5baSBill Taylor 
18939e39c5baSBill Taylor 		/*
18949e39c5baSBill Taylor 		 * Now that we know 'num_backed', increment the refcnt,
18959e39c5baSBill Taylor 		 * decrement the total number, and set 'span_offset' to
18969e39c5baSBill Taylor 		 * 0 in case we roll over into the next span.
18979e39c5baSBill Taylor 		 */
18989e39c5baSBill Taylor 		dma_info[index2].icm_refcnt += num_backed;
18999e39c5baSBill Taylor 		rindx += num_backed;
19009e39c5baSBill Taylor 		num -= num_backed;
19019e39c5baSBill Taylor 
19029e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
19039e39c5baSBill Taylor 			IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) index "
19049e39c5baSBill Taylor 			    "(0x%x, 0x%x) num_backed (0x%x)",
19059e39c5baSBill Taylor 			    type, index1, index2, num_backed);
19069e39c5baSBill Taylor 			IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) refcnt now "
19079e39c5baSBill Taylor 			    "(0x%x) num_remaining (0x%x)", type,
19089e39c5baSBill Taylor 			    dma_info[index2].icm_refcnt, num);
19099e39c5baSBill Taylor 		}
19109e39c5baSBill Taylor 		if (num == 0)
19119e39c5baSBill Taylor 			break;
19129e39c5baSBill Taylor 
19139e39c5baSBill Taylor 		hermon_index(index1, index2, rindx, icm_table, span_offset);
19149e39c5baSBill Taylor 		hermon_bitmap(bitmap, dma_info, icm_table, index1);
19159e39c5baSBill Taylor 	}
19169e39c5baSBill Taylor 	mutex_exit(&icm_table->icm_table_lock);
19179e39c5baSBill Taylor 
19189e39c5baSBill Taylor 	return (DDI_SUCCESS);
19199e39c5baSBill Taylor 
19209e39c5baSBill Taylor fail_alloc:
19219e39c5baSBill Taylor 	/* JBDB */
19229e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
19239e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
19249e39c5baSBill Taylor 		    "hw_entry_icm_confirm: FAILED ICM ALLOC: "
19259e39c5baSBill Taylor 		    "type (0x%x) num remaind (0x%x) index (0x%x, 0x%x)"
19269e39c5baSBill Taylor 		    "refcnt (0x%x)", type, num, index1, index2,
19279e39c5baSBill Taylor 		    icm_table->icm_dma[index1][index2].icm_refcnt);
19289e39c5baSBill Taylor 	}
19299e39c5baSBill Taylor 	IBTF_DPRINTF_L2("hermon", "WARNING: "
19309e39c5baSBill Taylor 	    "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
19319e39c5baSBill Taylor 
19329e39c5baSBill Taylor #if needs_work
19339e39c5baSBill Taylor 	/* free refcnt's and any spans we've allocated */
19349e39c5baSBill Taylor 	while (index-- != start) {
19359e39c5baSBill Taylor 		/*
19369e39c5baSBill Taylor 		 * JBDB - This is a bit tricky.  We need to
19379e39c5baSBill Taylor 		 * free refcnt's on any spans that we've
19389e39c5baSBill Taylor 		 * incremented them on, and completely free
19399e39c5baSBill Taylor 		 * spans that we've allocated. How do we do
19409e39c5baSBill Taylor 		 * this here? Does it need to be as involved
19419e39c5baSBill Taylor 		 * as the core of icm_free() below, or can
19429e39c5baSBill Taylor 		 * we leverage breadcrumbs somehow?
19439e39c5baSBill Taylor 		 */
19449e39c5baSBill Taylor 		HERMON_WARNING(state, "unable to allocate ICM memory: "
19459e39c5baSBill Taylor 		    "UNIMPLEMENTED HANDLING!!");
19469e39c5baSBill Taylor 	}
19479e39c5baSBill Taylor #else
19489e39c5baSBill Taylor 	cmn_err(CE_WARN,
19499e39c5baSBill Taylor 	    "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
19509e39c5baSBill Taylor #endif
19519e39c5baSBill Taylor 	mutex_exit(&icm_table->icm_table_lock);
19529e39c5baSBill Taylor 
19539e39c5baSBill Taylor 	HERMON_WARNING(state, "unable to allocate ICM memory");
19549e39c5baSBill Taylor 	return (DDI_FAILURE);
19559e39c5baSBill Taylor }
19569e39c5baSBill Taylor 
19579e39c5baSBill Taylor /*
19589e39c5baSBill Taylor  * hermon_rsrc_hw_entry_icm_free()
19599e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
19609e39c5baSBill Taylor  */
19619e39c5baSBill Taylor static int
19629e39c5baSBill Taylor hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
19639e39c5baSBill Taylor     hermon_rsrc_t *hdl)
19649e39c5baSBill Taylor {
19659e39c5baSBill Taylor 	hermon_state_t		*state;
19669e39c5baSBill Taylor 	hermon_icm_table_t	*icm_table;
19679e39c5baSBill Taylor 	uint8_t			*bitmap;
19689e39c5baSBill Taylor 	hermon_dma_info_t	*dma_info;
19699e39c5baSBill Taylor 	hermon_rsrc_type_t	type;
19709e39c5baSBill Taylor 	uint32_t		span_offset;
19719e39c5baSBill Taylor 	uint32_t		span_remain;
19729e39c5baSBill Taylor 	int			num_freed;
19739e39c5baSBill Taylor 	int			num;
19749e39c5baSBill Taylor 	uint32_t		index1, index2, rindx;
19759e39c5baSBill Taylor 
19769e39c5baSBill Taylor 	/*
19779e39c5baSBill Taylor 	 * Utility routine responsible for freeing references to ICM
19789e39c5baSBill Taylor 	 * DMA spans, and freeing the ICM memory if necessary.
19799e39c5baSBill Taylor 	 *
19809e39c5baSBill Taylor 	 * We may have allocated objects in a single contiguous resource
19819e39c5baSBill Taylor 	 * allocation that reside in a number of spans, at any given
19829e39c5baSBill Taylor 	 * starting offset within a span. We therefore must determine
19839e39c5baSBill Taylor 	 * where this allocation starts, and then determine if we need
19849e39c5baSBill Taylor 	 * to free objects in more than one span.
19859e39c5baSBill Taylor 	 */
19869e39c5baSBill Taylor 	state = pool_info->rsrc_state;
19879e39c5baSBill Taylor 	type  = pool_info->rsrc_type;
19889e39c5baSBill Taylor 	icm_table = &state->hs_icm[type];
19899e39c5baSBill Taylor 
19909e39c5baSBill Taylor 	rindx = hdl->hr_indx;
19919e39c5baSBill Taylor 	hermon_index(index1, index2, rindx, icm_table, span_offset);
19929e39c5baSBill Taylor 	hermon_bitmap(bitmap, dma_info, icm_table, index1);
19939e39c5baSBill Taylor 
19949e39c5baSBill Taylor 	/* determine the number of ICM objects in this allocation */
19959e39c5baSBill Taylor 	num = hdl->hr_len >> pool_info->rsrc_shift;
19969e39c5baSBill Taylor 
19979e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
19989e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_free: "
19999e39c5baSBill Taylor 		    "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x)",
20009e39c5baSBill Taylor 		    type, num, hdl->hr_len, index1, index2);
20019e39c5baSBill Taylor 	}
20029e39c5baSBill Taylor 	mutex_enter(&icm_table->icm_table_lock);
20039e39c5baSBill Taylor 	while (num) {
20049e39c5baSBill Taylor 		/*
20059e39c5baSBill Taylor 		 * As with the ICM confirm code above, we need to
20069e39c5baSBill Taylor 		 * decrement the ICM span(s) by the number of
20079e39c5baSBill Taylor 		 * resources being freed. So, determine the number
20089e39c5baSBill Taylor 		 * of objects that are backed in this span from
20099e39c5baSBill Taylor 		 * 'span_offset' onward, and set 'num_freed' to
20109e39c5baSBill Taylor 		 * the smaller of either that number ('span_remain'),
20119e39c5baSBill Taylor 		 * or the total number of objects being freed.
20129e39c5baSBill Taylor 		 */
20139e39c5baSBill Taylor 		span_remain = icm_table->span - span_offset;
20149e39c5baSBill Taylor 		if (num > span_remain) {
20159e39c5baSBill Taylor 			num_freed = span_remain;
20169e39c5baSBill Taylor 		} else {
20179e39c5baSBill Taylor 			num_freed = num;
20189e39c5baSBill Taylor 		}
20199e39c5baSBill Taylor 
20209e39c5baSBill Taylor 		/*
20219e39c5baSBill Taylor 		 * Now that we know 'num_freed', decrement the refcnt,
20229e39c5baSBill Taylor 		 * decrement the total number, and set 'span_offset' to
20239e39c5baSBill Taylor 		 * 0 in case we roll over into the next span.
20249e39c5baSBill Taylor 		 */
20259e39c5baSBill Taylor 		dma_info[index2].icm_refcnt -= num_freed;
20269e39c5baSBill Taylor 		num -= num_freed;
20279e39c5baSBill Taylor 		rindx += num_freed;
20289e39c5baSBill Taylor 
20299e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
20309e39c5baSBill Taylor 			IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) index "
20319e39c5baSBill Taylor 			    "(0x%x, 0x%x) num_freed (0x%x)", type,
20329e39c5baSBill Taylor 			    index1, index2, num_freed);
20339e39c5baSBill Taylor 			IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) refcnt now "
20349e39c5baSBill Taylor 			    "(0x%x) num remaining (0x%x)", type,
20359e39c5baSBill Taylor 			    icm_table->icm_dma[index1][index2].icm_refcnt, num);
20369e39c5baSBill Taylor 		}
20379e39c5baSBill Taylor 
20389e39c5baSBill Taylor #if HERMON_ICM_FREE_ENABLED
20399e39c5baSBill Taylor 		/* If we've freed the last object in this span, free it */
20409e39c5baSBill Taylor 		if ((index1 != 0 || index2 != 0) &&
20419e39c5baSBill Taylor 		    (dma_info[index2].icm_refcnt == 0)) {
20429e39c5baSBill Taylor 			if (hermon_rsrc_verbose) {
20439e39c5baSBill Taylor 				IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry"
20449e39c5baSBill Taylor 				    "_icm_free: freeing ICM type (0x%x) index"
20459e39c5baSBill Taylor 				    " (0x%x, 0x%x)", type, index1, index2);
20469e39c5baSBill Taylor 			}
20479e39c5baSBill Taylor 			hermon_icm_free(state, type, index1, index2);
20489e39c5baSBill Taylor 		}
20499e39c5baSBill Taylor #endif
20509e39c5baSBill Taylor 		if (num == 0)
20519e39c5baSBill Taylor 			break;
20529e39c5baSBill Taylor 
20539e39c5baSBill Taylor 		hermon_index(index1, index2, rindx, icm_table, span_offset);
20549e39c5baSBill Taylor 		hermon_bitmap(bitmap, dma_info, icm_table, index1);
20559e39c5baSBill Taylor 	}
20569e39c5baSBill Taylor 	mutex_exit(&icm_table->icm_table_lock);
20579e39c5baSBill Taylor 
20589e39c5baSBill Taylor 	return (DDI_SUCCESS);
20599e39c5baSBill Taylor }
20609e39c5baSBill Taylor 
20619e39c5baSBill Taylor 
20629e39c5baSBill Taylor 
20639e39c5baSBill Taylor /*
20649e39c5baSBill Taylor  * hermon_rsrc_swhdl_alloc()
20659e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
20669e39c5baSBill Taylor  */
20679e39c5baSBill Taylor static int
20689e39c5baSBill Taylor hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
20699e39c5baSBill Taylor     hermon_rsrc_t *hdl)
20709e39c5baSBill Taylor {
20719e39c5baSBill Taylor 	void	*addr;
20729e39c5baSBill Taylor 	int	flag;
20739e39c5baSBill Taylor 
20749e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
20759e39c5baSBill Taylor 	ASSERT(hdl != NULL);
20769e39c5baSBill Taylor 
20779e39c5baSBill Taylor 	/* Allocate the software handle structure */
20789e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
20799e39c5baSBill Taylor 	addr = kmem_cache_alloc(pool_info->rsrc_private, flag);
20809e39c5baSBill Taylor 	if (addr == NULL) {
20819e39c5baSBill Taylor 		return (DDI_FAILURE);
20829e39c5baSBill Taylor 	}
20839e39c5baSBill Taylor 	hdl->hr_len  = pool_info->rsrc_quantum;
20849e39c5baSBill Taylor 	hdl->hr_addr = addr;
20859e39c5baSBill Taylor 
20869e39c5baSBill Taylor 	return (DDI_SUCCESS);
20879e39c5baSBill Taylor }
20889e39c5baSBill Taylor 
20899e39c5baSBill Taylor 
20909e39c5baSBill Taylor /*
20919e39c5baSBill Taylor  * hermon_rsrc_swhdl_free()
20929e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
20939e39c5baSBill Taylor  */
20949e39c5baSBill Taylor static void
20959e39c5baSBill Taylor hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
20969e39c5baSBill Taylor {
20979e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
20989e39c5baSBill Taylor 	ASSERT(hdl != NULL);
20999e39c5baSBill Taylor 
21009e39c5baSBill Taylor 	/* Free the software handle structure */
21019e39c5baSBill Taylor 	kmem_cache_free(pool_info->rsrc_private, hdl->hr_addr);
21029e39c5baSBill Taylor }
21039e39c5baSBill Taylor 
21049e39c5baSBill Taylor 
21059e39c5baSBill Taylor /*
21069e39c5baSBill Taylor  * hermon_rsrc_pdhdl_alloc()
21079e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
21089e39c5baSBill Taylor  */
21099e39c5baSBill Taylor static int
21109e39c5baSBill Taylor hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
21119e39c5baSBill Taylor     hermon_rsrc_t *hdl)
21129e39c5baSBill Taylor {
21139e39c5baSBill Taylor 	hermon_pdhdl_t	addr;
21149e39c5baSBill Taylor 	void		*tmpaddr;
21159e39c5baSBill Taylor 	int		flag, status;
21169e39c5baSBill Taylor 
21179e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
21189e39c5baSBill Taylor 	ASSERT(hdl != NULL);
21199e39c5baSBill Taylor 
21209e39c5baSBill Taylor 	/* Allocate the software handle */
21219e39c5baSBill Taylor 	status = hermon_rsrc_swhdl_alloc(pool_info, sleepflag, hdl);
21229e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
21239e39c5baSBill Taylor 		return (DDI_FAILURE);
21249e39c5baSBill Taylor 	}
21259e39c5baSBill Taylor 	addr = (hermon_pdhdl_t)hdl->hr_addr;
21269e39c5baSBill Taylor 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr))
21279e39c5baSBill Taylor 
21289e39c5baSBill Taylor 	/* Allocate a PD number for the handle */
21299e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
21309e39c5baSBill Taylor 	tmpaddr = vmem_alloc(pool_info->rsrc_vmp, 1, flag);
21319e39c5baSBill Taylor 	if (tmpaddr == NULL) {
21329e39c5baSBill Taylor 		/* No more PD number entries available */
21339e39c5baSBill Taylor 		hermon_rsrc_swhdl_free(pool_info, hdl);
21349e39c5baSBill Taylor 		return (DDI_FAILURE);
21359e39c5baSBill Taylor 	}
21369e39c5baSBill Taylor 	addr->pd_pdnum = (uint32_t)(uintptr_t)tmpaddr;
21379e39c5baSBill Taylor 	addr->pd_rsrcp = hdl;
21389e39c5baSBill Taylor 	hdl->hr_indx   = addr->pd_pdnum;
21399e39c5baSBill Taylor 
21409e39c5baSBill Taylor 	return (DDI_SUCCESS);
21419e39c5baSBill Taylor }
21429e39c5baSBill Taylor 
21439e39c5baSBill Taylor 
21449e39c5baSBill Taylor /*
21459e39c5baSBill Taylor  * hermon_rsrc_pdhdl_free()
21469e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
21479e39c5baSBill Taylor  */
21489e39c5baSBill Taylor static void
21499e39c5baSBill Taylor hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
21509e39c5baSBill Taylor {
21519e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
21529e39c5baSBill Taylor 	ASSERT(hdl != NULL);
21539e39c5baSBill Taylor 
21549e39c5baSBill Taylor 	/* Use vmem_free() to free up the PD number */
21559e39c5baSBill Taylor 	vmem_free(pool_info->rsrc_vmp, (void *)(uintptr_t)hdl->hr_indx, 1);
21569e39c5baSBill Taylor 
21579e39c5baSBill Taylor 	/* Free the software handle structure */
21589e39c5baSBill Taylor 	hermon_rsrc_swhdl_free(pool_info, hdl);
21599e39c5baSBill Taylor }
21609e39c5baSBill Taylor 
21619e39c5baSBill Taylor 
21629e39c5baSBill Taylor /*
21639e39c5baSBill Taylor  * hermon_rsrc_pdhdl_constructor()
21649e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
21659e39c5baSBill Taylor  */
21669e39c5baSBill Taylor /* ARGSUSED */
21679e39c5baSBill Taylor static int
21689e39c5baSBill Taylor hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags)
21699e39c5baSBill Taylor {
21709e39c5baSBill Taylor 	hermon_pdhdl_t	pdhdl;
21719e39c5baSBill Taylor 	hermon_state_t	*state;
21729e39c5baSBill Taylor 
21739e39c5baSBill Taylor 	pdhdl = (hermon_pdhdl_t)pd;
21749e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
21759e39c5baSBill Taylor 
21769e39c5baSBill Taylor 	mutex_init(&pdhdl->pd_lock, NULL, MUTEX_DRIVER,
21779e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
21789e39c5baSBill Taylor 
21799e39c5baSBill Taylor 	return (DDI_SUCCESS);
21809e39c5baSBill Taylor }
21819e39c5baSBill Taylor 
21829e39c5baSBill Taylor 
21839e39c5baSBill Taylor /*
21849e39c5baSBill Taylor  * hermon_rsrc_pdhdl_destructor()
21859e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
21869e39c5baSBill Taylor  */
21879e39c5baSBill Taylor /* ARGSUSED */
21889e39c5baSBill Taylor static void
21899e39c5baSBill Taylor hermon_rsrc_pdhdl_destructor(void *pd, void *priv)
21909e39c5baSBill Taylor {
21919e39c5baSBill Taylor 	hermon_pdhdl_t	pdhdl;
21929e39c5baSBill Taylor 
21939e39c5baSBill Taylor 	pdhdl = (hermon_pdhdl_t)pd;
21949e39c5baSBill Taylor 
21959e39c5baSBill Taylor 	mutex_destroy(&pdhdl->pd_lock);
21969e39c5baSBill Taylor }
21979e39c5baSBill Taylor 
21989e39c5baSBill Taylor 
21999e39c5baSBill Taylor /*
22009e39c5baSBill Taylor  * hermon_rsrc_cqhdl_constructor()
22019e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22029e39c5baSBill Taylor  */
22039e39c5baSBill Taylor /* ARGSUSED */
22049e39c5baSBill Taylor static int
22059e39c5baSBill Taylor hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags)
22069e39c5baSBill Taylor {
22079e39c5baSBill Taylor 	hermon_cqhdl_t	cqhdl;
22089e39c5baSBill Taylor 	hermon_state_t	*state;
22099e39c5baSBill Taylor 
22109e39c5baSBill Taylor 	cqhdl = (hermon_cqhdl_t)cq;
22119e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
22129e39c5baSBill Taylor 
22139e39c5baSBill Taylor 	mutex_init(&cqhdl->cq_lock, NULL, MUTEX_DRIVER,
22149e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
22159e39c5baSBill Taylor 
22169e39c5baSBill Taylor 	return (DDI_SUCCESS);
22179e39c5baSBill Taylor }
22189e39c5baSBill Taylor 
22199e39c5baSBill Taylor 
22209e39c5baSBill Taylor /*
22219e39c5baSBill Taylor  * hermon_rsrc_cqhdl_destructor()
22229e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22239e39c5baSBill Taylor  */
22249e39c5baSBill Taylor /* ARGSUSED */
22259e39c5baSBill Taylor static void
22269e39c5baSBill Taylor hermon_rsrc_cqhdl_destructor(void *cq, void *priv)
22279e39c5baSBill Taylor {
22289e39c5baSBill Taylor 	hermon_cqhdl_t	cqhdl;
22299e39c5baSBill Taylor 
22309e39c5baSBill Taylor 	cqhdl = (hermon_cqhdl_t)cq;
22319e39c5baSBill Taylor 
22329e39c5baSBill Taylor 	mutex_destroy(&cqhdl->cq_lock);
22339e39c5baSBill Taylor }
22349e39c5baSBill Taylor 
22359e39c5baSBill Taylor 
22369e39c5baSBill Taylor /*
22379e39c5baSBill Taylor  * hermon_rsrc_qphdl_constructor()
22389e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22399e39c5baSBill Taylor  */
22409e39c5baSBill Taylor /* ARGSUSED */
22419e39c5baSBill Taylor static int
22429e39c5baSBill Taylor hermon_rsrc_qphdl_constructor(void *qp, void *priv, int flags)
22439e39c5baSBill Taylor {
22449e39c5baSBill Taylor 	hermon_qphdl_t	qphdl;
22459e39c5baSBill Taylor 	hermon_state_t	*state;
22469e39c5baSBill Taylor 
22479e39c5baSBill Taylor 	qphdl = (hermon_qphdl_t)qp;
22489e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
22499e39c5baSBill Taylor 
22509e39c5baSBill Taylor 	mutex_init(&qphdl->qp_lock, NULL, MUTEX_DRIVER,
22519e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
22529e39c5baSBill Taylor 
22539e39c5baSBill Taylor 	return (DDI_SUCCESS);
22549e39c5baSBill Taylor }
22559e39c5baSBill Taylor 
22569e39c5baSBill Taylor 
22579e39c5baSBill Taylor /*
22589e39c5baSBill Taylor  * hermon_rsrc_qphdl_destructor()
22599e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22609e39c5baSBill Taylor  */
22619e39c5baSBill Taylor /* ARGSUSED */
22629e39c5baSBill Taylor static void
22639e39c5baSBill Taylor hermon_rsrc_qphdl_destructor(void *qp, void *priv)
22649e39c5baSBill Taylor {
22659e39c5baSBill Taylor 	hermon_qphdl_t	qphdl;
22669e39c5baSBill Taylor 
22679e39c5baSBill Taylor 	qphdl = (hermon_qphdl_t)qp;
22689e39c5baSBill Taylor 
22699e39c5baSBill Taylor 	mutex_destroy(&qphdl->qp_lock);
22709e39c5baSBill Taylor }
22719e39c5baSBill Taylor 
22729e39c5baSBill Taylor 
22739e39c5baSBill Taylor /*
22749e39c5baSBill Taylor  * hermon_rsrc_srqhdl_constructor()
22759e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22769e39c5baSBill Taylor  */
22779e39c5baSBill Taylor /* ARGSUSED */
22789e39c5baSBill Taylor static int
22799e39c5baSBill Taylor hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags)
22809e39c5baSBill Taylor {
22819e39c5baSBill Taylor 	hermon_srqhdl_t	srqhdl;
22829e39c5baSBill Taylor 	hermon_state_t	*state;
22839e39c5baSBill Taylor 
22849e39c5baSBill Taylor 	srqhdl = (hermon_srqhdl_t)srq;
22859e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
22869e39c5baSBill Taylor 
22879e39c5baSBill Taylor 	mutex_init(&srqhdl->srq_lock, NULL, MUTEX_DRIVER,
22889e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
22899e39c5baSBill Taylor 
22909e39c5baSBill Taylor 	return (DDI_SUCCESS);
22919e39c5baSBill Taylor }
22929e39c5baSBill Taylor 
22939e39c5baSBill Taylor 
22949e39c5baSBill Taylor /*
22959e39c5baSBill Taylor  * hermon_rsrc_srqhdl_destructor()
22969e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
22979e39c5baSBill Taylor  */
22989e39c5baSBill Taylor /* ARGSUSED */
22999e39c5baSBill Taylor static void
23009e39c5baSBill Taylor hermon_rsrc_srqhdl_destructor(void *srq, void *priv)
23019e39c5baSBill Taylor {
23029e39c5baSBill Taylor 	hermon_srqhdl_t	srqhdl;
23039e39c5baSBill Taylor 
23049e39c5baSBill Taylor 	srqhdl = (hermon_srqhdl_t)srq;
23059e39c5baSBill Taylor 
23069e39c5baSBill Taylor 	mutex_destroy(&srqhdl->srq_lock);
23079e39c5baSBill Taylor }
23089e39c5baSBill Taylor 
23099e39c5baSBill Taylor 
23109e39c5baSBill Taylor /*
23119e39c5baSBill Taylor  * hermon_rsrc_refcnt_constructor()
23129e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23139e39c5baSBill Taylor  */
23149e39c5baSBill Taylor /* ARGSUSED */
23159e39c5baSBill Taylor static int
23169e39c5baSBill Taylor hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags)
23179e39c5baSBill Taylor {
23189e39c5baSBill Taylor 	hermon_sw_refcnt_t	*refcnt;
23199e39c5baSBill Taylor 	hermon_state_t		*state;
23209e39c5baSBill Taylor 
23219e39c5baSBill Taylor 	refcnt = (hermon_sw_refcnt_t *)rc;
23229e39c5baSBill Taylor 	state  = (hermon_state_t *)priv;
23239e39c5baSBill Taylor 
23249e39c5baSBill Taylor 	mutex_init(&refcnt->swrc_lock, NULL, MUTEX_DRIVER,
23259e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
23269e39c5baSBill Taylor 
23279e39c5baSBill Taylor 	return (DDI_SUCCESS);
23289e39c5baSBill Taylor }
23299e39c5baSBill Taylor 
23309e39c5baSBill Taylor 
23319e39c5baSBill Taylor /*
23329e39c5baSBill Taylor  * hermon_rsrc_refcnt_destructor()
23339e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23349e39c5baSBill Taylor  */
23359e39c5baSBill Taylor /* ARGSUSED */
23369e39c5baSBill Taylor static void
23379e39c5baSBill Taylor hermon_rsrc_refcnt_destructor(void *rc, void *priv)
23389e39c5baSBill Taylor {
23399e39c5baSBill Taylor 	hermon_sw_refcnt_t	*refcnt;
23409e39c5baSBill Taylor 
23419e39c5baSBill Taylor 	refcnt = (hermon_sw_refcnt_t *)rc;
23429e39c5baSBill Taylor 
23439e39c5baSBill Taylor 	mutex_destroy(&refcnt->swrc_lock);
23449e39c5baSBill Taylor }
23459e39c5baSBill Taylor 
23469e39c5baSBill Taylor 
23479e39c5baSBill Taylor /*
23489e39c5baSBill Taylor  * hermon_rsrc_ahhdl_constructor()
23499e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23509e39c5baSBill Taylor  */
23519e39c5baSBill Taylor /* ARGSUSED */
23529e39c5baSBill Taylor static int
23539e39c5baSBill Taylor hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags)
23549e39c5baSBill Taylor {
23559e39c5baSBill Taylor 	hermon_ahhdl_t	ahhdl;
23569e39c5baSBill Taylor 	hermon_state_t	*state;
23579e39c5baSBill Taylor 
23589e39c5baSBill Taylor 	ahhdl = (hermon_ahhdl_t)ah;
23599e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
23609e39c5baSBill Taylor 
23619e39c5baSBill Taylor 	mutex_init(&ahhdl->ah_lock, NULL, MUTEX_DRIVER,
23629e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
23639e39c5baSBill Taylor 	return (DDI_SUCCESS);
23649e39c5baSBill Taylor }
23659e39c5baSBill Taylor 
23669e39c5baSBill Taylor 
23679e39c5baSBill Taylor /*
23689e39c5baSBill Taylor  * hermon_rsrc_ahhdl_destructor()
23699e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23709e39c5baSBill Taylor  */
23719e39c5baSBill Taylor /* ARGSUSED */
23729e39c5baSBill Taylor static void
23739e39c5baSBill Taylor hermon_rsrc_ahhdl_destructor(void *ah, void *priv)
23749e39c5baSBill Taylor {
23759e39c5baSBill Taylor 	hermon_ahhdl_t	ahhdl;
23769e39c5baSBill Taylor 
23779e39c5baSBill Taylor 	ahhdl = (hermon_ahhdl_t)ah;
23789e39c5baSBill Taylor 
23799e39c5baSBill Taylor 	mutex_destroy(&ahhdl->ah_lock);
23809e39c5baSBill Taylor }
23819e39c5baSBill Taylor 
23829e39c5baSBill Taylor 
23839e39c5baSBill Taylor /*
23849e39c5baSBill Taylor  * hermon_rsrc_mrhdl_constructor()
23859e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23869e39c5baSBill Taylor  */
23879e39c5baSBill Taylor /* ARGSUSED */
23889e39c5baSBill Taylor static int
23899e39c5baSBill Taylor hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags)
23909e39c5baSBill Taylor {
23919e39c5baSBill Taylor 	hermon_mrhdl_t	mrhdl;
23929e39c5baSBill Taylor 	hermon_state_t	*state;
23939e39c5baSBill Taylor 
23949e39c5baSBill Taylor 	mrhdl = (hermon_mrhdl_t)mr;
23959e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
23969e39c5baSBill Taylor 
23979e39c5baSBill Taylor 	mutex_init(&mrhdl->mr_lock, NULL, MUTEX_DRIVER,
23989e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
23999e39c5baSBill Taylor 
24009e39c5baSBill Taylor 	return (DDI_SUCCESS);
24019e39c5baSBill Taylor }
24029e39c5baSBill Taylor 
24039e39c5baSBill Taylor 
24049e39c5baSBill Taylor /*
24059e39c5baSBill Taylor  * hermon_rsrc_mrhdl_destructor()
24069e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24079e39c5baSBill Taylor  */
24089e39c5baSBill Taylor /* ARGSUSED */
24099e39c5baSBill Taylor static void
24109e39c5baSBill Taylor hermon_rsrc_mrhdl_destructor(void *mr, void *priv)
24119e39c5baSBill Taylor {
24129e39c5baSBill Taylor 	hermon_mrhdl_t	mrhdl;
24139e39c5baSBill Taylor 
24149e39c5baSBill Taylor 	mrhdl = (hermon_mrhdl_t)mr;
24159e39c5baSBill Taylor 
24169e39c5baSBill Taylor 	mutex_destroy(&mrhdl->mr_lock);
24179e39c5baSBill Taylor }
24189e39c5baSBill Taylor 
24199e39c5baSBill Taylor 
24209e39c5baSBill Taylor /*
24219e39c5baSBill Taylor  * hermon_rsrc_mcg_entry_get_size()
24229e39c5baSBill Taylor  */
24239e39c5baSBill Taylor static int
24249e39c5baSBill Taylor hermon_rsrc_mcg_entry_get_size(hermon_state_t *state, uint_t *mcg_size_shift)
24259e39c5baSBill Taylor {
24269e39c5baSBill Taylor 	uint_t	num_qp_per_mcg, max_qp_per_mcg, log2;
24279e39c5baSBill Taylor 
24289e39c5baSBill Taylor 	/*
24299e39c5baSBill Taylor 	 * Round the configured number of QP per MCG to next larger
24309e39c5baSBill Taylor 	 * power-of-2 size and update.
24319e39c5baSBill Taylor 	 */
24329e39c5baSBill Taylor 	num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg + 8;
24339e39c5baSBill Taylor 	log2 = highbit(num_qp_per_mcg);
24349e39c5baSBill Taylor 	if ((num_qp_per_mcg & (num_qp_per_mcg - 1)) == 0) {
24359e39c5baSBill Taylor 		log2 = log2 - 1;
24369e39c5baSBill Taylor 	}
24379e39c5baSBill Taylor 	state->hs_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
24389e39c5baSBill Taylor 
24399e39c5baSBill Taylor 	/* Now make sure number of QP per MCG makes sense */
24409e39c5baSBill Taylor 	num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg;
24419e39c5baSBill Taylor 	max_qp_per_mcg = (1 << state->hs_devlim.log_max_qp_mcg);
24429e39c5baSBill Taylor 	if (num_qp_per_mcg > max_qp_per_mcg) {
24439e39c5baSBill Taylor 		return (DDI_FAILURE);
24449e39c5baSBill Taylor 	}
24459e39c5baSBill Taylor 
24469e39c5baSBill Taylor 	/* Return the (shift) size of an individual MCG HW entry */
24479e39c5baSBill Taylor 	*mcg_size_shift = log2 + 2;
24489e39c5baSBill Taylor 
24499e39c5baSBill Taylor 	return (DDI_SUCCESS);
24509e39c5baSBill Taylor }
2451