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 /*
|