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 /*
2317a2b317SBill Taylor  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
249e39c5baSBill Taylor  */
259e39c5baSBill Taylor 
269e39c5baSBill Taylor /*
279e39c5baSBill Taylor  * hermon_rsrc.c
289e39c5baSBill Taylor  *    Hermon Resource Management Routines
299e39c5baSBill Taylor  *
309e39c5baSBill Taylor  *    Implements all the routines necessary for setup, teardown, and
319e39c5baSBill Taylor  *    alloc/free of all Hermon resources, including those that are managed
329e39c5baSBill Taylor  *    by Hermon hardware or which live in Hermon's direct attached DDR memory.
339e39c5baSBill Taylor  */
349e39c5baSBill Taylor 
35*de710d24SJosef 'Jeff' Sipek #include <sys/sysmacros.h>
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);
11017a2b317SBill Taylor static void hermon_rsrc_mbox_free(hermon_rsrc_t *hdl);
1119e39c5baSBill Taylor 
1129e39c5baSBill Taylor static int hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info,
11317a2b317SBill Taylor     uint_t num, uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl);
1149e39c5baSBill Taylor static void hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
1159e39c5baSBill Taylor     hermon_rsrc_t *hdl);
11617a2b317SBill Taylor static int hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t *pool_info,
11717a2b317SBill Taylor     uint_t num, uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl);
1189e39c5baSBill Taylor 
1199e39c5baSBill Taylor static int hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info,
12017a2b317SBill Taylor     uint_t num, hermon_rsrc_t *hdl, int num_to_hdl);
1219e39c5baSBill Taylor static int hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
12217a2b317SBill Taylor     hermon_rsrc_t *hdl, int num_to_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 
13417a2b317SBill Taylor static int hermon_rsrc_fexch_alloc(hermon_state_t *state,
13517a2b317SBill Taylor     hermon_rsrc_type_t rsrc, uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl);
13617a2b317SBill Taylor static void hermon_rsrc_fexch_free(hermon_state_t *state, hermon_rsrc_t *hdl);
13717a2b317SBill Taylor static int hermon_rsrc_rfci_alloc(hermon_state_t *state,
13817a2b317SBill Taylor     hermon_rsrc_type_t rsrc, uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl);
13917a2b317SBill Taylor static void hermon_rsrc_rfci_free(hermon_state_t *state, hermon_rsrc_t *hdl);
14017a2b317SBill Taylor 
1419e39c5baSBill Taylor /*
1429e39c5baSBill Taylor  * The following routines are the constructors and destructors for several
1439e39c5baSBill Taylor  * of the SW handle type objects.  For certain types of SW handles objects
1449e39c5baSBill Taylor  * (all of which are implemented using kmem_cache), we need to do some
1459e39c5baSBill Taylor  * special field initialization (specifically, mutex_init/destroy).  These
1469e39c5baSBill Taylor  * routines enable that init and teardown.
1479e39c5baSBill Taylor  */
1489e39c5baSBill Taylor static int hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
1499e39c5baSBill Taylor static void hermon_rsrc_pdhdl_destructor(void *pd, void *state);
1509e39c5baSBill Taylor static int hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
1519e39c5baSBill Taylor static void hermon_rsrc_cqhdl_destructor(void *cq, void *state);
1529e39c5baSBill Taylor static int hermon_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
1539e39c5baSBill Taylor static void hermon_rsrc_qphdl_destructor(void *cq, void *state);
1549e39c5baSBill Taylor static int hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
1559e39c5baSBill Taylor static void hermon_rsrc_srqhdl_destructor(void *srq, void *state);
1569e39c5baSBill Taylor static int hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
1579e39c5baSBill Taylor static void hermon_rsrc_refcnt_destructor(void *rc, void *state);
1589e39c5baSBill Taylor static int hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
1599e39c5baSBill Taylor static void hermon_rsrc_ahhdl_destructor(void *ah, void *state);
1609e39c5baSBill Taylor static int hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
1619e39c5baSBill Taylor static void hermon_rsrc_mrhdl_destructor(void *mr, void *state);
1629e39c5baSBill Taylor 
1639e39c5baSBill Taylor /*
1649e39c5baSBill Taylor  * Special routine to calculate and return the size of a MCG object based
1659e39c5baSBill Taylor  * on current driver configuration (specifically, the number of QP per MCG
1669e39c5baSBill Taylor  * that has been configured.
1679e39c5baSBill Taylor  */
1689e39c5baSBill Taylor static int hermon_rsrc_mcg_entry_get_size(hermon_state_t *state,
1699e39c5baSBill Taylor     uint_t *mcg_size_shift);
1709e39c5baSBill Taylor 
1719e39c5baSBill Taylor 
1729e39c5baSBill Taylor /*
1739e39c5baSBill Taylor  * hermon_rsrc_alloc()
1749e39c5baSBill Taylor  *
1759e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
1769e39c5baSBill Taylor  *    The "sleepflag" parameter is used by all object allocators to
1779e39c5baSBill Taylor  *    determine whether to SLEEP for resources or not.
1789e39c5baSBill Taylor  */
1799e39c5baSBill Taylor int
hermon_rsrc_alloc(hermon_state_t * state,hermon_rsrc_type_t rsrc,uint_t num,uint_t sleepflag,hermon_rsrc_t ** hdl)1809e39c5baSBill Taylor hermon_rsrc_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num,
1819e39c5baSBill Taylor     uint_t sleepflag, hermon_rsrc_t **hdl)
1829e39c5baSBill Taylor {
1839e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
1849e39c5baSBill Taylor 	hermon_rsrc_t		*tmp_rsrc_hdl;
1859e39c5baSBill Taylor 	int			flag, status = DDI_FAILURE;
1869e39c5baSBill Taylor 
1879e39c5baSBill Taylor 	ASSERT(state != NULL);
1889e39c5baSBill Taylor 	ASSERT(hdl != NULL);
1899e39c5baSBill Taylor 
1909e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[rsrc];
1919e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
1929e39c5baSBill Taylor 
1939e39c5baSBill Taylor 	/*
1949e39c5baSBill Taylor 	 * Allocate space for the object used to track the resource handle
1959e39c5baSBill Taylor 	 */
1969e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
19717a2b317SBill Taylor 	tmp_rsrc_hdl = kmem_cache_alloc(state->hs_rsrc_cache, flag);
1989e39c5baSBill Taylor 	if (tmp_rsrc_hdl == NULL) {
1999e39c5baSBill Taylor 		return (DDI_FAILURE);
2009e39c5baSBill Taylor 	}
2019e39c5baSBill Taylor 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
2029e39c5baSBill Taylor 
2039e39c5baSBill Taylor 	/*
2049e39c5baSBill Taylor 	 * Set rsrc_hdl type.  This is later used by the hermon_rsrc_free call
2059e39c5baSBill Taylor 	 * to know what type of resource is being freed.
2069e39c5baSBill Taylor 	 */
2079e39c5baSBill Taylor 	tmp_rsrc_hdl->rsrc_type = rsrc;
2089e39c5baSBill Taylor 
2099e39c5baSBill Taylor 	/*
2109e39c5baSBill Taylor 	 * Depending on resource type, call the appropriate alloc routine
2119e39c5baSBill Taylor 	 */
21217a2b317SBill Taylor 	switch (rsrc) {
2139e39c5baSBill Taylor 	case HERMON_IN_MBOX:
2149e39c5baSBill Taylor 	case HERMON_OUT_MBOX:
2159e39c5baSBill Taylor 	case HERMON_INTR_IN_MBOX:
2169e39c5baSBill Taylor 	case HERMON_INTR_OUT_MBOX:
2179e39c5baSBill Taylor 		status = hermon_rsrc_mbox_alloc(rsrc_pool, num, tmp_rsrc_hdl);
2189e39c5baSBill Taylor 		break;
2199e39c5baSBill Taylor 
22017a2b317SBill Taylor 	case HERMON_DMPT:
22117a2b317SBill Taylor 		/* Allocate "num" (contiguous/aligned for FEXCH) DMPTs */
2229e39c5baSBill Taylor 	case HERMON_QPC:
22317a2b317SBill Taylor 		/* Allocate "num" (contiguous/aligned for RSS) QPCs */
224c7facc54SBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, num,
2259e39c5baSBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2269e39c5baSBill Taylor 		break;
2279e39c5baSBill Taylor 
22817a2b317SBill Taylor 	case HERMON_QPC_FEXCH_PORT1:
22917a2b317SBill Taylor 	case HERMON_QPC_FEXCH_PORT2:
23017a2b317SBill Taylor 		/* Allocate "num" contiguous/aligned QPCs for FEXCH */
23117a2b317SBill Taylor 		status = hermon_rsrc_fexch_alloc(state, rsrc, num,
23217a2b317SBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2339e39c5baSBill Taylor 		break;
2349e39c5baSBill Taylor 
23517a2b317SBill Taylor 	case HERMON_QPC_RFCI_PORT1:
23617a2b317SBill Taylor 	case HERMON_QPC_RFCI_PORT2:
23717a2b317SBill Taylor 		/* Allocate "num" contiguous/aligned QPCs for RFCI */
23817a2b317SBill Taylor 		status = hermon_rsrc_rfci_alloc(state, rsrc, num,
2399e39c5baSBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2409e39c5baSBill Taylor 		break;
2419e39c5baSBill Taylor 
2429e39c5baSBill Taylor 	case HERMON_MTT:
24317a2b317SBill Taylor 	case HERMON_CQC:
24417a2b317SBill Taylor 	case HERMON_SRQC:
24517a2b317SBill Taylor 	case HERMON_EQC:
24617a2b317SBill Taylor 	case HERMON_MCG:
2479e39c5baSBill Taylor 	case HERMON_UARPG:
24817a2b317SBill Taylor 		/* Allocate "num" unaligned resources */
2499e39c5baSBill Taylor 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
25017a2b317SBill Taylor 		    sleepflag, tmp_rsrc_hdl);
2519e39c5baSBill Taylor 		break;
2529e39c5baSBill Taylor 
2539e39c5baSBill Taylor 	case HERMON_MRHDL:
2549e39c5baSBill Taylor 	case HERMON_EQHDL:
2559e39c5baSBill Taylor 	case HERMON_CQHDL:
2569e39c5baSBill Taylor 	case HERMON_SRQHDL:
2579e39c5baSBill Taylor 	case HERMON_AHHDL:
2589e39c5baSBill Taylor 	case HERMON_QPHDL:
2599e39c5baSBill Taylor 	case HERMON_REFCNT:
2609e39c5baSBill Taylor 		status = hermon_rsrc_swhdl_alloc(rsrc_pool, sleepflag,
2619e39c5baSBill Taylor 		    tmp_rsrc_hdl);
2629e39c5baSBill Taylor 		break;
2639e39c5baSBill Taylor 
2649e39c5baSBill Taylor 	case HERMON_PDHDL:
2659e39c5baSBill Taylor 		status = hermon_rsrc_pdhdl_alloc(rsrc_pool, sleepflag,
2669e39c5baSBill Taylor 		    tmp_rsrc_hdl);
2679e39c5baSBill Taylor 		break;
2689e39c5baSBill Taylor 
2699e39c5baSBill Taylor 	case HERMON_RDB:	/* handled during HERMON_QPC */
2709e39c5baSBill Taylor 	case HERMON_ALTC:	/* handled during HERMON_QPC */
2719e39c5baSBill Taylor 	case HERMON_AUXC:	/* handled during HERMON_QPC */
2729e39c5baSBill Taylor 	case HERMON_CMPT_QPC:	/* handled during HERMON_QPC */
2739e39c5baSBill Taylor 	case HERMON_CMPT_SRQC:	/* handled during HERMON_SRQC */
2749e39c5baSBill Taylor 	case HERMON_CMPT_CQC:	/* handled during HERMON_CPC */
2759e39c5baSBill Taylor 	case HERMON_CMPT_EQC:	/* handled during HERMON_EPC */
2769e39c5baSBill Taylor 	default:
2779e39c5baSBill Taylor 		HERMON_WARNING(state, "unexpected resource type in alloc ");
2789e39c5baSBill Taylor 		cmn_err(CE_WARN, "Resource type %x \n", rsrc_pool->rsrc_type);
2799e39c5baSBill Taylor 		break;
2809e39c5baSBill Taylor 	}
2819e39c5baSBill Taylor 
2829e39c5baSBill Taylor 	/*
2839e39c5baSBill Taylor 	 * If the resource allocation failed, then free the special resource
2849e39c5baSBill Taylor 	 * tracking structure and return failure.  Otherwise return the
2859e39c5baSBill Taylor 	 * handle for the resource tracking structure.
2869e39c5baSBill Taylor 	 */
2879e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
2889e39c5baSBill Taylor 		kmem_cache_free(state->hs_rsrc_cache, tmp_rsrc_hdl);
2899e39c5baSBill Taylor 		return (DDI_FAILURE);
2909e39c5baSBill Taylor 	} else {
2919e39c5baSBill Taylor 		*hdl = tmp_rsrc_hdl;
2929e39c5baSBill Taylor 		return (DDI_SUCCESS);
2939e39c5baSBill Taylor 	}
2949e39c5baSBill Taylor }
2959e39c5baSBill Taylor 
2969e39c5baSBill Taylor 
29717a2b317SBill Taylor /*
29817a2b317SBill Taylor  * hermon_rsrc_reserve()
29917a2b317SBill Taylor  *
30017a2b317SBill Taylor  *    Context: Can only be called from attach.
30117a2b317SBill Taylor  *    The "sleepflag" parameter is used by all object allocators to
30217a2b317SBill Taylor  *    determine whether to SLEEP for resources or not.
30317a2b317SBill Taylor  */
30417a2b317SBill Taylor int
hermon_rsrc_reserve(hermon_state_t * state,hermon_rsrc_type_t rsrc,uint_t num,uint_t sleepflag,hermon_rsrc_t ** hdl)30517a2b317SBill Taylor hermon_rsrc_reserve(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num,
30617a2b317SBill Taylor     uint_t sleepflag, hermon_rsrc_t **hdl)
30717a2b317SBill Taylor {
30817a2b317SBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
30917a2b317SBill Taylor 	hermon_rsrc_t		*tmp_rsrc_hdl;
31017a2b317SBill Taylor 	int			flag, status = DDI_FAILURE;
31117a2b317SBill Taylor 
31217a2b317SBill Taylor 	ASSERT(state != NULL);
31317a2b317SBill Taylor 	ASSERT(hdl != NULL);
31417a2b317SBill Taylor 
31517a2b317SBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[rsrc];
31617a2b317SBill Taylor 	ASSERT(rsrc_pool != NULL);
31717a2b317SBill Taylor 
31817a2b317SBill Taylor 	/*
31917a2b317SBill Taylor 	 * Allocate space for the object used to track the resource handle
32017a2b317SBill Taylor 	 */
32117a2b317SBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
32217a2b317SBill Taylor 	tmp_rsrc_hdl = kmem_cache_alloc(state->hs_rsrc_cache, flag);
32317a2b317SBill Taylor 	if (tmp_rsrc_hdl == NULL) {
32417a2b317SBill Taylor 		return (DDI_FAILURE);
32517a2b317SBill Taylor 	}
32617a2b317SBill Taylor 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
32717a2b317SBill Taylor 
32817a2b317SBill Taylor 	/*
32917a2b317SBill Taylor 	 * Set rsrc_hdl type.  This is later used by the hermon_rsrc_free call
33017a2b317SBill Taylor 	 * to know what type of resource is being freed.
33117a2b317SBill Taylor 	 */
33217a2b317SBill Taylor 	tmp_rsrc_hdl->rsrc_type = rsrc;
33317a2b317SBill Taylor 
33417a2b317SBill Taylor 	switch (rsrc) {
33517a2b317SBill Taylor 	case HERMON_QPC:
33617a2b317SBill Taylor 	case HERMON_DMPT:
33717a2b317SBill Taylor 	case HERMON_MTT:
33817a2b317SBill Taylor 		/*
33917a2b317SBill Taylor 		 * Reserve num resources, naturally aligned (N * num).
34017a2b317SBill Taylor 		 */
34117a2b317SBill Taylor 		status = hermon_rsrc_hw_entry_reserve(rsrc_pool, num, num,
34217a2b317SBill Taylor 		    sleepflag, tmp_rsrc_hdl);
34317a2b317SBill Taylor 		break;
34417a2b317SBill Taylor 
34517a2b317SBill Taylor 	default:
34617a2b317SBill Taylor 		HERMON_WARNING(state, "unexpected resource type in reserve ");
34717a2b317SBill Taylor 		cmn_err(CE_WARN, "Resource type %x \n", rsrc);
34817a2b317SBill Taylor 		break;
34917a2b317SBill Taylor 	}
35017a2b317SBill Taylor 
35117a2b317SBill Taylor 	/*
35217a2b317SBill Taylor 	 * If the resource allocation failed, then free the special resource
35317a2b317SBill Taylor 	 * tracking structure and return failure.  Otherwise return the
35417a2b317SBill Taylor 	 * handle for the resource tracking structure.
35517a2b317SBill Taylor 	 */
35617a2b317SBill Taylor 	if (status != DDI_SUCCESS) {
35717a2b317SBill Taylor 		kmem_cache_free(state->hs_rsrc_cache, tmp_rsrc_hdl);
35817a2b317SBill Taylor 		return (DDI_FAILURE);
35917a2b317SBill Taylor 	} else {
36017a2b317SBill Taylor 		*hdl = tmp_rsrc_hdl;
36117a2b317SBill Taylor 		return (DDI_SUCCESS);
36217a2b317SBill Taylor 	}
36317a2b317SBill Taylor }
36417a2b317SBill Taylor 
36517a2b317SBill Taylor 
36617a2b317SBill Taylor /*
36717a2b317SBill Taylor  * hermon_rsrc_fexch_alloc()
36817a2b317SBill Taylor  *
36917a2b317SBill Taylor  *    Context: Can only be called from base context.
37017a2b317SBill Taylor  *    The "sleepflag" parameter is used by all object allocators to
37117a2b317SBill Taylor  *    determine whether to SLEEP for resources or not.
37217a2b317SBill Taylor  */
37317a2b317SBill Taylor static int
hermon_rsrc_fexch_alloc(hermon_state_t * state,hermon_rsrc_type_t rsrc,uint_t num,uint_t sleepflag,hermon_rsrc_t * hdl)37417a2b317SBill Taylor hermon_rsrc_fexch_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc,
37517a2b317SBill Taylor     uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl)
37617a2b317SBill Taylor {
37717a2b317SBill Taylor 	hermon_fcoib_t		*fcoib;
37817a2b317SBill Taylor 	void			*addr;
37917a2b317SBill Taylor 	uint32_t		fexch_qpn_base;
38017a2b317SBill Taylor 	hermon_rsrc_pool_info_t	*qpc_pool, *mpt_pool, *mtt_pool;
38117a2b317SBill Taylor 	int			flag, status;
38217a2b317SBill Taylor 	hermon_rsrc_t		mpt_hdl; /* temporary, just for icm_confirm */
38317a2b317SBill Taylor 	hermon_rsrc_t		mtt_hdl; /* temporary, just for icm_confirm */
38417a2b317SBill Taylor 	uint_t			portm1;	/* hca_port_number - 1 */
38517a2b317SBill Taylor 	uint_t			nummtt;
38617a2b317SBill Taylor 	vmem_t			*vmp;
38717a2b317SBill Taylor 
38817a2b317SBill Taylor 	ASSERT(state != NULL);
38917a2b317SBill Taylor 	ASSERT(hdl != NULL);
39017a2b317SBill Taylor 
39117a2b317SBill Taylor 	if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
39217a2b317SBill Taylor 		return (DDI_FAILURE);
39317a2b317SBill Taylor 
39417a2b317SBill Taylor 	portm1 = rsrc - HERMON_QPC_FEXCH_PORT1;
39517a2b317SBill Taylor 	fcoib = &state->hs_fcoib;
39617a2b317SBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
39717a2b317SBill Taylor 
39817a2b317SBill Taylor 	/* Allocate from the FEXCH QP range */
39917a2b317SBill Taylor 	vmp = fcoib->hfc_fexch_vmemp[portm1];
40017a2b317SBill Taylor 	addr = vmem_xalloc(vmp, num, num, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
40117a2b317SBill Taylor 	if (addr == NULL) {
40217a2b317SBill Taylor 		return (DDI_FAILURE);
40317a2b317SBill Taylor 	}
40417a2b317SBill Taylor 	fexch_qpn_base = (uint32_t)((uintptr_t)addr -
40517a2b317SBill Taylor 	    fcoib->hfc_vmemstart + fcoib->hfc_fexch_base[portm1]);
40617a2b317SBill Taylor 
40717a2b317SBill Taylor 	/* ICM confirm for the FEXCH QP range */
40817a2b317SBill Taylor 	qpc_pool = &state->hs_rsrc_hdl[HERMON_QPC];
40917a2b317SBill Taylor 	hdl->hr_len = num << qpc_pool->rsrc_shift;
41017a2b317SBill Taylor 	hdl->hr_addr = addr;	/* used only for vmem_xfree */
41117a2b317SBill Taylor 	hdl->hr_indx = fexch_qpn_base;
41217a2b317SBill Taylor 
41317a2b317SBill Taylor 	status = hermon_rsrc_hw_entry_icm_confirm(qpc_pool, num, hdl, 1);
41417a2b317SBill Taylor 	if (status != DDI_SUCCESS) {
41517a2b317SBill Taylor 		vmem_xfree(vmp, addr, num);
41617a2b317SBill Taylor 		return (DDI_FAILURE);
41717a2b317SBill Taylor 	}
41817a2b317SBill Taylor 
41917a2b317SBill Taylor 	/* ICM confirm for the Primary MKEYs (client side only) */
42017a2b317SBill Taylor 	mpt_pool = &state->hs_rsrc_hdl[HERMON_DMPT];
42117a2b317SBill Taylor 	mpt_hdl.hr_len = num << mpt_pool->rsrc_shift;
42217a2b317SBill Taylor 	mpt_hdl.hr_addr = NULL;
42317a2b317SBill Taylor 	mpt_hdl.hr_indx = fcoib->hfc_mpt_base[portm1] +
42417a2b317SBill Taylor 	    (fexch_qpn_base - fcoib->hfc_fexch_base[portm1]);
42517a2b317SBill Taylor 
42617a2b317SBill Taylor 	status = hermon_rsrc_hw_entry_icm_confirm(mpt_pool, num, &mpt_hdl, 0);
42717a2b317SBill Taylor 	if (status != DDI_SUCCESS) {
42817a2b317SBill Taylor 		status = hermon_rsrc_hw_entry_icm_free(qpc_pool, hdl, 1);
42917a2b317SBill Taylor 		vmem_xfree(vmp, addr, num);
43017a2b317SBill Taylor 		return (DDI_FAILURE);
43117a2b317SBill Taylor 	}
43217a2b317SBill Taylor 
43317a2b317SBill Taylor 	/* ICM confirm for the MTTs of the Primary MKEYs (client side only) */
43417a2b317SBill Taylor 	nummtt = fcoib->hfc_mtts_per_mpt;
43517a2b317SBill Taylor 	num *= nummtt;
43617a2b317SBill Taylor 	mtt_pool = &state->hs_rsrc_hdl[HERMON_MTT];
43717a2b317SBill Taylor 	mtt_hdl.hr_len = num << mtt_pool->rsrc_shift;
43817a2b317SBill Taylor 	mtt_hdl.hr_addr = NULL;
43917a2b317SBill Taylor 	mtt_hdl.hr_indx = fcoib->hfc_mtt_base[portm1] +
44017a2b317SBill Taylor 	    (fexch_qpn_base - fcoib->hfc_fexch_base[portm1]) *
44117a2b317SBill Taylor 	    nummtt;
44217a2b317SBill Taylor 
44317a2b317SBill Taylor 	status = hermon_rsrc_hw_entry_icm_confirm(mtt_pool, num, &mtt_hdl, 0);
44417a2b317SBill Taylor 	if (status != DDI_SUCCESS) {
44517a2b317SBill Taylor 		vmem_xfree(vmp, addr, num);
44617a2b317SBill Taylor 		return (DDI_FAILURE);
44717a2b317SBill Taylor 	}
44817a2b317SBill Taylor 	return (DDI_SUCCESS);
44917a2b317SBill Taylor }
45017a2b317SBill Taylor 
45117a2b317SBill Taylor static void
hermon_rsrc_fexch_free(hermon_state_t * state,hermon_rsrc_t * hdl)45217a2b317SBill Taylor hermon_rsrc_fexch_free(hermon_state_t *state, hermon_rsrc_t *hdl)
45317a2b317SBill Taylor {
45417a2b317SBill Taylor 	hermon_fcoib_t		*fcoib;
45517a2b317SBill Taylor 	uint_t			portm1; /* hca_port_number - 1 */
45617a2b317SBill Taylor 
45717a2b317SBill Taylor 	ASSERT(state != NULL);
45817a2b317SBill Taylor 	ASSERT(hdl != NULL);
45917a2b317SBill Taylor 
46017a2b317SBill Taylor 	portm1 = hdl->rsrc_type - HERMON_QPC_FEXCH_PORT1;
46117a2b317SBill Taylor 	fcoib = &state->hs_fcoib;
46217a2b317SBill Taylor 	vmem_xfree(fcoib->hfc_fexch_vmemp[portm1], hdl->hr_addr,
46317a2b317SBill Taylor 	    hdl->hr_len >> state->hs_rsrc_hdl[HERMON_QPC].rsrc_shift);
46417a2b317SBill Taylor }
46517a2b317SBill Taylor 
46617a2b317SBill Taylor /*
46717a2b317SBill Taylor  * hermon_rsrc_rfci_alloc()
46817a2b317SBill Taylor  *
46917a2b317SBill Taylor  *    Context: Can only be called from base context.
47017a2b317SBill Taylor  *    The "sleepflag" parameter is used by all object allocators to
47117a2b317SBill Taylor  *    determine whether to SLEEP for resources or not.
47217a2b317SBill Taylor  */
47317a2b317SBill Taylor static int
hermon_rsrc_rfci_alloc(hermon_state_t * state,hermon_rsrc_type_t rsrc,uint_t num,uint_t sleepflag,hermon_rsrc_t * hdl)47417a2b317SBill Taylor hermon_rsrc_rfci_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc,
47517a2b317SBill Taylor     uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl)
47617a2b317SBill Taylor {
47717a2b317SBill Taylor 	hermon_fcoib_t		*fcoib;
47817a2b317SBill Taylor 	void			*addr;
47917a2b317SBill Taylor 	uint32_t		rfci_qpn_base;
48017a2b317SBill Taylor 	hermon_rsrc_pool_info_t	*qpc_pool;
48117a2b317SBill Taylor 	int			flag, status;
48217a2b317SBill Taylor 	uint_t			portm1;	/* hca_port_number - 1 */
48317a2b317SBill Taylor 	vmem_t			*vmp;
48417a2b317SBill Taylor 
48517a2b317SBill Taylor 	ASSERT(state != NULL);
48617a2b317SBill Taylor 	ASSERT(hdl != NULL);
48717a2b317SBill Taylor 
48817a2b317SBill Taylor 	if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
48917a2b317SBill Taylor 		return (DDI_FAILURE);
49017a2b317SBill Taylor 
49117a2b317SBill Taylor 	portm1 = rsrc - HERMON_QPC_RFCI_PORT1;
49217a2b317SBill Taylor 	fcoib = &state->hs_fcoib;
49317a2b317SBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
49417a2b317SBill Taylor 
49517a2b317SBill Taylor 	/* Allocate from the RFCI QP range */
49617a2b317SBill Taylor 	vmp = fcoib->hfc_rfci_vmemp[portm1];
49717a2b317SBill Taylor 	addr = vmem_xalloc(vmp, num, num, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
49817a2b317SBill Taylor 	if (addr == NULL) {
49917a2b317SBill Taylor 		return (DDI_FAILURE);
50017a2b317SBill Taylor 	}
50117a2b317SBill Taylor 	rfci_qpn_base = (uint32_t)((uintptr_t)addr -
50217a2b317SBill Taylor 	    fcoib->hfc_vmemstart + fcoib->hfc_rfci_base[portm1]);
50317a2b317SBill Taylor 
50417a2b317SBill Taylor 	/* ICM confirm for the RFCI QP */
50517a2b317SBill Taylor 	qpc_pool = &state->hs_rsrc_hdl[HERMON_QPC];
50617a2b317SBill Taylor 	hdl->hr_len = num << qpc_pool->rsrc_shift;
50717a2b317SBill Taylor 	hdl->hr_addr = addr;	/* used only for vmem_xfree */
50817a2b317SBill Taylor 	hdl->hr_indx = rfci_qpn_base;
50917a2b317SBill Taylor 
51017a2b317SBill Taylor 	status = hermon_rsrc_hw_entry_icm_confirm(qpc_pool, num, hdl, 1);
51117a2b317SBill Taylor 	if (status != DDI_SUCCESS) {
51217a2b317SBill Taylor 		vmem_xfree(vmp, addr, num);
51317a2b317SBill Taylor 		return (DDI_FAILURE);
51417a2b317SBill Taylor 	}
51517a2b317SBill Taylor 	return (DDI_SUCCESS);
51617a2b317SBill Taylor }
51717a2b317SBill Taylor 
51817a2b317SBill Taylor static void
hermon_rsrc_rfci_free(hermon_state_t * state,hermon_rsrc_t * hdl)51917a2b317SBill Taylor hermon_rsrc_rfci_free(hermon_state_t *state, hermon_rsrc_t *hdl)
52017a2b317SBill Taylor {
52117a2b317SBill Taylor 	hermon_fcoib_t		*fcoib;
52217a2b317SBill Taylor 	uint_t			portm1; /* hca_port_number - 1 */
52317a2b317SBill Taylor 
52417a2b317SBill Taylor 	ASSERT(state != NULL);
52517a2b317SBill Taylor 	ASSERT(hdl != NULL);
52617a2b317SBill Taylor 
52717a2b317SBill Taylor 	portm1 = hdl->rsrc_type - HERMON_QPC_RFCI_PORT1;
52817a2b317SBill Taylor 	fcoib = &state->hs_fcoib;
52917a2b317SBill Taylor 	vmem_xfree(fcoib->hfc_rfci_vmemp[portm1], hdl->hr_addr,
53017a2b317SBill Taylor 	    hdl->hr_len >> state->hs_rsrc_hdl[HERMON_QPC].rsrc_shift);
53117a2b317SBill Taylor }
53217a2b317SBill Taylor 
53317a2b317SBill Taylor 
5349e39c5baSBill Taylor /*
5359e39c5baSBill Taylor  * hermon_rsrc_free()
5369e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
5379e39c5baSBill Taylor  */
5389e39c5baSBill Taylor void
hermon_rsrc_free(hermon_state_t * state,hermon_rsrc_t ** hdl)5399e39c5baSBill Taylor hermon_rsrc_free(hermon_state_t *state, hermon_rsrc_t **hdl)
5409e39c5baSBill Taylor {
5419e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
5429e39c5baSBill Taylor 
5439e39c5baSBill Taylor 	ASSERT(state != NULL);
5449e39c5baSBill Taylor 	ASSERT(hdl != NULL);
5459e39c5baSBill Taylor 
5469e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[(*hdl)->rsrc_type];
5479e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
5489e39c5baSBill Taylor 
5499e39c5baSBill Taylor 	/*
5509e39c5baSBill Taylor 	 * Depending on resource type, call the appropriate free routine
5519e39c5baSBill Taylor 	 */
5529e39c5baSBill Taylor 	switch (rsrc_pool->rsrc_type) {
5539e39c5baSBill Taylor 	case HERMON_IN_MBOX:
5549e39c5baSBill Taylor 	case HERMON_OUT_MBOX:
5559e39c5baSBill Taylor 	case HERMON_INTR_IN_MBOX:
5569e39c5baSBill Taylor 	case HERMON_INTR_OUT_MBOX:
55717a2b317SBill Taylor 		hermon_rsrc_mbox_free(*hdl);
55817a2b317SBill Taylor 		break;
55917a2b317SBill Taylor 
56017a2b317SBill Taylor 	case HERMON_QPC_FEXCH_PORT1:
56117a2b317SBill Taylor 	case HERMON_QPC_FEXCH_PORT2:
56217a2b317SBill Taylor 		hermon_rsrc_fexch_free(state, *hdl);
56317a2b317SBill Taylor 		break;
56417a2b317SBill Taylor 
56517a2b317SBill Taylor 	case HERMON_QPC_RFCI_PORT1:
56617a2b317SBill Taylor 	case HERMON_QPC_RFCI_PORT2:
56717a2b317SBill Taylor 		hermon_rsrc_rfci_free(state, *hdl);
5689e39c5baSBill Taylor 		break;
5699e39c5baSBill Taylor 
5709e39c5baSBill Taylor 	case HERMON_QPC:
5719e39c5baSBill Taylor 	case HERMON_CQC:
5729e39c5baSBill Taylor 	case HERMON_SRQC:
5739e39c5baSBill Taylor 	case HERMON_EQC:
5749e39c5baSBill Taylor 	case HERMON_DMPT:
5759e39c5baSBill Taylor 	case HERMON_MCG:
5769e39c5baSBill Taylor 	case HERMON_MTT:
5779e39c5baSBill Taylor 	case HERMON_UARPG:
5789e39c5baSBill Taylor 		hermon_rsrc_hw_entry_free(rsrc_pool, *hdl);
5799e39c5baSBill Taylor 		break;
5809e39c5baSBill Taylor 
5819e39c5baSBill Taylor 	case HERMON_MRHDL:
5829e39c5baSBill Taylor 	case HERMON_EQHDL:
5839e39c5baSBill Taylor 	case HERMON_CQHDL:
5849e39c5baSBill Taylor 	case HERMON_SRQHDL:
5859e39c5baSBill Taylor 	case HERMON_AHHDL:
5869e39c5baSBill Taylor 	case HERMON_QPHDL:
5879e39c5baSBill Taylor 	case HERMON_REFCNT:
5889e39c5baSBill Taylor 		hermon_rsrc_swhdl_free(rsrc_pool, *hdl);
5899e39c5baSBill Taylor 		break;
5909e39c5baSBill Taylor 
5919e39c5baSBill Taylor 	case HERMON_PDHDL:
5929e39c5baSBill Taylor 		hermon_rsrc_pdhdl_free(rsrc_pool, *hdl);
5939e39c5baSBill Taylor 		break;
5949e39c5baSBill Taylor 
5959e39c5baSBill Taylor 	case HERMON_RDB:
5969e39c5baSBill Taylor 	case HERMON_ALTC:
5979e39c5baSBill Taylor 	case HERMON_AUXC:
5989e39c5baSBill Taylor 	case HERMON_CMPT_QPC:
5999e39c5baSBill Taylor 	case HERMON_CMPT_SRQC:
6009e39c5baSBill Taylor 	case HERMON_CMPT_CQC:
6019e39c5baSBill Taylor 	case HERMON_CMPT_EQC:
6029e39c5baSBill Taylor 	default:
60317a2b317SBill Taylor 		cmn_err(CE_CONT, "!rsrc_type = 0x%x\n", rsrc_pool->rsrc_type);
6049e39c5baSBill Taylor 		break;
6059e39c5baSBill Taylor 	}
6069e39c5baSBill Taylor 
6079e39c5baSBill Taylor 	/*
6089e39c5baSBill Taylor 	 * Free the special resource tracking structure, set the handle to
6099e39c5baSBill Taylor 	 * NULL, and return.
6109e39c5baSBill Taylor 	 */
6119e39c5baSBill Taylor 	kmem_cache_free(state->hs_rsrc_cache, *hdl);
6129e39c5baSBill Taylor 	*hdl = NULL;
6139e39c5baSBill Taylor }
6149e39c5baSBill Taylor 
6159e39c5baSBill Taylor 
6169e39c5baSBill Taylor /*
6179e39c5baSBill Taylor  * hermon_rsrc_init_phase1()
6189e39c5baSBill Taylor  *
6199e39c5baSBill Taylor  *    Completes the first phase of Hermon resource/configuration init.
6209e39c5baSBill Taylor  *    This involves creating the kmem_cache for the "hermon_rsrc_t"
6219e39c5baSBill Taylor  *    structs, allocating the space for the resource pool handles,
6229e39c5baSBill Taylor  *    and setting up the "Out" mailboxes.
6239e39c5baSBill Taylor  *
6249e39c5baSBill Taylor  *    When this function completes, the Hermon driver is ready to
6259e39c5baSBill Taylor  *    post the following commands which return information only in the
6269e39c5baSBill Taylor  *    "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
6279e39c5baSBill Taylor  *    If any of these commands are to be posted at this time, they must be
6289e39c5baSBill Taylor  *    done so only when "spinning" (as the outstanding command list and
6299e39c5baSBill Taylor  *    EQ setup code has not yet run)
6309e39c5baSBill Taylor  *
6319e39c5baSBill Taylor  *    Context: Only called from attach() path context
6329e39c5baSBill Taylor  */
6339e39c5baSBill Taylor int
hermon_rsrc_init_phase1(hermon_state_t * state)6349e39c5baSBill Taylor hermon_rsrc_init_phase1(hermon_state_t *state)
6359e39c5baSBill Taylor {
6369e39c5baSBill Taylor 	hermon_rsrc_pool_info_t		*rsrc_pool;
6379e39c5baSBill Taylor 	hermon_rsrc_mbox_info_t 		mbox_info;
6389e39c5baSBill Taylor 	hermon_rsrc_cleanup_level_t	cleanup;
6399e39c5baSBill Taylor 	hermon_cfg_profile_t		*cfgprof;
6409e39c5baSBill Taylor 	uint64_t			num, size;
6419e39c5baSBill Taylor 	int				status;
6429e39c5baSBill Taylor 	char				*rsrc_name;
6439e39c5baSBill Taylor 
6449e39c5baSBill Taylor 	ASSERT(state != NULL);
6459e39c5baSBill Taylor 
6469e39c5baSBill Taylor 	/* This is where Phase 1 of resource initialization begins */
6479e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL0;
6489e39c5baSBill Taylor 
6499e39c5baSBill Taylor 	/* Build kmem cache name from Hermon instance */
65017a2b317SBill Taylor 	rsrc_name = kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
6519e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_RSRC_CACHE);
6529e39c5baSBill Taylor 
6539e39c5baSBill Taylor 	/*
6549e39c5baSBill Taylor 	 * Create the kmem_cache for "hermon_rsrc_t" structures
6559e39c5baSBill Taylor 	 * (kmem_cache_create will SLEEP until successful)
6569e39c5baSBill Taylor 	 */
6579e39c5baSBill Taylor 	state->hs_rsrc_cache = kmem_cache_create(rsrc_name,
6589e39c5baSBill Taylor 	    sizeof (hermon_rsrc_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
6599e39c5baSBill Taylor 
6609e39c5baSBill Taylor 	/*
6619e39c5baSBill Taylor 	 * Allocate an array of hermon_rsrc_pool_info_t's (used in all
6629e39c5baSBill Taylor 	 * subsequent resource allocations)
6639e39c5baSBill Taylor 	 */
6649e39c5baSBill Taylor 	state->hs_rsrc_hdl = kmem_zalloc(HERMON_NUM_RESOURCES *
6659e39c5baSBill Taylor 	    sizeof (hermon_rsrc_pool_info_t), KM_SLEEP);
6669e39c5baSBill Taylor 
6679e39c5baSBill Taylor 	/* Pull in the configuration profile */
6689e39c5baSBill Taylor 	cfgprof = state->hs_cfg_profile;
6699e39c5baSBill Taylor 
6709e39c5baSBill Taylor 	/* Initialize the resource pool for "out" mailboxes */
6719e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_outmbox);
6729e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
6739e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
6749e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
6759e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
6769e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
6779e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
6789e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
6799e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
6809e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
6819e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
6829e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
6839e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
6849e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
6859e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
6869e39c5baSBill Taylor 		status = DDI_FAILURE;
6879e39c5baSBill Taylor 		goto rsrcinitp1_fail;
6889e39c5baSBill Taylor 	}
6899e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL1;
6909e39c5baSBill Taylor 
6919e39c5baSBill Taylor 	/* Initialize the mailbox list */
6929e39c5baSBill Taylor 	status = hermon_outmbox_list_init(state);
6939e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
6949e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
6959e39c5baSBill Taylor 		status = DDI_FAILURE;
6969e39c5baSBill Taylor 		goto rsrcinitp1_fail;
6979e39c5baSBill Taylor 	}
6989e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL2;
6999e39c5baSBill Taylor 
7009e39c5baSBill Taylor 	/* Initialize the resource pool for "interrupt out" mailboxes */
7019e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_outmbox);
7029e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
7039e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
7049e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
7059e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
7069e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
7079e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
7089e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
7099e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
7109e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
7119e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
7129e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
7139e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
7149e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7159e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7169e39c5baSBill Taylor 		status = DDI_FAILURE;
7179e39c5baSBill Taylor 		goto rsrcinitp1_fail;
7189e39c5baSBill Taylor 	}
7199e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL3;
7209e39c5baSBill Taylor 
7219e39c5baSBill Taylor 	/* Initialize the mailbox list */
7229e39c5baSBill Taylor 	status = hermon_intr_outmbox_list_init(state);
7239e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7249e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7259e39c5baSBill Taylor 		status = DDI_FAILURE;
7269e39c5baSBill Taylor 		goto rsrcinitp1_fail;
7279e39c5baSBill Taylor 	}
7289e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL4;
7299e39c5baSBill Taylor 
7309e39c5baSBill Taylor 	/* Initialize the resource pool for "in" mailboxes */
7319e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_inmbox);
7329e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
7339e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
7349e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
7359e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
7369e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
7379e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
7389e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
7399e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
7409e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
7419e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
7429e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
7439e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
7449e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7459e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7469e39c5baSBill Taylor 		status = DDI_FAILURE;
7479e39c5baSBill Taylor 		goto rsrcinitp1_fail;
7489e39c5baSBill Taylor 	}
7499e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL5;
7509e39c5baSBill Taylor 
7519e39c5baSBill Taylor 	/* Initialize the mailbox list */
7529e39c5baSBill Taylor 	status = hermon_inmbox_list_init(state);
7539e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7549e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7559e39c5baSBill Taylor 		status = DDI_FAILURE;
7569e39c5baSBill Taylor 		goto rsrcinitp1_fail;
7579e39c5baSBill Taylor 	}
7589e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL6;
7599e39c5baSBill Taylor 
7609e39c5baSBill Taylor 	/* Initialize the resource pool for "interrupt in" mailboxes */
7619e39c5baSBill Taylor 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_inmbox);
7629e39c5baSBill Taylor 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
7639e39c5baSBill Taylor 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
7649e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
7659e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (size * num);
7669e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
7679e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
7689e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
7699e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
7709e39c5baSBill Taylor 	mbox_info.mbi_num	  = num;
7719e39c5baSBill Taylor 	mbox_info.mbi_size	  = size;
7729e39c5baSBill Taylor 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
7739e39c5baSBill Taylor 	status = hermon_rsrc_mbox_init(state, &mbox_info);
7749e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7759e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7769e39c5baSBill Taylor 		status = DDI_FAILURE;
7779e39c5baSBill Taylor 		goto rsrcinitp1_fail;
7789e39c5baSBill Taylor 	}
7799e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL7;
7809e39c5baSBill Taylor 
7819e39c5baSBill Taylor 	/* Initialize the mailbox list */
7829e39c5baSBill Taylor 	status = hermon_intr_inmbox_list_init(state);
7839e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
7849e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
7859e39c5baSBill Taylor 		status = DDI_FAILURE;
7869e39c5baSBill Taylor 		goto rsrcinitp1_fail;
7879e39c5baSBill Taylor 	}
7889e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
7899e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
7909e39c5baSBill Taylor 	return (DDI_SUCCESS);
7919e39c5baSBill Taylor 
7929e39c5baSBill Taylor rsrcinitp1_fail:
7939e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
7949e39c5baSBill Taylor 	return (status);
7959e39c5baSBill Taylor }
7969e39c5baSBill Taylor 
7979e39c5baSBill Taylor 
7989e39c5baSBill Taylor /*
7999e39c5baSBill Taylor  * hermon_rsrc_init_phase2()
8009e39c5baSBill Taylor  *    Context: Only called from attach() path context
8019e39c5baSBill Taylor  */
8029e39c5baSBill Taylor int
hermon_rsrc_init_phase2(hermon_state_t * state)8039e39c5baSBill Taylor hermon_rsrc_init_phase2(hermon_state_t *state)
8049e39c5baSBill Taylor {
8059e39c5baSBill Taylor 	hermon_rsrc_sw_hdl_info_t	hdl_info;
8069e39c5baSBill Taylor 	hermon_rsrc_hw_entry_info_t	entry_info;
8079e39c5baSBill Taylor 	hermon_rsrc_pool_info_t		*rsrc_pool;
8089e39c5baSBill Taylor 	hermon_rsrc_cleanup_level_t	cleanup, ncleanup;
8099e39c5baSBill Taylor 	hermon_cfg_profile_t		*cfgprof;
8109e39c5baSBill Taylor 	hermon_hw_querydevlim_t		*devlim;
8119e39c5baSBill Taylor 	uint64_t			num, max, num_prealloc;
8129e39c5baSBill Taylor 	uint_t				mcg_size, mcg_size_shift;
8139e39c5baSBill Taylor 	int				i, status;
8149e39c5baSBill Taylor 	char				*rsrc_name;
8159e39c5baSBill Taylor 
8169e39c5baSBill Taylor 	ASSERT(state != NULL);
8179e39c5baSBill Taylor 
8189e39c5baSBill Taylor 	/* Phase 2 initialization begins where Phase 1 left off */
8199e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
8209e39c5baSBill Taylor 
8219e39c5baSBill Taylor 	/* Allocate the ICM resource name space */
8229e39c5baSBill Taylor 
8239e39c5baSBill Taylor 	/* Build the ICM vmem arena names from Hermon instance */
82417a2b317SBill Taylor 	rsrc_name = kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
8259e39c5baSBill Taylor 
8269e39c5baSBill Taylor 	/*
8279e39c5baSBill Taylor 	 * Initialize the resource pools for all objects that exist in
8289e39c5baSBill Taylor 	 * context memory (ICM). The ICM consists of context tables, each
8299e39c5baSBill Taylor 	 * type of resource (QP, CQ, EQ, etc) having it's own context table
8309e39c5baSBill Taylor 	 * (QPC, CQC, EQC, etc...).
8319e39c5baSBill Taylor 	 */
8329e39c5baSBill Taylor 	cfgprof = state->hs_cfg_profile;
8339e39c5baSBill Taylor 	devlim	= &state->hs_devlim;
8349e39c5baSBill Taylor 
8359e39c5baSBill Taylor 	/*
8369e39c5baSBill Taylor 	 * Initialize the resource pools for each of the driver resources.
8379e39c5baSBill Taylor 	 * With a few exceptions, these resources fall into the two cateogories
8389e39c5baSBill Taylor 	 * of either hw_entries or sw_entries.
8399e39c5baSBill Taylor 	 */
8409e39c5baSBill Taylor 
8419e39c5baSBill Taylor 	/*
8429e39c5baSBill Taylor 	 * Initialize the resource pools for ICM (hardware) types first.
8439e39c5baSBill Taylor 	 * These resources are managed through vmem arenas, which are
8449e39c5baSBill Taylor 	 * created via the rsrc pool initialization routine. Note that,
8459e39c5baSBill Taylor 	 * due to further calculations, the MCG resource pool is
8469e39c5baSBill Taylor 	 * initialized seperately.
8479e39c5baSBill Taylor 	 */
8489e39c5baSBill Taylor 	for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
8499e39c5baSBill Taylor 
8509e39c5baSBill Taylor 		rsrc_pool = &state->hs_rsrc_hdl[i];
8519e39c5baSBill Taylor 		rsrc_pool->rsrc_type = i;
85217a2b317SBill Taylor 		rsrc_pool->rsrc_state = state;
8539e39c5baSBill Taylor 
8549e39c5baSBill Taylor 		/* Set the resource-specific attributes */
8559e39c5baSBill Taylor 		switch (i) {
8569e39c5baSBill Taylor 		case HERMON_MTT:
8579e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_mtt);
8589e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_mtt);
8599e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_MTT_VMEM);
8609e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL9;
8619e39c5baSBill Taylor 			break;
8629e39c5baSBill Taylor 
8639e39c5baSBill Taylor 		case HERMON_DMPT:
8649e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_dmpt);
8659e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_dmpt);
8669e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_DMPT_VMEM);
8679e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL10;
8689e39c5baSBill Taylor 			break;
8699e39c5baSBill Taylor 
8709e39c5baSBill Taylor 		case HERMON_QPC:
8719e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_qp);
8729e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_qp);
8739e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_QPC_VMEM);
8749e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL11;
8759e39c5baSBill Taylor 			break;
8769e39c5baSBill Taylor 
8779e39c5baSBill Taylor 		case HERMON_CQC:
8789e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_cq);
8799e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_cq);
8809e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_CQC_VMEM);
8819e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL13;
8829e39c5baSBill Taylor 			break;
8839e39c5baSBill Taylor 
8849e39c5baSBill Taylor 		case HERMON_SRQC:
8859e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_srq);
8869e39c5baSBill Taylor 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_srq);
8879e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_SRQC_VMEM);
8889e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL16;
8899e39c5baSBill Taylor 			break;
8909e39c5baSBill Taylor 
8919e39c5baSBill Taylor 		case HERMON_EQC:
8929e39c5baSBill Taylor 			max = ((uint64_t)1 << devlim->log_max_eq);
89317a2b317SBill Taylor 			num_prealloc = state->hs_rsvd_eqs;
8949e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_EQC_VMEM);
8959e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL18;
8969e39c5baSBill Taylor 			break;
8979e39c5baSBill Taylor 
8989e39c5baSBill Taylor 		case HERMON_MCG:	/* handled below */
8999e39c5baSBill Taylor 		case HERMON_AUXC:
9009e39c5baSBill Taylor 		case HERMON_ALTC:
9019e39c5baSBill Taylor 		case HERMON_RDB:
9029e39c5baSBill Taylor 		case HERMON_CMPT_QPC:
9039e39c5baSBill Taylor 		case HERMON_CMPT_SRQC:
9049e39c5baSBill Taylor 		case HERMON_CMPT_CQC:
9059e39c5baSBill Taylor 		case HERMON_CMPT_EQC:
9069e39c5baSBill Taylor 		default:
9079e39c5baSBill Taylor 			/* We don't need to initialize this rsrc here. */
9089e39c5baSBill Taylor 			continue;
9099e39c5baSBill Taylor 		}
9109e39c5baSBill Taylor 
9119e39c5baSBill Taylor 		/* Set the common values for all resource pools */
9129e39c5baSBill Taylor 		rsrc_pool->rsrc_state	  = state;
9139e39c5baSBill Taylor 		rsrc_pool->rsrc_loc	  = HERMON_IN_ICM;
9149e39c5baSBill Taylor 		rsrc_pool->rsrc_pool_size = state->hs_icm[i].table_size;
9159e39c5baSBill Taylor 		rsrc_pool->rsrc_align	  = state->hs_icm[i].table_size;
9169e39c5baSBill Taylor 		rsrc_pool->rsrc_shift	  = state->hs_icm[i].log_object_size;
9179e39c5baSBill Taylor 		rsrc_pool->rsrc_quantum	  = state->hs_icm[i].object_size;
9189e39c5baSBill Taylor 
9199e39c5baSBill Taylor 		/* Now, initialize the entry_info and call the init routine */
9209e39c5baSBill Taylor 		entry_info.hwi_num	  = state->hs_icm[i].num_entries;
9219e39c5baSBill Taylor 		entry_info.hwi_max	  = max;
9229e39c5baSBill Taylor 		entry_info.hwi_prealloc	  = num_prealloc;
9239e39c5baSBill Taylor 		entry_info.hwi_rsrcpool	  = rsrc_pool;
9249e39c5baSBill Taylor 		entry_info.hwi_rsrcname	  = rsrc_name;
9259e39c5baSBill Taylor 		status = hermon_rsrc_hw_entries_init(state, &entry_info);
9269e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
9279e39c5baSBill Taylor 			hermon_rsrc_fini(state, cleanup);
9289e39c5baSBill Taylor 			status = DDI_FAILURE;
9299e39c5baSBill Taylor 			goto rsrcinitp2_fail;
9309e39c5baSBill Taylor 		}
9319e39c5baSBill Taylor 		cleanup = ncleanup;
9329e39c5baSBill Taylor 	}
9339e39c5baSBill Taylor 
9349e39c5baSBill Taylor 	/*
9359e39c5baSBill Taylor 	 * Initialize the Multicast Group (MCG) entries. First, calculate
9369e39c5baSBill Taylor 	 * (and validate) the size of the MCGs.
9379e39c5baSBill Taylor 	 */
9389e39c5baSBill Taylor 	status = hermon_rsrc_mcg_entry_get_size(state, &mcg_size_shift);
9399e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9409e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
9419e39c5baSBill Taylor 		status = DDI_FAILURE;
9429e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9439e39c5baSBill Taylor 	}
9449e39c5baSBill Taylor 	mcg_size = HERMON_MCGMEM_SZ(state);
9459e39c5baSBill Taylor 
9469e39c5baSBill Taylor 	/*
9479e39c5baSBill Taylor 	 * Initialize the resource pool for the MCG table entries.  Notice
9489e39c5baSBill Taylor 	 * that the number of MCGs is configurable. Note also that a certain
9499e39c5baSBill Taylor 	 * number of MCGs must be set aside for Hermon firmware use (they
9509e39c5baSBill Taylor 	 * correspond to the number of MCGs used by the internal hash
9519e39c5baSBill Taylor 	 * function).
9529e39c5baSBill Taylor 	 */
9539e39c5baSBill Taylor 	num			  = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
9549e39c5baSBill Taylor 	max			  = ((uint64_t)1 << devlim->log_max_mcg);
9559e39c5baSBill Taylor 	num_prealloc	  = ((uint64_t)1 << cfgprof->cp_log_num_mcg_hash);
9569e39c5baSBill Taylor 	rsrc_pool		  = &state->hs_rsrc_hdl[HERMON_MCG];
9579e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_ICM;
9589e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (mcg_size * num);
9599e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = mcg_size_shift;
9609e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = mcg_size;
9619e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = (mcg_size * num);
9629e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
9639e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_MCG_VMEM);
9649e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
9659e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
9669e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
9679e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
9689e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
9699e39c5baSBill Taylor 	status = hermon_rsrc_hw_entries_init(state, &entry_info);
9709e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9719e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
9729e39c5baSBill Taylor 		status = DDI_FAILURE;
9739e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9749e39c5baSBill Taylor 	}
9759e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL19;
9769e39c5baSBill Taylor 
9779e39c5baSBill Taylor 	/*
9789e39c5baSBill Taylor 	 * Initialize the full range of ICM for the AUXC resource.
9799e39c5baSBill Taylor 	 * This is done because its size is so small, about 1 byte per QP.
9809e39c5baSBill Taylor 	 */
9819e39c5baSBill Taylor 
9829e39c5baSBill Taylor 	/*
9839e39c5baSBill Taylor 	 * Initialize the Hermon command handling interfaces.  This step
9849e39c5baSBill Taylor 	 * sets up the outstanding command tracking mechanism for easy access
9859e39c5baSBill Taylor 	 * and fast allocation (see hermon_cmd.c for more details).
9869e39c5baSBill Taylor 	 */
9879e39c5baSBill Taylor 	status = hermon_outstanding_cmdlist_init(state);
9889e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
9899e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
9909e39c5baSBill Taylor 		status = DDI_FAILURE;
9919e39c5baSBill Taylor 		goto rsrcinitp2_fail;
9929e39c5baSBill Taylor 	}
9939e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL20;
9949e39c5baSBill Taylor 
9959e39c5baSBill Taylor 	/* Initialize the resource pool and vmem arena for the PD handles */
9969e39c5baSBill Taylor 	rsrc_pool		 = &state->hs_rsrc_hdl[HERMON_PDHDL];
9979e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	 = HERMON_IN_SYSMEM;
9989e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	 = sizeof (struct hermon_sw_pd_s);
9999e39c5baSBill Taylor 	rsrc_pool->rsrc_state	 = state;
10009e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_PDHDL_CACHE);
10019e39c5baSBill Taylor 	hdl_info.swi_num	 = ((uint64_t)1 << cfgprof->cp_log_num_pd);
10029e39c5baSBill Taylor 	hdl_info.swi_max	 = ((uint64_t)1 << devlim->log_max_pd);
10039e39c5baSBill Taylor 	hdl_info.swi_rsrcpool	 = rsrc_pool;
10049e39c5baSBill Taylor 	hdl_info.swi_constructor = hermon_rsrc_pdhdl_constructor;
10059e39c5baSBill Taylor 	hdl_info.swi_destructor	 = hermon_rsrc_pdhdl_destructor;
10069e39c5baSBill Taylor 	hdl_info.swi_rsrcname	 = rsrc_name;
10079e39c5baSBill Taylor 	hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
10089e39c5baSBill Taylor 	status = hermon_rsrc_pd_handles_init(state, &hdl_info);
10099e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
10109e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
10119e39c5baSBill Taylor 		status = DDI_FAILURE;
10129e39c5baSBill Taylor 		goto rsrcinitp2_fail;
10139e39c5baSBill Taylor 	}
10149e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL21;
10159e39c5baSBill Taylor 
10169e39c5baSBill Taylor 	/*
10179e39c5baSBill Taylor 	 * Initialize the resource pools for the rest of the software handles.
10189e39c5baSBill Taylor 	 * This includes MR handles, EQ handles, QP handles, etc.  These
10199e39c5baSBill Taylor 	 * objects are almost entirely managed using kmem_cache routines,
10209e39c5baSBill Taylor 	 * and do not utilize a vmem arena.
10219e39c5baSBill Taylor 	 */
10229e39c5baSBill Taylor 	for (i = HERMON_NUM_ICM_RESOURCES; i < HERMON_NUM_RESOURCES; i++) {
10239e39c5baSBill Taylor 		rsrc_pool = &state->hs_rsrc_hdl[i];
102417a2b317SBill Taylor 		rsrc_pool->rsrc_type = i;
10259e39c5baSBill Taylor 
10269e39c5baSBill Taylor 		/* Set the resource-specific attributes */
10279e39c5baSBill Taylor 		switch (i) {
10289e39c5baSBill Taylor 		case HERMON_MRHDL:
10299e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
10309e39c5baSBill Taylor 			    sizeof (struct hermon_sw_mr_s);
10319e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_MRHDL_CACHE);
10329e39c5baSBill Taylor 			hdl_info.swi_num =
10339e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
10349e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_cmpt);
10359e39c5baSBill Taylor 			hdl_info.swi_max =
10369e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
10379e39c5baSBill Taylor 			    ((uint64_t)1 << cfgprof->cp_log_num_cmpt);
10389e39c5baSBill Taylor 			hdl_info.swi_constructor =
10399e39c5baSBill Taylor 			    hermon_rsrc_mrhdl_constructor;
10409e39c5baSBill Taylor 			hdl_info.swi_destructor	 = hermon_rsrc_mrhdl_destructor;
10419e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
10429e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL22;
10439e39c5baSBill Taylor 			break;
10449e39c5baSBill Taylor 
10459e39c5baSBill Taylor 		case HERMON_EQHDL:
10469e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
10479e39c5baSBill Taylor 			    sizeof (struct hermon_sw_eq_s);
10489e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_EQHDL_CACHE);
10499e39c5baSBill Taylor 			hdl_info.swi_num = HERMON_NUM_EQ;
10509e39c5baSBill Taylor 			hdl_info.swi_max = ((uint64_t)1 << devlim->log_max_eq);
10519e39c5baSBill Taylor 			hdl_info.swi_constructor = NULL;
10529e39c5baSBill Taylor 			hdl_info.swi_destructor	 = NULL;
10539e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
10549e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL23;
10559e39c5baSBill Taylor 			break;
10569e39c5baSBill Taylor 
10579e39c5baSBill Taylor 		case HERMON_CQHDL:
10589e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
10599e39c5baSBill Taylor 			    sizeof (struct hermon_sw_cq_s);
10609e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_CQHDL_CACHE);
10619e39c5baSBill Taylor 			hdl_info.swi_num =
10629e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_cq;
10639e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_cq;
10649e39c5baSBill Taylor 			hdl_info.swi_constructor =
10659e39c5baSBill Taylor 			    hermon_rsrc_cqhdl_constructor;
10669e39c5baSBill Taylor 			hdl_info.swi_destructor	 = hermon_rsrc_cqhdl_destructor;
106717a2b317SBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
10689e39c5baSBill Taylor 			hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
10699e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL24;
10709e39c5baSBill Taylor 			break;
10719e39c5baSBill Taylor 
10729e39c5baSBill Taylor 		case HERMON_SRQHDL:
10739e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
10749e39c5baSBill Taylor 			    sizeof (struct hermon_sw_srq_s);
10759e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_SRQHDL_CACHE);
10769e39c5baSBill Taylor 			hdl_info.swi_num =
10779e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_srq;
10789e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_srq;
10799e39c5baSBill Taylor 			hdl_info.swi_constructor =
10809e39c5baSBill Taylor 			    hermon_rsrc_srqhdl_constructor;
10819e39c5baSBill Taylor 			hdl_info.swi_destructor = hermon_rsrc_srqhdl_destructor;
108217a2b317SBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
10839e39c5baSBill Taylor 			hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
10849e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL25;
10859e39c5baSBill Taylor 			break;
10869e39c5baSBill Taylor 
10879e39c5baSBill Taylor 		case HERMON_AHHDL:
10889e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum	=
10899e39c5baSBill Taylor 			    sizeof (struct hermon_sw_ah_s);
10909e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_AHHDL_CACHE);
10919e39c5baSBill Taylor 			hdl_info.swi_num =
10929e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_ah;
10939e39c5baSBill Taylor 			hdl_info.swi_max = HERMON_NUM_AH;
10949e39c5baSBill Taylor 			hdl_info.swi_constructor =
10959e39c5baSBill Taylor 			    hermon_rsrc_ahhdl_constructor;
10969e39c5baSBill Taylor 			hdl_info.swi_destructor	 = hermon_rsrc_ahhdl_destructor;
10979e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
10989e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL26;
10999e39c5baSBill Taylor 			break;
11009e39c5baSBill Taylor 
11019e39c5baSBill Taylor 		case HERMON_QPHDL:
11029e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum =
11039e39c5baSBill Taylor 			    sizeof (struct hermon_sw_qp_s);
11049e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_QPHDL_CACHE);
11059e39c5baSBill Taylor 			hdl_info.swi_num =
11069e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_qp;
11079e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_qp;
11089e39c5baSBill Taylor 			hdl_info.swi_constructor =
11099e39c5baSBill Taylor 			    hermon_rsrc_qphdl_constructor;
11109e39c5baSBill Taylor 			hdl_info.swi_destructor	= hermon_rsrc_qphdl_destructor;
111117a2b317SBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
11129e39c5baSBill Taylor 			hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
11139e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL27;
11149e39c5baSBill Taylor 			break;
11159e39c5baSBill Taylor 
11169e39c5baSBill Taylor 		case HERMON_REFCNT:
11179e39c5baSBill Taylor 			rsrc_pool->rsrc_quantum	 = sizeof (hermon_sw_refcnt_t);
11189e39c5baSBill Taylor 			HERMON_RSRC_NAME(rsrc_name, HERMON_REFCNT_CACHE);
11199e39c5baSBill Taylor 			hdl_info.swi_num =
11209e39c5baSBill Taylor 			    (uint64_t)1 << cfgprof->cp_log_num_dmpt;
11219e39c5baSBill Taylor 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_dmpt;
11229e39c5baSBill Taylor 			hdl_info.swi_constructor =
11239e39c5baSBill Taylor 			    hermon_rsrc_refcnt_constructor;
11249e39c5baSBill Taylor 			hdl_info.swi_destructor = hermon_rsrc_refcnt_destructor;
11259e39c5baSBill Taylor 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
11269e39c5baSBill Taylor 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL28;
11279e39c5baSBill Taylor 			break;
11289e39c5baSBill Taylor 
11299e39c5baSBill Taylor 		default:
11309e39c5baSBill Taylor 			continue;
11319e39c5baSBill Taylor 		}
11329e39c5baSBill Taylor 
11339e39c5baSBill Taylor 		/* Set the common values and call the init routine */
11349e39c5baSBill Taylor 		rsrc_pool->rsrc_loc	 = HERMON_IN_SYSMEM;
11359e39c5baSBill Taylor 		rsrc_pool->rsrc_state    = state;
11369e39c5baSBill Taylor 		hdl_info.swi_rsrcpool    = rsrc_pool;
11379e39c5baSBill Taylor 		hdl_info.swi_rsrcname    = rsrc_name;
11389e39c5baSBill Taylor 		status = hermon_rsrc_sw_handles_init(state, &hdl_info);
11399e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
11409e39c5baSBill Taylor 			hermon_rsrc_fini(state, cleanup);
11419e39c5baSBill Taylor 			status = DDI_FAILURE;
11429e39c5baSBill Taylor 			goto rsrcinitp2_fail;
11439e39c5baSBill Taylor 		}
11449e39c5baSBill Taylor 		cleanup = ncleanup;
11459e39c5baSBill Taylor 	}
11469e39c5baSBill Taylor 
11479e39c5baSBill Taylor 	/*
11489e39c5baSBill Taylor 	 * Initialize a resource pool for the MCG handles.  Notice that for
11499e39c5baSBill Taylor 	 * these MCG handles, we are allocating a table of structures (used to
11509e39c5baSBill Taylor 	 * keep track of the MCG entries that are being written to hardware
11519e39c5baSBill Taylor 	 * and to speed up multicast attach/detach operations).
11529e39c5baSBill Taylor 	 */
11539e39c5baSBill Taylor 	hdl_info.swi_num	 = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
11549e39c5baSBill Taylor 	hdl_info.swi_max	 = ((uint64_t)1 << devlim->log_max_mcg);
11559e39c5baSBill Taylor 	hdl_info.swi_flags	 = HERMON_SWHDL_TABLE_INIT;
11569e39c5baSBill Taylor 	hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
11579e39c5baSBill Taylor 	status = hermon_rsrc_sw_handles_init(state, &hdl_info);
11589e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
11599e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
11609e39c5baSBill Taylor 		status = DDI_FAILURE;
11619e39c5baSBill Taylor 		goto rsrcinitp2_fail;
11629e39c5baSBill Taylor 	}
11639e39c5baSBill Taylor 	state->hs_mcghdl = hdl_info.swi_table_ptr;
11649e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_LEVEL29;
11659e39c5baSBill Taylor 
11669e39c5baSBill Taylor 	/*
11679e39c5baSBill Taylor 	 * Last, initialize the resource pool for the UAR pages, which contain
11689e39c5baSBill Taylor 	 * the hardware's doorbell registers. Each process supported in User
11699e39c5baSBill Taylor 	 * Mode is assigned a UAR page. Also coming from this pool are the
11709e39c5baSBill Taylor 	 * kernel-assigned UAR page, and any hardware-reserved pages. Note
11719e39c5baSBill Taylor 	 * that the number of UAR pages is configurable, the value must be less
11729e39c5baSBill Taylor 	 * than the maximum value (obtained from the QUERY_DEV_LIM command) or
11739e39c5baSBill Taylor 	 * the initialization will fail.  Note also that we assign the base
11749e39c5baSBill Taylor 	 * address of the UAR BAR to the rsrc_start parameter.
11759e39c5baSBill Taylor 	 */
11769e39c5baSBill Taylor 	num			  = ((uint64_t)1 << cfgprof->cp_log_num_uar);
11779e39c5baSBill Taylor 	max			  = num;
11789e39c5baSBill Taylor 	num_prealloc		  = max(devlim->num_rsvd_uar, 128);
11799e39c5baSBill Taylor 	rsrc_pool		  = &state->hs_rsrc_hdl[HERMON_UARPG];
11809e39c5baSBill Taylor 	rsrc_pool->rsrc_loc	  = HERMON_IN_UAR;
11819e39c5baSBill Taylor 	rsrc_pool->rsrc_pool_size = (num << PAGESHIFT);
11829e39c5baSBill Taylor 	rsrc_pool->rsrc_shift	  = PAGESHIFT;
11839e39c5baSBill Taylor 	rsrc_pool->rsrc_quantum	  = (uint_t)PAGESIZE;
11849e39c5baSBill Taylor 	rsrc_pool->rsrc_align	  = PAGESIZE;
11859e39c5baSBill Taylor 	rsrc_pool->rsrc_state	  = state;
11869e39c5baSBill Taylor 	rsrc_pool->rsrc_start	  = (void *)state->hs_reg_uar_baseaddr;
11879e39c5baSBill Taylor 	HERMON_RSRC_NAME(rsrc_name, HERMON_UAR_PAGE_VMEM_ATTCH);
11889e39c5baSBill Taylor 	entry_info.hwi_num	  = num;
11899e39c5baSBill Taylor 	entry_info.hwi_max	  = max;
11909e39c5baSBill Taylor 	entry_info.hwi_prealloc	  = num_prealloc;
11919e39c5baSBill Taylor 	entry_info.hwi_rsrcpool	  = rsrc_pool;
11929e39c5baSBill Taylor 	entry_info.hwi_rsrcname	  = rsrc_name;
11939e39c5baSBill Taylor 	status = hermon_rsrc_hw_entries_init(state, &entry_info);
11949e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
11959e39c5baSBill Taylor 		hermon_rsrc_fini(state, cleanup);
11969e39c5baSBill Taylor 		status = DDI_FAILURE;
11979e39c5baSBill Taylor 		goto rsrcinitp2_fail;
11989e39c5baSBill Taylor 	}
11999e39c5baSBill Taylor 
12009e39c5baSBill Taylor 	cleanup = HERMON_RSRC_CLEANUP_ALL;
12019e39c5baSBill Taylor 
12029e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
12039e39c5baSBill Taylor 	return (DDI_SUCCESS);
12049e39c5baSBill Taylor 
12059e39c5baSBill Taylor rsrcinitp2_fail:
12069e39c5baSBill Taylor 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
12079e39c5baSBill Taylor 	return (status);
12089e39c5baSBill Taylor }
12099e39c5baSBill Taylor 
12109e39c5baSBill Taylor 
12119e39c5baSBill Taylor /*
12129e39c5baSBill Taylor  * hermon_rsrc_fini()
12139e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
12149e39c5baSBill Taylor  */
12159e39c5baSBill Taylor void
hermon_rsrc_fini(hermon_state_t * state,hermon_rsrc_cleanup_level_t clean)12169e39c5baSBill Taylor hermon_rsrc_fini(hermon_state_t *state, hermon_rsrc_cleanup_level_t clean)
12179e39c5baSBill Taylor {
12189e39c5baSBill Taylor 	hermon_rsrc_sw_hdl_info_t	hdl_info;
12199e39c5baSBill Taylor 	hermon_rsrc_hw_entry_info_t	entry_info;
12209e39c5baSBill Taylor 	hermon_rsrc_mbox_info_t		mbox_info;
12219e39c5baSBill Taylor 	hermon_cfg_profile_t		*cfgprof;
12229e39c5baSBill Taylor 
12239e39c5baSBill Taylor 	ASSERT(state != NULL);
12249e39c5baSBill Taylor 
12259e39c5baSBill Taylor 	cfgprof = state->hs_cfg_profile;
12269e39c5baSBill Taylor 
12279e39c5baSBill Taylor 	/*
12289e39c5baSBill Taylor 	 * If init code above is shortened up (see comments), then we
12299e39c5baSBill Taylor 	 * need to establish how to safely and simply clean up from any
12309e39c5baSBill Taylor 	 * given failure point. Flags, maybe...
12319e39c5baSBill Taylor 	 */
12329e39c5baSBill Taylor 
12339e39c5baSBill Taylor 	switch (clean) {
12349e39c5baSBill Taylor 	/*
12359e39c5baSBill Taylor 	 * If we add more resources that need to be cleaned up here, we should
12369e39c5baSBill Taylor 	 * ensure that HERMON_RSRC_CLEANUP_ALL is still the first entry (i.e.
12379e39c5baSBill Taylor 	 * corresponds to the last resource allocated).
12389e39c5baSBill Taylor 	 */
12399e39c5baSBill Taylor 
12409e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_ALL:
12419e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL31:
12429e39c5baSBill Taylor 		/* Cleanup the UAR page resource pool, first the dbr pages */
12439e39c5baSBill Taylor 		if (state->hs_kern_dbr) {
12449e39c5baSBill Taylor 			hermon_dbr_kern_free(state);
12459e39c5baSBill Taylor 			state->hs_kern_dbr = NULL;
12469e39c5baSBill Taylor 		}
12479e39c5baSBill Taylor 
12489e39c5baSBill Taylor 		/* NS then, the pool itself */
12499e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_UARPG];
12509e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
12519e39c5baSBill Taylor 
12529e39c5baSBill Taylor 		/* FALLTHROUGH */
12539e39c5baSBill Taylor 
12549e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL30:
12559e39c5baSBill Taylor 		/* Cleanup the central MCG handle pointers list */
12569e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = NULL;
12579e39c5baSBill Taylor 		hdl_info.swi_table_ptr = state->hs_mcghdl;
12589e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
12599e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
12609e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
12619e39c5baSBill Taylor 		/* FALLTHROUGH */
12629e39c5baSBill Taylor 
12639e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL29:
12649e39c5baSBill Taylor 		/* Cleanup the reference count resource pool */
12659e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_REFCNT];
12669e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
12679e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
12689e39c5baSBill Taylor 		/* FALLTHROUGH */
12699e39c5baSBill Taylor 
12709e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL28:
12719e39c5baSBill Taylor 		/* Cleanup the QP handle resource pool */
12729e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_QPHDL];
127317a2b317SBill Taylor 		hdl_info.swi_table_ptr = NULL;
12749e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
12759e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
12769e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
12779e39c5baSBill Taylor 		/* FALLTHROUGH */
12789e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL27:
12799e39c5baSBill Taylor 		/* Cleanup the address handle resrouce pool */
12809e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_AHHDL];
12819e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
12829e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
12839e39c5baSBill Taylor 		/* FALLTHROUGH */
12849e39c5baSBill Taylor 
12859e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL26:
12869e39c5baSBill Taylor 		/* Cleanup the SRQ handle resource pool. */
12879e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_SRQHDL];
128817a2b317SBill Taylor 		hdl_info.swi_table_ptr = NULL;
12899e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
12909e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
12919e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
12929e39c5baSBill Taylor 		/* FALLTHROUGH */
12939e39c5baSBill Taylor 
12949e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL25:
12959e39c5baSBill Taylor 		/* Cleanup the CQ handle resource pool */
12969e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_CQHDL];
129717a2b317SBill Taylor 		hdl_info.swi_table_ptr = NULL;
12989e39c5baSBill Taylor 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
12999e39c5baSBill Taylor 		hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
13009e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
13019e39c5baSBill Taylor 		/* FALLTHROUGH */
13029e39c5baSBill Taylor 
13039e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL24:
13049e39c5baSBill Taylor 		/* Cleanup the EQ handle resource pool */
13059e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_EQHDL];
13069e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
13079e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
13089e39c5baSBill Taylor 		/* FALLTHROUGH */
13099e39c5baSBill Taylor 
13109e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL23:
13119e39c5baSBill Taylor 		/* Cleanup the MR handle resource pool */
13129e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_MRHDL];
13139e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
13149e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
13159e39c5baSBill Taylor 		/* FALLTHROUGH */
13169e39c5baSBill Taylor 
13179e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL22:
13189e39c5baSBill Taylor 		/* Cleanup the PD handle resource pool */
13199e39c5baSBill Taylor 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_PDHDL];
13209e39c5baSBill Taylor 		hdl_info.swi_table_ptr = NULL;
13219e39c5baSBill Taylor 		hermon_rsrc_pd_handles_fini(state, &hdl_info);
13229e39c5baSBill Taylor 		/* FALLTHROUGH */
13239e39c5baSBill Taylor 
13249e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL21:
13259e39c5baSBill Taylor 		/* Currently unused - FALLTHROUGH */
13269e39c5baSBill Taylor 
13279e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL20:
13289e39c5baSBill Taylor 		/* Cleanup the outstanding command list  */
13299e39c5baSBill Taylor 		hermon_outstanding_cmdlist_fini(state);
13309e39c5baSBill Taylor 		/* FALLTHROUGH */
13319e39c5baSBill Taylor 
13329e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL19:
13339e39c5baSBill Taylor 		/* Cleanup the EQC table resource pool */
13349e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_EQC];
13359e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13369e39c5baSBill Taylor 		/* FALLTHROUGH */
13379e39c5baSBill Taylor 
13389e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL18:
13399e39c5baSBill Taylor 		/* Cleanup the MCG table resource pool */
13409e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MCG];
13419e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13429e39c5baSBill Taylor 		/* FALLTHROUGH */
13439e39c5baSBill Taylor 
13449e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL17:
13459e39c5baSBill Taylor 		/* Currently Unused - fallthrough */
13469e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL16:
13479e39c5baSBill Taylor 		/* Cleanup the SRQC table resource pool */
13489e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_SRQC];
13499e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13509e39c5baSBill Taylor 		/* FALLTHROUGH */
13519e39c5baSBill Taylor 
13529e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL15:
13539e39c5baSBill Taylor 		/* Cleanup the AUXC table resource pool */
13549e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_AUXC];
13559e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13569e39c5baSBill Taylor 		/* FALLTHROUGH */
13579e39c5baSBill Taylor 
13589e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL14:
13599e39c5baSBill Taylor 		/* Cleanup the ALTCF table resource pool */
13609e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_ALTC];
13619e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13629e39c5baSBill Taylor 		/* FALLTHROUGH */
13639e39c5baSBill Taylor 
13649e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL13:
13659e39c5baSBill Taylor 		/* Cleanup the CQC table resource pool */
13669e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CQC];
13679e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13689e39c5baSBill Taylor 		/* FALLTHROUGH */
13699e39c5baSBill Taylor 
13709e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL12:
13719e39c5baSBill Taylor 		/* Cleanup the RDB table resource pool */
13729e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_RDB];
13739e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13749e39c5baSBill Taylor 		/* FALLTHROUGH */
13759e39c5baSBill Taylor 
13769e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL11:
13779e39c5baSBill Taylor 		/* Cleanup the QPC table resource pool */
13789e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_QPC];
13799e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13809e39c5baSBill Taylor 		/* FALLTHROUGH */
13819e39c5baSBill Taylor 
13829e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10EQ:
13839e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
13849e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_EQC];
13859e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13869e39c5baSBill Taylor 		/* FALLTHROUGH */
13879e39c5baSBill Taylor 
13889e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10CQ:
13899e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
13909e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_CQC];
13919e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13929e39c5baSBill Taylor 		/* FALLTHROUGH */
13939e39c5baSBill Taylor 
13949e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10SRQ:
13959e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
13969e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_SRQC];
13979e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
13989e39c5baSBill Taylor 		/* FALLTHROUGH */
13999e39c5baSBill Taylor 
14009e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10QP:
14019e39c5baSBill Taylor 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
14029e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_QPC];
14039e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
14049e39c5baSBill Taylor 		/* FALLTHROUGH */
14059e39c5baSBill Taylor 
14069e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL10:
14079e39c5baSBill Taylor 		/* Cleanup the dMPT table resource pool */
14089e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_DMPT];
14099e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
14109e39c5baSBill Taylor 		/* FALLTHROUGH */
14119e39c5baSBill Taylor 
14129e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL9:
14139e39c5baSBill Taylor 		/* Cleanup the MTT table resource pool */
14149e39c5baSBill Taylor 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MTT];
14159e39c5baSBill Taylor 		hermon_rsrc_hw_entries_fini(state, &entry_info);
14169e39c5baSBill Taylor 		break;
14179e39c5baSBill Taylor 
14189e39c5baSBill Taylor 	/*
14199e39c5baSBill Taylor 	 * The cleanup below comes from the "Phase 1" initialization step.
14209e39c5baSBill Taylor 	 * (see hermon_rsrc_init_phase1() above)
14219e39c5baSBill Taylor 	 */
14229e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_PHASE1_COMPLETE:
14239e39c5baSBill Taylor 		/* Cleanup the "In" mailbox list  */
14249e39c5baSBill Taylor 		hermon_intr_inmbox_list_fini(state);
14259e39c5baSBill Taylor 		/* FALLTHROUGH */
14269e39c5baSBill Taylor 
14279e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL7:
14289e39c5baSBill Taylor 		/* Cleanup the interrupt "In" mailbox resource pool */
14299e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool =
14309e39c5baSBill Taylor 		    &state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
14319e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
14329e39c5baSBill Taylor 		/* FALLTHROUGH */
14339e39c5baSBill Taylor 
14349e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL6:
14359e39c5baSBill Taylor 		/* Cleanup the "In" mailbox list  */
14369e39c5baSBill Taylor 		hermon_inmbox_list_fini(state);
14379e39c5baSBill Taylor 		/* FALLTHROUGH */
14389e39c5baSBill Taylor 
14399e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL5:
14409e39c5baSBill Taylor 		/* Cleanup the "In" mailbox resource pool */
14419e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
14429e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
14439e39c5baSBill Taylor 		/* FALLTHROUGH */
14449e39c5baSBill Taylor 
14459e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL4:
14469e39c5baSBill Taylor 		/* Cleanup the interrupt "Out" mailbox list  */
14479e39c5baSBill Taylor 		hermon_intr_outmbox_list_fini(state);
14489e39c5baSBill Taylor 		/* FALLTHROUGH */
14499e39c5baSBill Taylor 
14509e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL3:
14519e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox resource pool */
14529e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool =
14539e39c5baSBill Taylor 		    &state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
14549e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
14559e39c5baSBill Taylor 		/* FALLTHROUGH */
14569e39c5baSBill Taylor 
14579e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL2:
14589e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox list  */
14599e39c5baSBill Taylor 		hermon_outmbox_list_fini(state);
14609e39c5baSBill Taylor 		/* FALLTHROUGH */
14619e39c5baSBill Taylor 
14629e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL1:
14639e39c5baSBill Taylor 		/* Cleanup the "Out" mailbox resource pool */
14649e39c5baSBill Taylor 		mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
14659e39c5baSBill Taylor 		hermon_rsrc_mbox_fini(state, &mbox_info);
14669e39c5baSBill Taylor 		/* FALLTHROUGH */
14679e39c5baSBill Taylor 
14689e39c5baSBill Taylor 	case HERMON_RSRC_CLEANUP_LEVEL0:
14699e39c5baSBill Taylor 		/* Free the array of hermon_rsrc_pool_info_t's */
14709e39c5baSBill Taylor 
14719e39c5baSBill Taylor 		kmem_free(state->hs_rsrc_hdl, HERMON_NUM_RESOURCES *
14729e39c5baSBill Taylor 		    sizeof (hermon_rsrc_pool_info_t));
14739e39c5baSBill Taylor 
14749e39c5baSBill Taylor 		kmem_cache_destroy(state->hs_rsrc_cache);
14759e39c5baSBill Taylor 		break;
14769e39c5baSBill Taylor 
14779e39c5baSBill Taylor 	default:
14789e39c5baSBill Taylor 		HERMON_WARNING(state, "unexpected resource cleanup level");
14799e39c5baSBill Taylor 		break;
14809e39c5baSBill Taylor 	}
14819e39c5baSBill Taylor }
14829e39c5baSBill Taylor 
14839e39c5baSBill Taylor 
14849e39c5baSBill Taylor /*
14859e39c5baSBill Taylor  * hermon_rsrc_mbox_init()
14869e39c5baSBill Taylor  *    Context: Only called from attach() path context
14879e39c5baSBill Taylor  */
14889e39c5baSBill Taylor static int
hermon_rsrc_mbox_init(hermon_state_t * state,hermon_rsrc_mbox_info_t * info)14899e39c5baSBill Taylor hermon_rsrc_mbox_init(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
14909e39c5baSBill Taylor {
14919e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
14929e39c5baSBill Taylor 	hermon_rsrc_priv_mbox_t	*priv;
14939e39c5baSBill Taylor 
14949e39c5baSBill Taylor 	ASSERT(state != NULL);
14959e39c5baSBill Taylor 	ASSERT(info != NULL);
14969e39c5baSBill Taylor 
14979e39c5baSBill Taylor 	rsrc_pool = info->mbi_rsrcpool;
14989e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
14999e39c5baSBill Taylor 
15009e39c5baSBill Taylor 	/* Allocate and initialize mailbox private structure */
15019e39c5baSBill Taylor 	priv = kmem_zalloc(sizeof (hermon_rsrc_priv_mbox_t), KM_SLEEP);
15029e39c5baSBill Taylor 	priv->pmb_dip		= state->hs_dip;
15039e39c5baSBill Taylor 	priv->pmb_devaccattr	= state->hs_reg_accattr;
15049e39c5baSBill Taylor 	priv->pmb_xfer_mode	= DDI_DMA_CONSISTENT;
15059e39c5baSBill Taylor 
15069e39c5baSBill Taylor 	/*
15079e39c5baSBill Taylor 	 * Initialize many of the default DMA attributes.  Then set alignment
15089e39c5baSBill Taylor 	 * and scatter-gather restrictions specific for mailbox memory.
15099e39c5baSBill Taylor 	 */
15109e39c5baSBill Taylor 	hermon_dma_attr_init(state, &priv->pmb_dmaattr);
15119e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_align  = HERMON_MBOX_ALIGN;
15129e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_sgllen = 1;
15139e39c5baSBill Taylor 	priv->pmb_dmaattr.dma_attr_flags = 0;
15149e39c5baSBill Taylor 	rsrc_pool->rsrc_private = priv;
15159e39c5baSBill Taylor 
15169e39c5baSBill Taylor 	ASSERT(rsrc_pool->rsrc_loc == HERMON_IN_SYSMEM);
15179e39c5baSBill Taylor 
15189e39c5baSBill Taylor 	rsrc_pool->rsrc_start = NULL;
15199e39c5baSBill Taylor 	rsrc_pool->rsrc_vmp = NULL;
15209e39c5baSBill Taylor 
15219e39c5baSBill Taylor 	return (DDI_SUCCESS);
15229e39c5baSBill Taylor }
15239e39c5baSBill Taylor 
15249e39c5baSBill Taylor 
15259e39c5baSBill Taylor /*
15269e39c5baSBill Taylor  * hermon_rsrc_mbox_fini()
15279e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
15289e39c5baSBill Taylor  */
15299e39c5baSBill Taylor /* ARGSUSED */
15309e39c5baSBill Taylor static void
hermon_rsrc_mbox_fini(hermon_state_t * state,hermon_rsrc_mbox_info_t * info)15319e39c5baSBill Taylor hermon_rsrc_mbox_fini(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
15329e39c5baSBill Taylor {
15339e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
15349e39c5baSBill Taylor 
15359e39c5baSBill Taylor 	ASSERT(state != NULL);
15369e39c5baSBill Taylor 	ASSERT(info != NULL);
15379e39c5baSBill Taylor 
15389e39c5baSBill Taylor 	rsrc_pool = info->mbi_rsrcpool;
15399e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
15409e39c5baSBill Taylor 
15419e39c5baSBill Taylor 	/* Free up the private struct */
15429e39c5baSBill Taylor 	kmem_free(rsrc_pool->rsrc_private, sizeof (hermon_rsrc_priv_mbox_t));
15439e39c5baSBill Taylor }
15449e39c5baSBill Taylor 
15459e39c5baSBill Taylor 
15469e39c5baSBill Taylor /*
15479e39c5baSBill Taylor  * hermon_rsrc_hw_entries_init()
15489e39c5baSBill Taylor  *    Context: Only called from attach() path context
15499e39c5baSBill Taylor  */
15509e39c5baSBill Taylor int
hermon_rsrc_hw_entries_init(hermon_state_t * state,hermon_rsrc_hw_entry_info_t * info)15519e39c5baSBill Taylor hermon_rsrc_hw_entries_init(hermon_state_t *state,
15529e39c5baSBill Taylor     hermon_rsrc_hw_entry_info_t *info)
15539e39c5baSBill Taylor {
15549e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
15559e39c5baSBill Taylor 	hermon_rsrc_t		*rsvd_rsrc = NULL;
15569e39c5baSBill Taylor 	vmem_t			*vmp;
15579e39c5baSBill Taylor 	uint64_t		num_hwentry, max_hwentry, num_prealloc;
15589e39c5baSBill Taylor 	int			status;
15599e39c5baSBill Taylor 
15609e39c5baSBill Taylor 	ASSERT(state != NULL);
15619e39c5baSBill Taylor 	ASSERT(info != NULL);
15629e39c5baSBill Taylor 
15639e39c5baSBill Taylor 	rsrc_pool	= info->hwi_rsrcpool;
15649e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
15659e39c5baSBill Taylor 	num_hwentry	= info->hwi_num;
15669e39c5baSBill Taylor 	max_hwentry	= info->hwi_max;
15679e39c5baSBill Taylor 	num_prealloc	= info->hwi_prealloc;
15689e39c5baSBill Taylor 
15699e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
15709e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init: "
15719e39c5baSBill Taylor 		    "rsrc_type (0x%x) num (%llx) max (0x%llx) prealloc "
15729e39c5baSBill Taylor 		    "(0x%llx)", rsrc_pool->rsrc_type, (longlong_t)num_hwentry,
15739e39c5baSBill Taylor 		    (longlong_t)max_hwentry, (longlong_t)num_prealloc);
15749e39c5baSBill Taylor 	}
15759e39c5baSBill Taylor 
15769e39c5baSBill Taylor 	/* Make sure number of HW entries makes sense */
15779e39c5baSBill Taylor 	if (num_hwentry > max_hwentry) {
15789e39c5baSBill Taylor 		return (DDI_FAILURE);
15799e39c5baSBill Taylor 	}
15809e39c5baSBill Taylor 
15819e39c5baSBill Taylor 	/* Set this pool's rsrc_start from the initial ICM allocation */
15829e39c5baSBill Taylor 	if (rsrc_pool->rsrc_start == 0) {
1583c7facc54SBill Taylor 
1584c7facc54SBill Taylor 		/* use a ROUND value that works on both 32 and 64-bit kernels */
1585c7facc54SBill Taylor 		rsrc_pool->rsrc_start = (void *)(uintptr_t)0x10000000;
15869e39c5baSBill Taylor 
15879e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
15889e39c5baSBill Taylor 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
15899e39c5baSBill Taylor 			    " rsrc_type (0x%x) rsrc_start set (0x%lx)",
15909e39c5baSBill Taylor 			    rsrc_pool->rsrc_type, rsrc_pool->rsrc_start);
15919e39c5baSBill Taylor 		}
15929e39c5baSBill Taylor 	}
15939e39c5baSBill Taylor 
15949e39c5baSBill Taylor 	/*
15959e39c5baSBill Taylor 	 * Create new vmem arena for the HW entries table if rsrc_quantum
15969e39c5baSBill Taylor 	 * is non-zero.  Otherwise if rsrc_quantum is zero, then these HW
15979e39c5baSBill Taylor 	 * entries are not going to be dynamically allocatable (i.e. they
15989e39c5baSBill Taylor 	 * won't be allocated/freed through hermon_rsrc_alloc/free).  This
15999e39c5baSBill Taylor 	 * latter option is used for both ALTC and CMPT resources which
16009e39c5baSBill Taylor 	 * are managed by hardware.
16019e39c5baSBill Taylor 	 */
16029e39c5baSBill Taylor 	if (rsrc_pool->rsrc_quantum != 0) {
16039e39c5baSBill Taylor 		vmp = vmem_create(info->hwi_rsrcname,
16049e39c5baSBill Taylor 		    (void *)(uintptr_t)rsrc_pool->rsrc_start,
16059e39c5baSBill Taylor 		    rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_quantum,
16069e39c5baSBill Taylor 		    NULL, NULL, NULL, 0, VM_SLEEP);
16079e39c5baSBill Taylor 		if (vmp == NULL) {
16089e39c5baSBill Taylor 			/* failed to create vmem arena */
16099e39c5baSBill Taylor 			return (DDI_FAILURE);
16109e39c5baSBill Taylor 		}
16119e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = vmp;
16129e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
16139e39c5baSBill Taylor 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
16149e39c5baSBill Taylor 			    " rsrc_type (0x%x) created vmem arena for rsrc",
16159e39c5baSBill Taylor 			    rsrc_pool->rsrc_type);
16169e39c5baSBill Taylor 		}
16179e39c5baSBill Taylor 	} else {
16189e39c5baSBill Taylor 		/* we do not require a vmem arena */
16199e39c5baSBill Taylor 		rsrc_pool->rsrc_vmp = NULL;
16209e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
16219e39c5baSBill Taylor 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
16229e39c5baSBill Taylor 			    " rsrc_type (0x%x) vmem arena not required",
16239e39c5baSBill Taylor 			    rsrc_pool->rsrc_type);
16249e39c5baSBill Taylor 		}
16259e39c5baSBill Taylor 	}
16269e39c5baSBill Taylor 
16279e39c5baSBill Taylor 	/* Allocate hardware reserved resources, if any */
16289e39c5baSBill Taylor 	if (num_prealloc != 0) {
16299e39c5baSBill Taylor 		status = hermon_rsrc_alloc(state, rsrc_pool->rsrc_type,
16309e39c5baSBill Taylor 		    num_prealloc, HERMON_SLEEP, &rsvd_rsrc);
16319e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
16329e39c5baSBill Taylor 			/* unable to preallocate the reserved entries */
16339e39c5baSBill Taylor 			if (rsrc_pool->rsrc_vmp != NULL) {
16349e39c5baSBill Taylor 				vmem_destroy(rsrc_pool->rsrc_vmp);
16359e39c5baSBill Taylor 			}
16369e39c5baSBill Taylor 			return (DDI_FAILURE);
16379e39c5baSBill Taylor 		}
16389e39c5baSBill Taylor 	}
16399e39c5baSBill Taylor 	rsrc_pool->rsrc_private = rsvd_rsrc;
16409e39c5baSBill Taylor 
16419e39c5baSBill Taylor 	return (DDI_SUCCESS);
16429e39c5baSBill Taylor }
16439e39c5baSBill Taylor 
16449e39c5baSBill Taylor 
16459e39c5baSBill Taylor /*
16469e39c5baSBill Taylor  * hermon_rsrc_hw_entries_fini()
16479e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
16489e39c5baSBill Taylor  */
16499e39c5baSBill Taylor void
hermon_rsrc_hw_entries_fini(hermon_state_t * state,hermon_rsrc_hw_entry_info_t * info)16509e39c5baSBill Taylor hermon_rsrc_hw_entries_fini(hermon_state_t *state,
16519e39c5baSBill Taylor     hermon_rsrc_hw_entry_info_t *info)
16529e39c5baSBill Taylor {
16539e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
16549e39c5baSBill Taylor 	hermon_rsrc_t		*rsvd_rsrc;
16559e39c5baSBill Taylor 
16569e39c5baSBill Taylor 	ASSERT(state != NULL);
16579e39c5baSBill Taylor 	ASSERT(info != NULL);
16589e39c5baSBill Taylor 
16599e39c5baSBill Taylor 	rsrc_pool = info->hwi_rsrcpool;
16609e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
16619e39c5baSBill Taylor 
16629e39c5baSBill Taylor 	/* Free up any "reserved" (i.e. preallocated) HW entries */
16639e39c5baSBill Taylor 	rsvd_rsrc = (hermon_rsrc_t *)rsrc_pool->rsrc_private;
16649e39c5baSBill Taylor 	if (rsvd_rsrc != NULL) {
16659e39c5baSBill Taylor 		hermon_rsrc_free(state, &rsvd_rsrc);
16669e39c5baSBill Taylor 	}
16679e39c5baSBill Taylor 
16689e39c5baSBill Taylor 	/*
16699e39c5baSBill Taylor 	 * If we've actually setup a vmem arena for the HW entries, then
16709e39c5baSBill Taylor 	 * destroy it now
16719e39c5baSBill Taylor 	 */
16729e39c5baSBill Taylor 	if (rsrc_pool->rsrc_vmp != NULL) {
16739e39c5baSBill Taylor 		vmem_destroy(rsrc_pool->rsrc_vmp);
16749e39c5baSBill Taylor 	}
16759e39c5baSBill Taylor }
16769e39c5baSBill Taylor 
16779e39c5baSBill Taylor 
16789e39c5baSBill Taylor /*
16799e39c5baSBill Taylor  * hermon_rsrc_sw_handles_init()
16809e39c5baSBill Taylor  *    Context: Only called from attach() path context
16819e39c5baSBill Taylor  */
16829e39c5baSBill Taylor /* ARGSUSED */
16839e39c5baSBill Taylor static int
hermon_rsrc_sw_handles_init(hermon_state_t * state,hermon_rsrc_sw_hdl_info_t * info)16849e39c5baSBill Taylor hermon_rsrc_sw_handles_init(hermon_state_t *state,
16859e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
16869e39c5baSBill Taylor {
16879e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
16889e39c5baSBill Taylor 	uint64_t		num_swhdl, max_swhdl, prealloc_sz;
16899e39c5baSBill Taylor 
16909e39c5baSBill Taylor 	ASSERT(state != NULL);
16919e39c5baSBill Taylor 	ASSERT(info != NULL);
16929e39c5baSBill Taylor 
16939e39c5baSBill Taylor 	rsrc_pool	= info->swi_rsrcpool;
16949e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
16959e39c5baSBill Taylor 	num_swhdl	= info->swi_num;
16969e39c5baSBill Taylor 	max_swhdl	= info->swi_max;
16979e39c5baSBill Taylor 	prealloc_sz	= info->swi_prealloc_sz;
16989e39c5baSBill Taylor 
16999e39c5baSBill Taylor 
17009e39c5baSBill Taylor 	/* Make sure number of SW handles makes sense */
17019e39c5baSBill Taylor 	if (num_swhdl > max_swhdl) {
17029e39c5baSBill Taylor 		return (DDI_FAILURE);
17039e39c5baSBill Taylor 	}
17049e39c5baSBill Taylor 
17059e39c5baSBill Taylor 	/*
17069e39c5baSBill Taylor 	 * Depending on the flags parameter, create a kmem_cache for some
17079e39c5baSBill Taylor 	 * number of software handle structures.  Note: kmem_cache_create()
17089e39c5baSBill Taylor 	 * will SLEEP until successful.
17099e39c5baSBill Taylor 	 */
17109e39c5baSBill Taylor 	if (info->swi_flags & HERMON_SWHDL_KMEMCACHE_INIT) {
17119e39c5baSBill Taylor 		rsrc_pool->rsrc_private = kmem_cache_create(
17129e39c5baSBill Taylor 		    info->swi_rsrcname, rsrc_pool->rsrc_quantum, 0,
17139e39c5baSBill Taylor 		    info->swi_constructor, info->swi_destructor, NULL,
17149e39c5baSBill Taylor 		    rsrc_pool->rsrc_state, NULL, 0);
17159e39c5baSBill Taylor 	}
17169e39c5baSBill Taylor 
17179e39c5baSBill Taylor 
17189e39c5baSBill Taylor 	/* Allocate the central list of SW handle pointers */
17199e39c5baSBill Taylor 	if (info->swi_flags & HERMON_SWHDL_TABLE_INIT) {
17209e39c5baSBill Taylor 		info->swi_table_ptr = kmem_zalloc(num_swhdl * prealloc_sz,
17219e39c5baSBill Taylor 		    KM_SLEEP);
17229e39c5baSBill Taylor 	}
17239e39c5baSBill Taylor 
17249e39c5baSBill Taylor 	return (DDI_SUCCESS);
17259e39c5baSBill Taylor }
17269e39c5baSBill Taylor 
17279e39c5baSBill Taylor 
17289e39c5baSBill Taylor /*
17299e39c5baSBill Taylor  * hermon_rsrc_sw_handles_fini()
17309e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
17319e39c5baSBill Taylor  */
17329e39c5baSBill Taylor /* ARGSUSED */
17339e39c5baSBill Taylor static void
hermon_rsrc_sw_handles_fini(hermon_state_t * state,hermon_rsrc_sw_hdl_info_t * info)17349e39c5baSBill Taylor hermon_rsrc_sw_handles_fini(hermon_state_t *state,
17359e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
17369e39c5baSBill Taylor {
17379e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
17389e39c5baSBill Taylor 	uint64_t		num_swhdl, prealloc_sz;
17399e39c5baSBill Taylor 
17409e39c5baSBill Taylor 	ASSERT(state != NULL);
17419e39c5baSBill Taylor 	ASSERT(info != NULL);
17429e39c5baSBill Taylor 
17439e39c5baSBill Taylor 	rsrc_pool	= info->swi_rsrcpool;
17449e39c5baSBill Taylor 	num_swhdl	= info->swi_num;
17459e39c5baSBill Taylor 	prealloc_sz	= info->swi_prealloc_sz;
17469e39c5baSBill Taylor 
17479e39c5baSBill Taylor 	/*
17489e39c5baSBill Taylor 	 * If a "software handle" kmem_cache exists for this resource, then
17499e39c5baSBill Taylor 	 * destroy it now
17509e39c5baSBill Taylor 	 */
17519e39c5baSBill Taylor 	if (rsrc_pool != NULL) {
17529e39c5baSBill Taylor 		kmem_cache_destroy(rsrc_pool->rsrc_private);
17539e39c5baSBill Taylor 	}
17549e39c5baSBill Taylor 
17559e39c5baSBill Taylor 	/* Free up this central list of SW handle pointers */
17569e39c5baSBill Taylor 	if (info->swi_table_ptr != NULL) {
17579e39c5baSBill Taylor 		kmem_free(info->swi_table_ptr, num_swhdl * prealloc_sz);
17589e39c5baSBill Taylor 	}
17599e39c5baSBill Taylor }
17609e39c5baSBill Taylor 
17619e39c5baSBill Taylor 
17629e39c5baSBill Taylor /*
17639e39c5baSBill Taylor  * hermon_rsrc_pd_handles_init()
17649e39c5baSBill Taylor  *    Context: Only called from attach() path context
17659e39c5baSBill Taylor  */
17669e39c5baSBill Taylor static int
hermon_rsrc_pd_handles_init(hermon_state_t * state,hermon_rsrc_sw_hdl_info_t * info)17679e39c5baSBill Taylor hermon_rsrc_pd_handles_init(hermon_state_t *state,
17689e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
17699e39c5baSBill Taylor {
17709e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
17719e39c5baSBill Taylor 	vmem_t			*vmp;
17729e39c5baSBill Taylor 	char			vmem_name[HERMON_RSRC_NAME_MAXLEN];
17739e39c5baSBill Taylor 	int			status;
17749e39c5baSBill Taylor 
17759e39c5baSBill Taylor 	ASSERT(state != NULL);
17769e39c5baSBill Taylor 	ASSERT(info != NULL);
17779e39c5baSBill Taylor 
17789e39c5baSBill Taylor 	rsrc_pool = info->swi_rsrcpool;
17799e39c5baSBill Taylor 	ASSERT(rsrc_pool != NULL);
17809e39c5baSBill Taylor 
17819e39c5baSBill Taylor 	/* Initialize the resource pool for software handle table */
17829e39c5baSBill Taylor 	status = hermon_rsrc_sw_handles_init(state, info);
17839e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
17849e39c5baSBill Taylor 		return (DDI_FAILURE);
17859e39c5baSBill Taylor 	}
17869e39c5baSBill Taylor 
17879e39c5baSBill Taylor 	/* Build vmem arena name from Hermon instance */
17889e39c5baSBill Taylor 	HERMON_RSRC_NAME(vmem_name, HERMON_PDHDL_VMEM);
17899e39c5baSBill Taylor 
17909e39c5baSBill Taylor 	/* Create new vmem arena for PD numbers */
17919e39c5baSBill Taylor 	vmp = vmem_create(vmem_name, (caddr_t)1, info->swi_num, 1, NULL,
17929e39c5baSBill Taylor 	    NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
17939e39c5baSBill Taylor 	if (vmp == NULL) {
17949e39c5baSBill Taylor 		/* Unable to create vmem arena */
17959e39c5baSBill Taylor 		info->swi_table_ptr = NULL;
17969e39c5baSBill Taylor 		hermon_rsrc_sw_handles_fini(state, info);
17979e39c5baSBill Taylor 		return (DDI_FAILURE);
17989e39c5baSBill Taylor 	}
17999e39c5baSBill Taylor 	rsrc_pool->rsrc_vmp = vmp;
18009e39c5baSBill Taylor 
18019e39c5baSBill Taylor 	return (DDI_SUCCESS);
18029e39c5baSBill Taylor }
18039e39c5baSBill Taylor 
18049e39c5baSBill Taylor 
18059e39c5baSBill Taylor /*
18069e39c5baSBill Taylor  * hermon_rsrc_pd_handles_fini()
18079e39c5baSBill Taylor  *    Context: Only called from attach() and/or detach() path contexts
18089e39c5baSBill Taylor  */
18099e39c5baSBill Taylor static void
hermon_rsrc_pd_handles_fini(hermon_state_t * state,hermon_rsrc_sw_hdl_info_t * info)18109e39c5baSBill Taylor hermon_rsrc_pd_handles_fini(hermon_state_t *state,
18119e39c5baSBill Taylor     hermon_rsrc_sw_hdl_info_t *info)
18129e39c5baSBill Taylor {
18139e39c5baSBill Taylor 	hermon_rsrc_pool_info_t	*rsrc_pool;
18149e39c5baSBill Taylor 
18159e39c5baSBill Taylor 	ASSERT(state != NULL);
18169e39c5baSBill Taylor 	ASSERT(info != NULL);
18179e39c5baSBill Taylor 
18189e39c5baSBill Taylor 	rsrc_pool = info->swi_rsrcpool;
18199e39c5baSBill Taylor 
18209e39c5baSBill Taylor 	/* Destroy the specially created UAR scratch table vmem arena */
18219e39c5baSBill Taylor 	vmem_destroy(rsrc_pool->rsrc_vmp);
18229e39c5baSBill Taylor 
18239e39c5baSBill Taylor 	/* Destroy the "hermon_sw_pd_t" kmem_cache */
18249e39c5baSBill Taylor 	hermon_rsrc_sw_handles_fini(state, info);
18259e39c5baSBill Taylor }
18269e39c5baSBill Taylor 
18279e39c5baSBill Taylor 
18289e39c5baSBill Taylor /*
18299e39c5baSBill Taylor  * hermon_rsrc_mbox_alloc()
18309e39c5baSBill Taylor  *    Context: Only called from attach() path context
18319e39c5baSBill Taylor  */
18329e39c5baSBill Taylor static int
hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t * pool_info,uint_t num,hermon_rsrc_t * hdl)18339e39c5baSBill Taylor hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
18349e39c5baSBill Taylor     hermon_rsrc_t *hdl)
18359e39c5baSBill Taylor {
18369e39c5baSBill Taylor 	hermon_rsrc_priv_mbox_t	*priv;
18379e39c5baSBill Taylor 	caddr_t			kaddr;
18389e39c5baSBill Taylor 	size_t			real_len, temp_len;
18399e39c5baSBill Taylor 	int			status;
18409e39c5baSBill Taylor 
18419e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
18429e39c5baSBill Taylor 	ASSERT(hdl != NULL);
18439e39c5baSBill Taylor 
18449e39c5baSBill Taylor 	/* Get the private pointer for the mailboxes */
18459e39c5baSBill Taylor 	priv = pool_info->rsrc_private;
18469e39c5baSBill Taylor 	ASSERT(priv != NULL);
18479e39c5baSBill Taylor 
18489e39c5baSBill Taylor 	/* Allocate a DMA handle for the mailbox */
18499e39c5baSBill Taylor 	status = ddi_dma_alloc_handle(priv->pmb_dip, &priv->pmb_dmaattr,
18509e39c5baSBill Taylor 	    DDI_DMA_SLEEP, NULL, &hdl->hr_dmahdl);
18519e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
18529e39c5baSBill Taylor 		return (DDI_FAILURE);
18539e39c5baSBill Taylor 	}
18549e39c5baSBill Taylor 
18559e39c5baSBill Taylor 	/* Allocate memory for the mailbox */
185617a2b317SBill Taylor 	temp_len = (num << pool_info->rsrc_shift);
18579e39c5baSBill Taylor 	status = ddi_dma_mem_alloc(hdl->hr_dmahdl, temp_len,
18589e39c5baSBill Taylor 	    &priv->pmb_devaccattr, priv->pmb_xfer_mode, DDI_DMA_SLEEP,
18599e39c5baSBill Taylor 	    NULL, &kaddr, &real_len, &hdl->hr_acchdl);
18609e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
18619e39c5baSBill Taylor 		/* No more memory available for mailbox entries */
18629e39c5baSBill Taylor 		ddi_dma_free_handle(&hdl->hr_dmahdl);
18639e39c5baSBill Taylor 		return (DDI_FAILURE);
18649e39c5baSBill Taylor 	}
18659e39c5baSBill Taylor 
18669e39c5baSBill Taylor 	hdl->hr_addr = (void *)kaddr;
18679e39c5baSBill Taylor 	hdl->hr_len  = (uint32_t)real_len;
18689e39c5baSBill Taylor 
18699e39c5baSBill Taylor 	return (DDI_SUCCESS);
18709e39c5baSBill Taylor }
18719e39c5baSBill Taylor 
18729e39c5baSBill Taylor 
18739e39c5baSBill Taylor /*
18749e39c5baSBill Taylor  * hermon_rsrc_mbox_free()
18759e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
18769e39c5baSBill Taylor  */
18779e39c5baSBill Taylor static void
hermon_rsrc_mbox_free(hermon_rsrc_t * hdl)187817a2b317SBill Taylor hermon_rsrc_mbox_free(hermon_rsrc_t *hdl)
18799e39c5baSBill Taylor {
18809e39c5baSBill Taylor 	ASSERT(hdl != NULL);
18819e39c5baSBill Taylor 
18829e39c5baSBill Taylor 	/* Use ddi_dma_mem_free() to free up sys memory for mailbox */
18839e39c5baSBill Taylor 	ddi_dma_mem_free(&hdl->hr_acchdl);
18849e39c5baSBill Taylor 
18859e39c5baSBill Taylor 	/* Free the DMA handle for the mailbox */
18869e39c5baSBill Taylor 	ddi_dma_free_handle(&hdl->hr_dmahdl);
18879e39c5baSBill Taylor }
18889e39c5baSBill Taylor 
18899e39c5baSBill Taylor 
18909e39c5baSBill Taylor /*
18919e39c5baSBill Taylor  * hermon_rsrc_hw_entry_alloc()
18929e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
18939e39c5baSBill Taylor  */
18949e39c5baSBill Taylor static int
hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t * pool_info,uint_t num,uint_t num_align,uint_t sleepflag,hermon_rsrc_t * hdl)18959e39c5baSBill Taylor hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
189617a2b317SBill Taylor     uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl)
18979e39c5baSBill Taylor {
18989e39c5baSBill Taylor 	void			*addr;
18999e39c5baSBill Taylor 	uint64_t		offset;
19009e39c5baSBill Taylor 	uint32_t		align;
19019e39c5baSBill Taylor 	int			status;
19029e39c5baSBill Taylor 	int			flag;
19039e39c5baSBill Taylor 
19049e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
19059e39c5baSBill Taylor 	ASSERT(hdl != NULL);
19069e39c5baSBill Taylor 
19079e39c5baSBill Taylor 	/*
19089e39c5baSBill Taylor 	 * Use vmem_xalloc() to get a properly aligned pointer (based on
19099e39c5baSBill Taylor 	 * the number requested) to the HW entry(ies).  This handles the
19109e39c5baSBill Taylor 	 * cases (for special QPCs and for RDB entries) where we need more
19119e39c5baSBill Taylor 	 * than one and need to ensure that they are properly aligned.
19129e39c5baSBill Taylor 	 */
19139e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
191417a2b317SBill Taylor 	hdl->hr_len = (num << pool_info->rsrc_shift);
191517a2b317SBill Taylor 	align = (num_align << pool_info->rsrc_shift);
19169e39c5baSBill Taylor 
19179e39c5baSBill Taylor 	addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->hr_len,
19189e39c5baSBill Taylor 	    align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
19199e39c5baSBill Taylor 
19209e39c5baSBill Taylor 	if (addr == NULL) {
19219e39c5baSBill Taylor 		/* No more HW entries available */
19229e39c5baSBill Taylor 		return (DDI_FAILURE);
19239e39c5baSBill Taylor 	}
19249e39c5baSBill Taylor 
192517a2b317SBill Taylor 	hdl->hr_acchdl = NULL;	/* only used for mbox resources */
19269e39c5baSBill Taylor 
19279e39c5baSBill Taylor 	/* Calculate vaddr and HW table index */
19289e39c5baSBill Taylor 	offset = (uintptr_t)addr - (uintptr_t)pool_info->rsrc_start;
192917a2b317SBill Taylor 	hdl->hr_addr = addr;	/* only used for mbox and uarpg resources */
19309e39c5baSBill Taylor 	hdl->hr_indx = offset >> pool_info->rsrc_shift;
19319e39c5baSBill Taylor 
19329e39c5baSBill Taylor 	if (pool_info->rsrc_loc == HERMON_IN_ICM) {
193317a2b317SBill Taylor 		int num_to_hdl;
193417a2b317SBill Taylor 		hermon_rsrc_type_t rsrc_type = pool_info->rsrc_type;
193517a2b317SBill Taylor 
193617a2b317SBill Taylor 		num_to_hdl = (rsrc_type == HERMON_QPC ||
193717a2b317SBill Taylor 		    rsrc_type == HERMON_CQC || rsrc_type == HERMON_SRQC);
193817a2b317SBill Taylor 
19399e39c5baSBill Taylor 		/* confirm ICM is mapped, and allocate if necessary */
194017a2b317SBill Taylor 		status = hermon_rsrc_hw_entry_icm_confirm(pool_info, num, hdl,
194117a2b317SBill Taylor 		    num_to_hdl);
19429e39c5baSBill Taylor 		if (status != DDI_SUCCESS) {
19439e39c5baSBill Taylor 			return (DDI_FAILURE);
19449e39c5baSBill Taylor 		}
194517a2b317SBill Taylor 		hdl->hr_addr = NULL;	/* not used for ICM resources */
19469e39c5baSBill Taylor 	}
19479e39c5baSBill Taylor 
19489e39c5baSBill Taylor 	return (DDI_SUCCESS);
19499e39c5baSBill Taylor }
19509e39c5baSBill Taylor 
19519e39c5baSBill Taylor 
195217a2b317SBill Taylor /*
195317a2b317SBill Taylor  * hermon_rsrc_hw_entry_reserve()
195417a2b317SBill Taylor  *    Context: Can be called from interrupt or base context.
195517a2b317SBill Taylor  */
195617a2b317SBill Taylor int
hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t * pool_info,uint_t num,uint_t num_align,uint_t sleepflag,hermon_rsrc_t * hdl)195717a2b317SBill Taylor hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t *pool_info, uint_t num,
195817a2b317SBill Taylor     uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl)
195917a2b317SBill Taylor {
196017a2b317SBill Taylor 	void			*addr;
196117a2b317SBill Taylor 	uint64_t		offset;
196217a2b317SBill Taylor 	uint32_t		align;
196317a2b317SBill Taylor 	int			flag;
196417a2b317SBill Taylor 
196517a2b317SBill Taylor 	ASSERT(pool_info != NULL);
196617a2b317SBill Taylor 	ASSERT(hdl != NULL);
196717a2b317SBill Taylor 	ASSERT(pool_info->rsrc_loc == HERMON_IN_ICM);
196817a2b317SBill Taylor 
196917a2b317SBill Taylor 	/*
197017a2b317SBill Taylor 	 * Use vmem_xalloc() to get a properly aligned pointer (based on
197117a2b317SBill Taylor 	 * the number requested) to the HW entry(ies).  This handles the
197217a2b317SBill Taylor 	 * cases (for special QPCs and for RDB entries) where we need more
197317a2b317SBill Taylor 	 * than one and need to ensure that they are properly aligned.
197417a2b317SBill Taylor 	 */
197517a2b317SBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
197617a2b317SBill Taylor 	hdl->hr_len = (num << pool_info->rsrc_shift);
197717a2b317SBill Taylor 	align = (num_align << pool_info->rsrc_shift);
197817a2b317SBill Taylor 
197917a2b317SBill Taylor 	addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->hr_len,
198017a2b317SBill Taylor 	    align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
198117a2b317SBill Taylor 
198217a2b317SBill Taylor 	if (addr == NULL) {
198317a2b317SBill Taylor 		/* No more HW entries available */
198417a2b317SBill Taylor 		return (DDI_FAILURE);
198517a2b317SBill Taylor 	}
198617a2b317SBill Taylor 
198717a2b317SBill Taylor 	hdl->hr_acchdl = NULL;	/* only used for mbox resources */
198817a2b317SBill Taylor 
198917a2b317SBill Taylor 	/* Calculate vaddr and HW table index */
199017a2b317SBill Taylor 	offset = (uintptr_t)addr - (uintptr_t)pool_info->rsrc_start;
199117a2b317SBill Taylor 	hdl->hr_addr = NULL;
199217a2b317SBill Taylor 	hdl->hr_indx = offset >> pool_info->rsrc_shift;
199317a2b317SBill Taylor 
199417a2b317SBill Taylor 	/* ICM will be allocated and mapped if and when it gets used */
199517a2b317SBill Taylor 
199617a2b317SBill Taylor 	return (DDI_SUCCESS);
199717a2b317SBill Taylor }
199817a2b317SBill Taylor 
19999e39c5baSBill Taylor 
20009e39c5baSBill Taylor /*
20019e39c5baSBill Taylor  * hermon_rsrc_hw_entry_free()
20029e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
20039e39c5baSBill Taylor  */
20049e39c5baSBill Taylor static void
hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t * pool_info,hermon_rsrc_t * hdl)20059e39c5baSBill Taylor hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
20069e39c5baSBill Taylor     hermon_rsrc_t *hdl)
20079e39c5baSBill Taylor {
20089e39c5baSBill Taylor 	void			*addr;
20099e39c5baSBill Taylor 	uint64_t		offset;
20109e39c5baSBill Taylor 	int			status;
20119e39c5baSBill Taylor 
20129e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
20139e39c5baSBill Taylor 	ASSERT(hdl != NULL);
20149e39c5baSBill Taylor 
20159e39c5baSBill Taylor 	/* Calculate the allocated address */
20169e39c5baSBill Taylor 	offset = hdl->hr_indx << pool_info->rsrc_shift;
20179e39c5baSBill Taylor 	addr = (void *)(uintptr_t)(offset + (uintptr_t)pool_info->rsrc_start);
20189e39c5baSBill Taylor 
20199e39c5baSBill Taylor 	/* Use vmem_xfree() to free up the HW table entry */
20209e39c5baSBill Taylor 	vmem_xfree(pool_info->rsrc_vmp, addr, hdl->hr_len);
20219e39c5baSBill Taylor 
20229e39c5baSBill Taylor 	if (pool_info->rsrc_loc == HERMON_IN_ICM) {
202317a2b317SBill Taylor 		int num_to_hdl;
202417a2b317SBill Taylor 		hermon_rsrc_type_t rsrc_type = pool_info->rsrc_type;
202517a2b317SBill Taylor 
202617a2b317SBill Taylor 		num_to_hdl = (rsrc_type == HERMON_QPC ||
202717a2b317SBill Taylor 		    rsrc_type == HERMON_CQC || rsrc_type == HERMON_SRQC);
202817a2b317SBill Taylor 
20299e39c5baSBill Taylor 		/* free ICM references, and free ICM if required */
203017a2b317SBill Taylor 		status = hermon_rsrc_hw_entry_icm_free(pool_info, hdl,
203117a2b317SBill Taylor 		    num_to_hdl);
20329e39c5baSBill Taylor 		if (status != DDI_SUCCESS)
20339e39c5baSBill Taylor 			HERMON_WARNING(pool_info->rsrc_state,
20349e39c5baSBill Taylor 			    "failure in hw_entry_free");
20359e39c5baSBill Taylor 	}
20369e39c5baSBill Taylor }
20379e39c5baSBill Taylor 
20389e39c5baSBill Taylor /*
20399e39c5baSBill Taylor  * hermon_rsrc_hw_entry_icm_confirm()
20409e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
20419e39c5baSBill Taylor  */
20429e39c5baSBill Taylor static int
hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t * pool_info,uint_t num,hermon_rsrc_t * hdl,int num_to_hdl)20439e39c5baSBill Taylor hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info, uint_t num,
204417a2b317SBill Taylor     hermon_rsrc_t *hdl, int num_to_hdl)
20459e39c5baSBill Taylor {
20469e39c5baSBill Taylor 	hermon_state_t		*state;
20479e39c5baSBill Taylor 	hermon_icm_table_t	*icm_table;
20489e39c5baSBill Taylor 	uint8_t			*bitmap;
20499e39c5baSBill Taylor 	hermon_dma_info_t	*dma_info;
20509e39c5baSBill Taylor 	hermon_rsrc_type_t	type;
20519e39c5baSBill Taylor 	uint32_t		rindx, span_offset;
20529e39c5baSBill Taylor 	uint32_t		span_avail;
20539e39c5baSBill Taylor 	int			num_backed;
20549e39c5baSBill Taylor 	int			status;
20559e39c5baSBill Taylor 	uint32_t		index1, index2;
20569e39c5baSBill Taylor 
20579e39c5baSBill Taylor 	/*
20589e39c5baSBill Taylor 	 * Utility routine responsible for ensuring that there is memory
20599e39c5baSBill Taylor 	 * backing the ICM resources allocated via hermon_rsrc_hw_entry_alloc().
20609e39c5baSBill Taylor 	 * Confirm existing ICM mapping(s) or allocate ICM memory for the
20619e39c5baSBill Taylor 	 * given hardware resources being allocated, and increment the
20629e39c5baSBill Taylor 	 * ICM DMA structure(s) reference count.
20639e39c5baSBill Taylor 	 *
20649e39c5baSBill Taylor 	 * We may be allocating more objects than can fit in a single span,
20659e39c5baSBill Taylor 	 * or more than will fit in the remaining contiguous memory (from
20669e39c5baSBill Taylor 	 * the offset indicated by hdl->ar_indx) in the span in question.
20679e39c5baSBill Taylor 	 * In either of these cases, we'll be breaking up our allocation
20689e39c5baSBill Taylor 	 * into multiple spans.
20699e39c5baSBill Taylor 	 */
20709e39c5baSBill Taylor 	state = pool_info->rsrc_state;
20719e39c5baSBill Taylor 	type  = pool_info->rsrc_type;
20729e39c5baSBill Taylor 	icm_table = &state->hs_icm[type];
20739e39c5baSBill Taylor 
20749e39c5baSBill Taylor 	rindx = hdl->hr_indx;
20759e39c5baSBill Taylor 	hermon_index(index1, index2, rindx, icm_table, span_offset);
20769e39c5baSBill Taylor 
20779e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
20789e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_confirm: "
20799e39c5baSBill Taylor 		    "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x): ",
20809e39c5baSBill Taylor 		    type, num, hdl->hr_len, index1, index2);
20819e39c5baSBill Taylor 	}
20829e39c5baSBill Taylor 
20839e39c5baSBill Taylor 	mutex_enter(&icm_table->icm_table_lock);
208417a2b317SBill Taylor 	hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
20859e39c5baSBill Taylor 	while (num) {
20869e39c5baSBill Taylor #ifndef __lock_lint
20879e39c5baSBill Taylor 		while (icm_table->icm_busy) {
20889e39c5baSBill Taylor 			cv_wait(&icm_table->icm_table_cv,
20899e39c5baSBill Taylor 			    &icm_table->icm_table_lock);
20909e39c5baSBill Taylor 		}
20919e39c5baSBill Taylor #endif
20929e39c5baSBill Taylor 		if (!HERMON_BMAP_BIT_ISSET(bitmap, index2)) {
20939e39c5baSBill Taylor 			/* Allocate ICM for this span */
20949e39c5baSBill Taylor 			icm_table->icm_busy = 1;
20959e39c5baSBill Taylor 			mutex_exit(&icm_table->icm_table_lock);
20969e39c5baSBill Taylor 			status = hermon_icm_alloc(state, type, index1, index2);
20979e39c5baSBill Taylor 			mutex_enter(&icm_table->icm_table_lock);
20989e39c5baSBill Taylor 			icm_table->icm_busy = 0;
20999e39c5baSBill Taylor 			cv_broadcast(&icm_table->icm_table_cv);
21009e39c5baSBill Taylor 			if (status != DDI_SUCCESS) {
21019e39c5baSBill Taylor 				goto fail_alloc;
21029e39c5baSBill Taylor 			}
21039e39c5baSBill Taylor 			if (hermon_rsrc_verbose) {
21049e39c5baSBill Taylor 				IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
21059e39c5baSBill Taylor 				    "hw_entry_icm_confirm: ALLOCATED ICM: "
21069e39c5baSBill Taylor 				    "type (0x%x) index (0x%x, 0x%x)",
21079e39c5baSBill Taylor 				    type, index1, index2);
21089e39c5baSBill Taylor 			}
21099e39c5baSBill Taylor 		}
21109e39c5baSBill Taylor 
21119e39c5baSBill Taylor 		/*
21129e39c5baSBill Taylor 		 * We need to increment the refcnt of this span by the
21139e39c5baSBill Taylor 		 * number of objects in this resource allocation that are
21149e39c5baSBill Taylor 		 * backed by this span. Given that the rsrc allocation is
21159e39c5baSBill Taylor 		 * contiguous, this value will be the number of objects in
21169e39c5baSBill Taylor 		 * the span from 'span_offset' onward, either up to a max
21179e39c5baSBill Taylor 		 * of the total number of objects, or the end of the span.
21189e39c5baSBill Taylor 		 * So, determine the number of objects that can be backed
21199e39c5baSBill Taylor 		 * by this span ('span_avail'), then determine the number
21209e39c5baSBill Taylor 		 * of backed resources.
21219e39c5baSBill Taylor 		 */
21229e39c5baSBill Taylor 		span_avail = icm_table->span - span_offset;
21239e39c5baSBill Taylor 		if (num > span_avail) {
21249e39c5baSBill Taylor 			num_backed = span_avail;
21259e39c5baSBill Taylor 		} else {
21269e39c5baSBill Taylor 			num_backed = num;
21279e39c5baSBill Taylor 		}
21289e39c5baSBill Taylor 
21299e39c5baSBill Taylor 		/*
21309e39c5baSBill Taylor 		 * Now that we know 'num_backed', increment the refcnt,
21319e39c5baSBill Taylor 		 * decrement the total number, and set 'span_offset' to
21329e39c5baSBill Taylor 		 * 0 in case we roll over into the next span.
21339e39c5baSBill Taylor 		 */
21349e39c5baSBill Taylor 		dma_info[index2].icm_refcnt += num_backed;
21359e39c5baSBill Taylor 		rindx += num_backed;
21369e39c5baSBill Taylor 		num -= num_backed;
21379e39c5baSBill Taylor 
21389e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
21399e39c5baSBill Taylor 			IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) index "
21409e39c5baSBill Taylor 			    "(0x%x, 0x%x) num_backed (0x%x)",
21419e39c5baSBill Taylor 			    type, index1, index2, num_backed);
21429e39c5baSBill Taylor 			IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) refcnt now "
21439e39c5baSBill Taylor 			    "(0x%x) num_remaining (0x%x)", type,
21449e39c5baSBill Taylor 			    dma_info[index2].icm_refcnt, num);
21459e39c5baSBill Taylor 		}
21469e39c5baSBill Taylor 		if (num == 0)
21479e39c5baSBill Taylor 			break;
21489e39c5baSBill Taylor 
21499e39c5baSBill Taylor 		hermon_index(index1, index2, rindx, icm_table, span_offset);
215017a2b317SBill Taylor 		hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
21519e39c5baSBill Taylor 	}
21529e39c5baSBill Taylor 	mutex_exit(&icm_table->icm_table_lock);
21539e39c5baSBill Taylor 
21549e39c5baSBill Taylor 	return (DDI_SUCCESS);
21559e39c5baSBill Taylor 
21569e39c5baSBill Taylor fail_alloc:
21579e39c5baSBill Taylor 	/* JBDB */
21589e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
21599e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
21609e39c5baSBill Taylor 		    "hw_entry_icm_confirm: FAILED ICM ALLOC: "
21619e39c5baSBill Taylor 		    "type (0x%x) num remaind (0x%x) index (0x%x, 0x%x)"
21629e39c5baSBill Taylor 		    "refcnt (0x%x)", type, num, index1, index2,
21639e39c5baSBill Taylor 		    icm_table->icm_dma[index1][index2].icm_refcnt);
21649e39c5baSBill Taylor 	}
21659e39c5baSBill Taylor 	IBTF_DPRINTF_L2("hermon", "WARNING: "
21669e39c5baSBill Taylor 	    "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
21679e39c5baSBill Taylor 
21689e39c5baSBill Taylor #if needs_work
21699e39c5baSBill Taylor 	/* free refcnt's and any spans we've allocated */
21709e39c5baSBill Taylor 	while (index-- != start) {
21719e39c5baSBill Taylor 		/*
21729e39c5baSBill Taylor 		 * JBDB - This is a bit tricky.  We need to
21739e39c5baSBill Taylor 		 * free refcnt's on any spans that we've
21749e39c5baSBill Taylor 		 * incremented them on, and completely free
21759e39c5baSBill Taylor 		 * spans that we've allocated. How do we do
21769e39c5baSBill Taylor 		 * this here? Does it need to be as involved
21779e39c5baSBill Taylor 		 * as the core of icm_free() below, or can
21789e39c5baSBill Taylor 		 * we leverage breadcrumbs somehow?
21799e39c5baSBill Taylor 		 */
21809e39c5baSBill Taylor 		HERMON_WARNING(state, "unable to allocate ICM memory: "
21819e39c5baSBill Taylor 		    "UNIMPLEMENTED HANDLING!!");
21829e39c5baSBill Taylor 	}
21839e39c5baSBill Taylor #else
21849e39c5baSBill Taylor 	cmn_err(CE_WARN,
21859e39c5baSBill Taylor 	    "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
21869e39c5baSBill Taylor #endif
21879e39c5baSBill Taylor 	mutex_exit(&icm_table->icm_table_lock);
21889e39c5baSBill Taylor 
21899e39c5baSBill Taylor 	HERMON_WARNING(state, "unable to allocate ICM memory");
21909e39c5baSBill Taylor 	return (DDI_FAILURE);
21919e39c5baSBill Taylor }
21929e39c5baSBill Taylor 
21939e39c5baSBill Taylor /*
21949e39c5baSBill Taylor  * hermon_rsrc_hw_entry_icm_free()
21959e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
21969e39c5baSBill Taylor  */
21979e39c5baSBill Taylor static int
hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t * pool_info,hermon_rsrc_t * hdl,int num_to_hdl)21989e39c5baSBill Taylor hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
219917a2b317SBill Taylor     hermon_rsrc_t *hdl, int num_to_hdl)
22009e39c5baSBill Taylor {
22019e39c5baSBill Taylor 	hermon_state_t		*state;
22029e39c5baSBill Taylor 	hermon_icm_table_t	*icm_table;
22039e39c5baSBill Taylor 	uint8_t			*bitmap;
22049e39c5baSBill Taylor 	hermon_dma_info_t	*dma_info;
22059e39c5baSBill Taylor 	hermon_rsrc_type_t	type;
22069e39c5baSBill Taylor 	uint32_t		span_offset;
22079e39c5baSBill Taylor 	uint32_t		span_remain;
22089e39c5baSBill Taylor 	int			num_freed;
22099e39c5baSBill Taylor 	int			num;
22109e39c5baSBill Taylor 	uint32_t		index1, index2, rindx;
22119e39c5baSBill Taylor 
22129e39c5baSBill Taylor 	/*
22139e39c5baSBill Taylor 	 * Utility routine responsible for freeing references to ICM
22149e39c5baSBill Taylor 	 * DMA spans, and freeing the ICM memory if necessary.
22159e39c5baSBill Taylor 	 *
22169e39c5baSBill Taylor 	 * We may have allocated objects in a single contiguous resource
22179e39c5baSBill Taylor 	 * allocation that reside in a number of spans, at any given
22189e39c5baSBill Taylor 	 * starting offset within a span. We therefore must determine
22199e39c5baSBill Taylor 	 * where this allocation starts, and then determine if we need
22209e39c5baSBill Taylor 	 * to free objects in more than one span.
22219e39c5baSBill Taylor 	 */
22229e39c5baSBill Taylor 	state = pool_info->rsrc_state;
22239e39c5baSBill Taylor 	type  = pool_info->rsrc_type;
22249e39c5baSBill Taylor 	icm_table = &state->hs_icm[type];
22259e39c5baSBill Taylor 
22269e39c5baSBill Taylor 	rindx = hdl->hr_indx;
22279e39c5baSBill Taylor 	hermon_index(index1, index2, rindx, icm_table, span_offset);
222817a2b317SBill Taylor 	hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
22299e39c5baSBill Taylor 
22309e39c5baSBill Taylor 	/* determine the number of ICM objects in this allocation */
22319e39c5baSBill Taylor 	num = hdl->hr_len >> pool_info->rsrc_shift;
22329e39c5baSBill Taylor 
22339e39c5baSBill Taylor 	if (hermon_rsrc_verbose) {
22349e39c5baSBill Taylor 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_free: "
22359e39c5baSBill Taylor 		    "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x)",
22369e39c5baSBill Taylor 		    type, num, hdl->hr_len, index1, index2);
22379e39c5baSBill Taylor 	}
22389e39c5baSBill Taylor 	mutex_enter(&icm_table->icm_table_lock);
22399e39c5baSBill Taylor 	while (num) {
22409e39c5baSBill Taylor 		/*
22419e39c5baSBill Taylor 		 * As with the ICM confirm code above, we need to
22429e39c5baSBill Taylor 		 * decrement the ICM span(s) by the number of
22439e39c5baSBill Taylor 		 * resources being freed. So, determine the number
22449e39c5baSBill Taylor 		 * of objects that are backed in this span from
22459e39c5baSBill Taylor 		 * 'span_offset' onward, and set 'num_freed' to
22469e39c5baSBill Taylor 		 * the smaller of either that number ('span_remain'),
22479e39c5baSBill Taylor 		 * or the total number of objects being freed.
22489e39c5baSBill Taylor 		 */
22499e39c5baSBill Taylor 		span_remain = icm_table->span - span_offset;
22509e39c5baSBill Taylor 		if (num > span_remain) {
22519e39c5baSBill Taylor 			num_freed = span_remain;
22529e39c5baSBill Taylor 		} else {
22539e39c5baSBill Taylor 			num_freed = num;
22549e39c5baSBill Taylor 		}
22559e39c5baSBill Taylor 
22569e39c5baSBill Taylor 		/*
22579e39c5baSBill Taylor 		 * Now that we know 'num_freed', decrement the refcnt,
22589e39c5baSBill Taylor 		 * decrement the total number, and set 'span_offset' to
22599e39c5baSBill Taylor 		 * 0 in case we roll over into the next span.
22609e39c5baSBill Taylor 		 */
22619e39c5baSBill Taylor 		dma_info[index2].icm_refcnt -= num_freed;
22629e39c5baSBill Taylor 		num -= num_freed;
22639e39c5baSBill Taylor 		rindx += num_freed;
22649e39c5baSBill Taylor 
22659e39c5baSBill Taylor 		if (hermon_rsrc_verbose) {
22669e39c5baSBill Taylor 			IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) index "
22679e39c5baSBill Taylor 			    "(0x%x, 0x%x) num_freed (0x%x)", type,
22689e39c5baSBill Taylor 			    index1, index2, num_freed);
22699e39c5baSBill Taylor 			IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) refcnt now "
22709e39c5baSBill Taylor 			    "(0x%x) num remaining (0x%x)", type,
22719e39c5baSBill Taylor 			    icm_table->icm_dma[index1][index2].icm_refcnt, num);
22729e39c5baSBill Taylor 		}
22739e39c5baSBill Taylor 
22749e39c5baSBill Taylor #if HERMON_ICM_FREE_ENABLED
22759e39c5baSBill Taylor 		/* If we've freed the last object in this span, free it */
22769e39c5baSBill Taylor 		if ((index1 != 0 || index2 != 0) &&
22779e39c5baSBill Taylor 		    (dma_info[index2].icm_refcnt == 0)) {
22789e39c5baSBill Taylor 			if (hermon_rsrc_verbose) {
22799e39c5baSBill Taylor 				IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry"
22809e39c5baSBill Taylor 				    "_icm_free: freeing ICM type (0x%x) index"
22819e39c5baSBill Taylor 				    " (0x%x, 0x%x)", type, index1, index2);
22829e39c5baSBill Taylor 			}
22839e39c5baSBill Taylor 			hermon_icm_free(state, type, index1, index2);
22849e39c5baSBill Taylor 		}
22859e39c5baSBill Taylor #endif
22869e39c5baSBill Taylor 		if (num == 0)
22879e39c5baSBill Taylor 			break;
22889e39c5baSBill Taylor 
22899e39c5baSBill Taylor 		hermon_index(index1, index2, rindx, icm_table, span_offset);
229017a2b317SBill Taylor 		hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
22919e39c5baSBill Taylor 	}
22929e39c5baSBill Taylor 	mutex_exit(&icm_table->icm_table_lock);
22939e39c5baSBill Taylor 
22949e39c5baSBill Taylor 	return (DDI_SUCCESS);
22959e39c5baSBill Taylor }
22969e39c5baSBill Taylor 
22979e39c5baSBill Taylor 
22989e39c5baSBill Taylor 
22999e39c5baSBill Taylor /*
23009e39c5baSBill Taylor  * hermon_rsrc_swhdl_alloc()
23019e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23029e39c5baSBill Taylor  */
23039e39c5baSBill Taylor static int
hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t * pool_info,uint_t sleepflag,hermon_rsrc_t * hdl)23049e39c5baSBill Taylor hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
23059e39c5baSBill Taylor     hermon_rsrc_t *hdl)
23069e39c5baSBill Taylor {
23079e39c5baSBill Taylor 	void	*addr;
23089e39c5baSBill Taylor 	int	flag;
23099e39c5baSBill Taylor 
23109e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
23119e39c5baSBill Taylor 	ASSERT(hdl != NULL);
23129e39c5baSBill Taylor 
23139e39c5baSBill Taylor 	/* Allocate the software handle structure */
23149e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
23159e39c5baSBill Taylor 	addr = kmem_cache_alloc(pool_info->rsrc_private, flag);
23169e39c5baSBill Taylor 	if (addr == NULL) {
23179e39c5baSBill Taylor 		return (DDI_FAILURE);
23189e39c5baSBill Taylor 	}
23199e39c5baSBill Taylor 	hdl->hr_len  = pool_info->rsrc_quantum;
23209e39c5baSBill Taylor 	hdl->hr_addr = addr;
23219e39c5baSBill Taylor 
23229e39c5baSBill Taylor 	return (DDI_SUCCESS);
23239e39c5baSBill Taylor }
23249e39c5baSBill Taylor 
23259e39c5baSBill Taylor 
23269e39c5baSBill Taylor /*
23279e39c5baSBill Taylor  * hermon_rsrc_swhdl_free()
23289e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23299e39c5baSBill Taylor  */
23309e39c5baSBill Taylor static void
hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t * pool_info,hermon_rsrc_t * hdl)23319e39c5baSBill Taylor hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
23329e39c5baSBill Taylor {
23339e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
23349e39c5baSBill Taylor 	ASSERT(hdl != NULL);
23359e39c5baSBill Taylor 
23369e39c5baSBill Taylor 	/* Free the software handle structure */
23379e39c5baSBill Taylor 	kmem_cache_free(pool_info->rsrc_private, hdl->hr_addr);
23389e39c5baSBill Taylor }
23399e39c5baSBill Taylor 
23409e39c5baSBill Taylor 
23419e39c5baSBill Taylor /*
23429e39c5baSBill Taylor  * hermon_rsrc_pdhdl_alloc()
23439e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23449e39c5baSBill Taylor  */
23459e39c5baSBill Taylor static int
hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t * pool_info,uint_t sleepflag,hermon_rsrc_t * hdl)23469e39c5baSBill Taylor hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
23479e39c5baSBill Taylor     hermon_rsrc_t *hdl)
23489e39c5baSBill Taylor {
23499e39c5baSBill Taylor 	hermon_pdhdl_t	addr;
23509e39c5baSBill Taylor 	void		*tmpaddr;
23519e39c5baSBill Taylor 	int		flag, status;
23529e39c5baSBill Taylor 
23539e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
23549e39c5baSBill Taylor 	ASSERT(hdl != NULL);
23559e39c5baSBill Taylor 
23569e39c5baSBill Taylor 	/* Allocate the software handle */
23579e39c5baSBill Taylor 	status = hermon_rsrc_swhdl_alloc(pool_info, sleepflag, hdl);
23589e39c5baSBill Taylor 	if (status != DDI_SUCCESS) {
23599e39c5baSBill Taylor 		return (DDI_FAILURE);
23609e39c5baSBill Taylor 	}
23619e39c5baSBill Taylor 	addr = (hermon_pdhdl_t)hdl->hr_addr;
23629e39c5baSBill Taylor 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr))
23639e39c5baSBill Taylor 
23649e39c5baSBill Taylor 	/* Allocate a PD number for the handle */
23659e39c5baSBill Taylor 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
23669e39c5baSBill Taylor 	tmpaddr = vmem_alloc(pool_info->rsrc_vmp, 1, flag);
23679e39c5baSBill Taylor 	if (tmpaddr == NULL) {
23689e39c5baSBill Taylor 		/* No more PD number entries available */
23699e39c5baSBill Taylor 		hermon_rsrc_swhdl_free(pool_info, hdl);
23709e39c5baSBill Taylor 		return (DDI_FAILURE);
23719e39c5baSBill Taylor 	}
23729e39c5baSBill Taylor 	addr->pd_pdnum = (uint32_t)(uintptr_t)tmpaddr;
23739e39c5baSBill Taylor 	addr->pd_rsrcp = hdl;
23749e39c5baSBill Taylor 	hdl->hr_indx   = addr->pd_pdnum;
23759e39c5baSBill Taylor 
23769e39c5baSBill Taylor 	return (DDI_SUCCESS);
23779e39c5baSBill Taylor }
23789e39c5baSBill Taylor 
23799e39c5baSBill Taylor 
23809e39c5baSBill Taylor /*
23819e39c5baSBill Taylor  * hermon_rsrc_pdhdl_free()
23829e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
23839e39c5baSBill Taylor  */
23849e39c5baSBill Taylor static void
hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t * pool_info,hermon_rsrc_t * hdl)23859e39c5baSBill Taylor hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
23869e39c5baSBill Taylor {
23879e39c5baSBill Taylor 	ASSERT(pool_info != NULL);
23889e39c5baSBill Taylor 	ASSERT(hdl != NULL);
23899e39c5baSBill Taylor 
23909e39c5baSBill Taylor 	/* Use vmem_free() to free up the PD number */
23919e39c5baSBill Taylor 	vmem_free(pool_info->rsrc_vmp, (void *)(uintptr_t)hdl->hr_indx, 1);
23929e39c5baSBill Taylor 
23939e39c5baSBill Taylor 	/* Free the software handle structure */
23949e39c5baSBill Taylor 	hermon_rsrc_swhdl_free(pool_info, hdl);
23959e39c5baSBill Taylor }
23969e39c5baSBill Taylor 
23979e39c5baSBill Taylor 
23989e39c5baSBill Taylor /*
23999e39c5baSBill Taylor  * hermon_rsrc_pdhdl_constructor()
24009e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24019e39c5baSBill Taylor  */
24029e39c5baSBill Taylor /* ARGSUSED */
24039e39c5baSBill Taylor static int
hermon_rsrc_pdhdl_constructor(void * pd,void * priv,int flags)24049e39c5baSBill Taylor hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags)
24059e39c5baSBill Taylor {
24069e39c5baSBill Taylor 	hermon_pdhdl_t	pdhdl;
24079e39c5baSBill Taylor 	hermon_state_t	*state;
24089e39c5baSBill Taylor 
24099e39c5baSBill Taylor 	pdhdl = (hermon_pdhdl_t)pd;
24109e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
24119e39c5baSBill Taylor 
24129e39c5baSBill Taylor 	mutex_init(&pdhdl->pd_lock, NULL, MUTEX_DRIVER,
24139e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
24149e39c5baSBill Taylor 
24159e39c5baSBill Taylor 	return (DDI_SUCCESS);
24169e39c5baSBill Taylor }
24179e39c5baSBill Taylor 
24189e39c5baSBill Taylor 
24199e39c5baSBill Taylor /*
24209e39c5baSBill Taylor  * hermon_rsrc_pdhdl_destructor()
24219e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24229e39c5baSBill Taylor  */
24239e39c5baSBill Taylor /* ARGSUSED */
24249e39c5baSBill Taylor static void
hermon_rsrc_pdhdl_destructor(void * pd,void * priv)24259e39c5baSBill Taylor hermon_rsrc_pdhdl_destructor(void *pd, void *priv)
24269e39c5baSBill Taylor {
24279e39c5baSBill Taylor 	hermon_pdhdl_t	pdhdl;
24289e39c5baSBill Taylor 
24299e39c5baSBill Taylor 	pdhdl = (hermon_pdhdl_t)pd;
24309e39c5baSBill Taylor 
24319e39c5baSBill Taylor 	mutex_destroy(&pdhdl->pd_lock);
24329e39c5baSBill Taylor }
24339e39c5baSBill Taylor 
24349e39c5baSBill Taylor 
24359e39c5baSBill Taylor /*
24369e39c5baSBill Taylor  * hermon_rsrc_cqhdl_constructor()
24379e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24389e39c5baSBill Taylor  */
24399e39c5baSBill Taylor /* ARGSUSED */
24409e39c5baSBill Taylor static int
hermon_rsrc_cqhdl_constructor(void * cq,void * priv,int flags)24419e39c5baSBill Taylor hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags)
24429e39c5baSBill Taylor {
24439e39c5baSBill Taylor 	hermon_cqhdl_t	cqhdl;
24449e39c5baSBill Taylor 	hermon_state_t	*state;
24459e39c5baSBill Taylor 
24469e39c5baSBill Taylor 	cqhdl = (hermon_cqhdl_t)cq;
24479e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
24489e39c5baSBill Taylor 
24499e39c5baSBill Taylor 	mutex_init(&cqhdl->cq_lock, NULL, MUTEX_DRIVER,
24509e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
24519e39c5baSBill Taylor 
24529e39c5baSBill Taylor 	return (DDI_SUCCESS);
24539e39c5baSBill Taylor }
24549e39c5baSBill Taylor 
24559e39c5baSBill Taylor 
24569e39c5baSBill Taylor /*
24579e39c5baSBill Taylor  * hermon_rsrc_cqhdl_destructor()
24589e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24599e39c5baSBill Taylor  */
24609e39c5baSBill Taylor /* ARGSUSED */
24619e39c5baSBill Taylor static void
hermon_rsrc_cqhdl_destructor(void * cq,void * priv)24629e39c5baSBill Taylor hermon_rsrc_cqhdl_destructor(void *cq, void *priv)
24639e39c5baSBill Taylor {
24649e39c5baSBill Taylor 	hermon_cqhdl_t	cqhdl;
24659e39c5baSBill Taylor 
24669e39c5baSBill Taylor 	cqhdl = (hermon_cqhdl_t)cq;
24679e39c5baSBill Taylor 
24689e39c5baSBill Taylor 	mutex_destroy(&cqhdl->cq_lock);
24699e39c5baSBill Taylor }
24709e39c5baSBill Taylor 
24719e39c5baSBill Taylor 
24729e39c5baSBill Taylor /*
24739e39c5baSBill Taylor  * hermon_rsrc_qphdl_constructor()
24749e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24759e39c5baSBill Taylor  */
24769e39c5baSBill Taylor /* ARGSUSED */
24779e39c5baSBill Taylor static int
hermon_rsrc_qphdl_constructor(void * qp,void * priv,int flags)24789e39c5baSBill Taylor hermon_rsrc_qphdl_constructor(void *qp, void *priv, int flags)
24799e39c5baSBill Taylor {
24809e39c5baSBill Taylor 	hermon_qphdl_t	qphdl;
24819e39c5baSBill Taylor 	hermon_state_t	*state;
24829e39c5baSBill Taylor 
24839e39c5baSBill Taylor 	qphdl = (hermon_qphdl_t)qp;
24849e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
24859e39c5baSBill Taylor 
24869e39c5baSBill Taylor 	mutex_init(&qphdl->qp_lock, NULL, MUTEX_DRIVER,
24879e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
24889e39c5baSBill Taylor 
24899e39c5baSBill Taylor 	return (DDI_SUCCESS);
24909e39c5baSBill Taylor }
24919e39c5baSBill Taylor 
24929e39c5baSBill Taylor 
24939e39c5baSBill Taylor /*
24949e39c5baSBill Taylor  * hermon_rsrc_qphdl_destructor()
24959e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
24969e39c5baSBill Taylor  */
24979e39c5baSBill Taylor /* ARGSUSED */
24989e39c5baSBill Taylor static void
hermon_rsrc_qphdl_destructor(void * qp,void * priv)24999e39c5baSBill Taylor hermon_rsrc_qphdl_destructor(void *qp, void *priv)
25009e39c5baSBill Taylor {
25019e39c5baSBill Taylor 	hermon_qphdl_t	qphdl;
25029e39c5baSBill Taylor 
25039e39c5baSBill Taylor 	qphdl = (hermon_qphdl_t)qp;
25049e39c5baSBill Taylor 
25059e39c5baSBill Taylor 	mutex_destroy(&qphdl->qp_lock);
25069e39c5baSBill Taylor }
25079e39c5baSBill Taylor 
25089e39c5baSBill Taylor 
25099e39c5baSBill Taylor /*
25109e39c5baSBill Taylor  * hermon_rsrc_srqhdl_constructor()
25119e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25129e39c5baSBill Taylor  */
25139e39c5baSBill Taylor /* ARGSUSED */
25149e39c5baSBill Taylor static int
hermon_rsrc_srqhdl_constructor(void * srq,void * priv,int flags)25159e39c5baSBill Taylor hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags)
25169e39c5baSBill Taylor {
25179e39c5baSBill Taylor 	hermon_srqhdl_t	srqhdl;
25189e39c5baSBill Taylor 	hermon_state_t	*state;
25199e39c5baSBill Taylor 
25209e39c5baSBill Taylor 	srqhdl = (hermon_srqhdl_t)srq;
25219e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
25229e39c5baSBill Taylor 
25239e39c5baSBill Taylor 	mutex_init(&srqhdl->srq_lock, NULL, MUTEX_DRIVER,
25249e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
25259e39c5baSBill Taylor 
25269e39c5baSBill Taylor 	return (DDI_SUCCESS);
25279e39c5baSBill Taylor }
25289e39c5baSBill Taylor 
25299e39c5baSBill Taylor 
25309e39c5baSBill Taylor /*
25319e39c5baSBill Taylor  * hermon_rsrc_srqhdl_destructor()
25329e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25339e39c5baSBill Taylor  */
25349e39c5baSBill Taylor /* ARGSUSED */
25359e39c5baSBill Taylor static void
hermon_rsrc_srqhdl_destructor(void * srq,void * priv)25369e39c5baSBill Taylor hermon_rsrc_srqhdl_destructor(void *srq, void *priv)
25379e39c5baSBill Taylor {
25389e39c5baSBill Taylor 	hermon_srqhdl_t	srqhdl;
25399e39c5baSBill Taylor 
25409e39c5baSBill Taylor 	srqhdl = (hermon_srqhdl_t)srq;
25419e39c5baSBill Taylor 
25429e39c5baSBill Taylor 	mutex_destroy(&srqhdl->srq_lock);
25439e39c5baSBill Taylor }
25449e39c5baSBill Taylor 
25459e39c5baSBill Taylor 
25469e39c5baSBill Taylor /*
25479e39c5baSBill Taylor  * hermon_rsrc_refcnt_constructor()
25489e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25499e39c5baSBill Taylor  */
25509e39c5baSBill Taylor /* ARGSUSED */
25519e39c5baSBill Taylor static int
hermon_rsrc_refcnt_constructor(void * rc,void * priv,int flags)25529e39c5baSBill Taylor hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags)
25539e39c5baSBill Taylor {
25549e39c5baSBill Taylor 	hermon_sw_refcnt_t	*refcnt;
25559e39c5baSBill Taylor 	hermon_state_t		*state;
25569e39c5baSBill Taylor 
25579e39c5baSBill Taylor 	refcnt = (hermon_sw_refcnt_t *)rc;
25589e39c5baSBill Taylor 	state  = (hermon_state_t *)priv;
25599e39c5baSBill Taylor 
25609e39c5baSBill Taylor 	mutex_init(&refcnt->swrc_lock, NULL, MUTEX_DRIVER,
25619e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
25629e39c5baSBill Taylor 
25639e39c5baSBill Taylor 	return (DDI_SUCCESS);
25649e39c5baSBill Taylor }
25659e39c5baSBill Taylor 
25669e39c5baSBill Taylor 
25679e39c5baSBill Taylor /*
25689e39c5baSBill Taylor  * hermon_rsrc_refcnt_destructor()
25699e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25709e39c5baSBill Taylor  */
25719e39c5baSBill Taylor /* ARGSUSED */
25729e39c5baSBill Taylor static void
hermon_rsrc_refcnt_destructor(void * rc,void * priv)25739e39c5baSBill Taylor hermon_rsrc_refcnt_destructor(void *rc, void *priv)
25749e39c5baSBill Taylor {
25759e39c5baSBill Taylor 	hermon_sw_refcnt_t	*refcnt;
25769e39c5baSBill Taylor 
25779e39c5baSBill Taylor 	refcnt = (hermon_sw_refcnt_t *)rc;
25789e39c5baSBill Taylor 
25799e39c5baSBill Taylor 	mutex_destroy(&refcnt->swrc_lock);
25809e39c5baSBill Taylor }
25819e39c5baSBill Taylor 
25829e39c5baSBill Taylor 
25839e39c5baSBill Taylor /*
25849e39c5baSBill Taylor  * hermon_rsrc_ahhdl_constructor()
25859e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
25869e39c5baSBill Taylor  */
25879e39c5baSBill Taylor /* ARGSUSED */
25889e39c5baSBill Taylor static int
hermon_rsrc_ahhdl_constructor(void * ah,void * priv,int flags)25899e39c5baSBill Taylor hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags)
25909e39c5baSBill Taylor {
25919e39c5baSBill Taylor 	hermon_ahhdl_t	ahhdl;
25929e39c5baSBill Taylor 	hermon_state_t	*state;
25939e39c5baSBill Taylor 
25949e39c5baSBill Taylor 	ahhdl = (hermon_ahhdl_t)ah;
25959e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
25969e39c5baSBill Taylor 
25979e39c5baSBill Taylor 	mutex_init(&ahhdl->ah_lock, NULL, MUTEX_DRIVER,
25989e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
25999e39c5baSBill Taylor 	return (DDI_SUCCESS);
26009e39c5baSBill Taylor }
26019e39c5baSBill Taylor 
26029e39c5baSBill Taylor 
26039e39c5baSBill Taylor /*
26049e39c5baSBill Taylor  * hermon_rsrc_ahhdl_destructor()
26059e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
26069e39c5baSBill Taylor  */
26079e39c5baSBill Taylor /* ARGSUSED */
26089e39c5baSBill Taylor static void
hermon_rsrc_ahhdl_destructor(void * ah,void * priv)26099e39c5baSBill Taylor hermon_rsrc_ahhdl_destructor(void *ah, void *priv)
26109e39c5baSBill Taylor {
26119e39c5baSBill Taylor 	hermon_ahhdl_t	ahhdl;
26129e39c5baSBill Taylor 
26139e39c5baSBill Taylor 	ahhdl = (hermon_ahhdl_t)ah;
26149e39c5baSBill Taylor 
26159e39c5baSBill Taylor 	mutex_destroy(&ahhdl->ah_lock);
26169e39c5baSBill Taylor }
26179e39c5baSBill Taylor 
26189e39c5baSBill Taylor 
26199e39c5baSBill Taylor /*
26209e39c5baSBill Taylor  * hermon_rsrc_mrhdl_constructor()
26219e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
26229e39c5baSBill Taylor  */
26239e39c5baSBill Taylor /* ARGSUSED */
26249e39c5baSBill Taylor static int
hermon_rsrc_mrhdl_constructor(void * mr,void * priv,int flags)26259e39c5baSBill Taylor hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags)
26269e39c5baSBill Taylor {
26279e39c5baSBill Taylor 	hermon_mrhdl_t	mrhdl;
26289e39c5baSBill Taylor 	hermon_state_t	*state;
26299e39c5baSBill Taylor 
26309e39c5baSBill Taylor 	mrhdl = (hermon_mrhdl_t)mr;
26319e39c5baSBill Taylor 	state = (hermon_state_t *)priv;
26329e39c5baSBill Taylor 
26339e39c5baSBill Taylor 	mutex_init(&mrhdl->mr_lock, NULL, MUTEX_DRIVER,
26349e39c5baSBill Taylor 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
26359e39c5baSBill Taylor 
26369e39c5baSBill Taylor 	return (DDI_SUCCESS);
26379e39c5baSBill Taylor }
26389e39c5baSBill Taylor 
26399e39c5baSBill Taylor 
26409e39c5baSBill Taylor /*
26419e39c5baSBill Taylor  * hermon_rsrc_mrhdl_destructor()
26429e39c5baSBill Taylor  *    Context: Can be called from interrupt or base context.
26439e39c5baSBill Taylor  */
26449e39c5baSBill Taylor /* ARGSUSED */
26459e39c5baSBill Taylor static void
hermon_rsrc_mrhdl_destructor(void * mr,void * priv)26469e39c5baSBill Taylor hermon_rsrc_mrhdl_destructor(void *mr, void *priv)
26479e39c5baSBill Taylor {
26489e39c5baSBill Taylor 	hermon_mrhdl_t	mrhdl;
26499e39c5baSBill Taylor 
26509e39c5baSBill Taylor 	mrhdl = (hermon_mrhdl_t)mr;
26519e39c5baSBill Taylor 
26529e39c5baSBill Taylor 	mutex_destroy(&mrhdl->mr_lock);
26539e39c5baSBill Taylor }
26549e39c5baSBill Taylor 
26559e39c5baSBill Taylor 
26569e39c5baSBill Taylor /*
26579e39c5baSBill Taylor  * hermon_rsrc_mcg_entry_get_size()
26589e39c5baSBill Taylor  */
26599e39c5baSBill Taylor static int
hermon_rsrc_mcg_entry_get_size(hermon_state_t * state,uint_t * mcg_size_shift)26609e39c5baSBill Taylor hermon_rsrc_mcg_entry_get_size(hermon_state_t *state, uint_t *mcg_size_shift)
26619e39c5baSBill Taylor {
26629e39c5baSBill Taylor 	uint_t	num_qp_per_mcg, max_qp_per_mcg, log2;
26639e39c5baSBill Taylor 
26649e39c5baSBill Taylor 	/*
26659e39c5baSBill Taylor 	 * Round the configured number of QP per MCG to next larger
26669e39c5baSBill Taylor 	 * power-of-2 size and update.
26679e39c5baSBill Taylor 	 */
26689e39c5baSBill Taylor 	num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg + 8;
26699e39c5baSBill Taylor 	log2 = highbit(num_qp_per_mcg);
2670*de710d24SJosef 'Jeff' Sipek 	if (ISP2(num_qp_per_mcg)) {
26719e39c5baSBill Taylor 		log2 = log2 - 1;
26729e39c5baSBill Taylor 	}
26739e39c5baSBill Taylor 	state->hs_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
26749e39c5baSBill Taylor 
26759e39c5baSBill Taylor 	/* Now make sure number of QP per MCG makes sense */
26769e39c5baSBill Taylor 	num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg;
26779e39c5baSBill Taylor 	max_qp_per_mcg = (1 << state->hs_devlim.log_max_qp_mcg);
26789e39c5baSBill Taylor 	if (num_qp_per_mcg > max_qp_per_mcg) {
26799e39c5baSBill Taylor 		return (DDI_FAILURE);
26809e39c5baSBill Taylor 	}
26819e39c5baSBill Taylor 
26829e39c5baSBill Taylor 	/* Return the (shift) size of an individual MCG HW entry */
26839e39c5baSBill Taylor 	*mcg_size_shift = log2 + 2;
26849e39c5baSBill Taylor 
26859e39c5baSBill Taylor 	return (DDI_SUCCESS);
26869e39c5baSBill Taylor }
2687