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.
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.
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]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Hermon Resource Management Routines
30 * Implements all the routines necessary for setup, teardown, and
31 * alloc/free of all Hermon resources, including those that are managed
32 * by Hermon hardware or which live in Hermon's direct attached DDR memory.
35 #include <sys/sysmacros.h>
36 #include <sys/types.h>
39 #include <sys/sunddi.h>
40 #include <sys/modctl.h>
42 #include <sys/bitmap.h>
44 #include <sys/ib/adapters/hermon/hermon.h>
46 int hermon_rsrc_verbose
= 0;
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:
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.
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).
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.
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).
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.
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
);
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
);
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
);
105 * The following routines are used for allocating and freeing the specific
106 * types of objects described above from their associated resource pools.
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_t
*hdl
);
112 static int hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t
*pool_info
,
113 uint_t num
, uint_t num_align
, uint_t sleepflag
, hermon_rsrc_t
*hdl
);
114 static void hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t
*pool_info
,
116 static int hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t
*pool_info
,
117 uint_t num
, uint_t num_align
, uint_t sleepflag
, hermon_rsrc_t
*hdl
);
119 static int hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t
*pool_info
,
120 uint_t num
, hermon_rsrc_t
*hdl
, int num_to_hdl
);
121 static int hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t
*pool_info
,
122 hermon_rsrc_t
*hdl
, int num_to_hdl
);
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
,
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
,
134 static int hermon_rsrc_fexch_alloc(hermon_state_t
*state
,
135 hermon_rsrc_type_t rsrc
, uint_t num
, uint_t sleepflag
, hermon_rsrc_t
*hdl
);
136 static void hermon_rsrc_fexch_free(hermon_state_t
*state
, hermon_rsrc_t
*hdl
);
137 static int hermon_rsrc_rfci_alloc(hermon_state_t
*state
,
138 hermon_rsrc_type_t rsrc
, uint_t num
, uint_t sleepflag
, hermon_rsrc_t
*hdl
);
139 static void hermon_rsrc_rfci_free(hermon_state_t
*state
, hermon_rsrc_t
*hdl
);
142 * The following routines are the constructors and destructors for several
143 * of the SW handle type objects. For certain types of SW handles objects
144 * (all of which are implemented using kmem_cache), we need to do some
145 * special field initialization (specifically, mutex_init/destroy). These
146 * routines enable that init and teardown.
148 static int hermon_rsrc_pdhdl_constructor(void *pd
, void *priv
, int flags
);
149 static void hermon_rsrc_pdhdl_destructor(void *pd
, void *state
);
150 static int hermon_rsrc_cqhdl_constructor(void *cq
, void *priv
, int flags
);
151 static void hermon_rsrc_cqhdl_destructor(void *cq
, void *state
);
152 static int hermon_rsrc_qphdl_constructor(void *cq
, void *priv
, int flags
);
153 static void hermon_rsrc_qphdl_destructor(void *cq
, void *state
);
154 static int hermon_rsrc_srqhdl_constructor(void *srq
, void *priv
, int flags
);
155 static void hermon_rsrc_srqhdl_destructor(void *srq
, void *state
);
156 static int hermon_rsrc_refcnt_constructor(void *rc
, void *priv
, int flags
);
157 static void hermon_rsrc_refcnt_destructor(void *rc
, void *state
);
158 static int hermon_rsrc_ahhdl_constructor(void *ah
, void *priv
, int flags
);
159 static void hermon_rsrc_ahhdl_destructor(void *ah
, void *state
);
160 static int hermon_rsrc_mrhdl_constructor(void *mr
, void *priv
, int flags
);
161 static void hermon_rsrc_mrhdl_destructor(void *mr
, void *state
);
164 * Special routine to calculate and return the size of a MCG object based
165 * on current driver configuration (specifically, the number of QP per MCG
166 * that has been configured.
168 static int hermon_rsrc_mcg_entry_get_size(hermon_state_t
*state
,
169 uint_t
*mcg_size_shift
);
173 * hermon_rsrc_alloc()
175 * Context: Can be called from interrupt or base context.
176 * The "sleepflag" parameter is used by all object allocators to
177 * determine whether to SLEEP for resources or not.
180 hermon_rsrc_alloc(hermon_state_t
*state
, hermon_rsrc_type_t rsrc
, uint_t num
,
181 uint_t sleepflag
, hermon_rsrc_t
**hdl
)
183 hermon_rsrc_pool_info_t
*rsrc_pool
;
184 hermon_rsrc_t
*tmp_rsrc_hdl
;
185 int flag
, status
= DDI_FAILURE
;
187 ASSERT(state
!= NULL
);
190 rsrc_pool
= &state
->hs_rsrc_hdl
[rsrc
];
191 ASSERT(rsrc_pool
!= NULL
);
194 * Allocate space for the object used to track the resource handle
196 flag
= (sleepflag
== HERMON_SLEEP
) ? KM_SLEEP
: KM_NOSLEEP
;
197 tmp_rsrc_hdl
= kmem_cache_alloc(state
->hs_rsrc_cache
, flag
);
198 if (tmp_rsrc_hdl
== NULL
) {
199 return (DDI_FAILURE
);
201 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl
))
204 * Set rsrc_hdl type. This is later used by the hermon_rsrc_free call
205 * to know what type of resource is being freed.
207 tmp_rsrc_hdl
->rsrc_type
= rsrc
;
210 * Depending on resource type, call the appropriate alloc routine
214 case HERMON_OUT_MBOX
:
215 case HERMON_INTR_IN_MBOX
:
216 case HERMON_INTR_OUT_MBOX
:
217 status
= hermon_rsrc_mbox_alloc(rsrc_pool
, num
, tmp_rsrc_hdl
);
221 /* Allocate "num" (contiguous/aligned for FEXCH) DMPTs */
223 /* Allocate "num" (contiguous/aligned for RSS) QPCs */
224 status
= hermon_rsrc_hw_entry_alloc(rsrc_pool
, num
, num
,
225 sleepflag
, tmp_rsrc_hdl
);
228 case HERMON_QPC_FEXCH_PORT1
:
229 case HERMON_QPC_FEXCH_PORT2
:
230 /* Allocate "num" contiguous/aligned QPCs for FEXCH */
231 status
= hermon_rsrc_fexch_alloc(state
, rsrc
, num
,
232 sleepflag
, tmp_rsrc_hdl
);
235 case HERMON_QPC_RFCI_PORT1
:
236 case HERMON_QPC_RFCI_PORT2
:
237 /* Allocate "num" contiguous/aligned QPCs for RFCI */
238 status
= hermon_rsrc_rfci_alloc(state
, rsrc
, num
,
239 sleepflag
, tmp_rsrc_hdl
);
248 /* Allocate "num" unaligned resources */
249 status
= hermon_rsrc_hw_entry_alloc(rsrc_pool
, num
, 1,
250 sleepflag
, tmp_rsrc_hdl
);
260 status
= hermon_rsrc_swhdl_alloc(rsrc_pool
, sleepflag
,
265 status
= hermon_rsrc_pdhdl_alloc(rsrc_pool
, sleepflag
,
269 case HERMON_RDB
: /* handled during HERMON_QPC */
270 case HERMON_ALTC
: /* handled during HERMON_QPC */
271 case HERMON_AUXC
: /* handled during HERMON_QPC */
272 case HERMON_CMPT_QPC
: /* handled during HERMON_QPC */
273 case HERMON_CMPT_SRQC
: /* handled during HERMON_SRQC */
274 case HERMON_CMPT_CQC
: /* handled during HERMON_CPC */
275 case HERMON_CMPT_EQC
: /* handled during HERMON_EPC */
277 HERMON_WARNING(state
, "unexpected resource type in alloc ");
278 cmn_err(CE_WARN
, "Resource type %x \n", rsrc_pool
->rsrc_type
);
283 * If the resource allocation failed, then free the special resource
284 * tracking structure and return failure. Otherwise return the
285 * handle for the resource tracking structure.
287 if (status
!= DDI_SUCCESS
) {
288 kmem_cache_free(state
->hs_rsrc_cache
, tmp_rsrc_hdl
);
289 return (DDI_FAILURE
);
292 return (DDI_SUCCESS
);
298 * hermon_rsrc_reserve()
300 * Context: Can only be called from attach.
301 * The "sleepflag" parameter is used by all object allocators to
302 * determine whether to SLEEP for resources or not.
305 hermon_rsrc_reserve(hermon_state_t
*state
, hermon_rsrc_type_t rsrc
, uint_t num
,
306 uint_t sleepflag
, hermon_rsrc_t
**hdl
)
308 hermon_rsrc_pool_info_t
*rsrc_pool
;
309 hermon_rsrc_t
*tmp_rsrc_hdl
;
310 int flag
, status
= DDI_FAILURE
;
312 ASSERT(state
!= NULL
);
315 rsrc_pool
= &state
->hs_rsrc_hdl
[rsrc
];
316 ASSERT(rsrc_pool
!= NULL
);
319 * Allocate space for the object used to track the resource handle
321 flag
= (sleepflag
== HERMON_SLEEP
) ? KM_SLEEP
: KM_NOSLEEP
;
322 tmp_rsrc_hdl
= kmem_cache_alloc(state
->hs_rsrc_cache
, flag
);
323 if (tmp_rsrc_hdl
== NULL
) {
324 return (DDI_FAILURE
);
326 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl
))
329 * Set rsrc_hdl type. This is later used by the hermon_rsrc_free call
330 * to know what type of resource is being freed.
332 tmp_rsrc_hdl
->rsrc_type
= rsrc
;
339 * Reserve num resources, naturally aligned (N * num).
341 status
= hermon_rsrc_hw_entry_reserve(rsrc_pool
, num
, num
,
342 sleepflag
, tmp_rsrc_hdl
);
346 HERMON_WARNING(state
, "unexpected resource type in reserve ");
347 cmn_err(CE_WARN
, "Resource type %x \n", rsrc
);
352 * If the resource allocation failed, then free the special resource
353 * tracking structure and return failure. Otherwise return the
354 * handle for the resource tracking structure.
356 if (status
!= DDI_SUCCESS
) {
357 kmem_cache_free(state
->hs_rsrc_cache
, tmp_rsrc_hdl
);
358 return (DDI_FAILURE
);
361 return (DDI_SUCCESS
);
367 * hermon_rsrc_fexch_alloc()
369 * Context: Can only be called from base context.
370 * The "sleepflag" parameter is used by all object allocators to
371 * determine whether to SLEEP for resources or not.
374 hermon_rsrc_fexch_alloc(hermon_state_t
*state
, hermon_rsrc_type_t rsrc
,
375 uint_t num
, uint_t sleepflag
, hermon_rsrc_t
*hdl
)
377 hermon_fcoib_t
*fcoib
;
379 uint32_t fexch_qpn_base
;
380 hermon_rsrc_pool_info_t
*qpc_pool
, *mpt_pool
, *mtt_pool
;
382 hermon_rsrc_t mpt_hdl
; /* temporary, just for icm_confirm */
383 hermon_rsrc_t mtt_hdl
; /* temporary, just for icm_confirm */
384 uint_t portm1
; /* hca_port_number - 1 */
388 ASSERT(state
!= NULL
);
391 if ((state
->hs_ibtfinfo
.hca_attr
->hca_flags2
& IBT_HCA2_FC
) == 0)
392 return (DDI_FAILURE
);
394 portm1
= rsrc
- HERMON_QPC_FEXCH_PORT1
;
395 fcoib
= &state
->hs_fcoib
;
396 flag
= (sleepflag
== HERMON_SLEEP
) ? VM_SLEEP
: VM_NOSLEEP
;
398 /* Allocate from the FEXCH QP range */
399 vmp
= fcoib
->hfc_fexch_vmemp
[portm1
];
400 addr
= vmem_xalloc(vmp
, num
, num
, 0, 0, NULL
, NULL
, flag
| VM_FIRSTFIT
);
402 return (DDI_FAILURE
);
404 fexch_qpn_base
= (uint32_t)((uintptr_t)addr
-
405 fcoib
->hfc_vmemstart
+ fcoib
->hfc_fexch_base
[portm1
]);
407 /* ICM confirm for the FEXCH QP range */
408 qpc_pool
= &state
->hs_rsrc_hdl
[HERMON_QPC
];
409 hdl
->hr_len
= num
<< qpc_pool
->rsrc_shift
;
410 hdl
->hr_addr
= addr
; /* used only for vmem_xfree */
411 hdl
->hr_indx
= fexch_qpn_base
;
413 status
= hermon_rsrc_hw_entry_icm_confirm(qpc_pool
, num
, hdl
, 1);
414 if (status
!= DDI_SUCCESS
) {
415 vmem_xfree(vmp
, addr
, num
);
416 return (DDI_FAILURE
);
419 /* ICM confirm for the Primary MKEYs (client side only) */
420 mpt_pool
= &state
->hs_rsrc_hdl
[HERMON_DMPT
];
421 mpt_hdl
.hr_len
= num
<< mpt_pool
->rsrc_shift
;
422 mpt_hdl
.hr_addr
= NULL
;
423 mpt_hdl
.hr_indx
= fcoib
->hfc_mpt_base
[portm1
] +
424 (fexch_qpn_base
- fcoib
->hfc_fexch_base
[portm1
]);
426 status
= hermon_rsrc_hw_entry_icm_confirm(mpt_pool
, num
, &mpt_hdl
, 0);
427 if (status
!= DDI_SUCCESS
) {
428 status
= hermon_rsrc_hw_entry_icm_free(qpc_pool
, hdl
, 1);
429 vmem_xfree(vmp
, addr
, num
);
430 return (DDI_FAILURE
);
433 /* ICM confirm for the MTTs of the Primary MKEYs (client side only) */
434 nummtt
= fcoib
->hfc_mtts_per_mpt
;
436 mtt_pool
= &state
->hs_rsrc_hdl
[HERMON_MTT
];
437 mtt_hdl
.hr_len
= num
<< mtt_pool
->rsrc_shift
;
438 mtt_hdl
.hr_addr
= NULL
;
439 mtt_hdl
.hr_indx
= fcoib
->hfc_mtt_base
[portm1
] +
440 (fexch_qpn_base
- fcoib
->hfc_fexch_base
[portm1
]) *
443 status
= hermon_rsrc_hw_entry_icm_confirm(mtt_pool
, num
, &mtt_hdl
, 0);
444 if (status
!= DDI_SUCCESS
) {
445 vmem_xfree(vmp
, addr
, num
);
446 return (DDI_FAILURE
);
448 return (DDI_SUCCESS
);
452 hermon_rsrc_fexch_free(hermon_state_t
*state
, hermon_rsrc_t
*hdl
)
454 hermon_fcoib_t
*fcoib
;
455 uint_t portm1
; /* hca_port_number - 1 */
457 ASSERT(state
!= NULL
);
460 portm1
= hdl
->rsrc_type
- HERMON_QPC_FEXCH_PORT1
;
461 fcoib
= &state
->hs_fcoib
;
462 vmem_xfree(fcoib
->hfc_fexch_vmemp
[portm1
], hdl
->hr_addr
,
463 hdl
->hr_len
>> state
->hs_rsrc_hdl
[HERMON_QPC
].rsrc_shift
);
467 * hermon_rsrc_rfci_alloc()
469 * Context: Can only be called from base context.
470 * The "sleepflag" parameter is used by all object allocators to
471 * determine whether to SLEEP for resources or not.
474 hermon_rsrc_rfci_alloc(hermon_state_t
*state
, hermon_rsrc_type_t rsrc
,
475 uint_t num
, uint_t sleepflag
, hermon_rsrc_t
*hdl
)
477 hermon_fcoib_t
*fcoib
;
479 uint32_t rfci_qpn_base
;
480 hermon_rsrc_pool_info_t
*qpc_pool
;
482 uint_t portm1
; /* hca_port_number - 1 */
485 ASSERT(state
!= NULL
);
488 if ((state
->hs_ibtfinfo
.hca_attr
->hca_flags2
& IBT_HCA2_FC
) == 0)
489 return (DDI_FAILURE
);
491 portm1
= rsrc
- HERMON_QPC_RFCI_PORT1
;
492 fcoib
= &state
->hs_fcoib
;
493 flag
= (sleepflag
== HERMON_SLEEP
) ? VM_SLEEP
: VM_NOSLEEP
;
495 /* Allocate from the RFCI QP range */
496 vmp
= fcoib
->hfc_rfci_vmemp
[portm1
];
497 addr
= vmem_xalloc(vmp
, num
, num
, 0, 0, NULL
, NULL
, flag
| VM_FIRSTFIT
);
499 return (DDI_FAILURE
);
501 rfci_qpn_base
= (uint32_t)((uintptr_t)addr
-
502 fcoib
->hfc_vmemstart
+ fcoib
->hfc_rfci_base
[portm1
]);
504 /* ICM confirm for the RFCI QP */
505 qpc_pool
= &state
->hs_rsrc_hdl
[HERMON_QPC
];
506 hdl
->hr_len
= num
<< qpc_pool
->rsrc_shift
;
507 hdl
->hr_addr
= addr
; /* used only for vmem_xfree */
508 hdl
->hr_indx
= rfci_qpn_base
;
510 status
= hermon_rsrc_hw_entry_icm_confirm(qpc_pool
, num
, hdl
, 1);
511 if (status
!= DDI_SUCCESS
) {
512 vmem_xfree(vmp
, addr
, num
);
513 return (DDI_FAILURE
);
515 return (DDI_SUCCESS
);
519 hermon_rsrc_rfci_free(hermon_state_t
*state
, hermon_rsrc_t
*hdl
)
521 hermon_fcoib_t
*fcoib
;
522 uint_t portm1
; /* hca_port_number - 1 */
524 ASSERT(state
!= NULL
);
527 portm1
= hdl
->rsrc_type
- HERMON_QPC_RFCI_PORT1
;
528 fcoib
= &state
->hs_fcoib
;
529 vmem_xfree(fcoib
->hfc_rfci_vmemp
[portm1
], hdl
->hr_addr
,
530 hdl
->hr_len
>> state
->hs_rsrc_hdl
[HERMON_QPC
].rsrc_shift
);
536 * Context: Can be called from interrupt or base context.
539 hermon_rsrc_free(hermon_state_t
*state
, hermon_rsrc_t
**hdl
)
541 hermon_rsrc_pool_info_t
*rsrc_pool
;
543 ASSERT(state
!= NULL
);
546 rsrc_pool
= &state
->hs_rsrc_hdl
[(*hdl
)->rsrc_type
];
547 ASSERT(rsrc_pool
!= NULL
);
550 * Depending on resource type, call the appropriate free routine
552 switch (rsrc_pool
->rsrc_type
) {
554 case HERMON_OUT_MBOX
:
555 case HERMON_INTR_IN_MBOX
:
556 case HERMON_INTR_OUT_MBOX
:
557 hermon_rsrc_mbox_free(*hdl
);
560 case HERMON_QPC_FEXCH_PORT1
:
561 case HERMON_QPC_FEXCH_PORT2
:
562 hermon_rsrc_fexch_free(state
, *hdl
);
565 case HERMON_QPC_RFCI_PORT1
:
566 case HERMON_QPC_RFCI_PORT2
:
567 hermon_rsrc_rfci_free(state
, *hdl
);
578 hermon_rsrc_hw_entry_free(rsrc_pool
, *hdl
);
588 hermon_rsrc_swhdl_free(rsrc_pool
, *hdl
);
592 hermon_rsrc_pdhdl_free(rsrc_pool
, *hdl
);
598 case HERMON_CMPT_QPC
:
599 case HERMON_CMPT_SRQC
:
600 case HERMON_CMPT_CQC
:
601 case HERMON_CMPT_EQC
:
603 cmn_err(CE_CONT
, "!rsrc_type = 0x%x\n", rsrc_pool
->rsrc_type
);
608 * Free the special resource tracking structure, set the handle to
611 kmem_cache_free(state
->hs_rsrc_cache
, *hdl
);
617 * hermon_rsrc_init_phase1()
619 * Completes the first phase of Hermon resource/configuration init.
620 * This involves creating the kmem_cache for the "hermon_rsrc_t"
621 * structs, allocating the space for the resource pool handles,
622 * and setting up the "Out" mailboxes.
624 * When this function completes, the Hermon driver is ready to
625 * post the following commands which return information only in the
626 * "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
627 * If any of these commands are to be posted at this time, they must be
628 * done so only when "spinning" (as the outstanding command list and
629 * EQ setup code has not yet run)
631 * Context: Only called from attach() path context
634 hermon_rsrc_init_phase1(hermon_state_t
*state
)
636 hermon_rsrc_pool_info_t
*rsrc_pool
;
637 hermon_rsrc_mbox_info_t mbox_info
;
638 hermon_rsrc_cleanup_level_t cleanup
;
639 hermon_cfg_profile_t
*cfgprof
;
644 ASSERT(state
!= NULL
);
646 /* This is where Phase 1 of resource initialization begins */
647 cleanup
= HERMON_RSRC_CLEANUP_LEVEL0
;
649 /* Build kmem cache name from Hermon instance */
650 rsrc_name
= kmem_zalloc(HERMON_RSRC_NAME_MAXLEN
, KM_SLEEP
);
651 HERMON_RSRC_NAME(rsrc_name
, HERMON_RSRC_CACHE
);
654 * Create the kmem_cache for "hermon_rsrc_t" structures
655 * (kmem_cache_create will SLEEP until successful)
657 state
->hs_rsrc_cache
= kmem_cache_create(rsrc_name
,
658 sizeof (hermon_rsrc_t
), 0, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
661 * Allocate an array of hermon_rsrc_pool_info_t's (used in all
662 * subsequent resource allocations)
664 state
->hs_rsrc_hdl
= kmem_zalloc(HERMON_NUM_RESOURCES
*
665 sizeof (hermon_rsrc_pool_info_t
), KM_SLEEP
);
667 /* Pull in the configuration profile */
668 cfgprof
= state
->hs_cfg_profile
;
670 /* Initialize the resource pool for "out" mailboxes */
671 num
= ((uint64_t)1 << cfgprof
->cp_log_num_outmbox
);
672 size
= ((uint64_t)1 << cfgprof
->cp_log_outmbox_size
);
673 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_OUT_MBOX
];
674 rsrc_pool
->rsrc_loc
= HERMON_IN_SYSMEM
;
675 rsrc_pool
->rsrc_pool_size
= (size
* num
);
676 rsrc_pool
->rsrc_shift
= cfgprof
->cp_log_outmbox_size
;
677 rsrc_pool
->rsrc_quantum
= (uint_t
)size
;
678 rsrc_pool
->rsrc_align
= HERMON_MBOX_ALIGN
;
679 rsrc_pool
->rsrc_state
= state
;
680 mbox_info
.mbi_num
= num
;
681 mbox_info
.mbi_size
= size
;
682 mbox_info
.mbi_rsrcpool
= rsrc_pool
;
683 status
= hermon_rsrc_mbox_init(state
, &mbox_info
);
684 if (status
!= DDI_SUCCESS
) {
685 hermon_rsrc_fini(state
, cleanup
);
686 status
= DDI_FAILURE
;
687 goto rsrcinitp1_fail
;
689 cleanup
= HERMON_RSRC_CLEANUP_LEVEL1
;
691 /* Initialize the mailbox list */
692 status
= hermon_outmbox_list_init(state
);
693 if (status
!= DDI_SUCCESS
) {
694 hermon_rsrc_fini(state
, cleanup
);
695 status
= DDI_FAILURE
;
696 goto rsrcinitp1_fail
;
698 cleanup
= HERMON_RSRC_CLEANUP_LEVEL2
;
700 /* Initialize the resource pool for "interrupt out" mailboxes */
701 num
= ((uint64_t)1 << cfgprof
->cp_log_num_intr_outmbox
);
702 size
= ((uint64_t)1 << cfgprof
->cp_log_outmbox_size
);
703 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_INTR_OUT_MBOX
];
704 rsrc_pool
->rsrc_loc
= HERMON_IN_SYSMEM
;
705 rsrc_pool
->rsrc_pool_size
= (size
* num
);
706 rsrc_pool
->rsrc_shift
= cfgprof
->cp_log_outmbox_size
;
707 rsrc_pool
->rsrc_quantum
= (uint_t
)size
;
708 rsrc_pool
->rsrc_align
= HERMON_MBOX_ALIGN
;
709 rsrc_pool
->rsrc_state
= state
;
710 mbox_info
.mbi_num
= num
;
711 mbox_info
.mbi_size
= size
;
712 mbox_info
.mbi_rsrcpool
= rsrc_pool
;
713 status
= hermon_rsrc_mbox_init(state
, &mbox_info
);
714 if (status
!= DDI_SUCCESS
) {
715 hermon_rsrc_fini(state
, cleanup
);
716 status
= DDI_FAILURE
;
717 goto rsrcinitp1_fail
;
719 cleanup
= HERMON_RSRC_CLEANUP_LEVEL3
;
721 /* Initialize the mailbox list */
722 status
= hermon_intr_outmbox_list_init(state
);
723 if (status
!= DDI_SUCCESS
) {
724 hermon_rsrc_fini(state
, cleanup
);
725 status
= DDI_FAILURE
;
726 goto rsrcinitp1_fail
;
728 cleanup
= HERMON_RSRC_CLEANUP_LEVEL4
;
730 /* Initialize the resource pool for "in" mailboxes */
731 num
= ((uint64_t)1 << cfgprof
->cp_log_num_inmbox
);
732 size
= ((uint64_t)1 << cfgprof
->cp_log_inmbox_size
);
733 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_IN_MBOX
];
734 rsrc_pool
->rsrc_loc
= HERMON_IN_SYSMEM
;
735 rsrc_pool
->rsrc_pool_size
= (size
* num
);
736 rsrc_pool
->rsrc_shift
= cfgprof
->cp_log_inmbox_size
;
737 rsrc_pool
->rsrc_quantum
= (uint_t
)size
;
738 rsrc_pool
->rsrc_align
= HERMON_MBOX_ALIGN
;
739 rsrc_pool
->rsrc_state
= state
;
740 mbox_info
.mbi_num
= num
;
741 mbox_info
.mbi_size
= size
;
742 mbox_info
.mbi_rsrcpool
= rsrc_pool
;
743 status
= hermon_rsrc_mbox_init(state
, &mbox_info
);
744 if (status
!= DDI_SUCCESS
) {
745 hermon_rsrc_fini(state
, cleanup
);
746 status
= DDI_FAILURE
;
747 goto rsrcinitp1_fail
;
749 cleanup
= HERMON_RSRC_CLEANUP_LEVEL5
;
751 /* Initialize the mailbox list */
752 status
= hermon_inmbox_list_init(state
);
753 if (status
!= DDI_SUCCESS
) {
754 hermon_rsrc_fini(state
, cleanup
);
755 status
= DDI_FAILURE
;
756 goto rsrcinitp1_fail
;
758 cleanup
= HERMON_RSRC_CLEANUP_LEVEL6
;
760 /* Initialize the resource pool for "interrupt in" mailboxes */
761 num
= ((uint64_t)1 << cfgprof
->cp_log_num_intr_inmbox
);
762 size
= ((uint64_t)1 << cfgprof
->cp_log_inmbox_size
);
763 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_INTR_IN_MBOX
];
764 rsrc_pool
->rsrc_loc
= HERMON_IN_SYSMEM
;
765 rsrc_pool
->rsrc_pool_size
= (size
* num
);
766 rsrc_pool
->rsrc_shift
= cfgprof
->cp_log_inmbox_size
;
767 rsrc_pool
->rsrc_quantum
= (uint_t
)size
;
768 rsrc_pool
->rsrc_align
= HERMON_MBOX_ALIGN
;
769 rsrc_pool
->rsrc_state
= state
;
770 mbox_info
.mbi_num
= num
;
771 mbox_info
.mbi_size
= size
;
772 mbox_info
.mbi_rsrcpool
= rsrc_pool
;
773 status
= hermon_rsrc_mbox_init(state
, &mbox_info
);
774 if (status
!= DDI_SUCCESS
) {
775 hermon_rsrc_fini(state
, cleanup
);
776 status
= DDI_FAILURE
;
777 goto rsrcinitp1_fail
;
779 cleanup
= HERMON_RSRC_CLEANUP_LEVEL7
;
781 /* Initialize the mailbox list */
782 status
= hermon_intr_inmbox_list_init(state
);
783 if (status
!= DDI_SUCCESS
) {
784 hermon_rsrc_fini(state
, cleanup
);
785 status
= DDI_FAILURE
;
786 goto rsrcinitp1_fail
;
788 cleanup
= HERMON_RSRC_CLEANUP_PHASE1_COMPLETE
;
789 kmem_free(rsrc_name
, HERMON_RSRC_NAME_MAXLEN
);
790 return (DDI_SUCCESS
);
793 kmem_free(rsrc_name
, HERMON_RSRC_NAME_MAXLEN
);
799 * hermon_rsrc_init_phase2()
800 * Context: Only called from attach() path context
803 hermon_rsrc_init_phase2(hermon_state_t
*state
)
805 hermon_rsrc_sw_hdl_info_t hdl_info
;
806 hermon_rsrc_hw_entry_info_t entry_info
;
807 hermon_rsrc_pool_info_t
*rsrc_pool
;
808 hermon_rsrc_cleanup_level_t cleanup
, ncleanup
;
809 hermon_cfg_profile_t
*cfgprof
;
810 hermon_hw_querydevlim_t
*devlim
;
811 uint64_t num
, max
, num_prealloc
;
812 uint_t mcg_size
, mcg_size_shift
;
816 ASSERT(state
!= NULL
);
818 /* Phase 2 initialization begins where Phase 1 left off */
819 cleanup
= HERMON_RSRC_CLEANUP_PHASE1_COMPLETE
;
821 /* Allocate the ICM resource name space */
823 /* Build the ICM vmem arena names from Hermon instance */
824 rsrc_name
= kmem_zalloc(HERMON_RSRC_NAME_MAXLEN
, KM_SLEEP
);
827 * Initialize the resource pools for all objects that exist in
828 * context memory (ICM). The ICM consists of context tables, each
829 * type of resource (QP, CQ, EQ, etc) having it's own context table
830 * (QPC, CQC, EQC, etc...).
832 cfgprof
= state
->hs_cfg_profile
;
833 devlim
= &state
->hs_devlim
;
836 * Initialize the resource pools for each of the driver resources.
837 * With a few exceptions, these resources fall into the two cateogories
838 * of either hw_entries or sw_entries.
842 * Initialize the resource pools for ICM (hardware) types first.
843 * These resources are managed through vmem arenas, which are
844 * created via the rsrc pool initialization routine. Note that,
845 * due to further calculations, the MCG resource pool is
846 * initialized seperately.
848 for (i
= 0; i
< HERMON_NUM_ICM_RESOURCES
; i
++) {
850 rsrc_pool
= &state
->hs_rsrc_hdl
[i
];
851 rsrc_pool
->rsrc_type
= i
;
852 rsrc_pool
->rsrc_state
= state
;
854 /* Set the resource-specific attributes */
857 max
= ((uint64_t)1 << devlim
->log_max_mtt
);
858 num_prealloc
= ((uint64_t)1 << devlim
->log_rsvd_mtt
);
859 HERMON_RSRC_NAME(rsrc_name
, HERMON_MTT_VMEM
);
860 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL9
;
864 max
= ((uint64_t)1 << devlim
->log_max_dmpt
);
865 num_prealloc
= ((uint64_t)1 << devlim
->log_rsvd_dmpt
);
866 HERMON_RSRC_NAME(rsrc_name
, HERMON_DMPT_VMEM
);
867 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL10
;
871 max
= ((uint64_t)1 << devlim
->log_max_qp
);
872 num_prealloc
= ((uint64_t)1 << devlim
->log_rsvd_qp
);
873 HERMON_RSRC_NAME(rsrc_name
, HERMON_QPC_VMEM
);
874 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL11
;
878 max
= ((uint64_t)1 << devlim
->log_max_cq
);
879 num_prealloc
= ((uint64_t)1 << devlim
->log_rsvd_cq
);
880 HERMON_RSRC_NAME(rsrc_name
, HERMON_CQC_VMEM
);
881 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL13
;
885 max
= ((uint64_t)1 << devlim
->log_max_srq
);
886 num_prealloc
= ((uint64_t)1 << devlim
->log_rsvd_srq
);
887 HERMON_RSRC_NAME(rsrc_name
, HERMON_SRQC_VMEM
);
888 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL16
;
892 max
= ((uint64_t)1 << devlim
->log_max_eq
);
893 num_prealloc
= state
->hs_rsvd_eqs
;
894 HERMON_RSRC_NAME(rsrc_name
, HERMON_EQC_VMEM
);
895 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL18
;
898 case HERMON_MCG
: /* handled below */
902 case HERMON_CMPT_QPC
:
903 case HERMON_CMPT_SRQC
:
904 case HERMON_CMPT_CQC
:
905 case HERMON_CMPT_EQC
:
907 /* We don't need to initialize this rsrc here. */
911 /* Set the common values for all resource pools */
912 rsrc_pool
->rsrc_state
= state
;
913 rsrc_pool
->rsrc_loc
= HERMON_IN_ICM
;
914 rsrc_pool
->rsrc_pool_size
= state
->hs_icm
[i
].table_size
;
915 rsrc_pool
->rsrc_align
= state
->hs_icm
[i
].table_size
;
916 rsrc_pool
->rsrc_shift
= state
->hs_icm
[i
].log_object_size
;
917 rsrc_pool
->rsrc_quantum
= state
->hs_icm
[i
].object_size
;
919 /* Now, initialize the entry_info and call the init routine */
920 entry_info
.hwi_num
= state
->hs_icm
[i
].num_entries
;
921 entry_info
.hwi_max
= max
;
922 entry_info
.hwi_prealloc
= num_prealloc
;
923 entry_info
.hwi_rsrcpool
= rsrc_pool
;
924 entry_info
.hwi_rsrcname
= rsrc_name
;
925 status
= hermon_rsrc_hw_entries_init(state
, &entry_info
);
926 if (status
!= DDI_SUCCESS
) {
927 hermon_rsrc_fini(state
, cleanup
);
928 status
= DDI_FAILURE
;
929 goto rsrcinitp2_fail
;
935 * Initialize the Multicast Group (MCG) entries. First, calculate
936 * (and validate) the size of the MCGs.
938 status
= hermon_rsrc_mcg_entry_get_size(state
, &mcg_size_shift
);
939 if (status
!= DDI_SUCCESS
) {
940 hermon_rsrc_fini(state
, cleanup
);
941 status
= DDI_FAILURE
;
942 goto rsrcinitp2_fail
;
944 mcg_size
= HERMON_MCGMEM_SZ(state
);
947 * Initialize the resource pool for the MCG table entries. Notice
948 * that the number of MCGs is configurable. Note also that a certain
949 * number of MCGs must be set aside for Hermon firmware use (they
950 * correspond to the number of MCGs used by the internal hash
953 num
= ((uint64_t)1 << cfgprof
->cp_log_num_mcg
);
954 max
= ((uint64_t)1 << devlim
->log_max_mcg
);
955 num_prealloc
= ((uint64_t)1 << cfgprof
->cp_log_num_mcg_hash
);
956 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_MCG
];
957 rsrc_pool
->rsrc_loc
= HERMON_IN_ICM
;
958 rsrc_pool
->rsrc_pool_size
= (mcg_size
* num
);
959 rsrc_pool
->rsrc_shift
= mcg_size_shift
;
960 rsrc_pool
->rsrc_quantum
= mcg_size
;
961 rsrc_pool
->rsrc_align
= (mcg_size
* num
);
962 rsrc_pool
->rsrc_state
= state
;
963 HERMON_RSRC_NAME(rsrc_name
, HERMON_MCG_VMEM
);
964 entry_info
.hwi_num
= num
;
965 entry_info
.hwi_max
= max
;
966 entry_info
.hwi_prealloc
= num_prealloc
;
967 entry_info
.hwi_rsrcpool
= rsrc_pool
;
968 entry_info
.hwi_rsrcname
= rsrc_name
;
969 status
= hermon_rsrc_hw_entries_init(state
, &entry_info
);
970 if (status
!= DDI_SUCCESS
) {
971 hermon_rsrc_fini(state
, cleanup
);
972 status
= DDI_FAILURE
;
973 goto rsrcinitp2_fail
;
975 cleanup
= HERMON_RSRC_CLEANUP_LEVEL19
;
978 * Initialize the full range of ICM for the AUXC resource.
979 * This is done because its size is so small, about 1 byte per QP.
983 * Initialize the Hermon command handling interfaces. This step
984 * sets up the outstanding command tracking mechanism for easy access
985 * and fast allocation (see hermon_cmd.c for more details).
987 status
= hermon_outstanding_cmdlist_init(state
);
988 if (status
!= DDI_SUCCESS
) {
989 hermon_rsrc_fini(state
, cleanup
);
990 status
= DDI_FAILURE
;
991 goto rsrcinitp2_fail
;
993 cleanup
= HERMON_RSRC_CLEANUP_LEVEL20
;
995 /* Initialize the resource pool and vmem arena for the PD handles */
996 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_PDHDL
];
997 rsrc_pool
->rsrc_loc
= HERMON_IN_SYSMEM
;
998 rsrc_pool
->rsrc_quantum
= sizeof (struct hermon_sw_pd_s
);
999 rsrc_pool
->rsrc_state
= state
;
1000 HERMON_RSRC_NAME(rsrc_name
, HERMON_PDHDL_CACHE
);
1001 hdl_info
.swi_num
= ((uint64_t)1 << cfgprof
->cp_log_num_pd
);
1002 hdl_info
.swi_max
= ((uint64_t)1 << devlim
->log_max_pd
);
1003 hdl_info
.swi_rsrcpool
= rsrc_pool
;
1004 hdl_info
.swi_constructor
= hermon_rsrc_pdhdl_constructor
;
1005 hdl_info
.swi_destructor
= hermon_rsrc_pdhdl_destructor
;
1006 hdl_info
.swi_rsrcname
= rsrc_name
;
1007 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1008 status
= hermon_rsrc_pd_handles_init(state
, &hdl_info
);
1009 if (status
!= DDI_SUCCESS
) {
1010 hermon_rsrc_fini(state
, cleanup
);
1011 status
= DDI_FAILURE
;
1012 goto rsrcinitp2_fail
;
1014 cleanup
= HERMON_RSRC_CLEANUP_LEVEL21
;
1017 * Initialize the resource pools for the rest of the software handles.
1018 * This includes MR handles, EQ handles, QP handles, etc. These
1019 * objects are almost entirely managed using kmem_cache routines,
1020 * and do not utilize a vmem arena.
1022 for (i
= HERMON_NUM_ICM_RESOURCES
; i
< HERMON_NUM_RESOURCES
; i
++) {
1023 rsrc_pool
= &state
->hs_rsrc_hdl
[i
];
1024 rsrc_pool
->rsrc_type
= i
;
1026 /* Set the resource-specific attributes */
1029 rsrc_pool
->rsrc_quantum
=
1030 sizeof (struct hermon_sw_mr_s
);
1031 HERMON_RSRC_NAME(rsrc_name
, HERMON_MRHDL_CACHE
);
1033 ((uint64_t)1 << cfgprof
->cp_log_num_dmpt
) +
1034 ((uint64_t)1 << cfgprof
->cp_log_num_cmpt
);
1036 ((uint64_t)1 << cfgprof
->cp_log_num_dmpt
) +
1037 ((uint64_t)1 << cfgprof
->cp_log_num_cmpt
);
1038 hdl_info
.swi_constructor
=
1039 hermon_rsrc_mrhdl_constructor
;
1040 hdl_info
.swi_destructor
= hermon_rsrc_mrhdl_destructor
;
1041 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1042 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL22
;
1046 rsrc_pool
->rsrc_quantum
=
1047 sizeof (struct hermon_sw_eq_s
);
1048 HERMON_RSRC_NAME(rsrc_name
, HERMON_EQHDL_CACHE
);
1049 hdl_info
.swi_num
= HERMON_NUM_EQ
;
1050 hdl_info
.swi_max
= ((uint64_t)1 << devlim
->log_max_eq
);
1051 hdl_info
.swi_constructor
= NULL
;
1052 hdl_info
.swi_destructor
= NULL
;
1053 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1054 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL23
;
1058 rsrc_pool
->rsrc_quantum
=
1059 sizeof (struct hermon_sw_cq_s
);
1060 HERMON_RSRC_NAME(rsrc_name
, HERMON_CQHDL_CACHE
);
1062 (uint64_t)1 << cfgprof
->cp_log_num_cq
;
1063 hdl_info
.swi_max
= (uint64_t)1 << devlim
->log_max_cq
;
1064 hdl_info
.swi_constructor
=
1065 hermon_rsrc_cqhdl_constructor
;
1066 hdl_info
.swi_destructor
= hermon_rsrc_cqhdl_destructor
;
1067 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1068 hdl_info
.swi_prealloc_sz
= sizeof (hermon_cqhdl_t
);
1069 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL24
;
1073 rsrc_pool
->rsrc_quantum
=
1074 sizeof (struct hermon_sw_srq_s
);
1075 HERMON_RSRC_NAME(rsrc_name
, HERMON_SRQHDL_CACHE
);
1077 (uint64_t)1 << cfgprof
->cp_log_num_srq
;
1078 hdl_info
.swi_max
= (uint64_t)1 << devlim
->log_max_srq
;
1079 hdl_info
.swi_constructor
=
1080 hermon_rsrc_srqhdl_constructor
;
1081 hdl_info
.swi_destructor
= hermon_rsrc_srqhdl_destructor
;
1082 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1083 hdl_info
.swi_prealloc_sz
= sizeof (hermon_srqhdl_t
);
1084 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL25
;
1088 rsrc_pool
->rsrc_quantum
=
1089 sizeof (struct hermon_sw_ah_s
);
1090 HERMON_RSRC_NAME(rsrc_name
, HERMON_AHHDL_CACHE
);
1092 (uint64_t)1 << cfgprof
->cp_log_num_ah
;
1093 hdl_info
.swi_max
= HERMON_NUM_AH
;
1094 hdl_info
.swi_constructor
=
1095 hermon_rsrc_ahhdl_constructor
;
1096 hdl_info
.swi_destructor
= hermon_rsrc_ahhdl_destructor
;
1097 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1098 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL26
;
1102 rsrc_pool
->rsrc_quantum
=
1103 sizeof (struct hermon_sw_qp_s
);
1104 HERMON_RSRC_NAME(rsrc_name
, HERMON_QPHDL_CACHE
);
1106 (uint64_t)1 << cfgprof
->cp_log_num_qp
;
1107 hdl_info
.swi_max
= (uint64_t)1 << devlim
->log_max_qp
;
1108 hdl_info
.swi_constructor
=
1109 hermon_rsrc_qphdl_constructor
;
1110 hdl_info
.swi_destructor
= hermon_rsrc_qphdl_destructor
;
1111 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1112 hdl_info
.swi_prealloc_sz
= sizeof (hermon_qphdl_t
);
1113 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL27
;
1117 rsrc_pool
->rsrc_quantum
= sizeof (hermon_sw_refcnt_t
);
1118 HERMON_RSRC_NAME(rsrc_name
, HERMON_REFCNT_CACHE
);
1120 (uint64_t)1 << cfgprof
->cp_log_num_dmpt
;
1121 hdl_info
.swi_max
= (uint64_t)1 << devlim
->log_max_dmpt
;
1122 hdl_info
.swi_constructor
=
1123 hermon_rsrc_refcnt_constructor
;
1124 hdl_info
.swi_destructor
= hermon_rsrc_refcnt_destructor
;
1125 hdl_info
.swi_flags
= HERMON_SWHDL_KMEMCACHE_INIT
;
1126 ncleanup
= HERMON_RSRC_CLEANUP_LEVEL28
;
1133 /* Set the common values and call the init routine */
1134 rsrc_pool
->rsrc_loc
= HERMON_IN_SYSMEM
;
1135 rsrc_pool
->rsrc_state
= state
;
1136 hdl_info
.swi_rsrcpool
= rsrc_pool
;
1137 hdl_info
.swi_rsrcname
= rsrc_name
;
1138 status
= hermon_rsrc_sw_handles_init(state
, &hdl_info
);
1139 if (status
!= DDI_SUCCESS
) {
1140 hermon_rsrc_fini(state
, cleanup
);
1141 status
= DDI_FAILURE
;
1142 goto rsrcinitp2_fail
;
1148 * Initialize a resource pool for the MCG handles. Notice that for
1149 * these MCG handles, we are allocating a table of structures (used to
1150 * keep track of the MCG entries that are being written to hardware
1151 * and to speed up multicast attach/detach operations).
1153 hdl_info
.swi_num
= ((uint64_t)1 << cfgprof
->cp_log_num_mcg
);
1154 hdl_info
.swi_max
= ((uint64_t)1 << devlim
->log_max_mcg
);
1155 hdl_info
.swi_flags
= HERMON_SWHDL_TABLE_INIT
;
1156 hdl_info
.swi_prealloc_sz
= sizeof (struct hermon_sw_mcg_list_s
);
1157 status
= hermon_rsrc_sw_handles_init(state
, &hdl_info
);
1158 if (status
!= DDI_SUCCESS
) {
1159 hermon_rsrc_fini(state
, cleanup
);
1160 status
= DDI_FAILURE
;
1161 goto rsrcinitp2_fail
;
1163 state
->hs_mcghdl
= hdl_info
.swi_table_ptr
;
1164 cleanup
= HERMON_RSRC_CLEANUP_LEVEL29
;
1167 * Last, initialize the resource pool for the UAR pages, which contain
1168 * the hardware's doorbell registers. Each process supported in User
1169 * Mode is assigned a UAR page. Also coming from this pool are the
1170 * kernel-assigned UAR page, and any hardware-reserved pages. Note
1171 * that the number of UAR pages is configurable, the value must be less
1172 * than the maximum value (obtained from the QUERY_DEV_LIM command) or
1173 * the initialization will fail. Note also that we assign the base
1174 * address of the UAR BAR to the rsrc_start parameter.
1176 num
= ((uint64_t)1 << cfgprof
->cp_log_num_uar
);
1178 num_prealloc
= max(devlim
->num_rsvd_uar
, 128);
1179 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_UARPG
];
1180 rsrc_pool
->rsrc_loc
= HERMON_IN_UAR
;
1181 rsrc_pool
->rsrc_pool_size
= (num
<< PAGESHIFT
);
1182 rsrc_pool
->rsrc_shift
= PAGESHIFT
;
1183 rsrc_pool
->rsrc_quantum
= (uint_t
)PAGESIZE
;
1184 rsrc_pool
->rsrc_align
= PAGESIZE
;
1185 rsrc_pool
->rsrc_state
= state
;
1186 rsrc_pool
->rsrc_start
= (void *)state
->hs_reg_uar_baseaddr
;
1187 HERMON_RSRC_NAME(rsrc_name
, HERMON_UAR_PAGE_VMEM_ATTCH
);
1188 entry_info
.hwi_num
= num
;
1189 entry_info
.hwi_max
= max
;
1190 entry_info
.hwi_prealloc
= num_prealloc
;
1191 entry_info
.hwi_rsrcpool
= rsrc_pool
;
1192 entry_info
.hwi_rsrcname
= rsrc_name
;
1193 status
= hermon_rsrc_hw_entries_init(state
, &entry_info
);
1194 if (status
!= DDI_SUCCESS
) {
1195 hermon_rsrc_fini(state
, cleanup
);
1196 status
= DDI_FAILURE
;
1197 goto rsrcinitp2_fail
;
1200 cleanup
= HERMON_RSRC_CLEANUP_ALL
;
1202 kmem_free(rsrc_name
, HERMON_RSRC_NAME_MAXLEN
);
1203 return (DDI_SUCCESS
);
1206 kmem_free(rsrc_name
, HERMON_RSRC_NAME_MAXLEN
);
1212 * hermon_rsrc_fini()
1213 * Context: Only called from attach() and/or detach() path contexts
1216 hermon_rsrc_fini(hermon_state_t
*state
, hermon_rsrc_cleanup_level_t clean
)
1218 hermon_rsrc_sw_hdl_info_t hdl_info
;
1219 hermon_rsrc_hw_entry_info_t entry_info
;
1220 hermon_rsrc_mbox_info_t mbox_info
;
1221 hermon_cfg_profile_t
*cfgprof
;
1223 ASSERT(state
!= NULL
);
1225 cfgprof
= state
->hs_cfg_profile
;
1228 * If init code above is shortened up (see comments), then we
1229 * need to establish how to safely and simply clean up from any
1230 * given failure point. Flags, maybe...
1235 * If we add more resources that need to be cleaned up here, we should
1236 * ensure that HERMON_RSRC_CLEANUP_ALL is still the first entry (i.e.
1237 * corresponds to the last resource allocated).
1240 case HERMON_RSRC_CLEANUP_ALL
:
1241 case HERMON_RSRC_CLEANUP_LEVEL31
:
1242 /* Cleanup the UAR page resource pool, first the dbr pages */
1243 if (state
->hs_kern_dbr
) {
1244 hermon_dbr_kern_free(state
);
1245 state
->hs_kern_dbr
= NULL
;
1248 /* NS then, the pool itself */
1249 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_UARPG
];
1250 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1254 case HERMON_RSRC_CLEANUP_LEVEL30
:
1255 /* Cleanup the central MCG handle pointers list */
1256 hdl_info
.swi_rsrcpool
= NULL
;
1257 hdl_info
.swi_table_ptr
= state
->hs_mcghdl
;
1258 hdl_info
.swi_num
= ((uint64_t)1 << cfgprof
->cp_log_num_mcg
);
1259 hdl_info
.swi_prealloc_sz
= sizeof (struct hermon_sw_mcg_list_s
);
1260 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1263 case HERMON_RSRC_CLEANUP_LEVEL29
:
1264 /* Cleanup the reference count resource pool */
1265 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_REFCNT
];
1266 hdl_info
.swi_table_ptr
= NULL
;
1267 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1270 case HERMON_RSRC_CLEANUP_LEVEL28
:
1271 /* Cleanup the QP handle resource pool */
1272 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_QPHDL
];
1273 hdl_info
.swi_table_ptr
= NULL
;
1274 hdl_info
.swi_num
= ((uint64_t)1 << cfgprof
->cp_log_num_qp
);
1275 hdl_info
.swi_prealloc_sz
= sizeof (hermon_qphdl_t
);
1276 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1278 case HERMON_RSRC_CLEANUP_LEVEL27
:
1279 /* Cleanup the address handle resrouce pool */
1280 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_AHHDL
];
1281 hdl_info
.swi_table_ptr
= NULL
;
1282 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1285 case HERMON_RSRC_CLEANUP_LEVEL26
:
1286 /* Cleanup the SRQ handle resource pool. */
1287 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_SRQHDL
];
1288 hdl_info
.swi_table_ptr
= NULL
;
1289 hdl_info
.swi_num
= ((uint64_t)1 << cfgprof
->cp_log_num_srq
);
1290 hdl_info
.swi_prealloc_sz
= sizeof (hermon_srqhdl_t
);
1291 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1294 case HERMON_RSRC_CLEANUP_LEVEL25
:
1295 /* Cleanup the CQ handle resource pool */
1296 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_CQHDL
];
1297 hdl_info
.swi_table_ptr
= NULL
;
1298 hdl_info
.swi_num
= ((uint64_t)1 << cfgprof
->cp_log_num_cq
);
1299 hdl_info
.swi_prealloc_sz
= sizeof (hermon_cqhdl_t
);
1300 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1303 case HERMON_RSRC_CLEANUP_LEVEL24
:
1304 /* Cleanup the EQ handle resource pool */
1305 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_EQHDL
];
1306 hdl_info
.swi_table_ptr
= NULL
;
1307 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1310 case HERMON_RSRC_CLEANUP_LEVEL23
:
1311 /* Cleanup the MR handle resource pool */
1312 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_MRHDL
];
1313 hdl_info
.swi_table_ptr
= NULL
;
1314 hermon_rsrc_sw_handles_fini(state
, &hdl_info
);
1317 case HERMON_RSRC_CLEANUP_LEVEL22
:
1318 /* Cleanup the PD handle resource pool */
1319 hdl_info
.swi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_PDHDL
];
1320 hdl_info
.swi_table_ptr
= NULL
;
1321 hermon_rsrc_pd_handles_fini(state
, &hdl_info
);
1324 case HERMON_RSRC_CLEANUP_LEVEL21
:
1325 /* Currently unused - FALLTHROUGH */
1327 case HERMON_RSRC_CLEANUP_LEVEL20
:
1328 /* Cleanup the outstanding command list */
1329 hermon_outstanding_cmdlist_fini(state
);
1332 case HERMON_RSRC_CLEANUP_LEVEL19
:
1333 /* Cleanup the EQC table resource pool */
1334 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_EQC
];
1335 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1338 case HERMON_RSRC_CLEANUP_LEVEL18
:
1339 /* Cleanup the MCG table resource pool */
1340 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_MCG
];
1341 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1344 case HERMON_RSRC_CLEANUP_LEVEL17
:
1345 /* Currently Unused - fallthrough */
1346 case HERMON_RSRC_CLEANUP_LEVEL16
:
1347 /* Cleanup the SRQC table resource pool */
1348 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_SRQC
];
1349 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1352 case HERMON_RSRC_CLEANUP_LEVEL15
:
1353 /* Cleanup the AUXC table resource pool */
1354 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_AUXC
];
1355 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1358 case HERMON_RSRC_CLEANUP_LEVEL14
:
1359 /* Cleanup the ALTCF table resource pool */
1360 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_ALTC
];
1361 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1364 case HERMON_RSRC_CLEANUP_LEVEL13
:
1365 /* Cleanup the CQC table resource pool */
1366 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_CQC
];
1367 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1370 case HERMON_RSRC_CLEANUP_LEVEL12
:
1371 /* Cleanup the RDB table resource pool */
1372 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_RDB
];
1373 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1376 case HERMON_RSRC_CLEANUP_LEVEL11
:
1377 /* Cleanup the QPC table resource pool */
1378 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_QPC
];
1379 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1382 case HERMON_RSRC_CLEANUP_LEVEL10EQ
:
1383 /* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1384 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_CMPT_EQC
];
1385 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1388 case HERMON_RSRC_CLEANUP_LEVEL10CQ
:
1389 /* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1390 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_CMPT_CQC
];
1391 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1394 case HERMON_RSRC_CLEANUP_LEVEL10SRQ
:
1395 /* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1396 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_CMPT_SRQC
];
1397 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1400 case HERMON_RSRC_CLEANUP_LEVEL10QP
:
1401 /* Cleanup the cMPTs for the EQs, CQs, SRQs, and QPs */
1402 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_CMPT_QPC
];
1403 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1406 case HERMON_RSRC_CLEANUP_LEVEL10
:
1407 /* Cleanup the dMPT table resource pool */
1408 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_DMPT
];
1409 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1412 case HERMON_RSRC_CLEANUP_LEVEL9
:
1413 /* Cleanup the MTT table resource pool */
1414 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_MTT
];
1415 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
1419 * The cleanup below comes from the "Phase 1" initialization step.
1420 * (see hermon_rsrc_init_phase1() above)
1422 case HERMON_RSRC_CLEANUP_PHASE1_COMPLETE
:
1423 /* Cleanup the "In" mailbox list */
1424 hermon_intr_inmbox_list_fini(state
);
1427 case HERMON_RSRC_CLEANUP_LEVEL7
:
1428 /* Cleanup the interrupt "In" mailbox resource pool */
1429 mbox_info
.mbi_rsrcpool
=
1430 &state
->hs_rsrc_hdl
[HERMON_INTR_IN_MBOX
];
1431 hermon_rsrc_mbox_fini(state
, &mbox_info
);
1434 case HERMON_RSRC_CLEANUP_LEVEL6
:
1435 /* Cleanup the "In" mailbox list */
1436 hermon_inmbox_list_fini(state
);
1439 case HERMON_RSRC_CLEANUP_LEVEL5
:
1440 /* Cleanup the "In" mailbox resource pool */
1441 mbox_info
.mbi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_IN_MBOX
];
1442 hermon_rsrc_mbox_fini(state
, &mbox_info
);
1445 case HERMON_RSRC_CLEANUP_LEVEL4
:
1446 /* Cleanup the interrupt "Out" mailbox list */
1447 hermon_intr_outmbox_list_fini(state
);
1450 case HERMON_RSRC_CLEANUP_LEVEL3
:
1451 /* Cleanup the "Out" mailbox resource pool */
1452 mbox_info
.mbi_rsrcpool
=
1453 &state
->hs_rsrc_hdl
[HERMON_INTR_OUT_MBOX
];
1454 hermon_rsrc_mbox_fini(state
, &mbox_info
);
1457 case HERMON_RSRC_CLEANUP_LEVEL2
:
1458 /* Cleanup the "Out" mailbox list */
1459 hermon_outmbox_list_fini(state
);
1462 case HERMON_RSRC_CLEANUP_LEVEL1
:
1463 /* Cleanup the "Out" mailbox resource pool */
1464 mbox_info
.mbi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_OUT_MBOX
];
1465 hermon_rsrc_mbox_fini(state
, &mbox_info
);
1468 case HERMON_RSRC_CLEANUP_LEVEL0
:
1469 /* Free the array of hermon_rsrc_pool_info_t's */
1471 kmem_free(state
->hs_rsrc_hdl
, HERMON_NUM_RESOURCES
*
1472 sizeof (hermon_rsrc_pool_info_t
));
1474 kmem_cache_destroy(state
->hs_rsrc_cache
);
1478 HERMON_WARNING(state
, "unexpected resource cleanup level");
1485 * hermon_rsrc_mbox_init()
1486 * Context: Only called from attach() path context
1489 hermon_rsrc_mbox_init(hermon_state_t
*state
, hermon_rsrc_mbox_info_t
*info
)
1491 hermon_rsrc_pool_info_t
*rsrc_pool
;
1492 hermon_rsrc_priv_mbox_t
*priv
;
1494 ASSERT(state
!= NULL
);
1495 ASSERT(info
!= NULL
);
1497 rsrc_pool
= info
->mbi_rsrcpool
;
1498 ASSERT(rsrc_pool
!= NULL
);
1500 /* Allocate and initialize mailbox private structure */
1501 priv
= kmem_zalloc(sizeof (hermon_rsrc_priv_mbox_t
), KM_SLEEP
);
1502 priv
->pmb_dip
= state
->hs_dip
;
1503 priv
->pmb_devaccattr
= state
->hs_reg_accattr
;
1504 priv
->pmb_xfer_mode
= DDI_DMA_CONSISTENT
;
1507 * Initialize many of the default DMA attributes. Then set alignment
1508 * and scatter-gather restrictions specific for mailbox memory.
1510 hermon_dma_attr_init(state
, &priv
->pmb_dmaattr
);
1511 priv
->pmb_dmaattr
.dma_attr_align
= HERMON_MBOX_ALIGN
;
1512 priv
->pmb_dmaattr
.dma_attr_sgllen
= 1;
1513 priv
->pmb_dmaattr
.dma_attr_flags
= 0;
1514 rsrc_pool
->rsrc_private
= priv
;
1516 ASSERT(rsrc_pool
->rsrc_loc
== HERMON_IN_SYSMEM
);
1518 rsrc_pool
->rsrc_start
= NULL
;
1519 rsrc_pool
->rsrc_vmp
= NULL
;
1521 return (DDI_SUCCESS
);
1526 * hermon_rsrc_mbox_fini()
1527 * Context: Only called from attach() and/or detach() path contexts
1531 hermon_rsrc_mbox_fini(hermon_state_t
*state
, hermon_rsrc_mbox_info_t
*info
)
1533 hermon_rsrc_pool_info_t
*rsrc_pool
;
1535 ASSERT(state
!= NULL
);
1536 ASSERT(info
!= NULL
);
1538 rsrc_pool
= info
->mbi_rsrcpool
;
1539 ASSERT(rsrc_pool
!= NULL
);
1541 /* Free up the private struct */
1542 kmem_free(rsrc_pool
->rsrc_private
, sizeof (hermon_rsrc_priv_mbox_t
));
1547 * hermon_rsrc_hw_entries_init()
1548 * Context: Only called from attach() path context
1551 hermon_rsrc_hw_entries_init(hermon_state_t
*state
,
1552 hermon_rsrc_hw_entry_info_t
*info
)
1554 hermon_rsrc_pool_info_t
*rsrc_pool
;
1555 hermon_rsrc_t
*rsvd_rsrc
= NULL
;
1557 uint64_t num_hwentry
, max_hwentry
, num_prealloc
;
1560 ASSERT(state
!= NULL
);
1561 ASSERT(info
!= NULL
);
1563 rsrc_pool
= info
->hwi_rsrcpool
;
1564 ASSERT(rsrc_pool
!= NULL
);
1565 num_hwentry
= info
->hwi_num
;
1566 max_hwentry
= info
->hwi_max
;
1567 num_prealloc
= info
->hwi_prealloc
;
1569 if (hermon_rsrc_verbose
) {
1570 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init: "
1571 "rsrc_type (0x%x) num (%llx) max (0x%llx) prealloc "
1572 "(0x%llx)", rsrc_pool
->rsrc_type
, (longlong_t
)num_hwentry
,
1573 (longlong_t
)max_hwentry
, (longlong_t
)num_prealloc
);
1576 /* Make sure number of HW entries makes sense */
1577 if (num_hwentry
> max_hwentry
) {
1578 return (DDI_FAILURE
);
1581 /* Set this pool's rsrc_start from the initial ICM allocation */
1582 if (rsrc_pool
->rsrc_start
== 0) {
1584 /* use a ROUND value that works on both 32 and 64-bit kernels */
1585 rsrc_pool
->rsrc_start
= (void *)(uintptr_t)0x10000000;
1587 if (hermon_rsrc_verbose
) {
1588 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
1589 " rsrc_type (0x%x) rsrc_start set (0x%lx)",
1590 rsrc_pool
->rsrc_type
, rsrc_pool
->rsrc_start
);
1595 * Create new vmem arena for the HW entries table if rsrc_quantum
1596 * is non-zero. Otherwise if rsrc_quantum is zero, then these HW
1597 * entries are not going to be dynamically allocatable (i.e. they
1598 * won't be allocated/freed through hermon_rsrc_alloc/free). This
1599 * latter option is used for both ALTC and CMPT resources which
1600 * are managed by hardware.
1602 if (rsrc_pool
->rsrc_quantum
!= 0) {
1603 vmp
= vmem_create(info
->hwi_rsrcname
,
1604 (void *)(uintptr_t)rsrc_pool
->rsrc_start
,
1605 rsrc_pool
->rsrc_pool_size
, rsrc_pool
->rsrc_quantum
,
1606 NULL
, NULL
, NULL
, 0, VM_SLEEP
);
1608 /* failed to create vmem arena */
1609 return (DDI_FAILURE
);
1611 rsrc_pool
->rsrc_vmp
= vmp
;
1612 if (hermon_rsrc_verbose
) {
1613 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
1614 " rsrc_type (0x%x) created vmem arena for rsrc",
1615 rsrc_pool
->rsrc_type
);
1618 /* we do not require a vmem arena */
1619 rsrc_pool
->rsrc_vmp
= NULL
;
1620 if (hermon_rsrc_verbose
) {
1621 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
1622 " rsrc_type (0x%x) vmem arena not required",
1623 rsrc_pool
->rsrc_type
);
1627 /* Allocate hardware reserved resources, if any */
1628 if (num_prealloc
!= 0) {
1629 status
= hermon_rsrc_alloc(state
, rsrc_pool
->rsrc_type
,
1630 num_prealloc
, HERMON_SLEEP
, &rsvd_rsrc
);
1631 if (status
!= DDI_SUCCESS
) {
1632 /* unable to preallocate the reserved entries */
1633 if (rsrc_pool
->rsrc_vmp
!= NULL
) {
1634 vmem_destroy(rsrc_pool
->rsrc_vmp
);
1636 return (DDI_FAILURE
);
1639 rsrc_pool
->rsrc_private
= rsvd_rsrc
;
1641 return (DDI_SUCCESS
);
1646 * hermon_rsrc_hw_entries_fini()
1647 * Context: Only called from attach() and/or detach() path contexts
1650 hermon_rsrc_hw_entries_fini(hermon_state_t
*state
,
1651 hermon_rsrc_hw_entry_info_t
*info
)
1653 hermon_rsrc_pool_info_t
*rsrc_pool
;
1654 hermon_rsrc_t
*rsvd_rsrc
;
1656 ASSERT(state
!= NULL
);
1657 ASSERT(info
!= NULL
);
1659 rsrc_pool
= info
->hwi_rsrcpool
;
1660 ASSERT(rsrc_pool
!= NULL
);
1662 /* Free up any "reserved" (i.e. preallocated) HW entries */
1663 rsvd_rsrc
= (hermon_rsrc_t
*)rsrc_pool
->rsrc_private
;
1664 if (rsvd_rsrc
!= NULL
) {
1665 hermon_rsrc_free(state
, &rsvd_rsrc
);
1669 * If we've actually setup a vmem arena for the HW entries, then
1672 if (rsrc_pool
->rsrc_vmp
!= NULL
) {
1673 vmem_destroy(rsrc_pool
->rsrc_vmp
);
1679 * hermon_rsrc_sw_handles_init()
1680 * Context: Only called from attach() path context
1684 hermon_rsrc_sw_handles_init(hermon_state_t
*state
,
1685 hermon_rsrc_sw_hdl_info_t
*info
)
1687 hermon_rsrc_pool_info_t
*rsrc_pool
;
1688 uint64_t num_swhdl
, max_swhdl
, prealloc_sz
;
1690 ASSERT(state
!= NULL
);
1691 ASSERT(info
!= NULL
);
1693 rsrc_pool
= info
->swi_rsrcpool
;
1694 ASSERT(rsrc_pool
!= NULL
);
1695 num_swhdl
= info
->swi_num
;
1696 max_swhdl
= info
->swi_max
;
1697 prealloc_sz
= info
->swi_prealloc_sz
;
1700 /* Make sure number of SW handles makes sense */
1701 if (num_swhdl
> max_swhdl
) {
1702 return (DDI_FAILURE
);
1706 * Depending on the flags parameter, create a kmem_cache for some
1707 * number of software handle structures. Note: kmem_cache_create()
1708 * will SLEEP until successful.
1710 if (info
->swi_flags
& HERMON_SWHDL_KMEMCACHE_INIT
) {
1711 rsrc_pool
->rsrc_private
= kmem_cache_create(
1712 info
->swi_rsrcname
, rsrc_pool
->rsrc_quantum
, 0,
1713 info
->swi_constructor
, info
->swi_destructor
, NULL
,
1714 rsrc_pool
->rsrc_state
, NULL
, 0);
1718 /* Allocate the central list of SW handle pointers */
1719 if (info
->swi_flags
& HERMON_SWHDL_TABLE_INIT
) {
1720 info
->swi_table_ptr
= kmem_zalloc(num_swhdl
* prealloc_sz
,
1724 return (DDI_SUCCESS
);
1729 * hermon_rsrc_sw_handles_fini()
1730 * Context: Only called from attach() and/or detach() path contexts
1734 hermon_rsrc_sw_handles_fini(hermon_state_t
*state
,
1735 hermon_rsrc_sw_hdl_info_t
*info
)
1737 hermon_rsrc_pool_info_t
*rsrc_pool
;
1738 uint64_t num_swhdl
, prealloc_sz
;
1740 ASSERT(state
!= NULL
);
1741 ASSERT(info
!= NULL
);
1743 rsrc_pool
= info
->swi_rsrcpool
;
1744 num_swhdl
= info
->swi_num
;
1745 prealloc_sz
= info
->swi_prealloc_sz
;
1748 * If a "software handle" kmem_cache exists for this resource, then
1751 if (rsrc_pool
!= NULL
) {
1752 kmem_cache_destroy(rsrc_pool
->rsrc_private
);
1755 /* Free up this central list of SW handle pointers */
1756 if (info
->swi_table_ptr
!= NULL
) {
1757 kmem_free(info
->swi_table_ptr
, num_swhdl
* prealloc_sz
);
1763 * hermon_rsrc_pd_handles_init()
1764 * Context: Only called from attach() path context
1767 hermon_rsrc_pd_handles_init(hermon_state_t
*state
,
1768 hermon_rsrc_sw_hdl_info_t
*info
)
1770 hermon_rsrc_pool_info_t
*rsrc_pool
;
1772 char vmem_name
[HERMON_RSRC_NAME_MAXLEN
];
1775 ASSERT(state
!= NULL
);
1776 ASSERT(info
!= NULL
);
1778 rsrc_pool
= info
->swi_rsrcpool
;
1779 ASSERT(rsrc_pool
!= NULL
);
1781 /* Initialize the resource pool for software handle table */
1782 status
= hermon_rsrc_sw_handles_init(state
, info
);
1783 if (status
!= DDI_SUCCESS
) {
1784 return (DDI_FAILURE
);
1787 /* Build vmem arena name from Hermon instance */
1788 HERMON_RSRC_NAME(vmem_name
, HERMON_PDHDL_VMEM
);
1790 /* Create new vmem arena for PD numbers */
1791 vmp
= vmem_create(vmem_name
, (caddr_t
)1, info
->swi_num
, 1, NULL
,
1792 NULL
, NULL
, 0, VM_SLEEP
| VMC_IDENTIFIER
);
1794 /* Unable to create vmem arena */
1795 info
->swi_table_ptr
= NULL
;
1796 hermon_rsrc_sw_handles_fini(state
, info
);
1797 return (DDI_FAILURE
);
1799 rsrc_pool
->rsrc_vmp
= vmp
;
1801 return (DDI_SUCCESS
);
1806 * hermon_rsrc_pd_handles_fini()
1807 * Context: Only called from attach() and/or detach() path contexts
1810 hermon_rsrc_pd_handles_fini(hermon_state_t
*state
,
1811 hermon_rsrc_sw_hdl_info_t
*info
)
1813 hermon_rsrc_pool_info_t
*rsrc_pool
;
1815 ASSERT(state
!= NULL
);
1816 ASSERT(info
!= NULL
);
1818 rsrc_pool
= info
->swi_rsrcpool
;
1820 /* Destroy the specially created UAR scratch table vmem arena */
1821 vmem_destroy(rsrc_pool
->rsrc_vmp
);
1823 /* Destroy the "hermon_sw_pd_t" kmem_cache */
1824 hermon_rsrc_sw_handles_fini(state
, info
);
1829 * hermon_rsrc_mbox_alloc()
1830 * Context: Only called from attach() path context
1833 hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t
*pool_info
, uint_t num
,
1836 hermon_rsrc_priv_mbox_t
*priv
;
1838 size_t real_len
, temp_len
;
1841 ASSERT(pool_info
!= NULL
);
1842 ASSERT(hdl
!= NULL
);
1844 /* Get the private pointer for the mailboxes */
1845 priv
= pool_info
->rsrc_private
;
1846 ASSERT(priv
!= NULL
);
1848 /* Allocate a DMA handle for the mailbox */
1849 status
= ddi_dma_alloc_handle(priv
->pmb_dip
, &priv
->pmb_dmaattr
,
1850 DDI_DMA_SLEEP
, NULL
, &hdl
->hr_dmahdl
);
1851 if (status
!= DDI_SUCCESS
) {
1852 return (DDI_FAILURE
);
1855 /* Allocate memory for the mailbox */
1856 temp_len
= (num
<< pool_info
->rsrc_shift
);
1857 status
= ddi_dma_mem_alloc(hdl
->hr_dmahdl
, temp_len
,
1858 &priv
->pmb_devaccattr
, priv
->pmb_xfer_mode
, DDI_DMA_SLEEP
,
1859 NULL
, &kaddr
, &real_len
, &hdl
->hr_acchdl
);
1860 if (status
!= DDI_SUCCESS
) {
1861 /* No more memory available for mailbox entries */
1862 ddi_dma_free_handle(&hdl
->hr_dmahdl
);
1863 return (DDI_FAILURE
);
1866 hdl
->hr_addr
= (void *)kaddr
;
1867 hdl
->hr_len
= (uint32_t)real_len
;
1869 return (DDI_SUCCESS
);
1874 * hermon_rsrc_mbox_free()
1875 * Context: Can be called from interrupt or base context.
1878 hermon_rsrc_mbox_free(hermon_rsrc_t
*hdl
)
1880 ASSERT(hdl
!= NULL
);
1882 /* Use ddi_dma_mem_free() to free up sys memory for mailbox */
1883 ddi_dma_mem_free(&hdl
->hr_acchdl
);
1885 /* Free the DMA handle for the mailbox */
1886 ddi_dma_free_handle(&hdl
->hr_dmahdl
);
1891 * hermon_rsrc_hw_entry_alloc()
1892 * Context: Can be called from interrupt or base context.
1895 hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t
*pool_info
, uint_t num
,
1896 uint_t num_align
, uint_t sleepflag
, hermon_rsrc_t
*hdl
)
1904 ASSERT(pool_info
!= NULL
);
1905 ASSERT(hdl
!= NULL
);
1908 * Use vmem_xalloc() to get a properly aligned pointer (based on
1909 * the number requested) to the HW entry(ies). This handles the
1910 * cases (for special QPCs and for RDB entries) where we need more
1911 * than one and need to ensure that they are properly aligned.
1913 flag
= (sleepflag
== HERMON_SLEEP
) ? VM_SLEEP
: VM_NOSLEEP
;
1914 hdl
->hr_len
= (num
<< pool_info
->rsrc_shift
);
1915 align
= (num_align
<< pool_info
->rsrc_shift
);
1917 addr
= vmem_xalloc(pool_info
->rsrc_vmp
, hdl
->hr_len
,
1918 align
, 0, 0, NULL
, NULL
, flag
| VM_FIRSTFIT
);
1921 /* No more HW entries available */
1922 return (DDI_FAILURE
);
1925 hdl
->hr_acchdl
= NULL
; /* only used for mbox resources */
1927 /* Calculate vaddr and HW table index */
1928 offset
= (uintptr_t)addr
- (uintptr_t)pool_info
->rsrc_start
;
1929 hdl
->hr_addr
= addr
; /* only used for mbox and uarpg resources */
1930 hdl
->hr_indx
= offset
>> pool_info
->rsrc_shift
;
1932 if (pool_info
->rsrc_loc
== HERMON_IN_ICM
) {
1934 hermon_rsrc_type_t rsrc_type
= pool_info
->rsrc_type
;
1936 num_to_hdl
= (rsrc_type
== HERMON_QPC
||
1937 rsrc_type
== HERMON_CQC
|| rsrc_type
== HERMON_SRQC
);
1939 /* confirm ICM is mapped, and allocate if necessary */
1940 status
= hermon_rsrc_hw_entry_icm_confirm(pool_info
, num
, hdl
,
1942 if (status
!= DDI_SUCCESS
) {
1943 return (DDI_FAILURE
);
1945 hdl
->hr_addr
= NULL
; /* not used for ICM resources */
1948 return (DDI_SUCCESS
);
1953 * hermon_rsrc_hw_entry_reserve()
1954 * Context: Can be called from interrupt or base context.
1957 hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t
*pool_info
, uint_t num
,
1958 uint_t num_align
, uint_t sleepflag
, hermon_rsrc_t
*hdl
)
1965 ASSERT(pool_info
!= NULL
);
1966 ASSERT(hdl
!= NULL
);
1967 ASSERT(pool_info
->rsrc_loc
== HERMON_IN_ICM
);
1970 * Use vmem_xalloc() to get a properly aligned pointer (based on
1971 * the number requested) to the HW entry(ies). This handles the
1972 * cases (for special QPCs and for RDB entries) where we need more
1973 * than one and need to ensure that they are properly aligned.
1975 flag
= (sleepflag
== HERMON_SLEEP
) ? VM_SLEEP
: VM_NOSLEEP
;
1976 hdl
->hr_len
= (num
<< pool_info
->rsrc_shift
);
1977 align
= (num_align
<< pool_info
->rsrc_shift
);
1979 addr
= vmem_xalloc(pool_info
->rsrc_vmp
, hdl
->hr_len
,
1980 align
, 0, 0, NULL
, NULL
, flag
| VM_FIRSTFIT
);
1983 /* No more HW entries available */
1984 return (DDI_FAILURE
);
1987 hdl
->hr_acchdl
= NULL
; /* only used for mbox resources */
1989 /* Calculate vaddr and HW table index */
1990 offset
= (uintptr_t)addr
- (uintptr_t)pool_info
->rsrc_start
;
1991 hdl
->hr_addr
= NULL
;
1992 hdl
->hr_indx
= offset
>> pool_info
->rsrc_shift
;
1994 /* ICM will be allocated and mapped if and when it gets used */
1996 return (DDI_SUCCESS
);
2001 * hermon_rsrc_hw_entry_free()
2002 * Context: Can be called from interrupt or base context.
2005 hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t
*pool_info
,
2012 ASSERT(pool_info
!= NULL
);
2013 ASSERT(hdl
!= NULL
);
2015 /* Calculate the allocated address */
2016 offset
= hdl
->hr_indx
<< pool_info
->rsrc_shift
;
2017 addr
= (void *)(uintptr_t)(offset
+ (uintptr_t)pool_info
->rsrc_start
);
2019 /* Use vmem_xfree() to free up the HW table entry */
2020 vmem_xfree(pool_info
->rsrc_vmp
, addr
, hdl
->hr_len
);
2022 if (pool_info
->rsrc_loc
== HERMON_IN_ICM
) {
2024 hermon_rsrc_type_t rsrc_type
= pool_info
->rsrc_type
;
2026 num_to_hdl
= (rsrc_type
== HERMON_QPC
||
2027 rsrc_type
== HERMON_CQC
|| rsrc_type
== HERMON_SRQC
);
2029 /* free ICM references, and free ICM if required */
2030 status
= hermon_rsrc_hw_entry_icm_free(pool_info
, hdl
,
2032 if (status
!= DDI_SUCCESS
)
2033 HERMON_WARNING(pool_info
->rsrc_state
,
2034 "failure in hw_entry_free");
2039 * hermon_rsrc_hw_entry_icm_confirm()
2040 * Context: Can be called from interrupt or base context.
2043 hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t
*pool_info
, uint_t num
,
2044 hermon_rsrc_t
*hdl
, int num_to_hdl
)
2046 hermon_state_t
*state
;
2047 hermon_icm_table_t
*icm_table
;
2049 hermon_dma_info_t
*dma_info
;
2050 hermon_rsrc_type_t type
;
2051 uint32_t rindx
, span_offset
;
2052 uint32_t span_avail
;
2055 uint32_t index1
, index2
;
2058 * Utility routine responsible for ensuring that there is memory
2059 * backing the ICM resources allocated via hermon_rsrc_hw_entry_alloc().
2060 * Confirm existing ICM mapping(s) or allocate ICM memory for the
2061 * given hardware resources being allocated, and increment the
2062 * ICM DMA structure(s) reference count.
2064 * We may be allocating more objects than can fit in a single span,
2065 * or more than will fit in the remaining contiguous memory (from
2066 * the offset indicated by hdl->ar_indx) in the span in question.
2067 * In either of these cases, we'll be breaking up our allocation
2068 * into multiple spans.
2070 state
= pool_info
->rsrc_state
;
2071 type
= pool_info
->rsrc_type
;
2072 icm_table
= &state
->hs_icm
[type
];
2074 rindx
= hdl
->hr_indx
;
2075 hermon_index(index1
, index2
, rindx
, icm_table
, span_offset
);
2077 if (hermon_rsrc_verbose
) {
2078 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_confirm: "
2079 "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x): ",
2080 type
, num
, hdl
->hr_len
, index1
, index2
);
2083 mutex_enter(&icm_table
->icm_table_lock
);
2084 hermon_bitmap(bitmap
, dma_info
, icm_table
, index1
, num_to_hdl
);
2087 while (icm_table
->icm_busy
) {
2088 cv_wait(&icm_table
->icm_table_cv
,
2089 &icm_table
->icm_table_lock
);
2092 if (!HERMON_BMAP_BIT_ISSET(bitmap
, index2
)) {
2093 /* Allocate ICM for this span */
2094 icm_table
->icm_busy
= 1;
2095 mutex_exit(&icm_table
->icm_table_lock
);
2096 status
= hermon_icm_alloc(state
, type
, index1
, index2
);
2097 mutex_enter(&icm_table
->icm_table_lock
);
2098 icm_table
->icm_busy
= 0;
2099 cv_broadcast(&icm_table
->icm_table_cv
);
2100 if (status
!= DDI_SUCCESS
) {
2103 if (hermon_rsrc_verbose
) {
2104 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
2105 "hw_entry_icm_confirm: ALLOCATED ICM: "
2106 "type (0x%x) index (0x%x, 0x%x)",
2107 type
, index1
, index2
);
2112 * We need to increment the refcnt of this span by the
2113 * number of objects in this resource allocation that are
2114 * backed by this span. Given that the rsrc allocation is
2115 * contiguous, this value will be the number of objects in
2116 * the span from 'span_offset' onward, either up to a max
2117 * of the total number of objects, or the end of the span.
2118 * So, determine the number of objects that can be backed
2119 * by this span ('span_avail'), then determine the number
2120 * of backed resources.
2122 span_avail
= icm_table
->span
- span_offset
;
2123 if (num
> span_avail
) {
2124 num_backed
= span_avail
;
2130 * Now that we know 'num_backed', increment the refcnt,
2131 * decrement the total number, and set 'span_offset' to
2132 * 0 in case we roll over into the next span.
2134 dma_info
[index2
].icm_refcnt
+= num_backed
;
2135 rindx
+= num_backed
;
2138 if (hermon_rsrc_verbose
) {
2139 IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) index "
2140 "(0x%x, 0x%x) num_backed (0x%x)",
2141 type
, index1
, index2
, num_backed
);
2142 IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) refcnt now "
2143 "(0x%x) num_remaining (0x%x)", type
,
2144 dma_info
[index2
].icm_refcnt
, num
);
2149 hermon_index(index1
, index2
, rindx
, icm_table
, span_offset
);
2150 hermon_bitmap(bitmap
, dma_info
, icm_table
, index1
, num_to_hdl
);
2152 mutex_exit(&icm_table
->icm_table_lock
);
2154 return (DDI_SUCCESS
);
2158 if (hermon_rsrc_verbose
) {
2159 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
2160 "hw_entry_icm_confirm: FAILED ICM ALLOC: "
2161 "type (0x%x) num remaind (0x%x) index (0x%x, 0x%x)"
2162 "refcnt (0x%x)", type
, num
, index1
, index2
,
2163 icm_table
->icm_dma
[index1
][index2
].icm_refcnt
);
2165 IBTF_DPRINTF_L2("hermon", "WARNING: "
2166 "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
2169 /* free refcnt's and any spans we've allocated */
2170 while (index
-- != start
) {
2172 * JBDB - This is a bit tricky. We need to
2173 * free refcnt's on any spans that we've
2174 * incremented them on, and completely free
2175 * spans that we've allocated. How do we do
2176 * this here? Does it need to be as involved
2177 * as the core of icm_free() below, or can
2178 * we leverage breadcrumbs somehow?
2180 HERMON_WARNING(state
, "unable to allocate ICM memory: "
2181 "UNIMPLEMENTED HANDLING!!");
2185 "unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
2187 mutex_exit(&icm_table
->icm_table_lock
);
2189 HERMON_WARNING(state
, "unable to allocate ICM memory");
2190 return (DDI_FAILURE
);
2194 * hermon_rsrc_hw_entry_icm_free()
2195 * Context: Can be called from interrupt or base context.
2198 hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t
*pool_info
,
2199 hermon_rsrc_t
*hdl
, int num_to_hdl
)
2201 hermon_state_t
*state
;
2202 hermon_icm_table_t
*icm_table
;
2204 hermon_dma_info_t
*dma_info
;
2205 hermon_rsrc_type_t type
;
2206 uint32_t span_offset
;
2207 uint32_t span_remain
;
2210 uint32_t index1
, index2
, rindx
;
2213 * Utility routine responsible for freeing references to ICM
2214 * DMA spans, and freeing the ICM memory if necessary.
2216 * We may have allocated objects in a single contiguous resource
2217 * allocation that reside in a number of spans, at any given
2218 * starting offset within a span. We therefore must determine
2219 * where this allocation starts, and then determine if we need
2220 * to free objects in more than one span.
2222 state
= pool_info
->rsrc_state
;
2223 type
= pool_info
->rsrc_type
;
2224 icm_table
= &state
->hs_icm
[type
];
2226 rindx
= hdl
->hr_indx
;
2227 hermon_index(index1
, index2
, rindx
, icm_table
, span_offset
);
2228 hermon_bitmap(bitmap
, dma_info
, icm_table
, index1
, num_to_hdl
);
2230 /* determine the number of ICM objects in this allocation */
2231 num
= hdl
->hr_len
>> pool_info
->rsrc_shift
;
2233 if (hermon_rsrc_verbose
) {
2234 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_free: "
2235 "type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x)",
2236 type
, num
, hdl
->hr_len
, index1
, index2
);
2238 mutex_enter(&icm_table
->icm_table_lock
);
2241 * As with the ICM confirm code above, we need to
2242 * decrement the ICM span(s) by the number of
2243 * resources being freed. So, determine the number
2244 * of objects that are backed in this span from
2245 * 'span_offset' onward, and set 'num_freed' to
2246 * the smaller of either that number ('span_remain'),
2247 * or the total number of objects being freed.
2249 span_remain
= icm_table
->span
- span_offset
;
2250 if (num
> span_remain
) {
2251 num_freed
= span_remain
;
2257 * Now that we know 'num_freed', decrement the refcnt,
2258 * decrement the total number, and set 'span_offset' to
2259 * 0 in case we roll over into the next span.
2261 dma_info
[index2
].icm_refcnt
-= num_freed
;
2265 if (hermon_rsrc_verbose
) {
2266 IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) index "
2267 "(0x%x, 0x%x) num_freed (0x%x)", type
,
2268 index1
, index2
, num_freed
);
2269 IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) refcnt now "
2270 "(0x%x) num remaining (0x%x)", type
,
2271 icm_table
->icm_dma
[index1
][index2
].icm_refcnt
, num
);
2274 #if HERMON_ICM_FREE_ENABLED
2275 /* If we've freed the last object in this span, free it */
2276 if ((index1
!= 0 || index2
!= 0) &&
2277 (dma_info
[index2
].icm_refcnt
== 0)) {
2278 if (hermon_rsrc_verbose
) {
2279 IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry"
2280 "_icm_free: freeing ICM type (0x%x) index"
2281 " (0x%x, 0x%x)", type
, index1
, index2
);
2283 hermon_icm_free(state
, type
, index1
, index2
);
2289 hermon_index(index1
, index2
, rindx
, icm_table
, span_offset
);
2290 hermon_bitmap(bitmap
, dma_info
, icm_table
, index1
, num_to_hdl
);
2292 mutex_exit(&icm_table
->icm_table_lock
);
2294 return (DDI_SUCCESS
);
2300 * hermon_rsrc_swhdl_alloc()
2301 * Context: Can be called from interrupt or base context.
2304 hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t
*pool_info
, uint_t sleepflag
,
2310 ASSERT(pool_info
!= NULL
);
2311 ASSERT(hdl
!= NULL
);
2313 /* Allocate the software handle structure */
2314 flag
= (sleepflag
== HERMON_SLEEP
) ? KM_SLEEP
: KM_NOSLEEP
;
2315 addr
= kmem_cache_alloc(pool_info
->rsrc_private
, flag
);
2317 return (DDI_FAILURE
);
2319 hdl
->hr_len
= pool_info
->rsrc_quantum
;
2320 hdl
->hr_addr
= addr
;
2322 return (DDI_SUCCESS
);
2327 * hermon_rsrc_swhdl_free()
2328 * Context: Can be called from interrupt or base context.
2331 hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t
*pool_info
, hermon_rsrc_t
*hdl
)
2333 ASSERT(pool_info
!= NULL
);
2334 ASSERT(hdl
!= NULL
);
2336 /* Free the software handle structure */
2337 kmem_cache_free(pool_info
->rsrc_private
, hdl
->hr_addr
);
2342 * hermon_rsrc_pdhdl_alloc()
2343 * Context: Can be called from interrupt or base context.
2346 hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t
*pool_info
, uint_t sleepflag
,
2349 hermon_pdhdl_t addr
;
2353 ASSERT(pool_info
!= NULL
);
2354 ASSERT(hdl
!= NULL
);
2356 /* Allocate the software handle */
2357 status
= hermon_rsrc_swhdl_alloc(pool_info
, sleepflag
, hdl
);
2358 if (status
!= DDI_SUCCESS
) {
2359 return (DDI_FAILURE
);
2361 addr
= (hermon_pdhdl_t
)hdl
->hr_addr
;
2362 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr
))
2364 /* Allocate a PD number for the handle */
2365 flag
= (sleepflag
== HERMON_SLEEP
) ? VM_SLEEP
: VM_NOSLEEP
;
2366 tmpaddr
= vmem_alloc(pool_info
->rsrc_vmp
, 1, flag
);
2367 if (tmpaddr
== NULL
) {
2368 /* No more PD number entries available */
2369 hermon_rsrc_swhdl_free(pool_info
, hdl
);
2370 return (DDI_FAILURE
);
2372 addr
->pd_pdnum
= (uint32_t)(uintptr_t)tmpaddr
;
2373 addr
->pd_rsrcp
= hdl
;
2374 hdl
->hr_indx
= addr
->pd_pdnum
;
2376 return (DDI_SUCCESS
);
2381 * hermon_rsrc_pdhdl_free()
2382 * Context: Can be called from interrupt or base context.
2385 hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t
*pool_info
, hermon_rsrc_t
*hdl
)
2387 ASSERT(pool_info
!= NULL
);
2388 ASSERT(hdl
!= NULL
);
2390 /* Use vmem_free() to free up the PD number */
2391 vmem_free(pool_info
->rsrc_vmp
, (void *)(uintptr_t)hdl
->hr_indx
, 1);
2393 /* Free the software handle structure */
2394 hermon_rsrc_swhdl_free(pool_info
, hdl
);
2399 * hermon_rsrc_pdhdl_constructor()
2400 * Context: Can be called from interrupt or base context.
2404 hermon_rsrc_pdhdl_constructor(void *pd
, void *priv
, int flags
)
2406 hermon_pdhdl_t pdhdl
;
2407 hermon_state_t
*state
;
2409 pdhdl
= (hermon_pdhdl_t
)pd
;
2410 state
= (hermon_state_t
*)priv
;
2412 mutex_init(&pdhdl
->pd_lock
, NULL
, MUTEX_DRIVER
,
2413 DDI_INTR_PRI(state
->hs_intrmsi_pri
));
2415 return (DDI_SUCCESS
);
2420 * hermon_rsrc_pdhdl_destructor()
2421 * Context: Can be called from interrupt or base context.
2425 hermon_rsrc_pdhdl_destructor(void *pd
, void *priv
)
2427 hermon_pdhdl_t pdhdl
;
2429 pdhdl
= (hermon_pdhdl_t
)pd
;
2431 mutex_destroy(&pdhdl
->pd_lock
);
2436 * hermon_rsrc_cqhdl_constructor()
2437 * Context: Can be called from interrupt or base context.
2441 hermon_rsrc_cqhdl_constructor(void *cq
, void *priv
, int flags
)
2443 hermon_cqhdl_t cqhdl
;
2444 hermon_state_t
*state
;
2446 cqhdl
= (hermon_cqhdl_t
)cq
;
2447 state
= (hermon_state_t
*)priv
;
2449 mutex_init(&cqhdl
->cq_lock
, NULL
, MUTEX_DRIVER
,
2450 DDI_INTR_PRI(state
->hs_intrmsi_pri
));
2452 return (DDI_SUCCESS
);
2457 * hermon_rsrc_cqhdl_destructor()
2458 * Context: Can be called from interrupt or base context.
2462 hermon_rsrc_cqhdl_destructor(void *cq
, void *priv
)
2464 hermon_cqhdl_t cqhdl
;
2466 cqhdl
= (hermon_cqhdl_t
)cq
;
2468 mutex_destroy(&cqhdl
->cq_lock
);
2473 * hermon_rsrc_qphdl_constructor()
2474 * Context: Can be called from interrupt or base context.
2478 hermon_rsrc_qphdl_constructor(void *qp
, void *priv
, int flags
)
2480 hermon_qphdl_t qphdl
;
2481 hermon_state_t
*state
;
2483 qphdl
= (hermon_qphdl_t
)qp
;
2484 state
= (hermon_state_t
*)priv
;
2486 mutex_init(&qphdl
->qp_lock
, NULL
, MUTEX_DRIVER
,
2487 DDI_INTR_PRI(state
->hs_intrmsi_pri
));
2489 return (DDI_SUCCESS
);
2494 * hermon_rsrc_qphdl_destructor()
2495 * Context: Can be called from interrupt or base context.
2499 hermon_rsrc_qphdl_destructor(void *qp
, void *priv
)
2501 hermon_qphdl_t qphdl
;
2503 qphdl
= (hermon_qphdl_t
)qp
;
2505 mutex_destroy(&qphdl
->qp_lock
);
2510 * hermon_rsrc_srqhdl_constructor()
2511 * Context: Can be called from interrupt or base context.
2515 hermon_rsrc_srqhdl_constructor(void *srq
, void *priv
, int flags
)
2517 hermon_srqhdl_t srqhdl
;
2518 hermon_state_t
*state
;
2520 srqhdl
= (hermon_srqhdl_t
)srq
;
2521 state
= (hermon_state_t
*)priv
;
2523 mutex_init(&srqhdl
->srq_lock
, NULL
, MUTEX_DRIVER
,
2524 DDI_INTR_PRI(state
->hs_intrmsi_pri
));
2526 return (DDI_SUCCESS
);
2531 * hermon_rsrc_srqhdl_destructor()
2532 * Context: Can be called from interrupt or base context.
2536 hermon_rsrc_srqhdl_destructor(void *srq
, void *priv
)
2538 hermon_srqhdl_t srqhdl
;
2540 srqhdl
= (hermon_srqhdl_t
)srq
;
2542 mutex_destroy(&srqhdl
->srq_lock
);
2547 * hermon_rsrc_refcnt_constructor()
2548 * Context: Can be called from interrupt or base context.
2552 hermon_rsrc_refcnt_constructor(void *rc
, void *priv
, int flags
)
2554 hermon_sw_refcnt_t
*refcnt
;
2555 hermon_state_t
*state
;
2557 refcnt
= (hermon_sw_refcnt_t
*)rc
;
2558 state
= (hermon_state_t
*)priv
;
2560 mutex_init(&refcnt
->swrc_lock
, NULL
, MUTEX_DRIVER
,
2561 DDI_INTR_PRI(state
->hs_intrmsi_pri
));
2563 return (DDI_SUCCESS
);
2568 * hermon_rsrc_refcnt_destructor()
2569 * Context: Can be called from interrupt or base context.
2573 hermon_rsrc_refcnt_destructor(void *rc
, void *priv
)
2575 hermon_sw_refcnt_t
*refcnt
;
2577 refcnt
= (hermon_sw_refcnt_t
*)rc
;
2579 mutex_destroy(&refcnt
->swrc_lock
);
2584 * hermon_rsrc_ahhdl_constructor()
2585 * Context: Can be called from interrupt or base context.
2589 hermon_rsrc_ahhdl_constructor(void *ah
, void *priv
, int flags
)
2591 hermon_ahhdl_t ahhdl
;
2592 hermon_state_t
*state
;
2594 ahhdl
= (hermon_ahhdl_t
)ah
;
2595 state
= (hermon_state_t
*)priv
;
2597 mutex_init(&ahhdl
->ah_lock
, NULL
, MUTEX_DRIVER
,
2598 DDI_INTR_PRI(state
->hs_intrmsi_pri
));
2599 return (DDI_SUCCESS
);
2604 * hermon_rsrc_ahhdl_destructor()
2605 * Context: Can be called from interrupt or base context.
2609 hermon_rsrc_ahhdl_destructor(void *ah
, void *priv
)
2611 hermon_ahhdl_t ahhdl
;
2613 ahhdl
= (hermon_ahhdl_t
)ah
;
2615 mutex_destroy(&ahhdl
->ah_lock
);
2620 * hermon_rsrc_mrhdl_constructor()
2621 * Context: Can be called from interrupt or base context.
2625 hermon_rsrc_mrhdl_constructor(void *mr
, void *priv
, int flags
)
2627 hermon_mrhdl_t mrhdl
;
2628 hermon_state_t
*state
;
2630 mrhdl
= (hermon_mrhdl_t
)mr
;
2631 state
= (hermon_state_t
*)priv
;
2633 mutex_init(&mrhdl
->mr_lock
, NULL
, MUTEX_DRIVER
,
2634 DDI_INTR_PRI(state
->hs_intrmsi_pri
));
2636 return (DDI_SUCCESS
);
2641 * hermon_rsrc_mrhdl_destructor()
2642 * Context: Can be called from interrupt or base context.
2646 hermon_rsrc_mrhdl_destructor(void *mr
, void *priv
)
2648 hermon_mrhdl_t mrhdl
;
2650 mrhdl
= (hermon_mrhdl_t
)mr
;
2652 mutex_destroy(&mrhdl
->mr_lock
);
2657 * hermon_rsrc_mcg_entry_get_size()
2660 hermon_rsrc_mcg_entry_get_size(hermon_state_t
*state
, uint_t
*mcg_size_shift
)
2662 uint_t num_qp_per_mcg
, max_qp_per_mcg
, log2
;
2665 * Round the configured number of QP per MCG to next larger
2666 * power-of-2 size and update.
2668 num_qp_per_mcg
= state
->hs_cfg_profile
->cp_num_qp_per_mcg
+ 8;
2669 log2
= highbit(num_qp_per_mcg
);
2670 if (ISP2(num_qp_per_mcg
)) {
2673 state
->hs_cfg_profile
->cp_num_qp_per_mcg
= (1 << log2
) - 8;
2675 /* Now make sure number of QP per MCG makes sense */
2676 num_qp_per_mcg
= state
->hs_cfg_profile
->cp_num_qp_per_mcg
;
2677 max_qp_per_mcg
= (1 << state
->hs_devlim
.log_max_qp_mcg
);
2678 if (num_qp_per_mcg
> max_qp_per_mcg
) {
2679 return (DDI_FAILURE
);
2682 /* Return the (shift) size of an individual MCG HW entry */
2683 *mcg_size_shift
= log2
+ 2;
2685 return (DDI_SUCCESS
);