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