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 }