From: David Hu <[email protected]> Support the standard 1-step queue buffer creation for SRQ by `UVERBS_ATTR_CREATE_SRQ_BUF_UMEM` via `ib_umem_get_attr()`.
Set up hardware pble directly from the pinned SRQ umem via `irdma_setup_q_pbl_from_umem()`. Proper umem and pble cleanup, and error unwind are added into existing `irdma_srq_free_rsrc()` upon SRQ destruction. We maintain backward compatibility for the legacy 2-step registration if the UMEM attribute is not provided. Signed-off-by: David Hu <[email protected]> --- drivers/infiniband/hw/irdma/verbs.c | 68 ++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c index 41e56ab8aa6d..7e8a5e481730 100644 --- a/drivers/infiniband/hw/irdma/verbs.c +++ b/drivers/infiniband/hw/irdma/verbs.c @@ -1996,9 +1996,16 @@ static void irdma_srq_free_rsrc(struct irdma_pci_f *rf, struct irdma_srq *iwsrq) iwsrq->kmem.va = NULL; } else { /* Not called in any failure path, so iwpbl is valid. */ - struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr; + if (iwsrq->iwpbl) { + struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr; - refcount_dec(&iwmr->user_ring_refs); + if (iwmr && refcount_dec_and_test(&iwmr->user_ring_refs)) { + ib_umem_release(iwmr->region); + if (iwsrq->iwpbl->pbl_allocated) + irdma_free_pble(rf->pble_rsrc, &iwsrq->iwpbl->pble_alloc); + kfree(iwmr); + } + } } irdma_free_rsrc(rf, rf->allocated_srqs, srq->srq_uk.srq_id); @@ -2425,6 +2432,7 @@ static int irdma_setup_umode_srq(struct irdma_device *iwdev, struct ib_udata *udata, struct uverbs_attr_bundle *attrs) { + struct irdma_srq_uk_init_info *ukinfo = &info->srq_uk_init_info; struct irdma_create_srq_req req = {}; struct irdma_ucontext *ucontext; struct irdma_srq_mr *srqmr; @@ -2440,14 +2448,49 @@ static int irdma_setup_umode_srq(struct irdma_device *iwdev, if (ret) return ret; - spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags); - iwpbl = irdma_get_pbl((unsigned long)req.user_srq_buf, - &ucontext->srq_reg_mem_list); - spin_unlock_irqrestore(&ucontext->srq_reg_mem_list_lock, flags); - if (!iwpbl) - return -EPROTO; + if (attrs && uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_SRQ_BUF_UMEM)) { + struct irdma_mem_reg_req srq_req = {}; + struct ib_umem *umem; + u32 total; + u8 shift; - iwsrq->iwpbl = iwpbl; + irdma_get_wqe_shift(ukinfo->uk_attrs, ukinfo->max_srq_frag_cnt, 0, &shift); + srq_req.rq_pages = + DIV_ROUND_UP((ukinfo->srq_size << shift) * IRDMA_QP_WQE_MIN_SIZE, + IRDMA_HW_PAGE_SIZE); + total = srq_req.rq_pages + IRDMA_SHADOW_PGCNT; + + umem = ib_umem_get_attr(&iwdev->ibdev, attrs, + UVERBS_ATTR_CREATE_SRQ_BUF_UMEM, + total << IRDMA_HW_PAGE_SHIFT, + IB_ACCESS_LOCAL_WRITE); + if (IS_ERR(umem)) + return PTR_ERR(umem); + + iwsrq->iwpbl = irdma_setup_q_pbl_from_umem(iwdev, umem, + iwsrq->ibsrq.pd, + IRDMA_MEMREG_TYPE_SRQ, + &srq_req); + if (IS_ERR(iwsrq->iwpbl)) { + ret = PTR_ERR(iwsrq->iwpbl); + iwsrq->iwpbl = NULL; + ib_umem_release(umem); + return ret; + } + iwpbl = iwsrq->iwpbl; + } else { + if (!req.user_srq_buf) + return -EINVAL; + + spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags); + iwpbl = irdma_get_pbl((unsigned long)req.user_srq_buf, + &ucontext->srq_reg_mem_list); + spin_unlock_irqrestore(&ucontext->srq_reg_mem_list_lock, flags); + if (!iwpbl) + return -EPROTO; + + iwsrq->iwpbl = iwpbl; + } srqmr = &iwpbl->srq_mr; if (iwpbl->pbl_allocated) { @@ -2615,7 +2658,12 @@ static int irdma_create_srq(struct ib_srq *ibsrq, if (iwsrq->user_mode && iwsrq->iwpbl) { struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr; - refcount_dec(&iwmr->user_ring_refs); + if (iwmr && refcount_dec_and_test(&iwmr->user_ring_refs)) { + ib_umem_release(iwmr->region); + if (iwsrq->iwpbl->pbl_allocated) + irdma_free_pble(rf->pble_rsrc, &iwsrq->iwpbl->pble_alloc); + kfree(iwmr); + } } irdma_free_rsrc(rf, rf->allocated_srqs, iwsrq->srq_num); return err_code; -- 2.56.0.317.g454f8302e1-goog
