1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * hermon_rsrc.c
28  *    Hermon Resource Management Routines
29  *
30  *    Implements all the routines necessary for setup, teardown, and
31  *    alloc/free of all Hermon resources, including those that are managed
32  *    by Hermon hardware or which live in Hermon's direct attached DDR memory.
33  */
34 
35 #include <sys/types.h>
36 #include <sys/conf.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/modctl.h>
40 #include <sys/vmem.h>
41 #include <sys/bitmap.h>
42 
43 #include <sys/ib/adapters/hermon/hermon.h>
44 
45 int hermon_rsrc_verbose = 0;
46 
47 /*
48  * The following routines are used for initializing and destroying
49  * the resource pools used by the Hermon resource allocation routines.
50  * They consist of four classes of object:
51  *
52  * Mailboxes:  The "In" and "Out" mailbox types are used by the Hermon
53  *    command interface routines.  Mailboxes are used to pass information
54  *    back and forth to the Hermon firmware.  Either type of mailbox may
55  *    be allocated from Hermon's direct attached DDR memory or from system
56  *    memory (although currently all "In" mailboxes are in DDR and all "out"
57  *    mailboxes come from system memory.
58  *
59  * HW entry objects:  These objects represent resources required by the Hermon
60  *    hardware.  These objects include things like Queue Pair contexts (QPC),
61  *    Completion Queue contexts (CQC), Event Queue contexts (EQC), RDB (for
62  *    supporting RDMA Read/Atomic), Multicast Group entries (MCG), Memory
63  *    Protection Table entries (MPT), Memory Translation Table entries (MTT).
64  *
65  *    What these objects all have in common is that they are each required
66  *    to come from ICM memory, they are always allocated from tables, and
67  *    they are not to be directly accessed (read or written) by driver
68  *    software (Mellanox FMR access to MPT is an exception).
69  *    The other notable exceptions are the UAR pages (UAR_PG) which are
70  *    allocated from the UAR address space rather than DDR, and the UD
71  *    address vectors (UDAV) which are similar to the common object types
72  *    with the major difference being that UDAVs _are_ directly read and
73  *    written by driver software.
74  *
75  * SW handle objects: These objects represent resources required by Hermon
76  *    driver software.  They are primarily software tracking structures,
77  *    which are allocated from system memory (using kmem_cache).  Several of
78  *    the objects have both a "constructor" and "destructor" method
79  *    associated with them (see below).
80  *
81  * Protection Domain (PD) handle objects:  These objects are very much like
82  *    a SW handle object with the notable difference that all PD handle
83  *    objects have an actual Protection Domain number (PD) associated with
84  *    them (and the PD number is allocated/managed through a separate
85  *    vmem_arena specifically set aside for this purpose.
86  */
87 
88 static int hermon_rsrc_mbox_init(hermon_state_t *state,
89     hermon_rsrc_mbox_info_t *info);
90 static void hermon_rsrc_mbox_fini(hermon_state_t *state,
91     hermon_rsrc_mbox_info_t *info);
92 
93 static int hermon_rsrc_sw_handles_init(hermon_state_t *state,
94     hermon_rsrc_sw_hdl_info_t *info);
95 static void hermon_rsrc_sw_handles_fini(hermon_state_t *state,
96     hermon_rsrc_sw_hdl_info_t *info);
97 
98 static int hermon_rsrc_pd_handles_init(hermon_state_t *state,
99     hermon_rsrc_sw_hdl_info_t *info);
100 static void hermon_rsrc_pd_handles_fini(hermon_state_t *state,
101     hermon_rsrc_sw_hdl_info_t *info);
102 
103 /*
104  * The following routines are used for allocating and freeing the specific
105  * types of objects described above from their associated resource pools.
106  */
107 static int hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info,
108     uint_t num, hermon_rsrc_t *hdl);
109 static void hermon_rsrc_mbox_free(hermon_rsrc_t *hdl);
110 
111 static int hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info,
112     uint_t num, uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl);
113 static void hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
114     hermon_rsrc_t *hdl);
115 static int hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t *pool_info,
116     uint_t num, uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl);
117 
118 static int hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info,
119     uint_t num, hermon_rsrc_t *hdl, int num_to_hdl);
120 static int hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
121     hermon_rsrc_t *hdl, int num_to_hdl);
122 
123 static int hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
124     uint_t sleepflag, hermon_rsrc_t *hdl);
125 static void hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info,
126     hermon_rsrc_t *hdl);
127 
128 static int hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
129     uint_t sleepflag, hermon_rsrc_t *hdl);
130 static void hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t *pool_info,
131     hermon_rsrc_t *hdl);
132 
133 static int hermon_rsrc_fexch_alloc(hermon_state_t *state,
134     hermon_rsrc_type_t rsrc, uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl);
135 static void hermon_rsrc_fexch_free(hermon_state_t *state, hermon_rsrc_t *hdl);
136 static int hermon_rsrc_rfci_alloc(hermon_state_t *state,
137     hermon_rsrc_type_t rsrc, uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl);
138 static void hermon_rsrc_rfci_free(hermon_state_t *state, hermon_rsrc_t *hdl);
139 
140 /*
141  * The following routines are the constructors and destructors for several
142  * of the SW handle type objects.  For certain types of SW handles objects
143  * (all of which are implemented using kmem_cache), we need to do some
144  * special field initialization (specifically, mutex_init/destroy).  These
145  * routines enable that init and teardown.
146  */
147 static int hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
148 static void hermon_rsrc_pdhdl_destructor(void *pd, void *state);
149 static int hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
150 static void hermon_rsrc_cqhdl_destructor(void *cq, void *state);
151 static int hermon_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
152 static void hermon_rsrc_qphdl_destructor(void *cq, void *state);
153 static int hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
154 static void hermon_rsrc_srqhdl_destructor(void *srq, void *state);
155 static int hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
156 static void hermon_rsrc_refcnt_destructor(void *rc, void *state);
157 static int hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
158 static void hermon_rsrc_ahhdl_destructor(void *ah, void *state);
159 static int hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
160 static void hermon_rsrc_mrhdl_destructor(void *mr, void *state);
161 
162 /*
163  * Special routine to calculate and return the size of a MCG object based
164  * on current driver configuration (specifically, the number of QP per MCG
165  * that has been configured.
166  */
167 static int hermon_rsrc_mcg_entry_get_size(hermon_state_t *state,
168     uint_t *mcg_size_shift);
169 
170 
171 /*
172  * hermon_rsrc_alloc()
173  *
174  *    Context: Can be called from interrupt or base context.
175  *    The "sleepflag" parameter is used by all object allocators to
176  *    determine whether to SLEEP for resources or not.
177  */
178 int
179 hermon_rsrc_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num,
180     uint_t sleepflag, hermon_rsrc_t **hdl)
181 {
182 	hermon_rsrc_pool_info_t	*rsrc_pool;
183 	hermon_rsrc_t		*tmp_rsrc_hdl;
184 	int			flag, status = DDI_FAILURE;
185 
186 	ASSERT(state != NULL);
187 	ASSERT(hdl != NULL);
188 
189 	rsrc_pool = &state->hs_rsrc_hdl[rsrc];
190 	ASSERT(rsrc_pool != NULL);
191 
192 	/*
193 	 * Allocate space for the object used to track the resource handle
194 	 */
195 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
196 	tmp_rsrc_hdl = kmem_cache_alloc(state->hs_rsrc_cache, flag);
197 	if (tmp_rsrc_hdl == NULL) {
198 		return (DDI_FAILURE);
199 	}
200 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
201 
202 	/*
203 	 * Set rsrc_hdl type.  This is later used by the hermon_rsrc_free call
204 	 * to know what type of resource is being freed.
205 	 */
206 	tmp_rsrc_hdl->rsrc_type = rsrc;
207 
208 	/*
209 	 * Depending on resource type, call the appropriate alloc routine
210 	 */
211 	switch (rsrc) {
212 	case HERMON_IN_MBOX:
213 	case HERMON_OUT_MBOX:
214 	case HERMON_INTR_IN_MBOX:
215 	case HERMON_INTR_OUT_MBOX:
216 		status = hermon_rsrc_mbox_alloc(rsrc_pool, num, tmp_rsrc_hdl);
217 		break;
218 
219 	case HERMON_DMPT:
220 		/* Allocate "num" (contiguous/aligned for FEXCH) DMPTs */
221 	case HERMON_QPC:
222 		/* Allocate "num" (contiguous/aligned for RSS) QPCs */
223 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, num,
224 		    sleepflag, tmp_rsrc_hdl);
225 		break;
226 
227 	case HERMON_QPC_FEXCH_PORT1:
228 	case HERMON_QPC_FEXCH_PORT2:
229 		/* Allocate "num" contiguous/aligned QPCs for FEXCH */
230 		status = hermon_rsrc_fexch_alloc(state, rsrc, num,
231 		    sleepflag, tmp_rsrc_hdl);
232 		break;
233 
234 	case HERMON_QPC_RFCI_PORT1:
235 	case HERMON_QPC_RFCI_PORT2:
236 		/* Allocate "num" contiguous/aligned QPCs for RFCI */
237 		status = hermon_rsrc_rfci_alloc(state, rsrc, num,
238 		    sleepflag, tmp_rsrc_hdl);
239 		break;
240 
241 	case HERMON_MTT:
242 	case HERMON_CQC:
243 	case HERMON_SRQC:
244 	case HERMON_EQC:
245 	case HERMON_MCG:
246 	case HERMON_UARPG:
247 		/* Allocate "num" unaligned resources */
248 		status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
249 		    sleepflag, tmp_rsrc_hdl);
250 		break;
251 
252 	case HERMON_MRHDL:
253 	case HERMON_EQHDL:
254 	case HERMON_CQHDL:
255 	case HERMON_SRQHDL:
256 	case HERMON_AHHDL:
257 	case HERMON_QPHDL:
258 	case HERMON_REFCNT:
259 		status = hermon_rsrc_swhdl_alloc(rsrc_pool, sleepflag,
260 		    tmp_rsrc_hdl);
261 		break;
262 
263 	case HERMON_PDHDL:
264 		status = hermon_rsrc_pdhdl_alloc(rsrc_pool, sleepflag,
265 		    tmp_rsrc_hdl);
266 		break;
267 
268 	case HERMON_RDB:	/* handled during HERMON_QPC */
269 	case HERMON_ALTC:	/* handled during HERMON_QPC */
270 	case HERMON_AUXC:	/* handled during HERMON_QPC */
271 	case HERMON_CMPT_QPC:	/* handled during HERMON_QPC */
272 	case HERMON_CMPT_SRQC:	/* handled during HERMON_SRQC */
273 	case HERMON_CMPT_CQC:	/* handled during HERMON_CPC */
274 	case HERMON_CMPT_EQC:	/* handled during HERMON_EPC */
275 	default:
276 		HERMON_WARNING(state, "unexpected resource type in alloc ");
277 		cmn_err(CE_WARN, "Resource type %x \n", rsrc_pool->rsrc_type);
278 		break;
279 	}
280 
281 	/*
282 	 * If the resource allocation failed, then free the special resource
283 	 * tracking structure and return failure.  Otherwise return the
284 	 * handle for the resource tracking structure.
285 	 */
286 	if (status != DDI_SUCCESS) {
287 		kmem_cache_free(state->hs_rsrc_cache, tmp_rsrc_hdl);
288 		return (DDI_FAILURE);
289 	} else {
290 		*hdl = tmp_rsrc_hdl;
291 		return (DDI_SUCCESS);
292 	}
293 }
294 
295 
296 /*
297  * hermon_rsrc_reserve()
298  *
299  *    Context: Can only be called from attach.
300  *    The "sleepflag" parameter is used by all object allocators to
301  *    determine whether to SLEEP for resources or not.
302  */
303 int
304 hermon_rsrc_reserve(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num,
305     uint_t sleepflag, hermon_rsrc_t **hdl)
306 {
307 	hermon_rsrc_pool_info_t	*rsrc_pool;
308 	hermon_rsrc_t		*tmp_rsrc_hdl;
309 	int			flag, status = DDI_FAILURE;
310 
311 	ASSERT(state != NULL);
312 	ASSERT(hdl != NULL);
313 
314 	rsrc_pool = &state->hs_rsrc_hdl[rsrc];
315 	ASSERT(rsrc_pool != NULL);
316 
317 	/*
318 	 * Allocate space for the object used to track the resource handle
319 	 */
320 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
321 	tmp_rsrc_hdl = kmem_cache_alloc(state->hs_rsrc_cache, flag);
322 	if (tmp_rsrc_hdl == NULL) {
323 		return (DDI_FAILURE);
324 	}
325 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
326 
327 	/*
328 	 * Set rsrc_hdl type.  This is later used by the hermon_rsrc_free call
329 	 * to know what type of resource is being freed.
330 	 */
331 	tmp_rsrc_hdl->rsrc_type = rsrc;
332 
333 	switch (rsrc) {
334 	case HERMON_QPC:
335 	case HERMON_DMPT:
336 	case HERMON_MTT:
337 		/*
338 		 * Reserve num resources, naturally aligned (N * num).
339 		 */
340 		status = hermon_rsrc_hw_entry_reserve(rsrc_pool, num, num,
341 		    sleepflag, tmp_rsrc_hdl);
342 		break;
343 
344 	default:
345 		HERMON_WARNING(state, "unexpected resource type in reserve ");
346 		cmn_err(CE_WARN, "Resource type %x \n", rsrc);
347 		break;
348 	}
349 
350 	/*
351 	 * If the resource allocation failed, then free the special resource
352 	 * tracking structure and return failure.  Otherwise return the
353 	 * handle for the resource tracking structure.
354 	 */
355 	if (status != DDI_SUCCESS) {
356 		kmem_cache_free(state->hs_rsrc_cache, tmp_rsrc_hdl);
357 		return (DDI_FAILURE);
358 	} else {
359 		*hdl = tmp_rsrc_hdl;
360 		return (DDI_SUCCESS);
361 	}
362 }
363 
364 
365 /*
366  * hermon_rsrc_fexch_alloc()
367  *
368  *    Context: Can only be called from base context.
369  *    The "sleepflag" parameter is used by all object allocators to
370  *    determine whether to SLEEP for resources or not.
371  */
372 static int
373 hermon_rsrc_fexch_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc,
374     uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl)
375 {
376 	hermon_fcoib_t		*fcoib;
377 	void			*addr;
378 	uint32_t		fexch_qpn_base;
379 	hermon_rsrc_pool_info_t	*qpc_pool, *mpt_pool, *mtt_pool;
380 	int			flag, status;
381 	hermon_rsrc_t		mpt_hdl; /* temporary, just for icm_confirm */
382 	hermon_rsrc_t		mtt_hdl; /* temporary, just for icm_confirm */
383 	uint_t			portm1;	/* hca_port_number - 1 */
384 	uint_t			nummtt;
385 	vmem_t			*vmp;
386 
387 	ASSERT(state != NULL);
388 	ASSERT(hdl != NULL);
389 
390 	if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
391 		return (DDI_FAILURE);
392 
393 	portm1 = rsrc - HERMON_QPC_FEXCH_PORT1;
394 	fcoib = &state->hs_fcoib;
395 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
396 
397 	/* Allocate from the FEXCH QP range */
398 	vmp = fcoib->hfc_fexch_vmemp[portm1];
399 	addr = vmem_xalloc(vmp, num, num, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
400 	if (addr == NULL) {
401 		return (DDI_FAILURE);
402 	}
403 	fexch_qpn_base = (uint32_t)((uintptr_t)addr -
404 	    fcoib->hfc_vmemstart + fcoib->hfc_fexch_base[portm1]);
405 
406 	/* ICM confirm for the FEXCH QP range */
407 	qpc_pool = &state->hs_rsrc_hdl[HERMON_QPC];
408 	hdl->hr_len = num << qpc_pool->rsrc_shift;
409 	hdl->hr_addr = addr;	/* used only for vmem_xfree */
410 	hdl->hr_indx = fexch_qpn_base;
411 
412 	status = hermon_rsrc_hw_entry_icm_confirm(qpc_pool, num, hdl, 1);
413 	if (status != DDI_SUCCESS) {
414 		vmem_xfree(vmp, addr, num);
415 		return (DDI_FAILURE);
416 	}
417 
418 	/* ICM confirm for the Primary MKEYs (client side only) */
419 	mpt_pool = &state->hs_rsrc_hdl[HERMON_DMPT];
420 	mpt_hdl.hr_len = num << mpt_pool->rsrc_shift;
421 	mpt_hdl.hr_addr = NULL;
422 	mpt_hdl.hr_indx = fcoib->hfc_mpt_base[portm1] +
423 	    (fexch_qpn_base - fcoib->hfc_fexch_base[portm1]);
424 
425 	status = hermon_rsrc_hw_entry_icm_confirm(mpt_pool, num, &mpt_hdl, 0);
426 	if (status != DDI_SUCCESS) {
427 		status = hermon_rsrc_hw_entry_icm_free(qpc_pool, hdl, 1);
428 		vmem_xfree(vmp, addr, num);
429 		return (DDI_FAILURE);
430 	}
431 
432 	/* ICM confirm for the MTTs of the Primary MKEYs (client side only) */
433 	nummtt = fcoib->hfc_mtts_per_mpt;
434 	num *= nummtt;
435 	mtt_pool = &state->hs_rsrc_hdl[HERMON_MTT];
436 	mtt_hdl.hr_len = num << mtt_pool->rsrc_shift;
437 	mtt_hdl.hr_addr = NULL;
438 	mtt_hdl.hr_indx = fcoib->hfc_mtt_base[portm1] +
439 	    (fexch_qpn_base - fcoib->hfc_fexch_base[portm1]) *
440 	    nummtt;
441 
442 	status = hermon_rsrc_hw_entry_icm_confirm(mtt_pool, num, &mtt_hdl, 0);
443 	if (status != DDI_SUCCESS) {
444 		vmem_xfree(vmp, addr, num);
445 		return (DDI_FAILURE);
446 	}
447 	return (DDI_SUCCESS);
448 }
449 
450 static void
451 hermon_rsrc_fexch_free(hermon_state_t *state, hermon_rsrc_t *hdl)
452 {
453 	hermon_fcoib_t		*fcoib;
454 	uint_t			portm1; /* hca_port_number - 1 */
455 
456 	ASSERT(state != NULL);
457 	ASSERT(hdl != NULL);
458 
459 	portm1 = hdl->rsrc_type - HERMON_QPC_FEXCH_PORT1;
460 	fcoib = &state->hs_fcoib;
461 	vmem_xfree(fcoib->hfc_fexch_vmemp[portm1], hdl->hr_addr,
462 	    hdl->hr_len >> state->hs_rsrc_hdl[HERMON_QPC].rsrc_shift);
463 }
464 
465 /*
466  * hermon_rsrc_rfci_alloc()
467  *
468  *    Context: Can only be called from base context.
469  *    The "sleepflag" parameter is used by all object allocators to
470  *    determine whether to SLEEP for resources or not.
471  */
472 static int
473 hermon_rsrc_rfci_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc,
474     uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl)
475 {
476 	hermon_fcoib_t		*fcoib;
477 	void			*addr;
478 	uint32_t		rfci_qpn_base;
479 	hermon_rsrc_pool_info_t	*qpc_pool;
480 	int			flag, status;
481 	uint_t			portm1;	/* hca_port_number - 1 */
482 	vmem_t			*vmp;
483 
484 	ASSERT(state != NULL);
485 	ASSERT(hdl != NULL);
486 
487 	if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
488 		return (DDI_FAILURE);
489 
490 	portm1 = rsrc - HERMON_QPC_RFCI_PORT1;
491 	fcoib = &state->hs_fcoib;
492 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
493 
494 	/* Allocate from the RFCI QP range */
495 	vmp = fcoib->hfc_rfci_vmemp[portm1];
496 	addr = vmem_xalloc(vmp, num, num, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
497 	if (addr == NULL) {
498 		return (DDI_FAILURE);
499 	}
500 	rfci_qpn_base = (uint32_t)((uintptr_t)addr -
501 	    fcoib->hfc_vmemstart + fcoib->hfc_rfci_base[portm1]);
502 
503 	/* ICM confirm for the RFCI QP */
504 	qpc_pool = &state->hs_rsrc_hdl[HERMON_QPC];
505 	hdl->hr_len = num << qpc_pool->rsrc_shift;
506 	hdl->hr_addr = addr;	/* used only for vmem_xfree */
507 	hdl->hr_indx = rfci_qpn_base;
508 
509 	status = hermon_rsrc_hw_entry_icm_confirm(qpc_pool, num, hdl, 1);
510 	if (status != DDI_SUCCESS) {
511 		vmem_xfree(vmp, addr, num);
512 		return (DDI_FAILURE);
513 	}
514 	return (DDI_SUCCESS);
515 }
516 
517 static void
518 hermon_rsrc_rfci_free(hermon_state_t *state, hermon_rsrc_t *hdl)
519 {
520 	hermon_fcoib_t		*fcoib;
521 	uint_t			portm1; /* hca_port_number - 1 */
522 
523 	ASSERT(state != NULL);
524 	ASSERT(hdl != NULL);
525 
526 	portm1 = hdl->rsrc_type - HERMON_QPC_RFCI_PORT1;
527 	fcoib = &state->hs_fcoib;
528 	vmem_xfree(fcoib->hfc_rfci_vmemp[portm1], hdl->hr_addr,
529 	    hdl->hr_len >> state->hs_rsrc_hdl[HERMON_QPC].rsrc_shift);
530 }
531 
532 
533 /*
534  * hermon_rsrc_free()
535  *    Context: Can be called from interrupt or base context.
536  */
537 void
538 hermon_rsrc_free(hermon_state_t *state, hermon_rsrc_t **hdl)
539 {
540 	hermon_rsrc_pool_info_t	*rsrc_pool;
541 
542 	ASSERT(state != NULL);
543 	ASSERT(hdl != NULL);
544 
545 	rsrc_pool = &state->hs_rsrc_hdl[(*hdl)->rsrc_type];
546 	ASSERT(rsrc_pool != NULL);
547 
548 	/*
549 	 * Depending on resource type, call the appropriate free routine
550 	 */
551 	switch (rsrc_pool->rsrc_type) {
552 	case HERMON_IN_MBOX:
553 	case HERMON_OUT_MBOX:
554 	case HERMON_INTR_IN_MBOX:
555 	case HERMON_INTR_OUT_MBOX:
556 		hermon_rsrc_mbox_free(*hdl);
557 		break;
558 
559 	case HERMON_QPC_FEXCH_PORT1:
560 	case HERMON_QPC_FEXCH_PORT2:
561 		hermon_rsrc_fexch_free(state, *hdl);
562 		break;
563 
564 	case HERMON_QPC_RFCI_PORT1:
565 	case HERMON_QPC_RFCI_PORT2:
566 		hermon_rsrc_rfci_free(state, *hdl);
567 		break;
568 
569 	case HERMON_QPC:
570 	case HERMON_CQC:
571 	case HERMON_SRQC:
572 	case HERMON_EQC:
573 	case HERMON_DMPT:
574 	case HERMON_MCG:
575 	case HERMON_MTT:
576 	case HERMON_UARPG:
577 		hermon_rsrc_hw_entry_free(rsrc_pool, *hdl);
578 		break;
579 
580 	case HERMON_MRHDL:
581 	case HERMON_EQHDL:
582 	case HERMON_CQHDL:
583 	case HERMON_SRQHDL:
584 	case HERMON_AHHDL:
585 	case HERMON_QPHDL:
586 	case HERMON_REFCNT:
587 		hermon_rsrc_swhdl_free(rsrc_pool, *hdl);
588 		break;
589 
590 	case HERMON_PDHDL:
591 		hermon_rsrc_pdhdl_free(rsrc_pool, *hdl);
592 		break;
593 
594 	case HERMON_RDB:
595 	case HERMON_ALTC:
596 	case HERMON_AUXC:
597 	case HERMON_CMPT_QPC:
598 	case HERMON_CMPT_SRQC:
599 	case HERMON_CMPT_CQC:
600 	case HERMON_CMPT_EQC:
601 	default:
602 		cmn_err(CE_CONT, "!rsrc_type = 0x%x\n", rsrc_pool->rsrc_type);
603 		break;
604 	}
605 
606 	/*
607 	 * Free the special resource tracking structure, set the handle to
608 	 * NULL, and return.
609 	 */
610 	kmem_cache_free(state->hs_rsrc_cache, *hdl);
611 	*hdl = NULL;
612 }
613 
614 
615 /*
616  * hermon_rsrc_init_phase1()
617  *
618  *    Completes the first phase of Hermon resource/configuration init.
619  *    This involves creating the kmem_cache for the "hermon_rsrc_t"
620  *    structs, allocating the space for the resource pool handles,
621  *    and setting up the "Out" mailboxes.
622  *
623  *    When this function completes, the Hermon driver is ready to
624  *    post the following commands which return information only in the
625  *    "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
626  *    If any of these commands are to be posted at this time, they must be
627  *    done so only when "spinning" (as the outstanding command list and
628  *    EQ setup code has not yet run)
629  *
630  *    Context: Only called from attach() path context
631  */
632 int
633 hermon_rsrc_init_phase1(hermon_state_t *state)
634 {
635 	hermon_rsrc_pool_info_t		*rsrc_pool;
636 	hermon_rsrc_mbox_info_t 		mbox_info;
637 	hermon_rsrc_cleanup_level_t	cleanup;
638 	hermon_cfg_profile_t		*cfgprof;
639 	uint64_t			num, size;
640 	int				status;
641 	char				*rsrc_name;
642 
643 	ASSERT(state != NULL);
644 
645 	/* This is where Phase 1 of resource initialization begins */
646 	cleanup = HERMON_RSRC_CLEANUP_LEVEL0;
647 
648 	/* Build kmem cache name from Hermon instance */
649 	rsrc_name = kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
650 	HERMON_RSRC_NAME(rsrc_name, HERMON_RSRC_CACHE);
651 
652 	/*
653 	 * Create the kmem_cache for "hermon_rsrc_t" structures
654 	 * (kmem_cache_create will SLEEP until successful)
655 	 */
656 	state->hs_rsrc_cache = kmem_cache_create(rsrc_name,
657 	    sizeof (hermon_rsrc_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
658 
659 	/*
660 	 * Allocate an array of hermon_rsrc_pool_info_t's (used in all
661 	 * subsequent resource allocations)
662 	 */
663 	state->hs_rsrc_hdl = kmem_zalloc(HERMON_NUM_RESOURCES *
664 	    sizeof (hermon_rsrc_pool_info_t), KM_SLEEP);
665 
666 	/* Pull in the configuration profile */
667 	cfgprof = state->hs_cfg_profile;
668 
669 	/* Initialize the resource pool for "out" mailboxes */
670 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_outmbox);
671 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
672 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
673 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
674 	rsrc_pool->rsrc_pool_size = (size * num);
675 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
676 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
677 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
678 	rsrc_pool->rsrc_state	  = state;
679 	mbox_info.mbi_num	  = num;
680 	mbox_info.mbi_size	  = size;
681 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
682 	status = hermon_rsrc_mbox_init(state, &mbox_info);
683 	if (status != DDI_SUCCESS) {
684 		hermon_rsrc_fini(state, cleanup);
685 		status = DDI_FAILURE;
686 		goto rsrcinitp1_fail;
687 	}
688 	cleanup = HERMON_RSRC_CLEANUP_LEVEL1;
689 
690 	/* Initialize the mailbox list */
691 	status = hermon_outmbox_list_init(state);
692 	if (status != DDI_SUCCESS) {
693 		hermon_rsrc_fini(state, cleanup);
694 		status = DDI_FAILURE;
695 		goto rsrcinitp1_fail;
696 	}
697 	cleanup = HERMON_RSRC_CLEANUP_LEVEL2;
698 
699 	/* Initialize the resource pool for "interrupt out" mailboxes */
700 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_outmbox);
701 	size =  ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
702 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
703 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
704 	rsrc_pool->rsrc_pool_size = (size * num);
705 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_outmbox_size;
706 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
707 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
708 	rsrc_pool->rsrc_state	  = state;
709 	mbox_info.mbi_num	  = num;
710 	mbox_info.mbi_size	  = size;
711 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
712 	status = hermon_rsrc_mbox_init(state, &mbox_info);
713 	if (status != DDI_SUCCESS) {
714 		hermon_rsrc_fini(state, cleanup);
715 		status = DDI_FAILURE;
716 		goto rsrcinitp1_fail;
717 	}
718 	cleanup = HERMON_RSRC_CLEANUP_LEVEL3;
719 
720 	/* Initialize the mailbox list */
721 	status = hermon_intr_outmbox_list_init(state);
722 	if (status != DDI_SUCCESS) {
723 		hermon_rsrc_fini(state, cleanup);
724 		status = DDI_FAILURE;
725 		goto rsrcinitp1_fail;
726 	}
727 	cleanup = HERMON_RSRC_CLEANUP_LEVEL4;
728 
729 	/* Initialize the resource pool for "in" mailboxes */
730 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_inmbox);
731 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
732 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
733 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
734 	rsrc_pool->rsrc_pool_size = (size * num);
735 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
736 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
737 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
738 	rsrc_pool->rsrc_state	  = state;
739 	mbox_info.mbi_num	  = num;
740 	mbox_info.mbi_size	  = size;
741 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
742 	status = hermon_rsrc_mbox_init(state, &mbox_info);
743 	if (status != DDI_SUCCESS) {
744 		hermon_rsrc_fini(state, cleanup);
745 		status = DDI_FAILURE;
746 		goto rsrcinitp1_fail;
747 	}
748 	cleanup = HERMON_RSRC_CLEANUP_LEVEL5;
749 
750 	/* Initialize the mailbox list */
751 	status = hermon_inmbox_list_init(state);
752 	if (status != DDI_SUCCESS) {
753 		hermon_rsrc_fini(state, cleanup);
754 		status = DDI_FAILURE;
755 		goto rsrcinitp1_fail;
756 	}
757 	cleanup = HERMON_RSRC_CLEANUP_LEVEL6;
758 
759 	/* Initialize the resource pool for "interrupt in" mailboxes */
760 	num  =  ((uint64_t)1 << cfgprof->cp_log_num_intr_inmbox);
761 	size =  ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
762 	rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
763 	rsrc_pool->rsrc_loc	  = HERMON_IN_SYSMEM;
764 	rsrc_pool->rsrc_pool_size = (size * num);
765 	rsrc_pool->rsrc_shift	  = cfgprof->cp_log_inmbox_size;
766 	rsrc_pool->rsrc_quantum	  = (uint_t)size;
767 	rsrc_pool->rsrc_align	  = HERMON_MBOX_ALIGN;
768 	rsrc_pool->rsrc_state	  = state;
769 	mbox_info.mbi_num	  = num;
770 	mbox_info.mbi_size	  = size;
771 	mbox_info.mbi_rsrcpool	  = rsrc_pool;
772 	status = hermon_rsrc_mbox_init(state, &mbox_info);
773 	if (status != DDI_SUCCESS) {
774 		hermon_rsrc_fini(state, cleanup);
775 		status = DDI_FAILURE;
776 		goto rsrcinitp1_fail;
777 	}
778 	cleanup = HERMON_RSRC_CLEANUP_LEVEL7;
779 
780 	/* Initialize the mailbox list */
781 	status = hermon_intr_inmbox_list_init(state);
782 	if (status != DDI_SUCCESS) {
783 		hermon_rsrc_fini(state, cleanup);
784 		status = DDI_FAILURE;
785 		goto rsrcinitp1_fail;
786 	}
787 	cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
788 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
789 	return (DDI_SUCCESS);
790 
791 rsrcinitp1_fail:
792 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
793 	return (status);
794 }
795 
796 
797 /*
798  * hermon_rsrc_init_phase2()
799  *    Context: Only called from attach() path context
800  */
801 int
802 hermon_rsrc_init_phase2(hermon_state_t *state)
803 {
804 	hermon_rsrc_sw_hdl_info_t	hdl_info;
805 	hermon_rsrc_hw_entry_info_t	entry_info;
806 	hermon_rsrc_pool_info_t		*rsrc_pool;
807 	hermon_rsrc_cleanup_level_t	cleanup, ncleanup;
808 	hermon_cfg_profile_t		*cfgprof;
809 	hermon_hw_querydevlim_t		*devlim;
810 	uint64_t			num, max, num_prealloc;
811 	uint_t				mcg_size, mcg_size_shift;
812 	int				i, status;
813 	char				*rsrc_name;
814 
815 	ASSERT(state != NULL);
816 
817 	/* Phase 2 initialization begins where Phase 1 left off */
818 	cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
819 
820 	/* Allocate the ICM resource name space */
821 
822 	/* Build the ICM vmem arena names from Hermon instance */
823 	rsrc_name = kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
824 
825 	/*
826 	 * Initialize the resource pools for all objects that exist in
827 	 * context memory (ICM). The ICM consists of context tables, each
828 	 * type of resource (QP, CQ, EQ, etc) having it's own context table
829 	 * (QPC, CQC, EQC, etc...).
830 	 */
831 	cfgprof = state->hs_cfg_profile;
832 	devlim	= &state->hs_devlim;
833 
834 	/*
835 	 * Initialize the resource pools for each of the driver resources.
836 	 * With a few exceptions, these resources fall into the two cateogories
837 	 * of either hw_entries or sw_entries.
838 	 */
839 
840 	/*
841 	 * Initialize the resource pools for ICM (hardware) types first.
842 	 * These resources are managed through vmem arenas, which are
843 	 * created via the rsrc pool initialization routine. Note that,
844 	 * due to further calculations, the MCG resource pool is
845 	 * initialized seperately.
846 	 */
847 	for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
848 
849 		rsrc_pool = &state->hs_rsrc_hdl[i];
850 		rsrc_pool->rsrc_type = i;
851 		rsrc_pool->rsrc_state = state;
852 
853 		/* Set the resource-specific attributes */
854 		switch (i) {
855 		case HERMON_MTT:
856 			max = ((uint64_t)1 << devlim->log_max_mtt);
857 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_mtt);
858 			HERMON_RSRC_NAME(rsrc_name, HERMON_MTT_VMEM);
859 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL9;
860 			break;
861 
862 		case HERMON_DMPT:
863 			max = ((uint64_t)1 << devlim->log_max_dmpt);
864 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_dmpt);
865 			HERMON_RSRC_NAME(rsrc_name, HERMON_DMPT_VMEM);
866 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL10;
867 			break;
868 
869 		case HERMON_QPC:
870 			max = ((uint64_t)1 << devlim->log_max_qp);
871 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_qp);
872 			HERMON_RSRC_NAME(rsrc_name, HERMON_QPC_VMEM);
873 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL11;
874 			break;
875 
876 		case HERMON_CQC:
877 			max = ((uint64_t)1 << devlim->log_max_cq);
878 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_cq);
879 			HERMON_RSRC_NAME(rsrc_name, HERMON_CQC_VMEM);
880 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL13;
881 			break;
882 
883 		case HERMON_SRQC:
884 			max = ((uint64_t)1 << devlim->log_max_srq);
885 			num_prealloc = ((uint64_t)1 << devlim->log_rsvd_srq);
886 			HERMON_RSRC_NAME(rsrc_name, HERMON_SRQC_VMEM);
887 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL16;
888 			break;
889 
890 		case HERMON_EQC:
891 			max = ((uint64_t)1 << devlim->log_max_eq);
892 			num_prealloc = state->hs_rsvd_eqs;
893 			HERMON_RSRC_NAME(rsrc_name, HERMON_EQC_VMEM);
894 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL18;
895 			break;
896 
897 		case HERMON_MCG:	/* handled below */
898 		case HERMON_AUXC:
899 		case HERMON_ALTC:
900 		case HERMON_RDB:
901 		case HERMON_CMPT_QPC:
902 		case HERMON_CMPT_SRQC:
903 		case HERMON_CMPT_CQC:
904 		case HERMON_CMPT_EQC:
905 		default:
906 			/* We don't need to initialize this rsrc here. */
907 			continue;
908 		}
909 
910 		/* Set the common values for all resource pools */
911 		rsrc_pool->rsrc_state	  = state;
912 		rsrc_pool->rsrc_loc	  = HERMON_IN_ICM;
913 		rsrc_pool->rsrc_pool_size = state->hs_icm[i].table_size;
914 		rsrc_pool->rsrc_align	  = state->hs_icm[i].table_size;
915 		rsrc_pool->rsrc_shift	  = state->hs_icm[i].log_object_size;
916 		rsrc_pool->rsrc_quantum	  = state->hs_icm[i].object_size;
917 
918 		/* Now, initialize the entry_info and call the init routine */
919 		entry_info.hwi_num	  = state->hs_icm[i].num_entries;
920 		entry_info.hwi_max	  = max;
921 		entry_info.hwi_prealloc	  = num_prealloc;
922 		entry_info.hwi_rsrcpool	  = rsrc_pool;
923 		entry_info.hwi_rsrcname	  = rsrc_name;
924 		status = hermon_rsrc_hw_entries_init(state, &entry_info);
925 		if (status != DDI_SUCCESS) {
926 			hermon_rsrc_fini(state, cleanup);
927 			status = DDI_FAILURE;
928 			goto rsrcinitp2_fail;
929 		}
930 		cleanup = ncleanup;
931 	}
932 
933 	/*
934 	 * Initialize the Multicast Group (MCG) entries. First, calculate
935 	 * (and validate) the size of the MCGs.
936 	 */
937 	status = hermon_rsrc_mcg_entry_get_size(state, &mcg_size_shift);
938 	if (status != DDI_SUCCESS) {
939 		hermon_rsrc_fini(state, cleanup);
940 		status = DDI_FAILURE;
941 		goto rsrcinitp2_fail;
942 	}
943 	mcg_size = HERMON_MCGMEM_SZ(state);
944 
945 	/*
946 	 * Initialize the resource pool for the MCG table entries.  Notice
947 	 * that the number of MCGs is configurable. Note also that a certain
948 	 * number of MCGs must be set aside for Hermon firmware use (they
949 	 * correspond to the number of MCGs used by the internal hash
950 	 * function).
951 	 */
952 	num			  = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
953 	max			  = ((uint64_t)1 << devlim->log_max_mcg);
954 	num_prealloc	  = ((uint64_t)1 << cfgprof->cp_log_num_mcg_hash);
955 	rsrc_pool		  = &state->hs_rsrc_hdl[HERMON_MCG];
956 	rsrc_pool->rsrc_loc	  = HERMON_IN_ICM;
957 	rsrc_pool->rsrc_pool_size = (mcg_size * num);
958 	rsrc_pool->rsrc_shift	  = mcg_size_shift;
959 	rsrc_pool->rsrc_quantum	  = mcg_size;
960 	rsrc_pool->rsrc_align	  = (mcg_size * num);
961 	rsrc_pool->rsrc_state	  = state;
962 	HERMON_RSRC_NAME(rsrc_name, HERMON_MCG_VMEM);
963 	entry_info.hwi_num	  = num;
964 	entry_info.hwi_max	  = max;
965 	entry_info.hwi_prealloc	  = num_prealloc;
966 	entry_info.hwi_rsrcpool	  = rsrc_pool;
967 	entry_info.hwi_rsrcname	  = rsrc_name;
968 	status = hermon_rsrc_hw_entries_init(state, &entry_info);
969 	if (status != DDI_SUCCESS) {
970 		hermon_rsrc_fini(state, cleanup);
971 		status = DDI_FAILURE;
972 		goto rsrcinitp2_fail;
973 	}
974 	cleanup = HERMON_RSRC_CLEANUP_LEVEL19;
975 
976 	/*
977 	 * Initialize the full range of ICM for the AUXC resource.
978 	 * This is done because its size is so small, about 1 byte per QP.
979 	 */
980 
981 	/*
982 	 * Initialize the Hermon command handling interfaces.  This step
983 	 * sets up the outstanding command tracking mechanism for easy access
984 	 * and fast allocation (see hermon_cmd.c for more details).
985 	 */
986 	status = hermon_outstanding_cmdlist_init(state);
987 	if (status != DDI_SUCCESS) {
988 		hermon_rsrc_fini(state, cleanup);
989 		status = DDI_FAILURE;
990 		goto rsrcinitp2_fail;
991 	}
992 	cleanup = HERMON_RSRC_CLEANUP_LEVEL20;
993 
994 	/* Initialize the resource pool and vmem arena for the PD handles */
995 	rsrc_pool		 = &state->hs_rsrc_hdl[HERMON_PDHDL];
996 	rsrc_pool->rsrc_loc	 = HERMON_IN_SYSMEM;
997 	rsrc_pool->rsrc_quantum	 = sizeof (struct hermon_sw_pd_s);
998 	rsrc_pool->rsrc_state	 = state;
999 	HERMON_RSRC_NAME(rsrc_name, HERMON_PDHDL_CACHE);
1000 	hdl_info.swi_num	 = ((uint64_t)1 << cfgprof->cp_log_num_pd);
1001 	hdl_info.swi_max	 = ((uint64_t)1 << devlim->log_max_pd);
1002 	hdl_info.swi_rsrcpool	 = rsrc_pool;
1003 	hdl_info.swi_constructor = hermon_rsrc_pdhdl_constructor;
1004 	hdl_info.swi_destructor	 = hermon_rsrc_pdhdl_destructor;
1005 	hdl_info.swi_rsrcname	 = rsrc_name;
1006 	hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1007 	status = hermon_rsrc_pd_handles_init(state, &hdl_info);
1008 	if (status != DDI_SUCCESS) {
1009 		hermon_rsrc_fini(state, cleanup);
1010 		status = DDI_FAILURE;
1011 		goto rsrcinitp2_fail;
1012 	}
1013 	cleanup = HERMON_RSRC_CLEANUP_LEVEL21;
1014 
1015 	/*
1016 	 * Initialize the resource pools for the rest of the software handles.
1017 	 * This includes MR handles, EQ handles, QP handles, etc.  These
1018 	 * objects are almost entirely managed using kmem_cache routines,
1019 	 * and do not utilize a vmem arena.
1020 	 */
1021 	for (i = HERMON_NUM_ICM_RESOURCES; i < HERMON_NUM_RESOURCES; i++) {
1022 		rsrc_pool = &state->hs_rsrc_hdl[i];
1023 		rsrc_pool->rsrc_type = i;
1024 
1025 		/* Set the resource-specific attributes */
1026 		switch (i) {
1027 		case HERMON_MRHDL:
1028 			rsrc_pool->rsrc_quantum =
1029 			    sizeof (struct hermon_sw_mr_s);
1030 			HERMON_RSRC_NAME(rsrc_name, HERMON_MRHDL_CACHE);
1031 			hdl_info.swi_num =
1032 			    ((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
1033 			    ((uint64_t)1 << cfgprof->cp_log_num_cmpt);
1034 			hdl_info.swi_max =
1035 			    ((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
1036 			    ((uint64_t)1 << cfgprof->cp_log_num_cmpt);
1037 			hdl_info.swi_constructor =
1038 			    hermon_rsrc_mrhdl_constructor;
1039 			hdl_info.swi_destructor	 = hermon_rsrc_mrhdl_destructor;
1040 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1041 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL22;
1042 			break;
1043 
1044 		case HERMON_EQHDL:
1045 			rsrc_pool->rsrc_quantum =
1046 			    sizeof (struct hermon_sw_eq_s);
1047 			HERMON_RSRC_NAME(rsrc_name, HERMON_EQHDL_CACHE);
1048 			hdl_info.swi_num = HERMON_NUM_EQ;
1049 			hdl_info.swi_max = ((uint64_t)1 << devlim->log_max_eq);
1050 			hdl_info.swi_constructor = NULL;
1051 			hdl_info.swi_destructor	 = NULL;
1052 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1053 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL23;
1054 			break;
1055 
1056 		case HERMON_CQHDL:
1057 			rsrc_pool->rsrc_quantum =
1058 			    sizeof (struct hermon_sw_cq_s);
1059 			HERMON_RSRC_NAME(rsrc_name, HERMON_CQHDL_CACHE);
1060 			hdl_info.swi_num =
1061 			    (uint64_t)1 << cfgprof->cp_log_num_cq;
1062 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_cq;
1063 			hdl_info.swi_constructor =
1064 			    hermon_rsrc_cqhdl_constructor;
1065 			hdl_info.swi_destructor	 = hermon_rsrc_cqhdl_destructor;
1066 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1067 			hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
1068 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL24;
1069 			break;
1070 
1071 		case HERMON_SRQHDL:
1072 			rsrc_pool->rsrc_quantum =
1073 			    sizeof (struct hermon_sw_srq_s);
1074 			HERMON_RSRC_NAME(rsrc_name, HERMON_SRQHDL_CACHE);
1075 			hdl_info.swi_num =
1076 			    (uint64_t)1 << cfgprof->cp_log_num_srq;
1077 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_srq;
1078 			hdl_info.swi_constructor =
1079 			    hermon_rsrc_srqhdl_constructor;
1080 			hdl_info.swi_destructor = hermon_rsrc_srqhdl_destructor;
1081 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1082 			hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
1083 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL25;
1084 			break;
1085 
1086 		case HERMON_AHHDL:
1087 			rsrc_pool->rsrc_quantum	=
1088 			    sizeof (struct hermon_sw_ah_s);
1089 			HERMON_RSRC_NAME(rsrc_name, HERMON_AHHDL_CACHE);
1090 			hdl_info.swi_num =
1091 			    (uint64_t)1 << cfgprof->cp_log_num_ah;
1092 			hdl_info.swi_max = HERMON_NUM_AH;
1093 			hdl_info.swi_constructor =
1094 			    hermon_rsrc_ahhdl_constructor;
1095 			hdl_info.swi_destructor	 = hermon_rsrc_ahhdl_destructor;
1096 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1097 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL26;
1098 			break;
1099 
1100 		case HERMON_QPHDL:
1101 			rsrc_pool->rsrc_quantum =
1102 			    sizeof (struct hermon_sw_qp_s);
1103 			HERMON_RSRC_NAME(rsrc_name, HERMON_QPHDL_CACHE);
1104 			hdl_info.swi_num =
1105 			    (uint64_t)1 << cfgprof->cp_log_num_qp;
1106 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_qp;
1107 			hdl_info.swi_constructor =
1108 			    hermon_rsrc_qphdl_constructor;
1109 			hdl_info.swi_destructor	= hermon_rsrc_qphdl_destructor;
1110 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1111 			hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
1112 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL27;
1113 			break;
1114 
1115 		case HERMON_REFCNT:
1116 			rsrc_pool->rsrc_quantum	 = sizeof (hermon_sw_refcnt_t);
1117 			HERMON_RSRC_NAME(rsrc_name, HERMON_REFCNT_CACHE);
1118 			hdl_info.swi_num =
1119 			    (uint64_t)1 << cfgprof->cp_log_num_dmpt;
1120 			hdl_info.swi_max = (uint64_t)1 << devlim->log_max_dmpt;
1121 			hdl_info.swi_constructor =
1122 			    hermon_rsrc_refcnt_constructor;
1123 			hdl_info.swi_destructor = hermon_rsrc_refcnt_destructor;
1124 			hdl_info.swi_flags	 = HERMON_SWHDL_KMEMCACHE_INIT;
1125 			ncleanup = HERMON_RSRC_CLEANUP_LEVEL28;
1126 			break;
1127 
1128 		default:
1129 			continue;
1130 		}
1131 
1132 		/* Set the common values and call the init routine */
1133 		rsrc_pool->rsrc_loc	 = HERMON_IN_SYSMEM;
1134 		rsrc_pool->rsrc_state    = state;
1135 		hdl_info.swi_rsrcpool    = rsrc_pool;
1136 		hdl_info.swi_rsrcname    = rsrc_name;
1137 		status = hermon_rsrc_sw_handles_init(state, &hdl_info);
1138 		if (status != DDI_SUCCESS) {
1139 			hermon_rsrc_fini(state, cleanup);
1140 			status = DDI_FAILURE;
1141 			goto rsrcinitp2_fail;
1142 		}
1143 		cleanup = ncleanup;
1144 	}
1145 
1146 	/*
1147 	 * Initialize a resource pool for the MCG handles.  Notice that for
1148 	 * these MCG handles, we are allocating a table of structures (used to
1149 	 * keep track of the MCG entries that are being written to hardware
1150 	 * and to speed up multicast attach/detach operations).
1151 	 */
1152 	hdl_info.swi_num	 = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1153 	hdl_info.swi_max	 = ((uint64_t)1 << devlim->log_max_mcg);
1154 	hdl_info.swi_flags	 = HERMON_SWHDL_TABLE_INIT;
1155 	hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
1156 	status = hermon_rsrc_sw_handles_init(state, &hdl_info);
1157 	if (status != DDI_SUCCESS) {
1158 		hermon_rsrc_fini(state, cleanup);
1159 		status = DDI_FAILURE;
1160 		goto rsrcinitp2_fail;
1161 	}
1162 	state->hs_mcghdl = hdl_info.swi_table_ptr;
1163 	cleanup = HERMON_RSRC_CLEANUP_LEVEL29;
1164 
1165 	/*
1166 	 * Last, initialize the resource pool for the UAR pages, which contain
1167 	 * the hardware's doorbell registers. Each process supported in User
1168 	 * Mode is assigned a UAR page. Also coming from this pool are the
1169 	 * kernel-assigned UAR page, and any hardware-reserved pages. Note
1170 	 * that the number of UAR pages is configurable, the value must be less
1171 	 * than the maximum value (obtained from the QUERY_DEV_LIM command) or
1172 	 * the initialization will fail.  Note also that we assign the base
1173 	 * address of the UAR BAR to the rsrc_start parameter.
1174 	 */
1175 	num			  = ((uint64_t)1 << cfgprof->cp_log_num_uar);
1176 	max			  = num;
1177 	num_prealloc		  = max(devlim->num_rsvd_uar, 128);
1178 	rsrc_pool		  = &state->hs_rsrc_hdl[HERMON_UARPG];
1179 	rsrc_pool->rsrc_loc	  = HERMON_IN_UAR;
1180 	rsrc_pool->rsrc_pool_size = (num << PAGESHIFT);
1181 	rsrc_pool->rsrc_shift	  = PAGESHIFT;
1182 	rsrc_pool->rsrc_quantum	  = (uint_t)PAGESIZE;
1183 	rsrc_pool->rsrc_align	  = PAGESIZE;
1184 	rsrc_pool->rsrc_state	  = state;
1185 	rsrc_pool->rsrc_start	  = (void *)state->hs_reg_uar_baseaddr;
1186 	HERMON_RSRC_NAME(rsrc_name, HERMON_UAR_PAGE_VMEM_ATTCH);
1187 	entry_info.hwi_num	  = num;
1188 	entry_info.hwi_max	  = max;
1189 	entry_info.hwi_prealloc	  = num_prealloc;
1190 	entry_info.hwi_rsrcpool	  = rsrc_pool;
1191 	entry_info.hwi_rsrcname	  = rsrc_name;
1192 	status = hermon_rsrc_hw_entries_init(state, &entry_info);
1193 	if (status != DDI_SUCCESS) {
1194 		hermon_rsrc_fini(state, cleanup);
1195 		status = DDI_FAILURE;
1196 		goto rsrcinitp2_fail;
1197 	}
1198 
1199 	cleanup = HERMON_RSRC_CLEANUP_ALL;
1200 
1201 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
1202 	return (DDI_SUCCESS);
1203 
1204 rsrcinitp2_fail:
1205 	kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
1206 	return (status);
1207 }
1208 
1209 
1210 /*
1211  * hermon_rsrc_fini()
1212  *    Context: Only called from attach() and/or detach() path contexts
1213  */
1214 void
1215 hermon_rsrc_fini(hermon_state_t *state, hermon_rsrc_cleanup_level_t clean)
1216 {
1217 	hermon_rsrc_sw_hdl_info_t	hdl_info;
1218 	hermon_rsrc_hw_entry_info_t	entry_info;
1219 	hermon_rsrc_mbox_info_t		mbox_info;
1220 	hermon_cfg_profile_t		*cfgprof;
1221 
1222 	ASSERT(state != NULL);
1223 
1224 	cfgprof = state->hs_cfg_profile;
1225 
1226 	/*
1227 	 * If init code above is shortened up (see comments), then we
1228 	 * need to establish how to safely and simply clean up from any
1229 	 * given failure point. Flags, maybe...
1230 	 */
1231 
1232 	switch (clean) {
1233 	/*
1234 	 * If we add more resources that need to be cleaned up here, we should
1235 	 * ensure that HERMON_RSRC_CLEANUP_ALL is still the first entry (i.e.
1236 	 * corresponds to the last resource allocated).
1237 	 */
1238 
1239 	case HERMON_RSRC_CLEANUP_ALL:
1240 	case HERMON_RSRC_CLEANUP_LEVEL31:
1241 		/* Cleanup the UAR page resource pool, first the dbr pages */
1242 		if (state->hs_kern_dbr) {
1243 			hermon_dbr_kern_free(state);
1244 			state->hs_kern_dbr = NULL;
1245 		}
1246 
1247 		/* NS then, the pool itself */
1248 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_UARPG];
1249 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1250 
1251 		/* FALLTHROUGH */
1252 
1253 	case HERMON_RSRC_CLEANUP_LEVEL30:
1254 		/* Cleanup the central MCG handle pointers list */
1255 		hdl_info.swi_rsrcpool  = NULL;
1256 		hdl_info.swi_table_ptr = state->hs_mcghdl;
1257 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1258 		hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
1259 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1260 		/* FALLTHROUGH */
1261 
1262 	case HERMON_RSRC_CLEANUP_LEVEL29:
1263 		/* Cleanup the reference count resource pool */
1264 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_REFCNT];
1265 		hdl_info.swi_table_ptr = NULL;
1266 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1267 		/* FALLTHROUGH */
1268 
1269 	case HERMON_RSRC_CLEANUP_LEVEL28:
1270 		/* Cleanup the QP handle resource pool */
1271 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_QPHDL];
1272 		hdl_info.swi_table_ptr = NULL;
1273 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
1274 		hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
1275 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1276 		/* FALLTHROUGH */
1277 	case HERMON_RSRC_CLEANUP_LEVEL27:
1278 		/* Cleanup the address handle resrouce pool */
1279 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_AHHDL];
1280 		hdl_info.swi_table_ptr = NULL;
1281 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1282 		/* FALLTHROUGH */
1283 
1284 	case HERMON_RSRC_CLEANUP_LEVEL26:
1285 		/* Cleanup the SRQ handle resource pool. */
1286 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_SRQHDL];
1287 		hdl_info.swi_table_ptr = NULL;
1288 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
1289 		hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
1290 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1291 		/* FALLTHROUGH */
1292 
1293 	case HERMON_RSRC_CLEANUP_LEVEL25:
1294 		/* Cleanup the CQ handle resource pool */
1295 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_CQHDL];
1296 		hdl_info.swi_table_ptr = NULL;
1297 		hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
1298 		hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
1299 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1300 		/* FALLTHROUGH */
1301 
1302 	case HERMON_RSRC_CLEANUP_LEVEL24:
1303 		/* Cleanup the EQ handle resource pool */
1304 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_EQHDL];
1305 		hdl_info.swi_table_ptr = NULL;
1306 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1307 		/* FALLTHROUGH */
1308 
1309 	case HERMON_RSRC_CLEANUP_LEVEL23:
1310 		/* Cleanup the MR handle resource pool */
1311 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_MRHDL];
1312 		hdl_info.swi_table_ptr = NULL;
1313 		hermon_rsrc_sw_handles_fini(state, &hdl_info);
1314 		/* FALLTHROUGH */
1315 
1316 	case HERMON_RSRC_CLEANUP_LEVEL22:
1317 		/* Cleanup the PD handle resource pool */
1318 		hdl_info.swi_rsrcpool  = &state->hs_rsrc_hdl[HERMON_PDHDL];
1319 		hdl_info.swi_table_ptr = NULL;
1320 		hermon_rsrc_pd_handles_fini(state, &hdl_info);
1321 		/* FALLTHROUGH */
1322 
1323 	case HERMON_RSRC_CLEANUP_LEVEL21:
1324 		/* Currently unused - FALLTHROUGH */
1325 
1326 	case HERMON_RSRC_CLEANUP_LEVEL20:
1327 		/* Cleanup the outstanding command list  */
1328 		hermon_outstanding_cmdlist_fini(state);
1329 		/* FALLTHROUGH */
1330 
1331 	case HERMON_RSRC_CLEANUP_LEVEL19:
1332 		/* Cleanup the EQC table resource pool */
1333 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_EQC];
1334 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1335 		/* FALLTHROUGH */
1336 
1337 	case HERMON_RSRC_CLEANUP_LEVEL18:
1338 		/* Cleanup the MCG table resource pool */
1339 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MCG];
1340 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1341 		/* FALLTHROUGH */
1342 
1343 	case HERMON_RSRC_CLEANUP_LEVEL17:
1344 		/* Currently Unused - fallthrough */
1345 	case HERMON_RSRC_CLEANUP_LEVEL16:
1346 		/* Cleanup the SRQC table resource pool */
1347 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_SRQC];
1348 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1349 		/* FALLTHROUGH */
1350 
1351 	case HERMON_RSRC_CLEANUP_LEVEL15:
1352 		/* Cleanup the AUXC table resource pool */
1353 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_AUXC];
1354 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1355 		/* FALLTHROUGH */
1356 
1357 	case HERMON_RSRC_CLEANUP_LEVEL14:
1358 		/* Cleanup the ALTCF table resource pool */
1359 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_ALTC];
1360 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1361 		/* FALLTHROUGH */
1362 
1363 	case HERMON_RSRC_CLEANUP_LEVEL13:
1364 		/* Cleanup the CQC table resource pool */
1365 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CQC];
1366 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1367 		/* FALLTHROUGH */
1368 
1369 	case HERMON_RSRC_CLEANUP_LEVEL12:
1370 		/* Cleanup the RDB table resource pool */
1371 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_RDB];
1372 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1373 		/* FALLTHROUGH */
1374 
1375 	case HERMON_RSRC_CLEANUP_LEVEL11:
1376 		/* Cleanup the QPC table resource pool */
1377 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_QPC];
1378 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1379 		/* FALLTHROUGH */
1380 
1381 	case HERMON_RSRC_CLEANUP_LEVEL10EQ:
1382 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1383 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_EQC];
1384 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1385 		/* FALLTHROUGH */
1386 
1387 	case HERMON_RSRC_CLEANUP_LEVEL10CQ:
1388 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1389 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_CQC];
1390 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1391 		/* FALLTHROUGH */
1392 
1393 	case HERMON_RSRC_CLEANUP_LEVEL10SRQ:
1394 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1395 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_SRQC];
1396 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1397 		/* FALLTHROUGH */
1398 
1399 	case HERMON_RSRC_CLEANUP_LEVEL10QP:
1400 		/* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1401 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_QPC];
1402 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1403 		/* FALLTHROUGH */
1404 
1405 	case HERMON_RSRC_CLEANUP_LEVEL10:
1406 		/* Cleanup the dMPT table resource pool */
1407 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_DMPT];
1408 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1409 		/* FALLTHROUGH */
1410 
1411 	case HERMON_RSRC_CLEANUP_LEVEL9:
1412 		/* Cleanup the MTT table resource pool */
1413 		entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MTT];
1414 		hermon_rsrc_hw_entries_fini(state, &entry_info);
1415 		break;
1416 
1417 	/*
1418 	 * The cleanup below comes from the "Phase 1" initialization step.
1419 	 * (see hermon_rsrc_init_phase1() above)
1420 	 */
1421 	case HERMON_RSRC_CLEANUP_PHASE1_COMPLETE:
1422 		/* Cleanup the "In" mailbox list  */
1423 		hermon_intr_inmbox_list_fini(state);
1424 		/* FALLTHROUGH */
1425 
1426 	case HERMON_RSRC_CLEANUP_LEVEL7:
1427 		/* Cleanup the interrupt "In" mailbox resource pool */
1428 		mbox_info.mbi_rsrcpool =
1429 		    &state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
1430 		hermon_rsrc_mbox_fini(state, &mbox_info);
1431 		/* FALLTHROUGH */
1432 
1433 	case HERMON_RSRC_CLEANUP_LEVEL6:
1434 		/* Cleanup the "In" mailbox list  */
1435 		hermon_inmbox_list_fini(state);
1436 		/* FALLTHROUGH */
1437 
1438 	case HERMON_RSRC_CLEANUP_LEVEL5:
1439 		/* Cleanup the "In" mailbox resource pool */
1440 		mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
1441 		hermon_rsrc_mbox_fini(state, &mbox_info);
1442 		/* FALLTHROUGH */
1443 
1444 	case HERMON_RSRC_CLEANUP_LEVEL4:
1445 		/* Cleanup the interrupt "Out" mailbox list  */
1446 		hermon_intr_outmbox_list_fini(state);
1447 		/* FALLTHROUGH */
1448 
1449 	case HERMON_RSRC_CLEANUP_LEVEL3:
1450 		/* Cleanup the "Out" mailbox resource pool */
1451 		mbox_info.mbi_rsrcpool =
1452 		    &state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
1453 		hermon_rsrc_mbox_fini(state, &mbox_info);
1454 		/* FALLTHROUGH */
1455 
1456 	case HERMON_RSRC_CLEANUP_LEVEL2:
1457 		/* Cleanup the "Out" mailbox list  */
1458 		hermon_outmbox_list_fini(state);
1459 		/* FALLTHROUGH */
1460 
1461 	case HERMON_RSRC_CLEANUP_LEVEL1:
1462 		/* Cleanup the "Out" mailbox resource pool */
1463 		mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
1464 		hermon_rsrc_mbox_fini(state, &mbox_info);
1465 		/* FALLTHROUGH */
1466 
1467 	case HERMON_RSRC_CLEANUP_LEVEL0:
1468 		/* Free the array of hermon_rsrc_pool_info_t's */
1469 
1470 		kmem_free(state->hs_rsrc_hdl, HERMON_NUM_RESOURCES *
1471 		    sizeof (hermon_rsrc_pool_info_t));
1472 
1473 		kmem_cache_destroy(state->hs_rsrc_cache);
1474 		break;
1475 
1476 	default:
1477 		HERMON_WARNING(state, "unexpected resource cleanup level");
1478 		break;
1479 	}
1480 }
1481 
1482 
1483 /*
1484  * hermon_rsrc_mbox_init()
1485  *    Context: Only called from attach() path context
1486  */
1487 static int
1488 hermon_rsrc_mbox_init(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
1489 {
1490 	hermon_rsrc_pool_info_t	*rsrc_pool;
1491 	hermon_rsrc_priv_mbox_t	*priv;
1492 
1493 	ASSERT(state != NULL);
1494 	ASSERT(info != NULL);
1495 
1496 	rsrc_pool = info->mbi_rsrcpool;
1497 	ASSERT(rsrc_pool != NULL);
1498 
1499 	/* Allocate and initialize mailbox private structure */
1500 	priv = kmem_zalloc(sizeof (hermon_rsrc_priv_mbox_t), KM_SLEEP);
1501 	priv->pmb_dip		= state->hs_dip;
1502 	priv->pmb_devaccattr	= state->hs_reg_accattr;
1503 	priv->pmb_xfer_mode	= DDI_DMA_CONSISTENT;
1504 
1505 	/*
1506 	 * Initialize many of the default DMA attributes.  Then set alignment
1507 	 * and scatter-gather restrictions specific for mailbox memory.
1508 	 */
1509 	hermon_dma_attr_init(state, &priv->pmb_dmaattr);
1510 	priv->pmb_dmaattr.dma_attr_align  = HERMON_MBOX_ALIGN;
1511 	priv->pmb_dmaattr.dma_attr_sgllen = 1;
1512 	priv->pmb_dmaattr.dma_attr_flags = 0;
1513 	rsrc_pool->rsrc_private = priv;
1514 
1515 	ASSERT(rsrc_pool->rsrc_loc == HERMON_IN_SYSMEM);
1516 
1517 	rsrc_pool->rsrc_start = NULL;
1518 	rsrc_pool->rsrc_vmp = NULL;
1519 
1520 	return (DDI_SUCCESS);
1521 }
1522 
1523 
1524 /*
1525  * hermon_rsrc_mbox_fini()
1526  *    Context: Only called from attach() and/or detach() path contexts
1527  */
1528 /* ARGSUSED */
1529 static void
1530 hermon_rsrc_mbox_fini(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
1531 {
1532 	hermon_rsrc_pool_info_t	*rsrc_pool;
1533 
1534 	ASSERT(state != NULL);
1535 	ASSERT(info != NULL);
1536 
1537 	rsrc_pool = info->mbi_rsrcpool;
1538 	ASSERT(rsrc_pool != NULL);
1539 
1540 	/* Free up the private struct */
1541 	kmem_free(rsrc_pool->rsrc_private, sizeof (hermon_rsrc_priv_mbox_t));
1542 }
1543 
1544 
1545 /*
1546  * hermon_rsrc_hw_entries_init()
1547  *    Context: Only called from attach() path context
1548  */
1549 int
1550 hermon_rsrc_hw_entries_init(hermon_state_t *state,
1551     hermon_rsrc_hw_entry_info_t *info)
1552 {
1553 	hermon_rsrc_pool_info_t	*rsrc_pool;
1554 	hermon_rsrc_t		*rsvd_rsrc = NULL;
1555 	vmem_t			*vmp;
1556 	uint64_t		num_hwentry, max_hwentry, num_prealloc;
1557 	int			status;
1558 
1559 	ASSERT(state != NULL);
1560 	ASSERT(info != NULL);
1561 
1562 	rsrc_pool	= info->hwi_rsrcpool;
1563 	ASSERT(rsrc_pool != NULL);
1564 	num_hwentry	= info->hwi_num;
1565 	max_hwentry	= info->hwi_max;
1566 	num_prealloc	= info->hwi_prealloc;
1567 
1568 	if (hermon_rsrc_verbose) {
1569 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init: "
1570 		    "rsrc_type (0x%x) num (%llx) max (0x%llx) prealloc "
1571 		    "(0x%llx)", rsrc_pool->rsrc_type, (longlong_t)num_hwentry,
1572 		    (longlong_t)max_hwentry, (longlong_t)num_prealloc);
1573 	}
1574 
1575 	/* Make sure number of HW entries makes sense */
1576 	if (num_hwentry > max_hwentry) {
1577 		return (DDI_FAILURE);
1578 	}
1579 
1580 	/* Set this pool's rsrc_start from the initial ICM allocation */
1581 	if (rsrc_pool->rsrc_start == 0) {
1582 
1583 		/* use a ROUND value that works on both 32 and 64-bit kernels */
1584 		rsrc_pool->rsrc_start = (void *)(uintptr_t)0x10000000;
1585 
1586 		if (hermon_rsrc_verbose) {
1587 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
1588 			    " rsrc_type (0x%x) rsrc_start set (0x%lx)",
1589 			    rsrc_pool->rsrc_type, rsrc_pool->rsrc_start);
1590 		}
1591 	}
1592 
1593 	/*
1594 	 * Create new vmem arena for the HW entries table if rsrc_quantum
1595 	 * is non-zero.  Otherwise if rsrc_quantum is zero, then these HW
1596 	 * entries are not going to be dynamically allocatable (i.e. they
1597 	 * won't be allocated/freed through hermon_rsrc_alloc/free).  This
1598 	 * latter option is used for both ALTC and CMPT resources which
1599 	 * are managed by hardware.
1600 	 */
1601 	if (rsrc_pool->rsrc_quantum != 0) {
1602 		vmp = vmem_create(info->hwi_rsrcname,
1603 		    (void *)(uintptr_t)rsrc_pool->rsrc_start,
1604 		    rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_quantum,
1605 		    NULL, NULL, NULL, 0, VM_SLEEP);
1606 		if (vmp == NULL) {
1607 			/* failed to create vmem arena */
1608 			return (DDI_FAILURE);
1609 		}
1610 		rsrc_pool->rsrc_vmp = vmp;
1611 		if (hermon_rsrc_verbose) {
1612 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
1613 			    " rsrc_type (0x%x) created vmem arena for rsrc",
1614 			    rsrc_pool->rsrc_type);
1615 		}
1616 	} else {
1617 		/* we do not require a vmem arena */
1618 		rsrc_pool->rsrc_vmp = NULL;
1619 		if (hermon_rsrc_verbose) {
1620 			IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
1621 			    " rsrc_type (0x%x) vmem arena not required",
1622 			    rsrc_pool->rsrc_type);
1623 		}
1624 	}
1625 
1626 	/* Allocate hardware reserved resources, if any */
1627 	if (num_prealloc != 0) {
1628 		status = hermon_rsrc_alloc(state, rsrc_pool->rsrc_type,
1629 		    num_prealloc, HERMON_SLEEP, &rsvd_rsrc);
1630 		if (status != DDI_SUCCESS) {
1631 			/* unable to preallocate the reserved entries */
1632 			if (rsrc_pool->rsrc_vmp != NULL) {
1633 				vmem_destroy(rsrc_pool->rsrc_vmp);
1634 			}
1635 			return (DDI_FAILURE);
1636 		}
1637 	}
1638 	rsrc_pool->rsrc_private = rsvd_rsrc;
1639 
1640 	return (DDI_SUCCESS);
1641 }
1642 
1643 
1644 /*
1645  * hermon_rsrc_hw_entries_fini()
1646  *    Context: Only called from attach() and/or detach() path contexts
1647  */
1648 void
1649 hermon_rsrc_hw_entries_fini(hermon_state_t *state,
1650     hermon_rsrc_hw_entry_info_t *info)
1651 {
1652 	hermon_rsrc_pool_info_t	*rsrc_pool;
1653 	hermon_rsrc_t		*rsvd_rsrc;
1654 
1655 	ASSERT(state != NULL);
1656 	ASSERT(info != NULL);
1657 
1658 	rsrc_pool = info->hwi_rsrcpool;
1659 	ASSERT(rsrc_pool != NULL);
1660 
1661 	/* Free up any "reserved" (i.e. preallocated) HW entries */
1662 	rsvd_rsrc = (hermon_rsrc_t *)rsrc_pool->rsrc_private;
1663 	if (rsvd_rsrc != NULL) {
1664 		hermon_rsrc_free(state, &rsvd_rsrc);
1665 	}
1666 
1667 	/*
1668 	 * If we've actually setup a vmem arena for the HW entries, then
1669 	 * destroy it now
1670 	 */
1671 	if (rsrc_pool->rsrc_vmp != NULL) {
1672 		vmem_destroy(rsrc_pool->rsrc_vmp);
1673 	}
1674 }
1675 
1676 
1677 /*
1678  * hermon_rsrc_sw_handles_init()
1679  *    Context: Only called from attach() path context
1680  */
1681 /* ARGSUSED */
1682 static int
1683 hermon_rsrc_sw_handles_init(hermon_state_t *state,
1684     hermon_rsrc_sw_hdl_info_t *info)
1685 {
1686 	hermon_rsrc_pool_info_t	*rsrc_pool;
1687 	uint64_t		num_swhdl, max_swhdl, prealloc_sz;
1688 
1689 	ASSERT(state != NULL);
1690 	ASSERT(info != NULL);
1691 
1692 	rsrc_pool	= info->swi_rsrcpool;
1693 	ASSERT(rsrc_pool != NULL);
1694 	num_swhdl	= info->swi_num;
1695 	max_swhdl	= info->swi_max;
1696 	prealloc_sz	= info->swi_prealloc_sz;
1697 
1698 
1699 	/* Make sure number of SW handles makes sense */
1700 	if (num_swhdl > max_swhdl) {
1701 		return (DDI_FAILURE);
1702 	}
1703 
1704 	/*
1705 	 * Depending on the flags parameter, create a kmem_cache for some
1706 	 * number of software handle structures.  Note: kmem_cache_create()
1707 	 * will SLEEP until successful.
1708 	 */
1709 	if (info->swi_flags & HERMON_SWHDL_KMEMCACHE_INIT) {
1710 		rsrc_pool->rsrc_private = kmem_cache_create(
1711 		    info->swi_rsrcname, rsrc_pool->rsrc_quantum, 0,
1712 		    info->swi_constructor, info->swi_destructor, NULL,
1713 		    rsrc_pool->rsrc_state, NULL, 0);
1714 	}
1715 
1716 
1717 	/* Allocate the central list of SW handle pointers */
1718 	if (info->swi_flags & HERMON_SWHDL_TABLE_INIT) {
1719 		info->swi_table_ptr = kmem_zalloc(num_swhdl * prealloc_sz,
1720 		    KM_SLEEP);
1721 	}
1722 
1723 	return (DDI_SUCCESS);
1724 }
1725 
1726 
1727 /*
1728  * hermon_rsrc_sw_handles_fini()
1729  *    Context: Only called from attach() and/or detach() path contexts
1730  */
1731 /* ARGSUSED */
1732 static void
1733 hermon_rsrc_sw_handles_fini(hermon_state_t *state,
1734     hermon_rsrc_sw_hdl_info_t *info)
1735 {
1736 	hermon_rsrc_pool_info_t	*rsrc_pool;
1737 	uint64_t		num_swhdl, prealloc_sz;
1738 
1739 	ASSERT(state != NULL);
1740 	ASSERT(info != NULL);
1741 
1742 	rsrc_pool	= info->swi_rsrcpool;
1743 	num_swhdl	= info->swi_num;
1744 	prealloc_sz	= info->swi_prealloc_sz;
1745 
1746 	/*
1747 	 * If a "software handle" kmem_cache exists for this resource, then
1748 	 * destroy it now
1749 	 */
1750 	if (rsrc_pool != NULL) {
1751 		kmem_cache_destroy(rsrc_pool->rsrc_private);
1752 	}
1753 
1754 	/* Free up this central list of SW handle pointers */
1755 	if (info->swi_table_ptr != NULL) {
1756 		kmem_free(info->swi_table_ptr, num_swhdl * prealloc_sz);
1757 	}
1758 }
1759 
1760 
1761 /*
1762  * hermon_rsrc_pd_handles_init()
1763  *    Context: Only called from attach() path context
1764  */
1765 static int
1766 hermon_rsrc_pd_handles_init(hermon_state_t *state,
1767     hermon_rsrc_sw_hdl_info_t *info)
1768 {
1769 	hermon_rsrc_pool_info_t	*rsrc_pool;
1770 	vmem_t			*vmp;
1771 	char			vmem_name[HERMON_RSRC_NAME_MAXLEN];
1772 	int			status;
1773 
1774 	ASSERT(state != NULL);
1775 	ASSERT(info != NULL);
1776 
1777 	rsrc_pool = info->swi_rsrcpool;
1778 	ASSERT(rsrc_pool != NULL);
1779 
1780 	/* Initialize the resource pool for software handle table */
1781 	status = hermon_rsrc_sw_handles_init(state, info);
1782 	if (status != DDI_SUCCESS) {
1783 		return (DDI_FAILURE);
1784 	}
1785 
1786 	/* Build vmem arena name from Hermon instance */
1787 	HERMON_RSRC_NAME(vmem_name, HERMON_PDHDL_VMEM);
1788 
1789 	/* Create new vmem arena for PD numbers */
1790 	vmp = vmem_create(vmem_name, (caddr_t)1, info->swi_num, 1, NULL,
1791 	    NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
1792 	if (vmp == NULL) {
1793 		/* Unable to create vmem arena */
1794 		info->swi_table_ptr = NULL;
1795 		hermon_rsrc_sw_handles_fini(state, info);
1796 		return (DDI_FAILURE);
1797 	}
1798 	rsrc_pool->rsrc_vmp = vmp;
1799 
1800 	return (DDI_SUCCESS);
1801 }
1802 
1803 
1804 /*
1805  * hermon_rsrc_pd_handles_fini()
1806  *    Context: Only called from attach() and/or detach() path contexts
1807  */
1808 static void
1809 hermon_rsrc_pd_handles_fini(hermon_state_t *state,
1810     hermon_rsrc_sw_hdl_info_t *info)
1811 {
1812 	hermon_rsrc_pool_info_t	*rsrc_pool;
1813 
1814 	ASSERT(state != NULL);
1815 	ASSERT(info != NULL);
1816 
1817 	rsrc_pool = info->swi_rsrcpool;
1818 
1819 	/* Destroy the specially created UAR scratch table vmem arena */
1820 	vmem_destroy(rsrc_pool->rsrc_vmp);
1821 
1822 	/* Destroy the "hermon_sw_pd_t" kmem_cache */
1823 	hermon_rsrc_sw_handles_fini(state, info);
1824 }
1825 
1826 
1827 /*
1828  * hermon_rsrc_mbox_alloc()
1829  *    Context: Only called from attach() path context
1830  */
1831 static int
1832 hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
1833     hermon_rsrc_t *hdl)
1834 {
1835 	hermon_rsrc_priv_mbox_t	*priv;
1836 	caddr_t			kaddr;
1837 	size_t			real_len, temp_len;
1838 	int			status;
1839 
1840 	ASSERT(pool_info != NULL);
1841 	ASSERT(hdl != NULL);
1842 
1843 	/* Get the private pointer for the mailboxes */
1844 	priv = pool_info->rsrc_private;
1845 	ASSERT(priv != NULL);
1846 
1847 	/* Allocate a DMA handle for the mailbox */
1848 	status = ddi_dma_alloc_handle(priv->pmb_dip, &priv->pmb_dmaattr,
1849 	    DDI_DMA_SLEEP, NULL, &hdl->hr_dmahdl);
1850 	if (status != DDI_SUCCESS) {
1851 		return (DDI_FAILURE);
1852 	}
1853 
1854 	/* Allocate memory for the mailbox */
1855 	temp_len = (num << pool_info->rsrc_shift);
1856 	status = ddi_dma_mem_alloc(hdl->hr_dmahdl, temp_len,
1857 	    &priv->pmb_devaccattr, priv->pmb_xfer_mode, DDI_DMA_SLEEP,
1858 	    NULL, &kaddr, &real_len, &hdl->hr_acchdl);
1859 	if (status != DDI_SUCCESS) {
1860 		/* No more memory available for mailbox entries */
1861 		ddi_dma_free_handle(&hdl->hr_dmahdl);
1862 		return (DDI_FAILURE);
1863 	}
1864 
1865 	hdl->hr_addr = (void *)kaddr;
1866 	hdl->hr_len  = (uint32_t)real_len;
1867 
1868 	return (DDI_SUCCESS);
1869 }
1870 
1871 
1872 /*
1873  * hermon_rsrc_mbox_free()
1874  *    Context: Can be called from interrupt or base context.
1875  */
1876 static void
1877 hermon_rsrc_mbox_free(hermon_rsrc_t *hdl)
1878 {
1879 	ASSERT(hdl != NULL);
1880 
1881 	/* Use ddi_dma_mem_free() to free up sys memory for mailbox */
1882 	ddi_dma_mem_free(&hdl->hr_acchdl);
1883 
1884 	/* Free the DMA handle for the mailbox */
1885 	ddi_dma_free_handle(&hdl->hr_dmahdl);
1886 }
1887 
1888 
1889 /*
1890  * hermon_rsrc_hw_entry_alloc()
1891  *    Context: Can be called from interrupt or base context.
1892  */
1893 static int
1894 hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
1895     uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl)
1896 {
1897 	void			*addr;
1898 	uint64_t		offset;
1899 	uint32_t		align;
1900 	int			status;
1901 	int			flag;
1902 
1903 	ASSERT(pool_info != NULL);
1904 	ASSERT(hdl != NULL);
1905 
1906 	/*
1907 	 * Use vmem_xalloc() to get a properly aligned pointer (based on
1908 	 * the number requested) to the HW entry(ies).  This handles the
1909 	 * cases (for special QPCs and for RDB entries) where we need more
1910 	 * than one and need to ensure that they are properly aligned.
1911 	 */
1912 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
1913 	hdl->hr_len = (num << pool_info->rsrc_shift);
1914 	align = (num_align << pool_info->rsrc_shift);
1915 
1916 	addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->hr_len,
1917 	    align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
1918 
1919 	if (addr == NULL) {
1920 		/* No more HW entries available */
1921 		return (DDI_FAILURE);
1922 	}
1923 
1924 	hdl->hr_acchdl = NULL;	/* only used for mbox resources */
1925 
1926 	/* Calculate vaddr and HW table index */
1927 	offset = (uintptr_t)addr - (uintptr_t)pool_info->rsrc_start;
1928 	hdl->hr_addr = addr;	/* only used for mbox and uarpg resources */
1929 	hdl->hr_indx = offset >> pool_info->rsrc_shift;
1930 
1931 	if (pool_info->rsrc_loc == HERMON_IN_ICM) {
1932 		int num_to_hdl;
1933 		hermon_rsrc_type_t rsrc_type = pool_info->rsrc_type;
1934 
1935 		num_to_hdl = (rsrc_type == HERMON_QPC ||
1936 		    rsrc_type == HERMON_CQC || rsrc_type == HERMON_SRQC);
1937 
1938 		/* confirm ICM is mapped, and allocate if necessary */
1939 		status = hermon_rsrc_hw_entry_icm_confirm(pool_info, num, hdl,
1940 		    num_to_hdl);
1941 		if (status != DDI_SUCCESS) {
1942 			return (DDI_FAILURE);
1943 		}
1944 		hdl->hr_addr = NULL;	/* not used for ICM resources */
1945 	}
1946 
1947 	return (DDI_SUCCESS);
1948 }
1949 
1950 
1951 /*
1952  * hermon_rsrc_hw_entry_reserve()
1953  *    Context: Can be called from interrupt or base context.
1954  */
1955 int
1956 hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t *pool_info, uint_t num,
1957     uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl)
1958 {
1959 	void			*addr;
1960 	uint64_t		offset;
1961 	uint32_t		align;
1962 	int			flag;
1963 
1964 	ASSERT(pool_info != NULL);
1965 	ASSERT(hdl != NULL);
1966 	ASSERT(pool_info->rsrc_loc == HERMON_IN_ICM);
1967 
1968 	/*
1969 	 * Use vmem_xalloc() to get a properly aligned pointer (based on
1970 	 * the number requested) to the HW entry(ies).  This handles the
1971 	 * cases (for special QPCs and for RDB entries) where we need more
1972 	 * than one and need to ensure that they are properly aligned.
1973 	 */
1974 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
1975 	hdl->hr_len = (num << pool_info->rsrc_shift);
1976 	align = (num_align << pool_info->rsrc_shift);
1977 
1978 	addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->hr_len,
1979 	    align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
1980 
1981 	if (addr == NULL) {
1982 		/* No more HW entries available */
1983 		return (DDI_FAILURE);
1984 	}
1985 
1986 	hdl->hr_acchdl = NULL;	/* only used for mbox resources */
1987 
1988 	/* Calculate vaddr and HW table index */
1989 	offset = (uintptr_t)addr - (uintptr_t)pool_info->rsrc_start;
1990 	hdl->hr_addr = NULL;
1991 	hdl->hr_indx = offset >> pool_info->rsrc_shift;
1992 
1993 	/* ICM will be allocated and mapped if and when it gets used */
1994 
1995 	return (DDI_SUCCESS);
1996 }
1997 
1998 
1999 /*
2000  * hermon_rsrc_hw_entry_free()
2001  *    Context: Can be called from interrupt or base context.
2002  */
2003 static void
2004 hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
2005     hermon_rsrc_t *hdl)
2006 {
2007 	void			*addr;
2008 	uint64_t		offset;
2009 	int			status;
2010 
2011 	ASSERT(pool_info != NULL);
2012 	ASSERT(hdl != NULL);
2013 
2014 	/* Calculate the allocated address */
2015 	offset = hdl->hr_indx << pool_info->rsrc_shift;
2016 	addr = (void *)(uintptr_t)(offset + (uintptr_t)pool_info->rsrc_start);
2017 
2018 	/* Use vmem_xfree() to free up the HW table entry */
2019 	vmem_xfree(pool_info->rsrc_vmp, addr, hdl->hr_len);
2020 
2021 	if (pool_info->rsrc_loc == HERMON_IN_ICM) {
2022 		int num_to_hdl;
2023 		hermon_rsrc_type_t rsrc_type = pool_info->rsrc_type;
2024 
2025 		num_to_hdl = (rsrc_type == HERMON_QPC ||
2026 		    rsrc_type == HERMON_CQC || rsrc_type == HERMON_SRQC);
2027 
2028 		/* free ICM references, and free ICM if required */
2029 		status = hermon_rsrc_hw_entry_icm_free(pool_info, hdl,
2030 		    num_to_hdl);
2031 		if (status != DDI_SUCCESS)
2032 			HERMON_WARNING(pool_info->rsrc_state,
2033 			    "failure in hw_entry_free");
2034 	}
2035 }
2036 
2037 /*
2038  * hermon_rsrc_hw_entry_icm_confirm()
2039  *    Context: Can be called from interrupt or base context.
2040  */
2041 static int
2042 hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info, uint_t num,
2043     hermon_rsrc_t *hdl, int num_to_hdl)
2044 {
2045 	hermon_state_t		*state;
2046 	hermon_icm_table_t	*icm_table;
2047 	uint8_t			*bitmap;
2048 	hermon_dma_info_t	*dma_info;
2049 	hermon_rsrc_type_t	type;
2050 	uint32_t		rindx, span_offset;
2051 	uint32_t		span_avail;
2052 	int			num_backed;
2053 	int			status;
2054 	uint32_t		index1, index2;
2055 
2056 	/*
2057 	 * Utility routine responsible for ensuring that there is memory
2058 	 * backing the ICM resources allocated via hermon_rsrc_hw_entry_alloc().
2059 	 * Confirm existing ICM mapping(s) or allocate ICM memory for the
2060 	 * given hardware resources being allocated, and increment the
2061 	 * ICM DMA structure(s) reference count.
2062 	 *
2063 	 * We may be allocating more objects than can fit in a single span,
2064 	 * or more than will fit in the remaining contiguous memory (from
2065 	 * the offset indicated by hdl->ar_indx) in the span in question.
2066 	 * In either of these cases, we'll be breaking up our allocation
2067 	 * into multiple spans.
2068 	 */
2069 	state = pool_info->rsrc_state;
2070 	type  = pool_info->rsrc_type;
2071 	icm_table = &state->hs_icm[type];
2072 
2073 	rindx = hdl->hr_indx;
2074 	hermon_index(index1, index2, rindx, icm_table, span_offset);
2075 
2076 	if (hermon_rsrc_verbose) {
2077 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_confirm: "
2078 		    "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x): ",
2079 		    type, num, hdl->hr_len, index1, index2);
2080 	}
2081 
2082 	mutex_enter(&icm_table->icm_table_lock);
2083 	hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
2084 	while (num) {
2085 #ifndef __lock_lint
2086 		while (icm_table->icm_busy) {
2087 			cv_wait(&icm_table->icm_table_cv,
2088 			    &icm_table->icm_table_lock);
2089 		}
2090 #endif
2091 		if (!HERMON_BMAP_BIT_ISSET(bitmap, index2)) {
2092 			/* Allocate ICM for this span */
2093 			icm_table->icm_busy = 1;
2094 			mutex_exit(&icm_table->icm_table_lock);
2095 			status = hermon_icm_alloc(state, type, index1, index2);
2096 			mutex_enter(&icm_table->icm_table_lock);
2097 			icm_table->icm_busy = 0;
2098 			cv_broadcast(&icm_table->icm_table_cv);
2099 			if (status != DDI_SUCCESS) {
2100 				goto fail_alloc;
2101 			}
2102 			if (hermon_rsrc_verbose) {
2103 				IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
2104 				    "hw_entry_icm_confirm: ALLOCATED ICM: "
2105 				    "type (0x%x) index (0x%x, 0x%x)",
2106 				    type, index1, index2);
2107 			}
2108 		}
2109 
2110 		/*
2111 		 * We need to increment the refcnt of this span by the
2112 		 * number of objects in this resource allocation that are
2113 		 * backed by this span. Given that the rsrc allocation is
2114 		 * contiguous, this value will be the number of objects in
2115 		 * the span from 'span_offset' onward, either up to a max
2116 		 * of the total number of objects, or the end of the span.
2117 		 * So, determine the number of objects that can be backed
2118 		 * by this span ('span_avail'), then determine the number
2119 		 * of backed resources.
2120 		 */
2121 		span_avail = icm_table->span - span_offset;
2122 		if (num > span_avail) {
2123 			num_backed = span_avail;
2124 		} else {
2125 			num_backed = num;
2126 		}
2127 
2128 		/*
2129 		 * Now that we know 'num_backed', increment the refcnt,
2130 		 * decrement the total number, and set 'span_offset' to
2131 		 * 0 in case we roll over into the next span.
2132 		 */
2133 		dma_info[index2].icm_refcnt += num_backed;
2134 		rindx += num_backed;
2135 		num -= num_backed;
2136 
2137 		if (hermon_rsrc_verbose) {
2138 			IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) index "
2139 			    "(0x%x, 0x%x) num_backed (0x%x)",
2140 			    type, index1, index2, num_backed);
2141 			IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) refcnt now "
2142 			    "(0x%x) num_remaining (0x%x)", type,
2143 			    dma_info[index2].icm_refcnt, num);
2144 		}
2145 		if (num == 0)
2146 			break;
2147 
2148 		hermon_index(index1, index2, rindx, icm_table, span_offset);
2149 		hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
2150 	}
2151 	mutex_exit(&icm_table->icm_table_lock);
2152 
2153 	return (DDI_SUCCESS);
2154 
2155 fail_alloc:
2156 	/* JBDB */
2157 	if (hermon_rsrc_verbose) {
2158 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
2159 		    "hw_entry_icm_confirm: FAILED ICM ALLOC: "
2160 		    "type (0x%x) num remaind (0x%x) index (0x%x, 0x%x)"
2161 		    "refcnt (0x%x)", type, num, index1, index2,
2162 		    icm_table->icm_dma[index1][index2].icm_refcnt);
2163 	}
2164 	IBTF_DPRINTF_L2("hermon", "WARNING: "
2165 	    "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
2166 
2167 #if needs_work
2168 	/* free refcnt's and any spans we've allocated */
2169 	while (index-- != start) {
2170 		/*
2171 		 * JBDB - This is a bit tricky.  We need to
2172 		 * free refcnt's on any spans that we've
2173 		 * incremented them on, and completely free
2174 		 * spans that we've allocated. How do we do
2175 		 * this here? Does it need to be as involved
2176 		 * as the core of icm_free() below, or can
2177 		 * we leverage breadcrumbs somehow?
2178 		 */
2179 		HERMON_WARNING(state, "unable to allocate ICM memory: "
2180 		    "UNIMPLEMENTED HANDLING!!");
2181 	}
2182 #else
2183 	cmn_err(CE_WARN,
2184 	    "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
2185 #endif
2186 	mutex_exit(&icm_table->icm_table_lock);
2187 
2188 	HERMON_WARNING(state, "unable to allocate ICM memory");
2189 	return (DDI_FAILURE);
2190 }
2191 
2192 /*
2193  * hermon_rsrc_hw_entry_icm_free()
2194  *    Context: Can be called from interrupt or base context.
2195  */
2196 static int
2197 hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
2198     hermon_rsrc_t *hdl, int num_to_hdl)
2199 {
2200 	hermon_state_t		*state;
2201 	hermon_icm_table_t	*icm_table;
2202 	uint8_t			*bitmap;
2203 	hermon_dma_info_t	*dma_info;
2204 	hermon_rsrc_type_t	type;
2205 	uint32_t		span_offset;
2206 	uint32_t		span_remain;
2207 	int			num_freed;
2208 	int			num;
2209 	uint32_t		index1, index2, rindx;
2210 
2211 	/*
2212 	 * Utility routine responsible for freeing references to ICM
2213 	 * DMA spans, and freeing the ICM memory if necessary.
2214 	 *
2215 	 * We may have allocated objects in a single contiguous resource
2216 	 * allocation that reside in a number of spans, at any given
2217 	 * starting offset within a span. We therefore must determine
2218 	 * where this allocation starts, and then determine if we need
2219 	 * to free objects in more than one span.
2220 	 */
2221 	state = pool_info->rsrc_state;
2222 	type  = pool_info->rsrc_type;
2223 	icm_table = &state->hs_icm[type];
2224 
2225 	rindx = hdl->hr_indx;
2226 	hermon_index(index1, index2, rindx, icm_table, span_offset);
2227 	hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
2228 
2229 	/* determine the number of ICM objects in this allocation */
2230 	num = hdl->hr_len >> pool_info->rsrc_shift;
2231 
2232 	if (hermon_rsrc_verbose) {
2233 		IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_free: "
2234 		    "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x)",
2235 		    type, num, hdl->hr_len, index1, index2);
2236 	}
2237 	mutex_enter(&icm_table->icm_table_lock);
2238 	while (num) {
2239 		/*
2240 		 * As with the ICM confirm code above, we need to
2241 		 * decrement the ICM span(s) by the number of
2242 		 * resources being freed. So, determine the number
2243 		 * of objects that are backed in this span from
2244 		 * 'span_offset' onward, and set 'num_freed' to
2245 		 * the smaller of either that number ('span_remain'),
2246 		 * or the total number of objects being freed.
2247 		 */
2248 		span_remain = icm_table->span - span_offset;
2249 		if (num > span_remain) {
2250 			num_freed = span_remain;
2251 		} else {
2252 			num_freed = num;
2253 		}
2254 
2255 		/*
2256 		 * Now that we know 'num_freed', decrement the refcnt,
2257 		 * decrement the total number, and set 'span_offset' to
2258 		 * 0 in case we roll over into the next span.
2259 		 */
2260 		dma_info[index2].icm_refcnt -= num_freed;
2261 		num -= num_freed;
2262 		rindx += num_freed;
2263 
2264 		if (hermon_rsrc_verbose) {
2265 			IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) index "
2266 			    "(0x%x, 0x%x) num_freed (0x%x)", type,
2267 			    index1, index2, num_freed);
2268 			IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) refcnt now "
2269 			    "(0x%x) num remaining (0x%x)", type,
2270 			    icm_table->icm_dma[index1][index2].icm_refcnt, num);
2271 		}
2272 
2273 #if HERMON_ICM_FREE_ENABLED
2274 		/* If we've freed the last object in this span, free it */
2275 		if ((index1 != 0 || index2 != 0) &&
2276 		    (dma_info[index2].icm_refcnt == 0)) {
2277 			if (hermon_rsrc_verbose) {
2278 				IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry"
2279 				    "_icm_free: freeing ICM type (0x%x) index"
2280 				    " (0x%x, 0x%x)", type, index1, index2);
2281 			}
2282 			hermon_icm_free(state, type, index1, index2);
2283 		}
2284 #endif
2285 		if (num == 0)
2286 			break;
2287 
2288 		hermon_index(index1, index2, rindx, icm_table, span_offset);
2289 		hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
2290 	}
2291 	mutex_exit(&icm_table->icm_table_lock);
2292 
2293 	return (DDI_SUCCESS);
2294 }
2295 
2296 
2297 
2298 /*
2299  * hermon_rsrc_swhdl_alloc()
2300  *    Context: Can be called from interrupt or base context.
2301  */
2302 static int
2303 hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
2304     hermon_rsrc_t *hdl)
2305 {
2306 	void	*addr;
2307 	int	flag;
2308 
2309 	ASSERT(pool_info != NULL);
2310 	ASSERT(hdl != NULL);
2311 
2312 	/* Allocate the software handle structure */
2313 	flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
2314 	addr = kmem_cache_alloc(pool_info->rsrc_private, flag);
2315 	if (addr == NULL) {
2316 		return (DDI_FAILURE);
2317 	}
2318 	hdl->hr_len  = pool_info->rsrc_quantum;
2319 	hdl->hr_addr = addr;
2320 
2321 	return (DDI_SUCCESS);
2322 }
2323 
2324 
2325 /*
2326  * hermon_rsrc_swhdl_free()
2327  *    Context: Can be called from interrupt or base context.
2328  */
2329 static void
2330 hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
2331 {
2332 	ASSERT(pool_info != NULL);
2333 	ASSERT(hdl != NULL);
2334 
2335 	/* Free the software handle structure */
2336 	kmem_cache_free(pool_info->rsrc_private, hdl->hr_addr);
2337 }
2338 
2339 
2340 /*
2341  * hermon_rsrc_pdhdl_alloc()
2342  *    Context: Can be called from interrupt or base context.
2343  */
2344 static int
2345 hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
2346     hermon_rsrc_t *hdl)
2347 {
2348 	hermon_pdhdl_t	addr;
2349 	void		*tmpaddr;
2350 	int		flag, status;
2351 
2352 	ASSERT(pool_info != NULL);
2353 	ASSERT(hdl != NULL);
2354 
2355 	/* Allocate the software handle */
2356 	status = hermon_rsrc_swhdl_alloc(pool_info, sleepflag, hdl);
2357 	if (status != DDI_SUCCESS) {
2358 		return (DDI_FAILURE);
2359 	}
2360 	addr = (hermon_pdhdl_t)hdl->hr_addr;
2361 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr))
2362 
2363 	/* Allocate a PD number for the handle */
2364 	flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
2365 	tmpaddr = vmem_alloc(pool_info->rsrc_vmp, 1, flag);
2366 	if (tmpaddr == NULL) {
2367 		/* No more PD number entries available */
2368 		hermon_rsrc_swhdl_free(pool_info, hdl);
2369 		return (DDI_FAILURE);
2370 	}
2371 	addr->pd_pdnum = (uint32_t)(uintptr_t)tmpaddr;
2372 	addr->pd_rsrcp = hdl;
2373 	hdl->hr_indx   = addr->pd_pdnum;
2374 
2375 	return (DDI_SUCCESS);
2376 }
2377 
2378 
2379 /*
2380  * hermon_rsrc_pdhdl_free()
2381  *    Context: Can be called from interrupt or base context.
2382  */
2383 static void
2384 hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
2385 {
2386 	ASSERT(pool_info != NULL);
2387 	ASSERT(hdl != NULL);
2388 
2389 	/* Use vmem_free() to free up the PD number */
2390 	vmem_free(pool_info->rsrc_vmp, (void *)(uintptr_t)hdl->hr_indx, 1);
2391 
2392 	/* Free the software handle structure */
2393 	hermon_rsrc_swhdl_free(pool_info, hdl);
2394 }
2395 
2396 
2397 /*
2398  * hermon_rsrc_pdhdl_constructor()
2399  *    Context: Can be called from interrupt or base context.
2400  */
2401 /* ARGSUSED */
2402 static int
2403 hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags)
2404 {
2405 	hermon_pdhdl_t	pdhdl;
2406 	hermon_state_t	*state;
2407 
2408 	pdhdl = (hermon_pdhdl_t)pd;
2409 	state = (hermon_state_t *)priv;
2410 
2411 	mutex_init(&pdhdl->pd_lock, NULL, MUTEX_DRIVER,
2412 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
2413 
2414 	return (DDI_SUCCESS);
2415 }
2416 
2417 
2418 /*
2419  * hermon_rsrc_pdhdl_destructor()
2420  *    Context: Can be called from interrupt or base context.
2421  */
2422 /* ARGSUSED */
2423 static void
2424 hermon_rsrc_pdhdl_destructor(void *pd, void *priv)
2425 {
2426 	hermon_pdhdl_t	pdhdl;
2427 
2428 	pdhdl = (hermon_pdhdl_t)pd;
2429 
2430 	mutex_destroy(&pdhdl->pd_lock);
2431 }
2432 
2433 
2434 /*
2435  * hermon_rsrc_cqhdl_constructor()
2436  *    Context: Can be called from interrupt or base context.
2437  */
2438 /* ARGSUSED */
2439 static int
2440 hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags)
2441 {
2442 	hermon_cqhdl_t	cqhdl;
2443 	hermon_state_t	*state;
2444 
2445 	cqhdl = (hermon_cqhdl_t)cq;
2446 	state = (hermon_state_t *)priv;
2447 
2448 	mutex_init(&cqhdl->cq_lock, NULL, MUTEX_DRIVER,
2449 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
2450 
2451 	return (DDI_SUCCESS);
2452 }
2453 
2454 
2455 /*
2456  * hermon_rsrc_cqhdl_destructor()
2457  *    Context: Can be called from interrupt or base context.
2458  */
2459 /* ARGSUSED */
2460 static void
2461 hermon_rsrc_cqhdl_destructor(void *cq, void *priv)
2462 {
2463 	hermon_cqhdl_t	cqhdl;
2464 
2465 	cqhdl = (hermon_cqhdl_t)cq;
2466 
2467 	mutex_destroy(&cqhdl->cq_lock);
2468 }
2469 
2470 
2471 /*
2472  * hermon_rsrc_qphdl_constructor()
2473  *    Context: Can be called from interrupt or base context.
2474  */
2475 /* ARGSUSED */
2476 static int
2477 hermon_rsrc_qphdl_constructor(void *qp, void *priv, int flags)
2478 {
2479 	hermon_qphdl_t	qphdl;
2480 	hermon_state_t	*state;
2481 
2482 	qphdl = (hermon_qphdl_t)qp;
2483 	state = (hermon_state_t *)priv;
2484 
2485 	mutex_init(&qphdl->qp_lock, NULL, MUTEX_DRIVER,
2486 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
2487 
2488 	return (DDI_SUCCESS);
2489 }
2490 
2491 
2492 /*
2493  * hermon_rsrc_qphdl_destructor()
2494  *    Context: Can be called from interrupt or base context.
2495  */
2496 /* ARGSUSED */
2497 static void
2498 hermon_rsrc_qphdl_destructor(void *qp, void *priv)
2499 {
2500 	hermon_qphdl_t	qphdl;
2501 
2502 	qphdl = (hermon_qphdl_t)qp;
2503 
2504 	mutex_destroy(&qphdl->qp_lock);
2505 }
2506 
2507 
2508 /*
2509  * hermon_rsrc_srqhdl_constructor()
2510  *    Context: Can be called from interrupt or base context.
2511  */
2512 /* ARGSUSED */
2513 static int
2514 hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags)
2515 {
2516 	hermon_srqhdl_t	srqhdl;
2517 	hermon_state_t	*state;
2518 
2519 	srqhdl = (hermon_srqhdl_t)srq;
2520 	state = (hermon_state_t *)priv;
2521 
2522 	mutex_init(&srqhdl->srq_lock, NULL, MUTEX_DRIVER,
2523 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
2524 
2525 	return (DDI_SUCCESS);
2526 }
2527 
2528 
2529 /*
2530  * hermon_rsrc_srqhdl_destructor()
2531  *    Context: Can be called from interrupt or base context.
2532  */
2533 /* ARGSUSED */
2534 static void
2535 hermon_rsrc_srqhdl_destructor(void *srq, void *priv)
2536 {
2537 	hermon_srqhdl_t	srqhdl;
2538 
2539 	srqhdl = (hermon_srqhdl_t)srq;
2540 
2541 	mutex_destroy(&srqhdl->srq_lock);
2542 }
2543 
2544 
2545 /*
2546  * hermon_rsrc_refcnt_constructor()
2547  *    Context: Can be called from interrupt or base context.
2548  */
2549 /* ARGSUSED */
2550 static int
2551 hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags)
2552 {
2553 	hermon_sw_refcnt_t	*refcnt;
2554 	hermon_state_t		*state;
2555 
2556 	refcnt = (hermon_sw_refcnt_t *)rc;
2557 	state  = (hermon_state_t *)priv;
2558 
2559 	mutex_init(&refcnt->swrc_lock, NULL, MUTEX_DRIVER,
2560 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
2561 
2562 	return (DDI_SUCCESS);
2563 }
2564 
2565 
2566 /*
2567  * hermon_rsrc_refcnt_destructor()
2568  *    Context: Can be called from interrupt or base context.
2569  */
2570 /* ARGSUSED */
2571 static void
2572 hermon_rsrc_refcnt_destructor(void *rc, void *priv)
2573 {
2574 	hermon_sw_refcnt_t	*refcnt;
2575 
2576 	refcnt = (hermon_sw_refcnt_t *)rc;
2577 
2578 	mutex_destroy(&refcnt->swrc_lock);
2579 }
2580 
2581 
2582 /*
2583  * hermon_rsrc_ahhdl_constructor()
2584  *    Context: Can be called from interrupt or base context.
2585  */
2586 /* ARGSUSED */
2587 static int
2588 hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags)
2589 {
2590 	hermon_ahhdl_t	ahhdl;
2591 	hermon_state_t	*state;
2592 
2593 	ahhdl = (hermon_ahhdl_t)ah;
2594 	state = (hermon_state_t *)priv;
2595 
2596 	mutex_init(&ahhdl->ah_lock, NULL, MUTEX_DRIVER,
2597 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
2598 	return (DDI_SUCCESS);
2599 }
2600 
2601 
2602 /*
2603  * hermon_rsrc_ahhdl_destructor()
2604  *    Context: Can be called from interrupt or base context.
2605  */
2606 /* ARGSUSED */
2607 static void
2608 hermon_rsrc_ahhdl_destructor(void *ah, void *priv)
2609 {
2610 	hermon_ahhdl_t	ahhdl;
2611 
2612 	ahhdl = (hermon_ahhdl_t)ah;
2613 
2614 	mutex_destroy(&ahhdl->ah_lock);
2615 }
2616 
2617 
2618 /*
2619  * hermon_rsrc_mrhdl_constructor()
2620  *    Context: Can be called from interrupt or base context.
2621  */
2622 /* ARGSUSED */
2623 static int
2624 hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags)
2625 {
2626 	hermon_mrhdl_t	mrhdl;
2627 	hermon_state_t	*state;
2628 
2629 	mrhdl = (hermon_mrhdl_t)mr;
2630 	state = (hermon_state_t *)priv;
2631 
2632 	mutex_init(&mrhdl->mr_lock, NULL, MUTEX_DRIVER,
2633 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
2634 
2635 	return (DDI_SUCCESS);
2636 }
2637 
2638 
2639 /*
2640  * hermon_rsrc_mrhdl_destructor()
2641  *    Context: Can be called from interrupt or base context.
2642  */
2643 /* ARGSUSED */
2644 static void
2645 hermon_rsrc_mrhdl_destructor(void *mr, void *priv)
2646 {
2647 	hermon_mrhdl_t	mrhdl;
2648 
2649 	mrhdl = (hermon_mrhdl_t)mr;
2650 
2651 	mutex_destroy(&mrhdl->mr_lock);
2652 }
2653 
2654 
2655 /*
2656  * hermon_rsrc_mcg_entry_get_size()
2657  */
2658 static int
2659 hermon_rsrc_mcg_entry_get_size(hermon_state_t *state, uint_t *mcg_size_shift)
2660 {
2661 	uint_t	num_qp_per_mcg, max_qp_per_mcg, log2;
2662 
2663 	/*
2664 	 * Round the configured number of QP per MCG to next larger
2665 	 * power-of-2 size and update.
2666 	 */
2667 	num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg + 8;
2668 	log2 = highbit(num_qp_per_mcg);
2669 	if ((num_qp_per_mcg & (num_qp_per_mcg - 1)) == 0) {
2670 		log2 = log2 - 1;
2671 	}
2672 	state->hs_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
2673 
2674 	/* Now make sure number of QP per MCG makes sense */
2675 	num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg;
2676 	max_qp_per_mcg = (1 << state->hs_devlim.log_max_qp_mcg);
2677 	if (num_qp_per_mcg > max_qp_per_mcg) {
2678 		return (DDI_FAILURE);
2679 	}
2680 
2681 	/* Return the (shift) size of an individual MCG HW entry */
2682 	*mcg_size_shift = log2 + 2;
2683 
2684 	return (DDI_SUCCESS);
2685 }
2686