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 }