Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*


8276     ibt_channel_hdl_t *chan_hdl_p, ibt_chan_sizes_t *sizes)
8277 {
8278         daplka_hca_t    *hca_p;
8279         uint32_t        max_qps;
8280         boolean_t       acct_enabled;
8281         ibt_status_t    status;
8282 
8283         acct_enabled = daplka_accounting_enabled;
8284         hca_p = ep_rp->ep_hca;
8285         max_qps = daplka_max_qp_percent * hca_p->hca_attr.hca_max_chans / 100;
8286 
8287         if (acct_enabled) {
8288                 if (daplka_max_qp_percent != 0 &&
8289                     max_qps <= hca_p->hca_qp_count) {
8290                         DERR("ibt_alloc_rc_channel: resource limit exceeded "
8291                             "(limit %d, count %d)\n", max_qps,
8292                             hca_p->hca_qp_count);
8293                         return (IBT_INSUFF_RESOURCE);
8294                 }
8295                 DAPLKA_RS_ACCT_INC(ep_rp, 1);
8296                 atomic_add_32(&hca_p->hca_qp_count, 1);
8297         }
8298         status = ibt_alloc_rc_channel(hca_hdl, flags, args, chan_hdl_p, sizes);
8299 
8300         if (status != IBT_SUCCESS && acct_enabled) {
8301                 DAPLKA_RS_ACCT_DEC(ep_rp, 1);
8302                 atomic_add_32(&hca_p->hca_qp_count, -1);
8303         }
8304         return (status);
8305 }
8306 
8307 static ibt_status_t
8308 daplka_ibt_free_channel(daplka_ep_resource_t *ep_rp, ibt_channel_hdl_t chan_hdl)
8309 {
8310         daplka_hca_t    *hca_p;
8311         ibt_status_t    status;
8312 
8313         hca_p = ep_rp->ep_hca;
8314 
8315         status = ibt_free_channel(chan_hdl);
8316         if (status != IBT_SUCCESS) {
8317                 return (status);
8318         }
8319         if (DAPLKA_RS_ACCT_CHARGED(ep_rp) > 0) {
8320                 DAPLKA_RS_ACCT_DEC(ep_rp, 1);
8321                 atomic_add_32(&hca_p->hca_qp_count, -1);
8322         }
8323         return (status);
8324 }
8325 
8326 static ibt_status_t
8327 daplka_ibt_alloc_cq(daplka_evd_resource_t *evd_rp, ibt_hca_hdl_t hca_hdl,
8328     ibt_cq_attr_t *cq_attr, ibt_cq_hdl_t *ibt_cq_p, uint32_t *real_size)
8329 {
8330         daplka_hca_t    *hca_p;
8331         uint32_t        max_cqs;
8332         boolean_t       acct_enabled;
8333         ibt_status_t    status;
8334 
8335         acct_enabled = daplka_accounting_enabled;
8336         hca_p = evd_rp->evd_hca;
8337         max_cqs = daplka_max_cq_percent * hca_p->hca_attr.hca_max_cq / 100;
8338 
8339         if (acct_enabled) {
8340                 if (daplka_max_cq_percent != 0 &&
8341                     max_cqs <= hca_p->hca_cq_count) {
8342                         DERR("ibt_alloc_cq: resource limit exceeded "
8343                             "(limit %d, count %d)\n", max_cqs,
8344                             hca_p->hca_cq_count);
8345                         return (IBT_INSUFF_RESOURCE);
8346                 }
8347                 DAPLKA_RS_ACCT_INC(evd_rp, 1);
8348                 atomic_add_32(&hca_p->hca_cq_count, 1);
8349         }
8350         status = ibt_alloc_cq(hca_hdl, cq_attr, ibt_cq_p, real_size);
8351 
8352         if (status != IBT_SUCCESS && acct_enabled) {
8353                 DAPLKA_RS_ACCT_DEC(evd_rp, 1);
8354                 atomic_add_32(&hca_p->hca_cq_count, -1);
8355         }
8356         return (status);
8357 }
8358 
8359 static ibt_status_t
8360 daplka_ibt_free_cq(daplka_evd_resource_t *evd_rp, ibt_cq_hdl_t cq_hdl)
8361 {
8362         daplka_hca_t    *hca_p;
8363         ibt_status_t    status;
8364 
8365         hca_p = evd_rp->evd_hca;
8366 
8367         status = ibt_free_cq(cq_hdl);
8368         if (status != IBT_SUCCESS) {
8369                 return (status);
8370         }
8371         if (DAPLKA_RS_ACCT_CHARGED(evd_rp) > 0) {
8372                 DAPLKA_RS_ACCT_DEC(evd_rp, 1);
8373                 atomic_add_32(&hca_p->hca_cq_count, -1);
8374         }
8375         return (status);
8376 }
8377 
8378 static ibt_status_t
8379 daplka_ibt_alloc_pd(daplka_pd_resource_t *pd_rp, ibt_hca_hdl_t hca_hdl,
8380     ibt_pd_flags_t flags, ibt_pd_hdl_t *pd_hdl_p)
8381 {
8382         daplka_hca_t    *hca_p;
8383         uint32_t        max_pds;
8384         boolean_t       acct_enabled;
8385         ibt_status_t    status;
8386 
8387         acct_enabled = daplka_accounting_enabled;
8388         hca_p = pd_rp->pd_hca;
8389         max_pds = daplka_max_pd_percent * hca_p->hca_attr.hca_max_pd / 100;
8390 
8391         if (acct_enabled) {
8392                 if (daplka_max_pd_percent != 0 &&
8393                     max_pds <= hca_p->hca_pd_count) {
8394                         DERR("ibt_alloc_pd: resource limit exceeded "
8395                             "(limit %d, count %d)\n", max_pds,
8396                             hca_p->hca_pd_count);
8397                         return (IBT_INSUFF_RESOURCE);
8398                 }
8399                 DAPLKA_RS_ACCT_INC(pd_rp, 1);
8400                 atomic_add_32(&hca_p->hca_pd_count, 1);
8401         }
8402         status = ibt_alloc_pd(hca_hdl, flags, pd_hdl_p);
8403 
8404         if (status != IBT_SUCCESS && acct_enabled) {
8405                 DAPLKA_RS_ACCT_DEC(pd_rp, 1);
8406                 atomic_add_32(&hca_p->hca_pd_count, -1);
8407         }
8408         return (status);
8409 }
8410 
8411 static ibt_status_t
8412 daplka_ibt_free_pd(daplka_pd_resource_t *pd_rp, ibt_hca_hdl_t hca_hdl,
8413     ibt_pd_hdl_t pd_hdl)
8414 {
8415         daplka_hca_t    *hca_p;
8416         ibt_status_t    status;
8417 
8418         hca_p = pd_rp->pd_hca;
8419 
8420         status = ibt_free_pd(hca_hdl, pd_hdl);
8421         if (status != IBT_SUCCESS) {
8422                 return (status);
8423         }
8424         if (DAPLKA_RS_ACCT_CHARGED(pd_rp) > 0) {
8425                 DAPLKA_RS_ACCT_DEC(pd_rp, 1);
8426                 atomic_add_32(&hca_p->hca_pd_count, -1);
8427         }
8428         return (status);
8429 }
8430 
8431 static ibt_status_t
8432 daplka_ibt_alloc_mw(daplka_mw_resource_t *mw_rp, ibt_hca_hdl_t hca_hdl,
8433     ibt_pd_hdl_t pd_hdl, ibt_mw_flags_t flags, ibt_mw_hdl_t *mw_hdl_p,
8434     ibt_rkey_t *rkey_p)
8435 {
8436         daplka_hca_t    *hca_p;
8437         uint32_t        max_mws;
8438         boolean_t       acct_enabled;
8439         ibt_status_t    status;
8440 
8441         acct_enabled = daplka_accounting_enabled;
8442         hca_p = mw_rp->mw_hca;
8443         max_mws = daplka_max_mw_percent * hca_p->hca_attr.hca_max_mem_win / 100;
8444 
8445         if (acct_enabled) {
8446                 if (daplka_max_mw_percent != 0 &&
8447                     max_mws <= hca_p->hca_mw_count) {
8448                         DERR("ibt_alloc_mw: resource limit exceeded "
8449                             "(limit %d, count %d)\n", max_mws,
8450                             hca_p->hca_mw_count);
8451                         return (IBT_INSUFF_RESOURCE);
8452                 }
8453                 DAPLKA_RS_ACCT_INC(mw_rp, 1);
8454                 atomic_add_32(&hca_p->hca_mw_count, 1);
8455         }
8456         status = ibt_alloc_mw(hca_hdl, pd_hdl, flags, mw_hdl_p, rkey_p);
8457 
8458         if (status != IBT_SUCCESS && acct_enabled) {
8459                 DAPLKA_RS_ACCT_DEC(mw_rp, 1);
8460                 atomic_add_32(&hca_p->hca_mw_count, -1);
8461         }
8462         return (status);
8463 }
8464 
8465 static ibt_status_t
8466 daplka_ibt_free_mw(daplka_mw_resource_t *mw_rp, ibt_hca_hdl_t hca_hdl,
8467     ibt_mw_hdl_t mw_hdl)
8468 {
8469         daplka_hca_t    *hca_p;
8470         ibt_status_t    status;
8471 
8472         hca_p = mw_rp->mw_hca;
8473 
8474         status = ibt_free_mw(hca_hdl, mw_hdl);
8475         if (status != IBT_SUCCESS) {
8476                 return (status);
8477         }
8478         if (DAPLKA_RS_ACCT_CHARGED(mw_rp) > 0) {
8479                 DAPLKA_RS_ACCT_DEC(mw_rp, 1);
8480                 atomic_add_32(&hca_p->hca_mw_count, -1);
8481         }
8482         return (status);
8483 }
8484 
8485 static ibt_status_t
8486 daplka_ibt_register_mr(daplka_mr_resource_t *mr_rp, ibt_hca_hdl_t hca_hdl,
8487     ibt_pd_hdl_t pd_hdl, ibt_mr_attr_t *mr_attr, ibt_mr_hdl_t *mr_hdl_p,
8488     ibt_mr_desc_t *mr_desc_p)
8489 {
8490         daplka_hca_t    *hca_p;
8491         uint32_t        max_mrs;
8492         boolean_t       acct_enabled;
8493         ibt_status_t    status;
8494 
8495         acct_enabled = daplka_accounting_enabled;
8496         hca_p = mr_rp->mr_hca;
8497         max_mrs = daplka_max_mr_percent * hca_p->hca_attr.hca_max_memr / 100;
8498 
8499         if (acct_enabled) {
8500                 if (daplka_max_mr_percent != 0 &&
8501                     max_mrs <= hca_p->hca_mr_count) {
8502                         DERR("ibt_register_mr: resource limit exceeded "
8503                             "(limit %d, count %d)\n", max_mrs,
8504                             hca_p->hca_mr_count);
8505                         return (IBT_INSUFF_RESOURCE);
8506                 }
8507                 DAPLKA_RS_ACCT_INC(mr_rp, 1);
8508                 atomic_add_32(&hca_p->hca_mr_count, 1);
8509         }
8510         status = ibt_register_mr(hca_hdl, pd_hdl, mr_attr, mr_hdl_p, mr_desc_p);
8511 
8512         if (status != IBT_SUCCESS && acct_enabled) {
8513                 DAPLKA_RS_ACCT_DEC(mr_rp, 1);
8514                 atomic_add_32(&hca_p->hca_mr_count, -1);
8515         }
8516         return (status);
8517 }
8518 
8519 static ibt_status_t
8520 daplka_ibt_register_shared_mr(daplka_mr_resource_t *mr_rp,
8521     ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl, ibt_pd_hdl_t pd_hdl,
8522     ibt_smr_attr_t *smr_attr_p, ibt_mr_hdl_t *mr_hdl_p,
8523     ibt_mr_desc_t *mr_desc_p)
8524 {
8525         daplka_hca_t    *hca_p;
8526         uint32_t        max_mrs;
8527         boolean_t       acct_enabled;
8528         ibt_status_t    status;
8529 
8530         acct_enabled = daplka_accounting_enabled;
8531         hca_p = mr_rp->mr_hca;
8532         max_mrs = daplka_max_mr_percent * hca_p->hca_attr.hca_max_memr / 100;
8533 
8534         if (acct_enabled) {
8535                 if (daplka_max_mr_percent != 0 &&
8536                     max_mrs <= hca_p->hca_mr_count) {
8537                         DERR("ibt_register_shared_mr: resource limit exceeded "
8538                             "(limit %d, count %d)\n", max_mrs,
8539                             hca_p->hca_mr_count);
8540                         return (IBT_INSUFF_RESOURCE);
8541                 }
8542                 DAPLKA_RS_ACCT_INC(mr_rp, 1);
8543                 atomic_add_32(&hca_p->hca_mr_count, 1);
8544         }
8545         status = ibt_register_shared_mr(hca_hdl, mr_hdl, pd_hdl,
8546             smr_attr_p, mr_hdl_p, mr_desc_p);
8547 
8548         if (status != IBT_SUCCESS && acct_enabled) {
8549                 DAPLKA_RS_ACCT_DEC(mr_rp, 1);
8550                 atomic_add_32(&hca_p->hca_mr_count, -1);
8551         }
8552         return (status);
8553 }
8554 
8555 static ibt_status_t
8556 daplka_ibt_deregister_mr(daplka_mr_resource_t *mr_rp, ibt_hca_hdl_t hca_hdl,
8557     ibt_mr_hdl_t mr_hdl)
8558 {
8559         daplka_hca_t    *hca_p;
8560         ibt_status_t    status;
8561 
8562         hca_p = mr_rp->mr_hca;
8563 
8564         status = ibt_deregister_mr(hca_hdl, mr_hdl);
8565         if (status != IBT_SUCCESS) {
8566                 return (status);
8567         }
8568         if (DAPLKA_RS_ACCT_CHARGED(mr_rp) > 0) {
8569                 DAPLKA_RS_ACCT_DEC(mr_rp, 1);
8570                 atomic_add_32(&hca_p->hca_mr_count, -1);
8571         }
8572         return (status);
8573 }
8574 
8575 static ibt_status_t
8576 daplka_ibt_alloc_srq(daplka_srq_resource_t *srq_rp, ibt_hca_hdl_t hca_hdl,
8577     ibt_srq_flags_t flags, ibt_pd_hdl_t pd, ibt_srq_sizes_t *reqsz,
8578     ibt_srq_hdl_t *srq_hdl_p, ibt_srq_sizes_t *realsz)
8579 {
8580         daplka_hca_t    *hca_p;
8581         uint32_t        max_srqs;
8582         boolean_t       acct_enabled;
8583         ibt_status_t    status;
8584 
8585         acct_enabled = daplka_accounting_enabled;
8586         hca_p = srq_rp->srq_hca;
8587         max_srqs = daplka_max_srq_percent * hca_p->hca_attr.hca_max_srqs / 100;
8588 
8589         if (acct_enabled) {
8590                 if (daplka_max_srq_percent != 0 &&
8591                     max_srqs <= hca_p->hca_srq_count) {
8592                         DERR("ibt_alloc_srq: resource limit exceeded "
8593                             "(limit %d, count %d)\n", max_srqs,
8594                             hca_p->hca_srq_count);
8595                         return (IBT_INSUFF_RESOURCE);
8596                 }
8597                 DAPLKA_RS_ACCT_INC(srq_rp, 1);
8598                 atomic_add_32(&hca_p->hca_srq_count, 1);
8599         }
8600         status = ibt_alloc_srq(hca_hdl, flags, pd, reqsz, srq_hdl_p, realsz);
8601 
8602         if (status != IBT_SUCCESS && acct_enabled) {
8603                 DAPLKA_RS_ACCT_DEC(srq_rp, 1);
8604                 atomic_add_32(&hca_p->hca_srq_count, -1);
8605         }
8606         return (status);
8607 }
8608 
8609 static ibt_status_t
8610 daplka_ibt_free_srq(daplka_srq_resource_t *srq_rp, ibt_srq_hdl_t srq_hdl)
8611 {
8612         daplka_hca_t    *hca_p;
8613         ibt_status_t    status;
8614 
8615         hca_p = srq_rp->srq_hca;
8616 
8617         D3("ibt_free_srq: %p %p\n", srq_rp, srq_hdl);
8618 
8619         status = ibt_free_srq(srq_hdl);
8620         if (status != IBT_SUCCESS) {
8621                 return (status);
8622         }
8623         if (DAPLKA_RS_ACCT_CHARGED(srq_rp) > 0) {
8624                 DAPLKA_RS_ACCT_DEC(srq_rp, 1);
8625                 atomic_add_32(&hca_p->hca_srq_count, -1);
8626         }
8627         return (status);
8628 }
8629 
8630 
8631 static int
8632 daplka_common_ioctl(int cmd, minor_t rnum, intptr_t arg, int mode,
8633         cred_t *cred, int *rvalp)
8634 {
8635         int error;
8636 
8637         switch (cmd) {
8638         case DAPL_IA_CREATE:
8639                 error = daplka_ia_create(rnum, arg, mode, cred, rvalp);
8640                 break;
8641 
8642         /* can potentially add other commands here */
8643 
8644         default:
8645                 DERR("daplka_common_ioctl: cmd not supported\n");


9018                 return (ENOMEM);
9019         }
9020 
9021         return (DDI_SUCCESS);
9022 }
9023 
9024 /* ARGSUSED */
9025 static int
9026 daplka_close(dev_t dev, int flag, int otyp, struct cred *cred)
9027 {
9028         daplka_ia_resource_t    *ia_rp;
9029         minor_t                 rnum = getminor(dev);
9030 
9031         /*
9032          * Char only
9033          */
9034         if (otyp != OTYP_CHR) {
9035                 return (EINVAL);
9036         }
9037         D2("daplka_close: closing rnum = %d\n", rnum);
9038         atomic_add_32(&daplka_pending_close, 1);
9039 
9040         /*
9041          * remove from resource table.
9042          */
9043         ia_rp = (daplka_ia_resource_t *)daplka_resource_remove(rnum);
9044 
9045         /*
9046          * remove the initial reference
9047          */
9048         if (ia_rp != NULL) {
9049                 DAPLKA_RS_UNREF(ia_rp);
9050         }
9051         atomic_add_32(&daplka_pending_close, -1);
9052         return (DDI_SUCCESS);
9053 }
9054 
9055 
9056 /*
9057  * Resource management routines
9058  *
9059  * We start with no resource array. Each time we run out of slots, we
9060  * reallocate a new larger array and copy the pointer to the new array and
9061  * a new resource blk is allocated and added to the hash table.
9062  *
9063  * The resource control block contains:
9064  *      root    - array of pointer of resource blks
9065  *      sz      - current size of array.
9066  *      len     - last valid entry in array.
9067  *
9068  * A search operation based on a resource number is as follows:
9069  *      index = rnum / RESOURCE_BLKSZ;
9070  *      ASSERT(index < resource_block.len);
9071  *      ASSERT(index < resource_block.sz);


9829 static void
9830 daplka_hash_generic_lookup(void *obj)
9831 {
9832         daplka_resource_t       *rp = (daplka_resource_t *)obj;
9833 
9834         mutex_enter(&rp->rs_reflock);
9835         rp->rs_refcnt++;
9836         ASSERT(rp->rs_refcnt != 0);
9837         mutex_exit(&rp->rs_reflock);
9838 }
9839 
9840 /*
9841  * Generates a non-zero 32 bit hash key used for the timer hash table.
9842  */
9843 static uint32_t
9844 daplka_timer_hkey_gen()
9845 {
9846         uint32_t new_hkey;
9847 
9848         do {
9849                 new_hkey = atomic_add_32_nv(&daplka_timer_hkey, 1);
9850         } while (new_hkey == 0);
9851 
9852         return (new_hkey);
9853 }
9854 
9855 
9856 /*
9857  * The DAPL KA debug logging routines
9858  */
9859 
9860 /*
9861  * Add the string str to the end of the debug log, followed by a newline.
9862  */
9863 static void
9864 daplka_dbglog(char *str)
9865 {
9866         size_t  length;
9867         size_t  remlen;
9868 
9869         /*




8276     ibt_channel_hdl_t *chan_hdl_p, ibt_chan_sizes_t *sizes)
8277 {
8278         daplka_hca_t    *hca_p;
8279         uint32_t        max_qps;
8280         boolean_t       acct_enabled;
8281         ibt_status_t    status;
8282 
8283         acct_enabled = daplka_accounting_enabled;
8284         hca_p = ep_rp->ep_hca;
8285         max_qps = daplka_max_qp_percent * hca_p->hca_attr.hca_max_chans / 100;
8286 
8287         if (acct_enabled) {
8288                 if (daplka_max_qp_percent != 0 &&
8289                     max_qps <= hca_p->hca_qp_count) {
8290                         DERR("ibt_alloc_rc_channel: resource limit exceeded "
8291                             "(limit %d, count %d)\n", max_qps,
8292                             hca_p->hca_qp_count);
8293                         return (IBT_INSUFF_RESOURCE);
8294                 }
8295                 DAPLKA_RS_ACCT_INC(ep_rp, 1);
8296                 atomic_inc_32(&hca_p->hca_qp_count);
8297         }
8298         status = ibt_alloc_rc_channel(hca_hdl, flags, args, chan_hdl_p, sizes);
8299 
8300         if (status != IBT_SUCCESS && acct_enabled) {
8301                 DAPLKA_RS_ACCT_DEC(ep_rp, 1);
8302                 atomic_dec_32(&hca_p->hca_qp_count);
8303         }
8304         return (status);
8305 }
8306 
8307 static ibt_status_t
8308 daplka_ibt_free_channel(daplka_ep_resource_t *ep_rp, ibt_channel_hdl_t chan_hdl)
8309 {
8310         daplka_hca_t    *hca_p;
8311         ibt_status_t    status;
8312 
8313         hca_p = ep_rp->ep_hca;
8314 
8315         status = ibt_free_channel(chan_hdl);
8316         if (status != IBT_SUCCESS) {
8317                 return (status);
8318         }
8319         if (DAPLKA_RS_ACCT_CHARGED(ep_rp) > 0) {
8320                 DAPLKA_RS_ACCT_DEC(ep_rp, 1);
8321                 atomic_dec_32(&hca_p->hca_qp_count);
8322         }
8323         return (status);
8324 }
8325 
8326 static ibt_status_t
8327 daplka_ibt_alloc_cq(daplka_evd_resource_t *evd_rp, ibt_hca_hdl_t hca_hdl,
8328     ibt_cq_attr_t *cq_attr, ibt_cq_hdl_t *ibt_cq_p, uint32_t *real_size)
8329 {
8330         daplka_hca_t    *hca_p;
8331         uint32_t        max_cqs;
8332         boolean_t       acct_enabled;
8333         ibt_status_t    status;
8334 
8335         acct_enabled = daplka_accounting_enabled;
8336         hca_p = evd_rp->evd_hca;
8337         max_cqs = daplka_max_cq_percent * hca_p->hca_attr.hca_max_cq / 100;
8338 
8339         if (acct_enabled) {
8340                 if (daplka_max_cq_percent != 0 &&
8341                     max_cqs <= hca_p->hca_cq_count) {
8342                         DERR("ibt_alloc_cq: resource limit exceeded "
8343                             "(limit %d, count %d)\n", max_cqs,
8344                             hca_p->hca_cq_count);
8345                         return (IBT_INSUFF_RESOURCE);
8346                 }
8347                 DAPLKA_RS_ACCT_INC(evd_rp, 1);
8348                 atomic_inc_32(&hca_p->hca_cq_count);
8349         }
8350         status = ibt_alloc_cq(hca_hdl, cq_attr, ibt_cq_p, real_size);
8351 
8352         if (status != IBT_SUCCESS && acct_enabled) {
8353                 DAPLKA_RS_ACCT_DEC(evd_rp, 1);
8354                 atomic_dec_32(&hca_p->hca_cq_count);
8355         }
8356         return (status);
8357 }
8358 
8359 static ibt_status_t
8360 daplka_ibt_free_cq(daplka_evd_resource_t *evd_rp, ibt_cq_hdl_t cq_hdl)
8361 {
8362         daplka_hca_t    *hca_p;
8363         ibt_status_t    status;
8364 
8365         hca_p = evd_rp->evd_hca;
8366 
8367         status = ibt_free_cq(cq_hdl);
8368         if (status != IBT_SUCCESS) {
8369                 return (status);
8370         }
8371         if (DAPLKA_RS_ACCT_CHARGED(evd_rp) > 0) {
8372                 DAPLKA_RS_ACCT_DEC(evd_rp, 1);
8373                 atomic_dec_32(&hca_p->hca_cq_count);
8374         }
8375         return (status);
8376 }
8377 
8378 static ibt_status_t
8379 daplka_ibt_alloc_pd(daplka_pd_resource_t *pd_rp, ibt_hca_hdl_t hca_hdl,
8380     ibt_pd_flags_t flags, ibt_pd_hdl_t *pd_hdl_p)
8381 {
8382         daplka_hca_t    *hca_p;
8383         uint32_t        max_pds;
8384         boolean_t       acct_enabled;
8385         ibt_status_t    status;
8386 
8387         acct_enabled = daplka_accounting_enabled;
8388         hca_p = pd_rp->pd_hca;
8389         max_pds = daplka_max_pd_percent * hca_p->hca_attr.hca_max_pd / 100;
8390 
8391         if (acct_enabled) {
8392                 if (daplka_max_pd_percent != 0 &&
8393                     max_pds <= hca_p->hca_pd_count) {
8394                         DERR("ibt_alloc_pd: resource limit exceeded "
8395                             "(limit %d, count %d)\n", max_pds,
8396                             hca_p->hca_pd_count);
8397                         return (IBT_INSUFF_RESOURCE);
8398                 }
8399                 DAPLKA_RS_ACCT_INC(pd_rp, 1);
8400                 atomic_inc_32(&hca_p->hca_pd_count);
8401         }
8402         status = ibt_alloc_pd(hca_hdl, flags, pd_hdl_p);
8403 
8404         if (status != IBT_SUCCESS && acct_enabled) {
8405                 DAPLKA_RS_ACCT_DEC(pd_rp, 1);
8406                 atomic_dec_32(&hca_p->hca_pd_count);
8407         }
8408         return (status);
8409 }
8410 
8411 static ibt_status_t
8412 daplka_ibt_free_pd(daplka_pd_resource_t *pd_rp, ibt_hca_hdl_t hca_hdl,
8413     ibt_pd_hdl_t pd_hdl)
8414 {
8415         daplka_hca_t    *hca_p;
8416         ibt_status_t    status;
8417 
8418         hca_p = pd_rp->pd_hca;
8419 
8420         status = ibt_free_pd(hca_hdl, pd_hdl);
8421         if (status != IBT_SUCCESS) {
8422                 return (status);
8423         }
8424         if (DAPLKA_RS_ACCT_CHARGED(pd_rp) > 0) {
8425                 DAPLKA_RS_ACCT_DEC(pd_rp, 1);
8426                 atomic_dec_32(&hca_p->hca_pd_count);
8427         }
8428         return (status);
8429 }
8430 
8431 static ibt_status_t
8432 daplka_ibt_alloc_mw(daplka_mw_resource_t *mw_rp, ibt_hca_hdl_t hca_hdl,
8433     ibt_pd_hdl_t pd_hdl, ibt_mw_flags_t flags, ibt_mw_hdl_t *mw_hdl_p,
8434     ibt_rkey_t *rkey_p)
8435 {
8436         daplka_hca_t    *hca_p;
8437         uint32_t        max_mws;
8438         boolean_t       acct_enabled;
8439         ibt_status_t    status;
8440 
8441         acct_enabled = daplka_accounting_enabled;
8442         hca_p = mw_rp->mw_hca;
8443         max_mws = daplka_max_mw_percent * hca_p->hca_attr.hca_max_mem_win / 100;
8444 
8445         if (acct_enabled) {
8446                 if (daplka_max_mw_percent != 0 &&
8447                     max_mws <= hca_p->hca_mw_count) {
8448                         DERR("ibt_alloc_mw: resource limit exceeded "
8449                             "(limit %d, count %d)\n", max_mws,
8450                             hca_p->hca_mw_count);
8451                         return (IBT_INSUFF_RESOURCE);
8452                 }
8453                 DAPLKA_RS_ACCT_INC(mw_rp, 1);
8454                 atomic_inc_32(&hca_p->hca_mw_count);
8455         }
8456         status = ibt_alloc_mw(hca_hdl, pd_hdl, flags, mw_hdl_p, rkey_p);
8457 
8458         if (status != IBT_SUCCESS && acct_enabled) {
8459                 DAPLKA_RS_ACCT_DEC(mw_rp, 1);
8460                 atomic_dec_32(&hca_p->hca_mw_count);
8461         }
8462         return (status);
8463 }
8464 
8465 static ibt_status_t
8466 daplka_ibt_free_mw(daplka_mw_resource_t *mw_rp, ibt_hca_hdl_t hca_hdl,
8467     ibt_mw_hdl_t mw_hdl)
8468 {
8469         daplka_hca_t    *hca_p;
8470         ibt_status_t    status;
8471 
8472         hca_p = mw_rp->mw_hca;
8473 
8474         status = ibt_free_mw(hca_hdl, mw_hdl);
8475         if (status != IBT_SUCCESS) {
8476                 return (status);
8477         }
8478         if (DAPLKA_RS_ACCT_CHARGED(mw_rp) > 0) {
8479                 DAPLKA_RS_ACCT_DEC(mw_rp, 1);
8480                 atomic_dec_32(&hca_p->hca_mw_count);
8481         }
8482         return (status);
8483 }
8484 
8485 static ibt_status_t
8486 daplka_ibt_register_mr(daplka_mr_resource_t *mr_rp, ibt_hca_hdl_t hca_hdl,
8487     ibt_pd_hdl_t pd_hdl, ibt_mr_attr_t *mr_attr, ibt_mr_hdl_t *mr_hdl_p,
8488     ibt_mr_desc_t *mr_desc_p)
8489 {
8490         daplka_hca_t    *hca_p;
8491         uint32_t        max_mrs;
8492         boolean_t       acct_enabled;
8493         ibt_status_t    status;
8494 
8495         acct_enabled = daplka_accounting_enabled;
8496         hca_p = mr_rp->mr_hca;
8497         max_mrs = daplka_max_mr_percent * hca_p->hca_attr.hca_max_memr / 100;
8498 
8499         if (acct_enabled) {
8500                 if (daplka_max_mr_percent != 0 &&
8501                     max_mrs <= hca_p->hca_mr_count) {
8502                         DERR("ibt_register_mr: resource limit exceeded "
8503                             "(limit %d, count %d)\n", max_mrs,
8504                             hca_p->hca_mr_count);
8505                         return (IBT_INSUFF_RESOURCE);
8506                 }
8507                 DAPLKA_RS_ACCT_INC(mr_rp, 1);
8508                 atomic_inc_32(&hca_p->hca_mr_count);
8509         }
8510         status = ibt_register_mr(hca_hdl, pd_hdl, mr_attr, mr_hdl_p, mr_desc_p);
8511 
8512         if (status != IBT_SUCCESS && acct_enabled) {
8513                 DAPLKA_RS_ACCT_DEC(mr_rp, 1);
8514                 atomic_dec_32(&hca_p->hca_mr_count);
8515         }
8516         return (status);
8517 }
8518 
8519 static ibt_status_t
8520 daplka_ibt_register_shared_mr(daplka_mr_resource_t *mr_rp,
8521     ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl, ibt_pd_hdl_t pd_hdl,
8522     ibt_smr_attr_t *smr_attr_p, ibt_mr_hdl_t *mr_hdl_p,
8523     ibt_mr_desc_t *mr_desc_p)
8524 {
8525         daplka_hca_t    *hca_p;
8526         uint32_t        max_mrs;
8527         boolean_t       acct_enabled;
8528         ibt_status_t    status;
8529 
8530         acct_enabled = daplka_accounting_enabled;
8531         hca_p = mr_rp->mr_hca;
8532         max_mrs = daplka_max_mr_percent * hca_p->hca_attr.hca_max_memr / 100;
8533 
8534         if (acct_enabled) {
8535                 if (daplka_max_mr_percent != 0 &&
8536                     max_mrs <= hca_p->hca_mr_count) {
8537                         DERR("ibt_register_shared_mr: resource limit exceeded "
8538                             "(limit %d, count %d)\n", max_mrs,
8539                             hca_p->hca_mr_count);
8540                         return (IBT_INSUFF_RESOURCE);
8541                 }
8542                 DAPLKA_RS_ACCT_INC(mr_rp, 1);
8543                 atomic_inc_32(&hca_p->hca_mr_count);
8544         }
8545         status = ibt_register_shared_mr(hca_hdl, mr_hdl, pd_hdl,
8546             smr_attr_p, mr_hdl_p, mr_desc_p);
8547 
8548         if (status != IBT_SUCCESS && acct_enabled) {
8549                 DAPLKA_RS_ACCT_DEC(mr_rp, 1);
8550                 atomic_dec_32(&hca_p->hca_mr_count);
8551         }
8552         return (status);
8553 }
8554 
8555 static ibt_status_t
8556 daplka_ibt_deregister_mr(daplka_mr_resource_t *mr_rp, ibt_hca_hdl_t hca_hdl,
8557     ibt_mr_hdl_t mr_hdl)
8558 {
8559         daplka_hca_t    *hca_p;
8560         ibt_status_t    status;
8561 
8562         hca_p = mr_rp->mr_hca;
8563 
8564         status = ibt_deregister_mr(hca_hdl, mr_hdl);
8565         if (status != IBT_SUCCESS) {
8566                 return (status);
8567         }
8568         if (DAPLKA_RS_ACCT_CHARGED(mr_rp) > 0) {
8569                 DAPLKA_RS_ACCT_DEC(mr_rp, 1);
8570                 atomic_dec_32(&hca_p->hca_mr_count);
8571         }
8572         return (status);
8573 }
8574 
8575 static ibt_status_t
8576 daplka_ibt_alloc_srq(daplka_srq_resource_t *srq_rp, ibt_hca_hdl_t hca_hdl,
8577     ibt_srq_flags_t flags, ibt_pd_hdl_t pd, ibt_srq_sizes_t *reqsz,
8578     ibt_srq_hdl_t *srq_hdl_p, ibt_srq_sizes_t *realsz)
8579 {
8580         daplka_hca_t    *hca_p;
8581         uint32_t        max_srqs;
8582         boolean_t       acct_enabled;
8583         ibt_status_t    status;
8584 
8585         acct_enabled = daplka_accounting_enabled;
8586         hca_p = srq_rp->srq_hca;
8587         max_srqs = daplka_max_srq_percent * hca_p->hca_attr.hca_max_srqs / 100;
8588 
8589         if (acct_enabled) {
8590                 if (daplka_max_srq_percent != 0 &&
8591                     max_srqs <= hca_p->hca_srq_count) {
8592                         DERR("ibt_alloc_srq: resource limit exceeded "
8593                             "(limit %d, count %d)\n", max_srqs,
8594                             hca_p->hca_srq_count);
8595                         return (IBT_INSUFF_RESOURCE);
8596                 }
8597                 DAPLKA_RS_ACCT_INC(srq_rp, 1);
8598                 atomic_inc_32(&hca_p->hca_srq_count);
8599         }
8600         status = ibt_alloc_srq(hca_hdl, flags, pd, reqsz, srq_hdl_p, realsz);
8601 
8602         if (status != IBT_SUCCESS && acct_enabled) {
8603                 DAPLKA_RS_ACCT_DEC(srq_rp, 1);
8604                 atomic_dec_32(&hca_p->hca_srq_count);
8605         }
8606         return (status);
8607 }
8608 
8609 static ibt_status_t
8610 daplka_ibt_free_srq(daplka_srq_resource_t *srq_rp, ibt_srq_hdl_t srq_hdl)
8611 {
8612         daplka_hca_t    *hca_p;
8613         ibt_status_t    status;
8614 
8615         hca_p = srq_rp->srq_hca;
8616 
8617         D3("ibt_free_srq: %p %p\n", srq_rp, srq_hdl);
8618 
8619         status = ibt_free_srq(srq_hdl);
8620         if (status != IBT_SUCCESS) {
8621                 return (status);
8622         }
8623         if (DAPLKA_RS_ACCT_CHARGED(srq_rp) > 0) {
8624                 DAPLKA_RS_ACCT_DEC(srq_rp, 1);
8625                 atomic_dec_32(&hca_p->hca_srq_count);
8626         }
8627         return (status);
8628 }
8629 
8630 
8631 static int
8632 daplka_common_ioctl(int cmd, minor_t rnum, intptr_t arg, int mode,
8633         cred_t *cred, int *rvalp)
8634 {
8635         int error;
8636 
8637         switch (cmd) {
8638         case DAPL_IA_CREATE:
8639                 error = daplka_ia_create(rnum, arg, mode, cred, rvalp);
8640                 break;
8641 
8642         /* can potentially add other commands here */
8643 
8644         default:
8645                 DERR("daplka_common_ioctl: cmd not supported\n");


9018                 return (ENOMEM);
9019         }
9020 
9021         return (DDI_SUCCESS);
9022 }
9023 
9024 /* ARGSUSED */
9025 static int
9026 daplka_close(dev_t dev, int flag, int otyp, struct cred *cred)
9027 {
9028         daplka_ia_resource_t    *ia_rp;
9029         minor_t                 rnum = getminor(dev);
9030 
9031         /*
9032          * Char only
9033          */
9034         if (otyp != OTYP_CHR) {
9035                 return (EINVAL);
9036         }
9037         D2("daplka_close: closing rnum = %d\n", rnum);
9038         atomic_inc_32(&daplka_pending_close);
9039 
9040         /*
9041          * remove from resource table.
9042          */
9043         ia_rp = (daplka_ia_resource_t *)daplka_resource_remove(rnum);
9044 
9045         /*
9046          * remove the initial reference
9047          */
9048         if (ia_rp != NULL) {
9049                 DAPLKA_RS_UNREF(ia_rp);
9050         }
9051         atomic_dec_32(&daplka_pending_close);
9052         return (DDI_SUCCESS);
9053 }
9054 
9055 
9056 /*
9057  * Resource management routines
9058  *
9059  * We start with no resource array. Each time we run out of slots, we
9060  * reallocate a new larger array and copy the pointer to the new array and
9061  * a new resource blk is allocated and added to the hash table.
9062  *
9063  * The resource control block contains:
9064  *      root    - array of pointer of resource blks
9065  *      sz      - current size of array.
9066  *      len     - last valid entry in array.
9067  *
9068  * A search operation based on a resource number is as follows:
9069  *      index = rnum / RESOURCE_BLKSZ;
9070  *      ASSERT(index < resource_block.len);
9071  *      ASSERT(index < resource_block.sz);


9829 static void
9830 daplka_hash_generic_lookup(void *obj)
9831 {
9832         daplka_resource_t       *rp = (daplka_resource_t *)obj;
9833 
9834         mutex_enter(&rp->rs_reflock);
9835         rp->rs_refcnt++;
9836         ASSERT(rp->rs_refcnt != 0);
9837         mutex_exit(&rp->rs_reflock);
9838 }
9839 
9840 /*
9841  * Generates a non-zero 32 bit hash key used for the timer hash table.
9842  */
9843 static uint32_t
9844 daplka_timer_hkey_gen()
9845 {
9846         uint32_t new_hkey;
9847 
9848         do {
9849                 new_hkey = atomic_inc_32_nv(&daplka_timer_hkey);
9850         } while (new_hkey == 0);
9851 
9852         return (new_hkey);
9853 }
9854 
9855 
9856 /*
9857  * The DAPL KA debug logging routines
9858  */
9859 
9860 /*
9861  * Add the string str to the end of the debug log, followed by a newline.
9862  */
9863 static void
9864 daplka_dbglog(char *str)
9865 {
9866         size_t  length;
9867         size_t  remlen;
9868 
9869         /*