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