summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Romanovsky <leonro@nvidia.com>2026-02-13 12:57:41 +0200
committerLeon Romanovsky <leonro@nvidia.com>2026-02-25 08:15:30 -0500
commit25c741048891c4d3fc627cd5220e2cae4bab42a1 (patch)
tree094952ef61ca105d7be7e8f98fae2db14167201f
parenta731c8626507d2df0b34a572719e3e6efcf10530 (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.c2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c1
-rw-r--r--drivers/infiniband/core/uverbs_std_types_cq.c7
-rw-r--r--drivers/infiniband/core/verbs.c2
-rw-r--r--drivers/infiniband/hw/efa/efa_verbs.c24
-rw-r--r--include/rdma/ib_verbs.h1
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: