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