hermon_rsrc.c revision 9517:b4839b0aa7a4
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
46int 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
89static int hermon_rsrc_mbox_init(hermon_state_t *state,
90    hermon_rsrc_mbox_info_t *info);
91static void hermon_rsrc_mbox_fini(hermon_state_t *state,
92    hermon_rsrc_mbox_info_t *info);
93
94static int hermon_rsrc_sw_handles_init(hermon_state_t *state,
95    hermon_rsrc_sw_hdl_info_t *info);
96static void hermon_rsrc_sw_handles_fini(hermon_state_t *state,
97    hermon_rsrc_sw_hdl_info_t *info);
98
99static int hermon_rsrc_pd_handles_init(hermon_state_t *state,
100    hermon_rsrc_sw_hdl_info_t *info);
101static 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 */
108static int hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info,
109    uint_t num, hermon_rsrc_t *hdl);
110static void hermon_rsrc_mbox_free(hermon_rsrc_pool_info_t *pool_info,
111    hermon_rsrc_t *hdl);
112
113static 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);
116static void hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
117    hermon_rsrc_t *hdl);
118
119static int hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info,
120    uint_t num, hermon_rsrc_t *hdl);
121static int hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
122    hermon_rsrc_t *hdl);
123
124static int hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
125    uint_t sleepflag, hermon_rsrc_t *hdl);
126static void hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info,
127    hermon_rsrc_t *hdl);
128
129static int hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
130    uint_t sleepflag, hermon_rsrc_t *hdl);
131static 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 */
141static int hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
142static void hermon_rsrc_pdhdl_destructor(void *pd, void *state);
143static int hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
144static void hermon_rsrc_cqhdl_destructor(void *cq, void *state);
145static int hermon_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
146static void hermon_rsrc_qphdl_destructor(void *cq, void *state);
147static int hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
148static void hermon_rsrc_srqhdl_destructor(void *srq, void *state);
149static int hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
150static void hermon_rsrc_refcnt_destructor(void *rc, void *state);
151static int hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
152static void hermon_rsrc_ahhdl_destructor(void *ah, void *state);
153static int hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
154static 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 */
161static 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 */
172int
173hermon_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 */
318void
319hermon_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 */
403int
404hermon_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
566rsrcinitp1_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 */
576int
577hermon_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
1011rsrcinitp2_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 */
1021void
1022hermon_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 */
1294static int
1295hermon_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 */
1336static void
1337hermon_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 */
1356int
1357hermon_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 */
1454void
1455hermon_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 */
1488static int
1489hermon_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 */
1538static void
1539hermon_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 */
1571static int
1572hermon_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 */
1614static void
1615hermon_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 */
1637static int
1638hermon_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 */
1682static void
1683hermon_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 */
1700static int
1701hermon_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 */
1763static void
1764hermon_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 */
1794static int
1795hermon_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
1915fail_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 */
1956static int
1957hermon_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 */
2062static int
2063hermon_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 */
2089static void
2090hermon_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 */
2104static int
2105hermon_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 */
2143static void
2144hermon_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 */
2162static int
2163hermon_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 */
2183static void
2184hermon_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 */
2199static int
2200hermon_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 */
2220static void
2221hermon_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 */
2236static int
2237hermon_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 */
2257static void
2258hermon_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 */
2273static int
2274hermon_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 */
2294static void
2295hermon_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 */
2310static int
2311hermon_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 */
2331static void
2332hermon_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 */
2347static int
2348hermon_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 */
2367static void
2368hermon_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 */
2383static int
2384hermon_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 */
2404static void
2405hermon_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 */
2418static int
2419hermon_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