diff options
| author | Leon Romanovsky <leonro@nvidia.com> | 2026-02-13 12:57:41 +0200 |
|---|---|---|
| committer | Leon Romanovsky <leonro@nvidia.com> | 2026-02-25 08:15:30 -0500 |
| commit | 25c741048891c4d3fc627cd5220e2cae4bab42a1 (patch) | |
| tree | 094952ef61ca105d7be7e8f98fae2db14167201f | |
| parent | a731c8626507d2df0b34a572719e3e6efcf10530 (diff) | |
RDMA/core: Manage CQ umem in core code
In the current implementation, CQ umem is handled both by ib_core and
the driver. ib_core sometimes creates and destroys it, while the driver
also destroys it.
Store the umem in struct ib_cq and ensure that only ib_core manages
its lifetime, relying solely on its internal reference counter.
Link: https://patch.msgid.link/20260213-refactor-umem-v1-5-f3be85847922@nvidia.com
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
| -rw-r--r-- | drivers/infiniband/core/umem.c | 2 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 1 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_std_types_cq.c | 7 | ||||
| -rw-r--r-- | drivers/infiniband/core/verbs.c | 2 | ||||
| -rw-r--r-- | drivers/infiniband/hw/efa/efa_verbs.c | 24 | ||||
| -rw-r--r-- | include/rdma/ib_verbs.h | 1 |
6 files changed, 22 insertions, 15 deletions
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index cff4fcca2c34..4eef7b76fe46 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -283,7 +283,7 @@ EXPORT_SYMBOL(ib_umem_get); */ void ib_umem_release(struct ib_umem *umem) { - if (!umem) + if (IS_ERR_OR_NULL(umem)) return; if (umem->is_dmabuf) return ib_umem_dmabuf_release(to_ib_umem_dmabuf(umem)); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 758ed4ae5f7a..87f327fc1f4e 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1085,6 +1085,7 @@ static int create_cq(struct uverbs_attr_bundle *attrs, return uverbs_response(attrs, &resp, sizeof(resp)); err_free: + ib_umem_release(cq->umem); rdma_restrack_put(&cq->res); kfree(cq); err_file: diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c index fab5d914029d..05809f9ff0f6 100644 --- a/drivers/infiniband/core/uverbs_std_types_cq.c +++ b/drivers/infiniband/core/uverbs_std_types_cq.c @@ -186,6 +186,11 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)( cq->comp_handler = ib_uverbs_comp_handler; cq->event_handler = ib_uverbs_cq_event_handler; cq->cq_context = ev_file ? &ev_file->ev_queue : NULL; + /* + * If UMEM is not provided here, legacy drivers will set it during + * CQ creation based on their internal udata. + */ + cq->umem = umem; atomic_set(&cq->usecnt, 0); rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ); @@ -206,7 +211,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)( return ret; err_free: - ib_umem_release(umem); + ib_umem_release(cq->umem); rdma_restrack_put(&cq->res); kfree(cq); err_event_file: diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index dc2c46f3bf64..29694145ce5f 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -49,6 +49,7 @@ #include <rdma/ib_verbs.h> #include <rdma/ib_cache.h> #include <rdma/ib_addr.h> +#include <rdma/ib_umem.h> #include <rdma/rw.h> #include <rdma/lag.h> @@ -2249,6 +2250,7 @@ int ib_destroy_cq_user(struct ib_cq *cq, struct ib_udata *udata) if (ret) return ret; + ib_umem_release(cq->umem); rdma_restrack_del(&cq->res); kfree(cq); return ret; diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c index 1ef9da94b98f..7180d31218c5 100644 --- a/drivers/infiniband/hw/efa/efa_verbs.c +++ b/drivers/infiniband/hw/efa/efa_verbs.c @@ -1083,15 +1083,14 @@ int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) cq->cq_idx, cq->cpu_addr, cq->size, &cq->dma_addr); efa_destroy_cq_idx(dev, cq->cq_idx); - efa_cq_user_mmap_entries_remove(cq); + if (cq->cpu_addr) + efa_cq_user_mmap_entries_remove(cq); if (cq->eq) { xa_erase(&dev->cqs_xa, cq->cq_idx); synchronize_irq(cq->eq->irq.irqn); } - if (cq->umem) - ib_umem_release(cq->umem); - else + if (cq->cpu_addr) efa_free_mapped(dev, cq->cpu_addr, cq->dma_addr, cq->size, DMA_FROM_DEVICE); return 0; } @@ -1212,22 +1211,20 @@ int efa_create_cq_umem(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, cq->ucontext = ucontext; cq->size = PAGE_ALIGN(cmd.cq_entry_size * entries * cmd.num_sub_cqs); - if (umem) { - if (umem->length < cq->size) { + if (ibcq->umem) { + if (ibcq->umem->length < cq->size) { ibdev_dbg(&dev->ibdev, "External memory too small\n"); err = -EINVAL; goto err_out; } - if (!ib_umem_is_contiguous(umem)) { + if (!ib_umem_is_contiguous(ibcq->umem)) { ibdev_dbg(&dev->ibdev, "Non contiguous CQ unsupported\n"); err = -EINVAL; goto err_out; } - cq->cpu_addr = NULL; - cq->dma_addr = ib_umem_start_dma_addr(umem); - cq->umem = umem; + cq->dma_addr = ib_umem_start_dma_addr(ibcq->umem); } else { cq->cpu_addr = efa_zalloc_mapped(dev, &cq->dma_addr, cq->size, DMA_FROM_DEVICE); @@ -1259,7 +1256,7 @@ int efa_create_cq_umem(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, cq->ibcq.cqe = result.actual_depth; WARN_ON_ONCE(entries != result.actual_depth); - if (!umem) + if (cq->cpu_addr) err = cq_mmap_entries_setup(dev, cq, &resp, result.db_valid); if (err) { @@ -1296,11 +1293,12 @@ err_xa_erase: if (cq->eq) xa_erase(&dev->cqs_xa, cq->cq_idx); err_remove_mmap: - efa_cq_user_mmap_entries_remove(cq); + if (cq->cpu_addr) + efa_cq_user_mmap_entries_remove(cq); err_destroy_cq: efa_destroy_cq_idx(dev, cq->cq_idx); err_free_mapped: - if (!umem) + if (cq->cpu_addr) efa_free_mapped(dev, cq->cpu_addr, cq->dma_addr, cq->size, DMA_FROM_DEVICE); err_out: diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 7bdd77ed7e20..8531eed7b394 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -1650,6 +1650,7 @@ struct ib_cq { u8 interrupt:1; u8 shared:1; unsigned int comp_vector; + struct ib_umem *umem; /* * Implementation details of the RDMA core, don't use in drivers: |
