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