]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/core: Manage CQ umem in core code
authorLeon Romanovsky <leonro@nvidia.com>
Fri, 13 Feb 2026 10:57:41 +0000 (12:57 +0200)
committerLeon Romanovsky <leonro@nvidia.com>
Wed, 25 Feb 2026 13:15:30 +0000 (08:15 -0500)
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>
drivers/infiniband/core/umem.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_std_types_cq.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/efa/efa_verbs.c
include/rdma/ib_verbs.h

index cff4fcca2c345a5a1552924a6f95056970fad3de..4eef7b76fe4653458d8eca89f6413cedf78e4643 100644 (file)
@@ -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));
index 758ed4ae5f7a8585b666946e197b9bf34d2ab20b..87f327fc1f4e1b7828bbf58118ec376864bee352 100644 (file)
@@ -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:
index fab5d914029dd76e51cbaa796dd2ac51b640d2cd..05809f9ff0f6a3f24618774c7969bba9bbbae3bd 100644 (file)
@@ -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:
index dc2c46f3bf648e1cbb414a3ef5d38aba9c851d22..29694145ce5fe5d467eecfb2ab5a2f1a02cb8e10 100644 (file)
@@ -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;
index 1ef9da94b98ff83bb6497441aa3832777d136a45..7180d31218c5a793fb80d34b8e216d1edfcf433f 100644 (file)
@@ -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:
index 7bdd77ed7e20a9b4ef7882a052a5698169eb8398..8531eed7b394167ccdd6908fb52e683da0274b00 100644 (file)
@@ -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: