* [PATCH rdma-next 1/4] RDMA/irdma: Deduplicate the irdma_del_memlist logic
2026-06-18 20:14 [PATCH rdma-next 0/4] RDMA/irdma: Prevent premature deregistration of user ring MRs Jacob Moroni
@ 2026-06-18 20:14 ` Jacob Moroni
2026-06-18 20:14 ` [PATCH rdma-next 2/4] RDMA/irdma: Add a refcount to track user ring MR associations Jacob Moroni
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jacob Moroni @ 2026-06-18 20:14 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
Simplify/dedup the irdma_del_memlist logic in preparation for
the QP/CQ/SRQ ring MR refcounting change that will follow in
a subsequent commit.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 31 +++++++++++------------------
1 file changed, 12 insertions(+), 19 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index b79f5afe6..af04dd554 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -3929,35 +3929,28 @@ static void irdma_del_memlist(struct irdma_mr *iwmr,
{
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
unsigned long flags;
+ spinlock_t *lock;
switch (iwmr->type) {
case IRDMA_MEMREG_TYPE_CQ:
- spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
- if (iwpbl->on_list) {
- iwpbl->on_list = false;
- list_del(&iwpbl->list);
- }
- spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
+ lock = &ucontext->cq_reg_mem_list_lock;
break;
case IRDMA_MEMREG_TYPE_QP:
- spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags);
- if (iwpbl->on_list) {
- iwpbl->on_list = false;
- list_del(&iwpbl->list);
- }
- spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags);
+ lock = &ucontext->qp_reg_mem_list_lock;
break;
case IRDMA_MEMREG_TYPE_SRQ:
- spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags);
- if (iwpbl->on_list) {
- iwpbl->on_list = false;
- list_del(&iwpbl->list);
- }
- spin_unlock_irqrestore(&ucontext->srq_reg_mem_list_lock, flags);
+ lock = &ucontext->srq_reg_mem_list_lock;
break;
default:
- break;
+ return;
+ }
+
+ spin_lock_irqsave(lock, flags);
+ if (iwpbl->on_list) {
+ iwpbl->on_list = false;
+ list_del(&iwpbl->list);
}
+ spin_unlock_irqrestore(lock, flags);
}
/**
--
2.55.0.rc0.738.g0c8ab3ebcc-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH rdma-next 2/4] RDMA/irdma: Add a refcount to track user ring MR associations
2026-06-18 20:14 [PATCH rdma-next 0/4] RDMA/irdma: Prevent premature deregistration of user ring MRs Jacob Moroni
2026-06-18 20:14 ` [PATCH rdma-next 1/4] RDMA/irdma: Deduplicate the irdma_del_memlist logic Jacob Moroni
@ 2026-06-18 20:14 ` Jacob Moroni
2026-06-18 20:14 ` [PATCH rdma-next 3/4] RDMA/irdma: Add irdma_cq fields to track pbl allocations Jacob Moroni
2026-06-18 20:14 ` [PATCH rdma-next 4/4] RDMA/irdma: Add refcounting to user ring MRs Jacob Moroni
3 siblings, 0 replies; 5+ messages in thread
From: Jacob Moroni @ 2026-06-18 20:14 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
User QP/CQ/SRQ rings are registered with the normal reg_mr
mechanism prior to creating the actual QP/CQ/SRQ object. In
order to prevent userspace from deregistering these special MRs
while the child object still exists, a refcount will be used.
This commit adds the refcount and logic to reject a dereg_mr
with active references. Subsequent commits will add logic to
bump this refcount when the user QP/CQ/SRQ objects are created.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 21 +++++++++++++++++----
drivers/infiniband/hw/irdma/verbs.h | 1 +
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index af04dd554..2c51684dd 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -3363,6 +3363,7 @@ static struct irdma_mr *irdma_alloc_iwmr(struct ib_umem *region,
if (!iwmr)
return ERR_PTR(-ENOMEM);
+ refcount_set(&iwmr->user_ring_refs, 1);
iwpbl = &iwmr->iwpbl;
iwpbl->iwmr = iwmr;
iwmr->region = region;
@@ -3923,13 +3924,16 @@ static struct ib_mr *irdma_get_dma_mr(struct ib_pd *pd, int acc)
* irdma_del_memlist - Deleting pbl list entries for CQ/QP
* @iwmr: iwmr for IB's user page addresses
* @ucontext: ptr to user context
+ *
+ * Return: True if the MR is currently in-use by a QP/CQ/SRQ ring.
*/
-static void irdma_del_memlist(struct irdma_mr *iwmr,
+static bool irdma_del_memlist(struct irdma_mr *iwmr,
struct irdma_ucontext *ucontext)
{
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
unsigned long flags;
spinlock_t *lock;
+ bool in_use = false;
switch (iwmr->type) {
case IRDMA_MEMREG_TYPE_CQ:
@@ -3942,15 +3946,19 @@ static void irdma_del_memlist(struct irdma_mr *iwmr,
lock = &ucontext->srq_reg_mem_list_lock;
break;
default:
- return;
+ return false;
}
spin_lock_irqsave(lock, flags);
- if (iwpbl->on_list) {
+ if (!refcount_dec_if_one(&iwmr->user_ring_refs)) {
+ in_use = true;
+ } else if (iwpbl->on_list) {
iwpbl->on_list = false;
list_del(&iwpbl->list);
}
spin_unlock_irqrestore(lock, flags);
+
+ return in_use;
}
/**
@@ -3973,7 +3981,12 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
ucontext = rdma_udata_to_drv_context(udata,
struct irdma_ucontext,
ibucontext);
- irdma_del_memlist(iwmr, ucontext);
+
+ /* Do not allow the MR to be unpinned if it is still
+ * backing a user ring.
+ */
+ if (irdma_del_memlist(iwmr, ucontext))
+ return -EBUSY;
}
goto done;
}
diff --git a/drivers/infiniband/hw/irdma/verbs.h b/drivers/infiniband/hw/irdma/verbs.h
index 289ebc9b2..fbd487dbe 100644
--- a/drivers/infiniband/hw/irdma/verbs.h
+++ b/drivers/infiniband/hw/irdma/verbs.h
@@ -120,6 +120,7 @@ struct irdma_mr {
u64 len;
u64 pgaddrmem[IRDMA_MAX_SAVED_PHY_PGADDR];
struct irdma_pbl iwpbl;
+ refcount_t user_ring_refs;
};
struct irdma_srq {
--
2.55.0.rc0.738.g0c8ab3ebcc-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH rdma-next 3/4] RDMA/irdma: Add irdma_cq fields to track pbl allocations
2026-06-18 20:14 [PATCH rdma-next 0/4] RDMA/irdma: Prevent premature deregistration of user ring MRs Jacob Moroni
2026-06-18 20:14 ` [PATCH rdma-next 1/4] RDMA/irdma: Deduplicate the irdma_del_memlist logic Jacob Moroni
2026-06-18 20:14 ` [PATCH rdma-next 2/4] RDMA/irdma: Add a refcount to track user ring MR associations Jacob Moroni
@ 2026-06-18 20:14 ` Jacob Moroni
2026-06-18 20:14 ` [PATCH rdma-next 4/4] RDMA/irdma: Add refcounting to user ring MRs Jacob Moroni
3 siblings, 0 replies; 5+ messages in thread
From: Jacob Moroni @ 2026-06-18 20:14 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
These fields will be used in a subsequent commit which adds
refcounting to user CQ MRs.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 25 +++++++++++++++----------
drivers/infiniband/hw/irdma/verbs.h | 2 ++
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 2c51684dd..dccecff3c 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -2129,6 +2129,11 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
goto error;
spin_lock_irqsave(&iwcq->lock, flags);
+ if (udata)
+ /* Only update if the resize was successful. Otherwise, HW is
+ * still pointing to the old PBL.
+ */
+ iwcq->iwpbl = iwpbl_buf;
if (cq_buf) {
cq_buf->kmem_buf = iwcq->kmem;
cq_buf->hw = dev->hw;
@@ -2499,6 +2504,8 @@ static int irdma_create_cq(struct ib_cq *ibcq,
INIT_LIST_HEAD(&iwcq->resize_list);
INIT_LIST_HEAD(&iwcq->cmpl_generated);
iwcq->cq_num = cq_num;
+ iwcq->iwpbl = NULL;
+ iwcq->iwpbl_shadow = NULL;
info.dev = dev;
ukinfo->cq_size = max(entries, 4);
ukinfo->cq_id = cq_num;
@@ -2518,8 +2525,6 @@ static int irdma_create_cq(struct ib_cq *ibcq,
struct irdma_ucontext *ucontext;
struct irdma_create_cq_req req = {};
struct irdma_cq_mr *cqmr;
- struct irdma_pbl *iwpbl;
- struct irdma_pbl *iwpbl_shadow;
struct irdma_cq_mr *cqmr_shadow;
iwcq->user_mode = true;
@@ -2533,34 +2538,34 @@ static int irdma_create_cq(struct ib_cq *ibcq,
}
spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
- iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
- &ucontext->cq_reg_mem_list);
+ iwcq->iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
+ &ucontext->cq_reg_mem_list);
spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
- if (!iwpbl) {
+ if (!iwcq->iwpbl) {
err_code = -EPROTO;
goto cq_free_rsrc;
}
- cqmr = &iwpbl->cq_mr;
+ cqmr = &iwcq->iwpbl->cq_mr;
if (rf->sc_dev.hw_attrs.uk_attrs.feature_flags &
IRDMA_FEATURE_CQ_RESIZE) {
spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
- iwpbl_shadow = irdma_get_pbl(
+ iwcq->iwpbl_shadow = irdma_get_pbl(
(unsigned long)req.user_shadow_area,
&ucontext->cq_reg_mem_list);
spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
- if (!iwpbl_shadow) {
+ if (!iwcq->iwpbl_shadow) {
err_code = -EPROTO;
goto cq_free_rsrc;
}
- cqmr_shadow = &iwpbl_shadow->cq_mr;
+ cqmr_shadow = &iwcq->iwpbl_shadow->cq_mr;
info.shadow_area_pa = cqmr_shadow->cq_pbl.addr;
} else {
info.shadow_area_pa = cqmr->shadow;
}
- if (iwpbl->pbl_allocated) {
+ if (iwcq->iwpbl->pbl_allocated) {
info.virtual_map = true;
info.pbl_chunk_size = 1;
info.first_pm_pbl_idx = cqmr->cq_pbl.idx;
diff --git a/drivers/infiniband/hw/irdma/verbs.h b/drivers/infiniband/hw/irdma/verbs.h
index fbd487dbe..a1651641e 100644
--- a/drivers/infiniband/hw/irdma/verbs.h
+++ b/drivers/infiniband/hw/irdma/verbs.h
@@ -153,6 +153,8 @@ struct irdma_cq {
struct list_head resize_list;
struct irdma_cq_poll_info cur_cqe;
struct list_head cmpl_generated;
+ struct irdma_pbl *iwpbl;
+ struct irdma_pbl *iwpbl_shadow;
};
struct irdma_cmpl_gen {
--
2.55.0.rc0.738.g0c8ab3ebcc-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH rdma-next 4/4] RDMA/irdma: Add refcounting to user ring MRs
2026-06-18 20:14 [PATCH rdma-next 0/4] RDMA/irdma: Prevent premature deregistration of user ring MRs Jacob Moroni
` (2 preceding siblings ...)
2026-06-18 20:14 ` [PATCH rdma-next 3/4] RDMA/irdma: Add irdma_cq fields to track pbl allocations Jacob Moroni
@ 2026-06-18 20:14 ` Jacob Moroni
3 siblings, 0 replies; 5+ messages in thread
From: Jacob Moroni @ 2026-06-18 20:14 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
Prevent userspace from deregistering the MRs that back QP/CQ/SRQ rings
by bumping the MR's refcount upon association.
Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/utils.c | 6 ++++
drivers/infiniband/hw/irdma/verbs.c | 45 +++++++++++++++++++++++++++--
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index e4037d5ef..290ad02ed 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -1168,6 +1168,12 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
iwqp->kqp.dma_mem.va = NULL;
kfree(iwqp->kqp.sq_wrid_mem);
kfree(iwqp->kqp.rq_wrid_mem);
+
+ if (iwqp->user_mode && iwqp->iwpbl) {
+ struct irdma_mr *iwmr = iwqp->iwpbl->iwmr;
+
+ refcount_dec(&iwmr->user_ring_refs);
+ }
}
/**
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index dccecff3c..70201e1e2 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -464,6 +464,9 @@ static struct irdma_pbl *irdma_get_pbl(unsigned long va,
list_for_each_entry (iwpbl, pbl_list, list) {
if (iwpbl->user_base == va) {
+ struct irdma_mr *iwmr = iwpbl->iwmr;
+
+ refcount_inc(&iwmr->user_ring_refs);
list_del(&iwpbl->list);
iwpbl->on_list = false;
return iwpbl;
@@ -1881,6 +1884,11 @@ static void irdma_srq_free_rsrc(struct irdma_pci_f *rf, struct irdma_srq *iwsrq)
dma_free_coherent(rf->sc_dev.hw->device, iwsrq->kmem.size,
iwsrq->kmem.va, iwsrq->kmem.pa);
iwsrq->kmem.va = NULL;
+ } else {
+ /* Not called in any failure path, so iwpbl is valid. */
+ struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr;
+
+ refcount_dec(&iwmr->user_ring_refs);
}
irdma_free_rsrc(rf, rf->allocated_srqs, srq->srq_uk.srq_id);
@@ -1903,6 +1911,21 @@ static void irdma_cq_free_rsrc(struct irdma_pci_f *rf, struct irdma_cq *iwcq)
iwcq->kmem_shadow.size,
iwcq->kmem_shadow.va, iwcq->kmem_shadow.pa);
iwcq->kmem_shadow.va = NULL;
+ } else {
+ struct irdma_mr *iwmr;
+
+ /* May be called in a failure path before iwpbl is valid. */
+ if (iwcq->iwpbl) {
+ iwmr = iwcq->iwpbl->iwmr;
+
+ refcount_dec(&iwmr->user_ring_refs);
+ }
+
+ if (iwcq->iwpbl_shadow) {
+ iwmr = iwcq->iwpbl_shadow->iwmr;
+
+ refcount_dec(&iwmr->user_ring_refs);
+ }
}
irdma_free_rsrc(rf, rf->allocated_cqs, cq->cq_uk.cq_id);
@@ -2018,7 +2041,7 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
struct irdma_modify_cq_info info = {};
struct irdma_dma_mem kmem_buf;
struct irdma_cq_mr *cqmr_buf;
- struct irdma_pbl *iwpbl_buf;
+ struct irdma_pbl *iwpbl_buf = NULL;
struct irdma_device *iwdev;
struct irdma_pci_f *rf;
struct irdma_cq_buf *cq_buf = NULL;
@@ -2129,11 +2152,19 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
goto error;
spin_lock_irqsave(&iwcq->lock, flags);
- if (udata)
+ if (udata) {
+ struct irdma_pbl *old_iwpbl = iwcq->iwpbl;
+
/* Only update if the resize was successful. Otherwise, HW is
* still pointing to the old PBL.
*/
iwcq->iwpbl = iwpbl_buf;
+ if (old_iwpbl) {
+ struct irdma_mr *old_iwmr = old_iwpbl->iwmr;
+
+ refcount_dec(&old_iwmr->user_ring_refs);
+ }
+ }
if (cq_buf) {
cq_buf->kmem_buf = iwcq->kmem;
cq_buf->hw = dev->hw;
@@ -2149,6 +2180,11 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
return 0;
error:
+ if (iwpbl_buf) {
+ struct irdma_mr *iwmr = iwpbl_buf->iwmr;
+
+ refcount_dec(&iwmr->user_ring_refs);
+ }
if (!udata) {
dma_free_coherent(dev->hw->device, kmem_buf.size, kmem_buf.va,
kmem_buf.pa);
@@ -2425,6 +2461,11 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
dma_free_coherent(rf->hw.device, iwsrq->kmem.size,
iwsrq->kmem.va, iwsrq->kmem.pa);
free_rsrc:
+ if (iwsrq->user_mode && iwsrq->iwpbl) {
+ struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr;
+
+ refcount_dec(&iwmr->user_ring_refs);
+ }
irdma_free_rsrc(rf, rf->allocated_srqs, iwsrq->srq_num);
return err_code;
}
--
2.55.0.rc0.738.g0c8ab3ebcc-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread