Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ
@ 2026-07-21 11:54 Selvin Xavier
  2026-07-21 11:54 ` [PATCH for-next v4 1/4] RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays Selvin Xavier
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Selvin Xavier @ 2026-07-21 11:54 UTC (permalink / raw)
  To: leon, jgg
  Cc: linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Selvin Xavier

Based on the suggestion from Jason (
https://patchwork.kernel.org/project/linux-rdma/patch/20260615224751.232802-5-selvin.xavier@broadcom.com/)
, adding the uverb object to retrieve the CQ an SRQ structures while getting the
toggle mem. To work with older rdma-core, retain the existing code with
modification.
The rdma-core pull request is here: https://github.com/linux-rdma/rdma-core/pull/1761
Please review and apply the series.
Thanks,
Selvin Xavier

v3 -> v4:
 - Fix a NULL pointer possibility by adding a check for res_uobj->object
 - Locking changes in patch1 based on Leon's comment
 - The kref of the mmap entry (patch 3 of the previous series) is folded
   into the patch 2 of this series that fixes the lifetime of the toggle
   pages.
 - Adds a clearing of the MAYWRITE option, so that read-only mapping
   can't later be upgraded.
 - v3: https://lore.kernel.org/linux-rdma/20260713135830.1934471-1-selvin.xavier@broadcom.com/

v2 -> v3:
 - Patch2 fixes toggle-page lifetime by making the rdma_user_mmap_entry
   the sole owner of the page
 - Patch 3 adds a reference to the uobject in the legacy path to avoid
   the usage of the page va after the resource destroy.
 - v2: https://lore.kernel.org/linux-rdma/20260624223927.521882-1-selvin.xavier@broadcom.com/

v1->v2 :
 - Fix the error cleanup for SRQ and CQ create paths
 - Fix a synchronization issue for the legacy path which can cause a
   UAF
 - v1: https://lore.kernel.org/linux-rdma/20260622100528.132463-1-selvin.xavier@broadcom.com/

Selvin Xavier (4):
  RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays
  RDMA/bnxt_re: Defer toggle page free to rdma_user_mmap_entry teardown
  RDMA/bnxt_re: Fix toggle page UAF in GET_TOGGLE_MEM with mmap entry
    refcount
  RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page


Selvin Xavier (4):
  RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays
  RDMA/bnxt_re: Defer toggle page free to rdma_user_mmap_entry teardown
  RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page
  RDMA/bnxt_re: Clear VM_MAYWRITE on DBR/toggle page mmap

 drivers/infiniband/hw/bnxt_re/bnxt_re.h  |   6 -
 drivers/infiniband/hw/bnxt_re/ib_verbs.c | 125 +++++++++++++---
 drivers/infiniband/hw/bnxt_re/ib_verbs.h |   8 +-
 drivers/infiniband/hw/bnxt_re/main.c     |   4 -
 drivers/infiniband/hw/bnxt_re/uapi.c     | 183 +++++++++++++++--------
 include/uapi/rdma/bnxt_re-abi.h          |   4 +
 6 files changed, 233 insertions(+), 97 deletions(-)

-- 
2.39.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH for-next v4 1/4] RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays
  2026-07-21 11:54 [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Selvin Xavier
@ 2026-07-21 11:54 ` Selvin Xavier
  2026-07-21 11:54 ` [PATCH for-next v4 2/4] RDMA/bnxt_re: Defer toggle page free to rdma_user_mmap_entry teardown Selvin Xavier
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Selvin Xavier @ 2026-07-21 11:54 UTC (permalink / raw)
  To: leon, jgg
  Cc: linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Selvin Xavier

The CQ and SRQ hash tables (cq_hash, srq_hash) on struct bnxt_re_dev
were used exclusively to look up a toggle-page pointer from a
user-space-supplied hardware queue ID in the GET_TOGGLE_MEM
ioctl handler. This approach has couple of problems. First,
because the tables are per-device, any user can look up another
user's CQ or SRQ by guessing the hardware queue ID. Second,
concurrent add and remove operations on the hash table are not
protected by any lock, leaving a race window.

The correct fix is to retrieve the CQ and SRQ objects via the uverbs
object handle, which gives built-in ownership verification and reference
pinning for the duration of the ioctl. That is added in a later patch of
this series.

To maintain backward compatibility with older rdma-core versions that
do not send a uverbs object handle, the driver must continue to support
the existing TYPE + RES_ID lookup path. This patch replaces the per-device
hash tables with per-ucontext XArrays (cq_xa and srq_xa on struct
bnxt_re_ucontext), which narrows the lookup scope to the calling context,
eliminating the cross-user visibility. Also adds Xarray locking mechanism
for synchronization.

The GET_TOGGLE_MEM ioctl handler is updated to call xa_load()
in place of the now-removed bnxt_re_search_for_cq()/
bnxt_re_search_for_srq() helpers. No ABI changes are required.

bnxt_re_create_user_cq()/bnxt_re_create_srq() publish the uobject into
cq_xa/srq_xa before returning to the uverbs core, but the core only
sets uobject->object once the create callback has returned success.
Guard the lookup against this so a concurrent GET_TOGGLE_MEM racing an
in-progress create cannot feed a NULL ->object into container_of().

Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
---
 drivers/infiniband/hw/bnxt_re/bnxt_re.h  |  6 --
 drivers/infiniband/hw/bnxt_re/ib_verbs.c | 87 +++++++++++++++++++-----
 drivers/infiniband/hw/bnxt_re/ib_verbs.h |  6 +-
 drivers/infiniband/hw/bnxt_re/main.c     |  4 --
 drivers/infiniband/hw/bnxt_re/uapi.c     | 85 +++++++++--------------
 5 files changed, 107 insertions(+), 81 deletions(-)

diff --git a/drivers/infiniband/hw/bnxt_re/bnxt_re.h b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
index 3a7ce4729fcf..a43e678151d3 100644
--- a/drivers/infiniband/hw/bnxt_re/bnxt_re.h
+++ b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
@@ -41,7 +41,6 @@
 #define __BNXT_RE_H__
 #include <rdma/uverbs_ioctl.h>
 #include "hw_counters.h"
-#include <linux/hashtable.h>
 #define ROCE_DRV_MODULE_NAME		"bnxt_re"
 
 #define BNXT_RE_DESC	"Broadcom NetXtreme-C/E RoCE Driver"
@@ -158,9 +157,6 @@ struct bnxt_re_nq_record {
 	struct mutex		load_lock;
 };
 
-#define MAX_CQ_HASH_BITS		(16)
-#define MAX_SRQ_HASH_BITS		(16)
-
 static inline bool bnxt_re_chip_gen_p7(u16 chip_num)
 {
 	return (chip_num == CHIP_NUM_58818 ||
@@ -215,8 +211,6 @@ struct bnxt_re_dev {
 	struct bnxt_re_pacing pacing;
 	struct work_struct dbq_fifo_check_work;
 	struct delayed_work dbq_pacing_work;
-	DECLARE_HASHTABLE(cq_hash, MAX_CQ_HASH_BITS);
-	DECLARE_HASHTABLE(srq_hash, MAX_SRQ_HASH_BITS);
 	struct dentry			*dbg_root;
 	struct dentry			*qp_debugfs;
 	unsigned long			event_bitmap;
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 90138d64adee..dbf89abde85b 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -2151,11 +2151,26 @@ int bnxt_re_destroy_srq(struct ib_srq *ib_srq, struct ib_udata *udata)
 	if (ret)
 		return ret;
 
-	if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT)
-		hash_del(&srq->hash_entry);
+	if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT) {
+		struct bnxt_re_ucontext *uctx =
+			rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
+
+		/*
+		 * Untrack the SRQ before releasing its hardware ID below, so a
+		 * concurrent create that gets the same ID reused by firmware
+		 * cannot have its fresh XArray entry erased by this destroy.
+		 */
+		if (uctx)
+			xa_erase(&uctx->srq_xa, srq->qplib_srq.id);
+	}
 	bnxt_qplib_destroy_srq(&rdev->qplib_res, qplib_srq);
-	if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT)
-		free_page((unsigned long)srq->uctx_srq_page);
+	if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT) {
+		struct bnxt_re_ucontext *uctx =
+			rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
+
+		if (uctx)
+			free_page((unsigned long)srq->uctx_srq_page);
+	}
 	ib_umem_release(srq->umem);
 	atomic_dec(&rdev->stats.res.srq_count);
 	return ib_respond_empty_udata(udata);
@@ -2262,20 +2277,21 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
 
 		resp.srqid = srq->qplib_srq.id;
 		if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT) {
-			hash_add(rdev->srq_hash, &srq->hash_entry, srq->qplib_srq.id);
 			srq->uctx_srq_page = (void *)get_zeroed_page(GFP_KERNEL);
 			if (!srq->uctx_srq_page) {
 				rc = -ENOMEM;
-				goto fail;
+				goto fail_destroy_srq;
+			}
+			if (xa_is_err(xa_store(&uctx->srq_xa, srq->qplib_srq.id,
+					       ib_srq->uobject, GFP_KERNEL))) {
+				rc = -ENOMEM;
+				goto fail_free_srq_page;
 			}
 			resp.comp_mask |= BNXT_RE_SRQ_TOGGLE_PAGE_SUPPORT;
 		}
 		rc = ib_respond_udata(udata, resp);
-		if (rc) {
-			bnxt_qplib_destroy_srq(&rdev->qplib_res,
-					       &srq->qplib_srq);
-			goto fail;
-		}
+		if (rc)
+			goto fail_respond;
 	}
 	active_srqs = atomic_inc_return(&rdev->stats.res.srq_count);
 	if (active_srqs > rdev->stats.res.srq_watermark)
@@ -2284,6 +2300,17 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
 
 	return 0;
 
+fail_respond:
+	if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT) {
+		xa_erase(&uctx->srq_xa, srq->qplib_srq.id);
+		free_page((unsigned long)srq->uctx_srq_page);
+	}
+	bnxt_qplib_destroy_srq(&rdev->qplib_res, &srq->qplib_srq);
+	goto fail;
+fail_free_srq_page:
+	free_page((unsigned long)srq->uctx_srq_page);
+fail_destroy_srq:
+	bnxt_qplib_destroy_srq(&rdev->qplib_res, &srq->qplib_srq);
 fail:
 	ib_umem_release(srq->umem);
 exit:
@@ -3474,11 +3501,26 @@ int bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
 	if (ret)
 		return ret;
 
-	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT)
-		hash_del(&cq->hash_entry);
+	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT) {
+		struct bnxt_re_ucontext *uctx =
+			rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
+
+		/*
+		 * Untrack the CQ before releasing its hardware ID below, so a
+		 * concurrent create that gets the same ID reused by firmware
+		 * cannot have its fresh XArray entry erased by this destroy.
+		 */
+		if (uctx)
+			xa_erase(&uctx->cq_xa, cq->qplib_cq.id);
+	}
 	bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
-	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT)
-		free_page((unsigned long)cq->uctx_cq_page);
+	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT) {
+		struct bnxt_re_ucontext *uctx =
+			rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
+
+		if (uctx)
+			free_page((unsigned long)cq->uctx_cq_page);
+	}
 
 	bnxt_re_put_nq(rdev, nq);
 
@@ -3553,14 +3595,16 @@ int bnxt_re_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *att
 	spin_lock_init(&cq->cq_lock);
 
 	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT) {
-		hash_add(rdev->cq_hash, &cq->hash_entry, cq->qplib_cq.id);
-		/* Allocate a page */
 		cq->uctx_cq_page = (void *)get_zeroed_page(GFP_KERNEL);
 		if (!cq->uctx_cq_page) {
 			rc = -ENOMEM;
 			goto destroy_cq;
 		}
-
+		if (xa_is_err(xa_store(&uctx->cq_xa, cq->qplib_cq.id,
+				       ibcq->uobject, GFP_KERNEL))) {
+			rc = -ENOMEM;
+			goto free_cq_page;
+		}
 		resp.comp_mask |= BNXT_RE_CQ_TOGGLE_PAGE_SUPPORT;
 	}
 	resp.cqid = cq->qplib_cq.id;
@@ -3573,6 +3617,9 @@ int bnxt_re_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *att
 	return 0;
 
 free_mem:
+	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT)
+		xa_erase(&uctx->cq_xa, cq->qplib_cq.id);
+free_cq_page:
 	free_page((unsigned long)cq->uctx_cq_page);
 destroy_cq:
 	bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
@@ -4794,6 +4841,8 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
 		goto cfail;
 	}
 	uctx->shpage_mmap = &entry->rdma_entry;
+	xa_init(&uctx->cq_xa);
+	xa_init(&uctx->srq_xa);
 	if (rdev->pacing.dbr_pacing)
 		resp.comp_mask |= BNXT_RE_UCNTX_CMASK_DBR_PACING_ENABLED;
 
@@ -4846,6 +4895,8 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx)
 	uctx->shpage_mmap = NULL;
 	if (uctx->shpg)
 		free_page((unsigned long)uctx->shpg);
+	xa_destroy(&uctx->cq_xa);
+	xa_destroy(&uctx->srq_xa);
 
 	if (uctx->dpi.dbr) {
 		/* Free DPI only if this is the first PD allocated by the
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index 22bf81668cfb..4c78c183784b 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -70,6 +70,8 @@ struct bnxt_re_ah {
 	struct bnxt_qplib_ah	qplib_ah;
 };
 
+struct bnxt_re_user_mmap_entry;
+
 struct bnxt_re_srq {
 	struct ib_srq		ib_srq;
 	struct bnxt_re_dev	*rdev;
@@ -78,7 +80,6 @@ struct bnxt_re_srq {
 	struct ib_umem		*umem;
 	spinlock_t		lock;		/* protect srq */
 	void			*uctx_srq_page;
-	struct hlist_node       hash_entry;
 };
 
 struct bnxt_re_qp {
@@ -113,7 +114,6 @@ struct bnxt_re_cq {
 	struct ib_umem		*resize_umem;
 	int			resize_cqe;
 	void			*uctx_cq_page;
-	struct hlist_node	hash_entry;
 };
 
 struct bnxt_re_mr {
@@ -147,6 +147,8 @@ struct bnxt_re_ucontext {
 	void			*shpg;
 	spinlock_t		sh_lock;	/* protect shpg */
 	struct rdma_user_mmap_entry *shpage_mmap;
+	struct xarray		cq_xa;  /* cqid → ib_uobject, per-context toggle page lookup */
+	struct xarray		srq_xa; /* srqid → ib_uobject, per-context toggle page lookup */
 	u64 cmask;
 };
 
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index d25fdc458120..ce72db1b4bc3 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -2337,10 +2337,6 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
 		if (!(rdev->qplib_res.en_dev->flags & BNXT_EN_FLAG_ROCE_VF_RES_MGMT))
 			bnxt_re_vf_res_config(rdev);
 	}
-	hash_init(rdev->cq_hash);
-	if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT)
-		hash_init(rdev->srq_hash);
-
 	bnxt_re_debugfs_add_pdev(rdev);
 
 	bnxt_re_init_dcb_wq(rdev);
diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
index 263238a6e4cd..c5e4e6e47b5f 100644
--- a/drivers/infiniband/hw/bnxt_re/uapi.c
+++ b/drivers/infiniband/hw/bnxt_re/uapi.c
@@ -22,31 +22,6 @@
 #include "bnxt_re.h"
 #include "ib_verbs.h"
 
-static struct bnxt_re_cq *bnxt_re_search_for_cq(struct bnxt_re_dev *rdev, u32 cq_id)
-{
-	struct bnxt_re_cq *cq = NULL, *tmp_cq;
-
-	hash_for_each_possible(rdev->cq_hash, tmp_cq, hash_entry, cq_id) {
-		if (tmp_cq->qplib_cq.id == cq_id) {
-			cq = tmp_cq;
-			break;
-		}
-	}
-	return cq;
-}
-
-static struct bnxt_re_srq *bnxt_re_search_for_srq(struct bnxt_re_dev *rdev, u32 srq_id)
-{
-	struct bnxt_re_srq *srq = NULL, *tmp_srq;
-
-	hash_for_each_possible(rdev->srq_hash, tmp_srq, hash_entry, srq_id) {
-		if (tmp_srq->qplib_srq.id == srq_id) {
-			srq = tmp_srq;
-			break;
-		}
-	}
-	return srq;
-}
 
 static int UVERBS_HANDLER(BNXT_RE_METHOD_NOTIFY_DRV)(struct uverbs_attr_bundle *attrs)
 {
@@ -244,12 +219,10 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
 	enum bnxt_re_mmap_flag mmap_flag = BNXT_RE_MMAP_TOGGLE_PAGE;
 	enum bnxt_re_get_toggle_mem_type res_type;
 	struct bnxt_re_user_mmap_entry *entry;
+	struct ib_uobject *res_uobj;
 	struct bnxt_re_ucontext *uctx;
 	struct ib_ucontext *ib_uctx;
-	struct bnxt_re_dev *rdev;
-	struct bnxt_re_srq *srq;
 	u32 length = PAGE_SIZE;
-	struct bnxt_re_cq *cq;
 	u64 mem_offset;
 	u32 offset = 0;
 	u64 addr = 0;
@@ -265,35 +238,45 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
 		return err;
 
 	uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
-	rdev = uctx->rdev;
 	err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
 	if (err)
 		return err;
 
-	switch (res_type) {
-	case BNXT_RE_CQ_TOGGLE_MEM:
-		cq = bnxt_re_search_for_cq(rdev, res_id);
-		if (!cq)
-			return -EINVAL;
-
-		addr = (u64)cq->uctx_cq_page;
-		if (!addr)
-			return -EOPNOTSUPP;
-		break;
-	case BNXT_RE_SRQ_TOGGLE_MEM:
-		srq = bnxt_re_search_for_srq(rdev, res_id);
-		if (!srq)
-			return -EINVAL;
-
-		addr = (u64)srq->uctx_srq_page;
-		if (!addr)
-			return -EOPNOTSUPP;
-		break;
-
-	default:
+	/*
+	 * bnxt_re_create_cq/srq() publishes the uobject into cq_xa/srq_xa
+	 * before returning to the uverbs core, but the core only sets
+	 * uobject->object once the create callback has returned success.
+	 * A lookup that races with an in-progress create can therefore
+	 * find a uobject whose ->object is still NULL; skip it instead of
+	 * feeding NULL to container_of().
+	 */
+	if (res_type == BNXT_RE_CQ_TOGGLE_MEM) {
+		struct bnxt_re_cq *cq;
+
+		xa_lock(&uctx->cq_xa);
+		res_uobj = xa_load(&uctx->cq_xa, res_id);
+		if (res_uobj && res_uobj->object) {
+			cq = container_of(res_uobj->object, struct bnxt_re_cq, ib_cq);
+			addr = (u64)cq->uctx_cq_page;
+		}
+		xa_unlock(&uctx->cq_xa);
+	} else if (res_type == BNXT_RE_SRQ_TOGGLE_MEM) {
+		struct bnxt_re_srq *srq;
+
+		xa_lock(&uctx->srq_xa);
+		res_uobj = xa_load(&uctx->srq_xa, res_id);
+		if (res_uobj && res_uobj->object) {
+			srq = container_of(res_uobj->object, struct bnxt_re_srq, ib_srq);
+			addr = (u64)srq->uctx_srq_page;
+		}
+		xa_unlock(&uctx->srq_xa);
+	} else {
 		return -EOPNOTSUPP;
 	}
 
+	if (!addr)
+		return -EOPNOTSUPP;
+
 	entry = bnxt_re_mmap_entry_insert(uctx, addr, mmap_flag, &mem_offset);
 	if (!entry)
 		return -ENOMEM;
@@ -322,7 +305,7 @@ static int get_toggle_mem_obj_cleanup(struct ib_uobject *uobject,
 				      enum rdma_remove_reason why,
 				      struct uverbs_attr_bundle *attrs)
 {
-	struct  bnxt_re_user_mmap_entry *entry = uobject->object;
+	struct bnxt_re_user_mmap_entry *entry = uobject->object;
 
 	rdma_user_mmap_entry_remove(&entry->rdma_entry);
 	return 0;
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH for-next v4 2/4] RDMA/bnxt_re: Defer toggle page free to rdma_user_mmap_entry teardown
  2026-07-21 11:54 [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Selvin Xavier
  2026-07-21 11:54 ` [PATCH for-next v4 1/4] RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays Selvin Xavier
@ 2026-07-21 11:54 ` Selvin Xavier
  2026-07-21 11:54 ` [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page Selvin Xavier
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Selvin Xavier @ 2026-07-21 11:54 UTC (permalink / raw)
  To: leon, jgg
  Cc: linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Selvin Xavier

Fix the page lifetime by making the rdma_user_mmap_entry the sole owner
of the toggle page allocation. Creating the rdma_user_mmap_entry and page
during the CQ/SRQ creation time. Freeing the page is handled when the
mmap free is called. Introduce struct bnxt_re_toggle_mem to carry
the mmap_offset for the lifetime of the GET_TOGGLE_MEM uobject handle.

bnxt_re_destroy_cq/srq can erase the entry from the XArray and call
rdma_user_mmap_entry_remove() on the toggle_entry concurrently with
the caller's xa_load() and its subsequent use of that toggle_entry.
Guard against this by taking an extra kref directly on the
toggle_entry's rdma_user_mmap_entry while the GET_TOGGLE_MEM handle
exists, released when the handle is destroyed. This pins exactly the
resource that GET_TOGGLE_MEM hands out (the mmap offset/page),
independent of the CQ/SRQ's own lifetime.

Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
---
 drivers/infiniband/hw/bnxt_re/ib_verbs.c | 40 ++++++++++++++++---
 drivers/infiniband/hw/bnxt_re/ib_verbs.h |  2 +
 drivers/infiniband/hw/bnxt_re/uapi.c     | 51 ++++++++++++++++++------
 3 files changed, 75 insertions(+), 18 deletions(-)

diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index dbf89abde85b..0ff862ca982c 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -2169,7 +2169,7 @@ int bnxt_re_destroy_srq(struct ib_srq *ib_srq, struct ib_udata *udata)
 			rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
 
 		if (uctx)
-			free_page((unsigned long)srq->uctx_srq_page);
+			rdma_user_mmap_entry_remove(&srq->toggle_entry->rdma_entry);
 	}
 	ib_umem_release(srq->umem);
 	atomic_dec(&rdev->stats.res.srq_count);
@@ -2282,10 +2282,17 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
 				rc = -ENOMEM;
 				goto fail_destroy_srq;
 			}
+			srq->toggle_entry = bnxt_re_mmap_entry_insert(uctx, (u64)srq->uctx_srq_page,
+								      BNXT_RE_MMAP_TOGGLE_PAGE,
+								      NULL);
+			if (!srq->toggle_entry) {
+				rc = -ENOMEM;
+				goto fail_free_srq_page;
+			}
 			if (xa_is_err(xa_store(&uctx->srq_xa, srq->qplib_srq.id,
 					       ib_srq->uobject, GFP_KERNEL))) {
 				rc = -ENOMEM;
-				goto fail_free_srq_page;
+				goto fail_remove_toggle_entry;
 			}
 			resp.comp_mask |= BNXT_RE_SRQ_TOGGLE_PAGE_SUPPORT;
 		}
@@ -2303,10 +2310,13 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
 fail_respond:
 	if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT) {
 		xa_erase(&uctx->srq_xa, srq->qplib_srq.id);
-		free_page((unsigned long)srq->uctx_srq_page);
+		goto fail_remove_toggle_entry;
 	}
 	bnxt_qplib_destroy_srq(&rdev->qplib_res, &srq->qplib_srq);
 	goto fail;
+fail_remove_toggle_entry:
+	rdma_user_mmap_entry_remove(&srq->toggle_entry->rdma_entry);
+	goto fail_destroy_srq;
 fail_free_srq_page:
 	free_page((unsigned long)srq->uctx_srq_page);
 fail_destroy_srq:
@@ -3519,7 +3529,7 @@ int bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
 			rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
 
 		if (uctx)
-			free_page((unsigned long)cq->uctx_cq_page);
+			rdma_user_mmap_entry_remove(&cq->toggle_entry->rdma_entry);
 	}
 
 	bnxt_re_put_nq(rdev, nq);
@@ -3600,10 +3610,16 @@ int bnxt_re_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *att
 			rc = -ENOMEM;
 			goto destroy_cq;
 		}
+		cq->toggle_entry = bnxt_re_mmap_entry_insert(uctx, (u64)cq->uctx_cq_page,
+							     BNXT_RE_MMAP_TOGGLE_PAGE, NULL);
+		if (!cq->toggle_entry) {
+			rc = -ENOMEM;
+			goto free_cq_page;
+		}
 		if (xa_is_err(xa_store(&uctx->cq_xa, cq->qplib_cq.id,
 				       ibcq->uobject, GFP_KERNEL))) {
 			rc = -ENOMEM;
-			goto free_cq_page;
+			goto remove_toggle_entry;
 		}
 		resp.comp_mask |= BNXT_RE_CQ_TOGGLE_PAGE_SUPPORT;
 	}
@@ -3619,6 +3635,10 @@ int bnxt_re_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *att
 free_mem:
 	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT)
 		xa_erase(&uctx->cq_xa, cq->qplib_cq.id);
+remove_toggle_entry:
+	if (cctx->modes.toggle_bits & BNXT_QPLIB_CQ_TOGGLE_BIT)
+		rdma_user_mmap_entry_remove(&cq->toggle_entry->rdma_entry);
+	goto destroy_cq;
 free_cq_page:
 	free_page((unsigned long)cq->uctx_cq_page);
 destroy_cq:
@@ -5063,6 +5083,16 @@ void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry)
 	bnxt_entry = container_of(rdma_entry, struct bnxt_re_user_mmap_entry,
 				  rdma_entry);
 
+	/*
+	 * For toggle pages the kernel VA was stored directly in mem_offset
+	 * at creation time (bnxt_re_create_user_cq / bnxt_re_create_srq).
+	 * Free it here — this is the only place it is freed, ensuring the
+	 * page outlives every concurrent bnxt_re_mmap() call that may have
+	 * incremented the entry's reference count.
+	 */
+	if (bnxt_entry->mmap_flag == BNXT_RE_MMAP_TOGGLE_PAGE)
+		free_page((unsigned long)bnxt_entry->mem_offset);
+
 	if (bnxt_entry->dpi_valid)
 		bnxt_qplib_free_uc_dpi(&bnxt_entry->uctx->rdev->qplib_res,
 				       &bnxt_entry->dpi);
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index 4c78c183784b..b7b33f6acf91 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -80,6 +80,7 @@ struct bnxt_re_srq {
 	struct ib_umem		*umem;
 	spinlock_t		lock;		/* protect srq */
 	void			*uctx_srq_page;
+	struct bnxt_re_user_mmap_entry *toggle_entry;
 };
 
 struct bnxt_re_qp {
@@ -114,6 +115,7 @@ struct bnxt_re_cq {
 	struct ib_umem		*resize_umem;
 	int			resize_cqe;
 	void			*uctx_cq_page;
+	struct bnxt_re_user_mmap_entry *toggle_entry;
 };
 
 struct bnxt_re_mr {
diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
index c5e4e6e47b5f..97bc0e755511 100644
--- a/drivers/infiniband/hw/bnxt_re/uapi.c
+++ b/drivers/infiniband/hw/bnxt_re/uapi.c
@@ -213,19 +213,23 @@ DECLARE_UVERBS_GLOBAL_METHODS(BNXT_RE_OBJECT_NOTIFY_DRV,
 			      &UVERBS_METHOD(BNXT_RE_METHOD_NOTIFY_DRV));
 
 /* Toggle MEM */
+struct bnxt_re_toggle_mem {
+	struct bnxt_re_user_mmap_entry *toggle_entry;
+	u64 mmap_offset;
+};
+
 static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bundle *attrs)
 {
 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_TOGGLE_MEM_HANDLE);
-	enum bnxt_re_mmap_flag mmap_flag = BNXT_RE_MMAP_TOGGLE_PAGE;
+	struct bnxt_re_user_mmap_entry *toggle_entry = NULL;
 	enum bnxt_re_get_toggle_mem_type res_type;
-	struct bnxt_re_user_mmap_entry *entry;
+	struct bnxt_re_toggle_mem *tmem;
 	struct ib_uobject *res_uobj;
 	struct bnxt_re_ucontext *uctx;
 	struct ib_ucontext *ib_uctx;
 	u32 length = PAGE_SIZE;
-	u64 mem_offset;
+	u64 mmap_offset = 0;
 	u32 offset = 0;
-	u64 addr = 0;
 	u32 res_id;
 	int err;
 
@@ -243,6 +247,10 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
 		return err;
 
 	/*
+	 * Hold xa_lock across xa_load + kref_get so that a concurrent
+	 * bnxt_re_destroy_cq/srq cannot call __xa_erase and remove the
+	 * toggle_entry between our load and our reference on it.
+	 *
 	 * bnxt_re_create_cq/srq() publishes the uobject into cq_xa/srq_xa
 	 * before returning to the uverbs core, but the core only sets
 	 * uobject->object once the create callback has returned success.
@@ -257,7 +265,13 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
 		res_uobj = xa_load(&uctx->cq_xa, res_id);
 		if (res_uobj && res_uobj->object) {
 			cq = container_of(res_uobj->object, struct bnxt_re_cq, ib_cq);
-			addr = (u64)cq->uctx_cq_page;
+			if (cq->toggle_entry)
+				mmap_offset =
+					rdma_user_mmap_get_offset(&cq->toggle_entry->rdma_entry);
+			if (mmap_offset) {
+				kref_get(&cq->toggle_entry->rdma_entry.ref);
+				toggle_entry = cq->toggle_entry;
+			}
 		}
 		xa_unlock(&uctx->cq_xa);
 	} else if (res_type == BNXT_RE_SRQ_TOGGLE_MEM) {
@@ -267,24 +281,34 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
 		res_uobj = xa_load(&uctx->srq_xa, res_id);
 		if (res_uobj && res_uobj->object) {
 			srq = container_of(res_uobj->object, struct bnxt_re_srq, ib_srq);
-			addr = (u64)srq->uctx_srq_page;
+			if (srq->toggle_entry)
+				mmap_offset =
+					rdma_user_mmap_get_offset(&srq->toggle_entry->rdma_entry);
+			if (mmap_offset) {
+				kref_get(&srq->toggle_entry->rdma_entry.ref);
+				toggle_entry = srq->toggle_entry;
+			}
 		}
 		xa_unlock(&uctx->srq_xa);
 	} else {
 		return -EOPNOTSUPP;
 	}
 
-	if (!addr)
+	if (!mmap_offset)
 		return -EOPNOTSUPP;
 
-	entry = bnxt_re_mmap_entry_insert(uctx, addr, mmap_flag, &mem_offset);
-	if (!entry)
+	tmem = kzalloc_obj(*tmem);
+	if (!tmem) {
+		rdma_user_mmap_entry_put(&toggle_entry->rdma_entry);
 		return -ENOMEM;
+	}
 
-	uobj->object = entry;
+	tmem->toggle_entry = toggle_entry;
+	tmem->mmap_offset = mmap_offset;
+	uobj->object = tmem;
 	uverbs_finalize_uobj_create(attrs, BNXT_RE_TOGGLE_MEM_HANDLE);
 	err = uverbs_copy_to(attrs, BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
-			     &mem_offset, sizeof(mem_offset));
+			     &mmap_offset, sizeof(mmap_offset));
 	if (err)
 		return err;
 
@@ -305,9 +329,10 @@ static int get_toggle_mem_obj_cleanup(struct ib_uobject *uobject,
 				      enum rdma_remove_reason why,
 				      struct uverbs_attr_bundle *attrs)
 {
-	struct bnxt_re_user_mmap_entry *entry = uobject->object;
+	struct bnxt_re_toggle_mem *tmem = uobject->object;
 
-	rdma_user_mmap_entry_remove(&entry->rdma_entry);
+	rdma_user_mmap_entry_put(&tmem->toggle_entry->rdma_entry);
+	kfree(tmem);
 	return 0;
 }
 
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page
  2026-07-21 11:54 [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Selvin Xavier
  2026-07-21 11:54 ` [PATCH for-next v4 1/4] RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays Selvin Xavier
  2026-07-21 11:54 ` [PATCH for-next v4 2/4] RDMA/bnxt_re: Defer toggle page free to rdma_user_mmap_entry teardown Selvin Xavier
@ 2026-07-21 11:54 ` Selvin Xavier
  2026-07-27  6:21   ` Leon Romanovsky
  2026-07-21 11:54 ` [PATCH for-next v4 4/4] RDMA/bnxt_re: Clear VM_MAYWRITE on DBR/toggle page mmap Selvin Xavier
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Selvin Xavier @ 2026-07-21 11:54 UTC (permalink / raw)
  To: leon, jgg
  Cc: linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Selvin Xavier,
	Jason Gunthorpe

The current GET_TOGGLE_MEM ioctl requires the caller to supply
a type enum and a raw hardware queue ID (RES_ID). The kernel
looks up the CQ or SRQ by that ID without verifying that the
caller owns the resource.

Add a new, preferred code path that accepts standard uverbs
object handles (BNXT_RE_TOGGLE_MEM_CQ_HANDLE /
BNXT_RE_TOGGLE_MEM_SRQ_HANDLE) instead. The uverbs core validates
that the handle belongs to the calling context as part of resolving
it, so this path no longer needs the driver's own XArray lookup for
ownership checking. As with the legacy path, the toggle_entry's own
mmap-entry refcount (not a CQ/SRQ uobject reference) is what pins
the toggle page for the life of the GET_TOGGLE_MEM handle.

Only newer rdma-core versions support this path, if the
driver reports the supported resp mask
(BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT).
The existing TYPE + RES_ID path is retained for backward
compatibility with older rdma-core.

Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
---
 drivers/infiniband/hw/bnxt_re/ib_verbs.c |  2 +
 drivers/infiniband/hw/bnxt_re/uapi.c     | 55 +++++++++++++++++++++---
 include/uapi/rdma/bnxt_re-abi.h          |  4 ++
 3 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 0ff862ca982c..a14b17d4261f 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -4872,6 +4872,8 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
 	if (_is_modify_qp_rate_limit_supported(dev_attr->dev_cap_flags2))
 		resp.comp_mask |= BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED;
 
+	resp.comp_mask |= BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT;
+
 	if (udata->inlen) {
 		rc = ib_copy_validate_udata_in_cm(
 			udata, ureq, comp_mask,
diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
index 97bc0e755511..feaf98631fc5 100644
--- a/drivers/infiniband/hw/bnxt_re/uapi.c
+++ b/drivers/infiniband/hw/bnxt_re/uapi.c
@@ -237,16 +237,52 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
 	if (IS_ERR(ib_uctx))
 		return PTR_ERR(ib_uctx);
 
+	uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
+
+	/* New path: updated libbnxt_re passes the CQ or SRQ uverbs handle */
+	if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_CQ_HANDLE)) {
+		struct bnxt_re_cq *cq;
+
+		res_uobj = uverbs_attr_get_uobject(attrs,
+						   BNXT_RE_TOGGLE_MEM_CQ_HANDLE);
+		if (IS_ERR(res_uobj))
+			return PTR_ERR(res_uobj);
+		cq = container_of(res_uobj->object, struct bnxt_re_cq, ib_cq);
+		if (!cq->toggle_entry)
+			return -EOPNOTSUPP;
+		mmap_offset = rdma_user_mmap_get_offset(&cq->toggle_entry->rdma_entry);
+		if (!mmap_offset)
+			return -EOPNOTSUPP;
+		kref_get(&cq->toggle_entry->rdma_entry.ref);
+		toggle_entry = cq->toggle_entry;
+		goto alloc_tmem;
+	} else if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_SRQ_HANDLE)) {
+		struct bnxt_re_srq *srq;
+
+		res_uobj = uverbs_attr_get_uobject(attrs,
+						   BNXT_RE_TOGGLE_MEM_SRQ_HANDLE);
+		if (IS_ERR(res_uobj))
+			return PTR_ERR(res_uobj);
+		srq = container_of(res_uobj->object, struct bnxt_re_srq, ib_srq);
+		if (!srq->toggle_entry)
+			return -EOPNOTSUPP;
+		mmap_offset = rdma_user_mmap_get_offset(&srq->toggle_entry->rdma_entry);
+		if (!mmap_offset)
+			return -EOPNOTSUPP;
+		kref_get(&srq->toggle_entry->rdma_entry.ref);
+		toggle_entry = srq->toggle_entry;
+		goto alloc_tmem;
+	}
+
 	err = uverbs_get_const(&res_type, attrs, BNXT_RE_TOGGLE_MEM_TYPE);
 	if (err)
 		return err;
-
-	uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
 	err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
 	if (err)
 		return err;
 
 	/*
+	 * Legacy path: old libbnxt_re sends TYPE + RES_ID.
 	 * Hold xa_lock across xa_load + kref_get so that a concurrent
 	 * bnxt_re_destroy_cq/srq cannot call __xa_erase and remove the
 	 * toggle_entry between our load and our reference on it.
@@ -297,6 +333,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
 	if (!mmap_offset)
 		return -EOPNOTSUPP;
 
+alloc_tmem:
 	tmem = kzalloc_obj(*tmem);
 	if (!tmem) {
 		rdma_user_mmap_entry_put(&toggle_entry->rdma_entry);
@@ -343,10 +380,10 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
 					    UA_MANDATORY),
 			    UVERBS_ATTR_CONST_IN(BNXT_RE_TOGGLE_MEM_TYPE,
 						 enum bnxt_re_get_toggle_mem_type,
-						 UA_MANDATORY),
+						 UA_OPTIONAL),
 			    UVERBS_ATTR_PTR_IN(BNXT_RE_TOGGLE_MEM_RES_ID,
 					       UVERBS_ATTR_TYPE(u32),
-					       UA_MANDATORY),
+					       UA_OPTIONAL),
 			    UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
 						UVERBS_ATTR_TYPE(u64),
 						UA_MANDATORY),
@@ -355,7 +392,15 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
 						UA_MANDATORY),
 			    UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
 						UVERBS_ATTR_TYPE(u32),
-						UA_MANDATORY));
+						UA_MANDATORY),
+			    UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
+					    UVERBS_OBJECT_CQ,
+					    UVERBS_ACCESS_READ,
+					    UA_OPTIONAL),
+			    UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
+					    UVERBS_OBJECT_SRQ,
+					    UVERBS_ACCESS_READ,
+					    UA_OPTIONAL));
 
 DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM,
 				    UVERBS_ATTR_IDR(BNXT_RE_RELEASE_TOGGLE_MEM_HANDLE,
diff --git a/include/uapi/rdma/bnxt_re-abi.h b/include/uapi/rdma/bnxt_re-abi.h
index a4599d7b736a..c0ee9ce389ac 100644
--- a/include/uapi/rdma/bnxt_re-abi.h
+++ b/include/uapi/rdma/bnxt_re-abi.h
@@ -57,6 +57,8 @@ enum {
 	BNXT_RE_UCNTX_CMASK_POW2_DISABLED = 0x10ULL,
 	BNXT_RE_UCNTX_CMASK_MSN_TABLE_ENABLED = 0x40,
 	BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED = 0x80ULL,
+	 /* Some reserved fields to manage compatibility with Out of tree drivers */
+	BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT = 0x400000ULL,
 };
 
 enum bnxt_re_wqe_mode {
@@ -218,6 +220,8 @@ enum bnxt_re_var_toggle_mem_attrs {
 	BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
 	BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
 	BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
+	BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
+	BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
 };
 
 enum bnxt_re_toggle_mem_attrs {
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH for-next v4 4/4] RDMA/bnxt_re: Clear VM_MAYWRITE on DBR/toggle page mmap
  2026-07-21 11:54 [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Selvin Xavier
                   ` (2 preceding siblings ...)
  2026-07-21 11:54 ` [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page Selvin Xavier
@ 2026-07-21 11:54 ` Selvin Xavier
  2026-07-22 16:20 ` (subset) [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Leon Romanovsky
  2026-07-27  9:52 ` Leon Romanovsky
  5 siblings, 0 replies; 11+ messages in thread
From: Selvin Xavier @ 2026-07-21 11:54 UTC (permalink / raw)
  To: leon, jgg
  Cc: linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Selvin Xavier

bnxt_re_mmap() rejects VM_WRITE for the DBR_PAGE and TOGGLE_PAGE mmap
flags, but a read-only mapping can still retain VM_MAYWRITE. nd later
be upgraded with mprotect(PROT_WRITE). This can bypass the write check
that only runs at mmap time.

Clear VM_MAYWRITE before vm_insert_page() in the shared DBR/toggle-page
branch, matching the existing policy that userspace writes are not
expected for these pages.

Suggested-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
---
 drivers/infiniband/hw/bnxt_re/ib_verbs.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index a14b17d4261f..883c0674b90c 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -5063,11 +5063,13 @@ int bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma)
 	case BNXT_RE_MMAP_DBR_PAGE:
 	case BNXT_RE_MMAP_TOGGLE_PAGE:
 		/* Driver doesn't expect write access for user space */
-		if (vma->vm_flags & VM_WRITE)
+		if (vma->vm_flags & VM_WRITE) {
 			ret = -EFAULT;
-		else
+		} else {
+			vm_flags_clear(vma, VM_MAYWRITE);
 			ret = vm_insert_page(vma, vma->vm_start,
 					     virt_to_page((void *)bnxt_entry->mem_offset));
+		}
 		break;
 	default:
 		ret = -EINVAL;
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: (subset) [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ
  2026-07-21 11:54 [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Selvin Xavier
                   ` (3 preceding siblings ...)
  2026-07-21 11:54 ` [PATCH for-next v4 4/4] RDMA/bnxt_re: Clear VM_MAYWRITE on DBR/toggle page mmap Selvin Xavier
@ 2026-07-22 16:20 ` Leon Romanovsky
  2026-07-27  9:52 ` Leon Romanovsky
  5 siblings, 0 replies; 11+ messages in thread
From: Leon Romanovsky @ 2026-07-22 16:20 UTC (permalink / raw)
  To: leon, jgg, Selvin Xavier
  Cc: linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef


On Tue, 21 Jul 2026 04:54:36 -0700, Selvin Xavier wrote:
> Based on the suggestion from Jason (
> https://patchwork.kernel.org/project/linux-rdma/patch/20260615224751.232802-5-selvin.xavier@broadcom.com/)
> , adding the uverb object to retrieve the CQ an SRQ structures while getting the
> toggle mem. To work with older rdma-core, retain the existing code with
> modification.
> The rdma-core pull request is here: https://github.com/linux-rdma/rdma-core/pull/1761
> Please review and apply the series.
> Thanks,
> Selvin Xavier
> 
> [...]

Applied, thanks!

[4/4] RDMA/bnxt_re: Clear VM_MAYWRITE on DBR/toggle page mmap
      https://git.kernel.org/rdma/rdma/c/85fddc66959716

Best regards,
-- 
Leon Romanovsky <leonro@nvidia.com>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page
  2026-07-21 11:54 ` [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page Selvin Xavier
@ 2026-07-27  6:21   ` Leon Romanovsky
  2026-07-27  6:56     ` Selvin Xavier
  0 siblings, 1 reply; 11+ messages in thread
From: Leon Romanovsky @ 2026-07-27  6:21 UTC (permalink / raw)
  To: Selvin Xavier
  Cc: jgg, linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Jason Gunthorpe

On Tue, Jul 21, 2026 at 04:54:39AM -0700, Selvin Xavier wrote:
> The current GET_TOGGLE_MEM ioctl requires the caller to supply
> a type enum and a raw hardware queue ID (RES_ID). The kernel
> looks up the CQ or SRQ by that ID without verifying that the
> caller owns the resource.
> 
> Add a new, preferred code path that accepts standard uverbs
> object handles (BNXT_RE_TOGGLE_MEM_CQ_HANDLE /
> BNXT_RE_TOGGLE_MEM_SRQ_HANDLE) instead. The uverbs core validates
> that the handle belongs to the calling context as part of resolving
> it, so this path no longer needs the driver's own XArray lookup for
> ownership checking. As with the legacy path, the toggle_entry's own
> mmap-entry refcount (not a CQ/SRQ uobject reference) is what pins
> the toggle page for the life of the GET_TOGGLE_MEM handle.
> 
> Only newer rdma-core versions support this path, if the
> driver reports the supported resp mask
> (BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT).
> The existing TYPE + RES_ID path is retained for backward
> compatibility with older rdma-core.
> 
> Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
> ---
>  drivers/infiniband/hw/bnxt_re/ib_verbs.c |  2 +
>  drivers/infiniband/hw/bnxt_re/uapi.c     | 55 +++++++++++++++++++++---
>  include/uapi/rdma/bnxt_re-abi.h          |  4 ++
>  3 files changed, 56 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> index 0ff862ca982c..a14b17d4261f 100644
> --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> @@ -4872,6 +4872,8 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
>  	if (_is_modify_qp_rate_limit_supported(dev_attr->dev_cap_flags2))
>  		resp.comp_mask |= BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED;
>  
> +	resp.comp_mask |= BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT;
> +
>  	if (udata->inlen) {
>  		rc = ib_copy_validate_udata_in_cm(
>  			udata, ureq, comp_mask,
> diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
> index 97bc0e755511..feaf98631fc5 100644
> --- a/drivers/infiniband/hw/bnxt_re/uapi.c
> +++ b/drivers/infiniband/hw/bnxt_re/uapi.c
> @@ -237,16 +237,52 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
>  	if (IS_ERR(ib_uctx))
>  		return PTR_ERR(ib_uctx);
>  
> +	uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
> +
> +	/* New path: updated libbnxt_re passes the CQ or SRQ uverbs handle */
> +	if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_CQ_HANDLE)) {
> +		struct bnxt_re_cq *cq;
> +
> +		res_uobj = uverbs_attr_get_uobject(attrs,
> +						   BNXT_RE_TOGGLE_MEM_CQ_HANDLE);
> +		if (IS_ERR(res_uobj))
> +			return PTR_ERR(res_uobj);
> +		cq = container_of(res_uobj->object, struct bnxt_re_cq, ib_cq);
> +		if (!cq->toggle_entry)
> +			return -EOPNOTSUPP;
> +		mmap_offset = rdma_user_mmap_get_offset(&cq->toggle_entry->rdma_entry);
> +		if (!mmap_offset)
> +			return -EOPNOTSUPP;
> +		kref_get(&cq->toggle_entry->rdma_entry.ref);
> +		toggle_entry = cq->toggle_entry;
> +		goto alloc_tmem;
> +	} else if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_SRQ_HANDLE)) {
> +		struct bnxt_re_srq *srq;
> +
> +		res_uobj = uverbs_attr_get_uobject(attrs,
> +						   BNXT_RE_TOGGLE_MEM_SRQ_HANDLE);
> +		if (IS_ERR(res_uobj))
> +			return PTR_ERR(res_uobj);
> +		srq = container_of(res_uobj->object, struct bnxt_re_srq, ib_srq);
> +		if (!srq->toggle_entry)
> +			return -EOPNOTSUPP;
> +		mmap_offset = rdma_user_mmap_get_offset(&srq->toggle_entry->rdma_entry);
> +		if (!mmap_offset)
> +			return -EOPNOTSUPP;
> +		kref_get(&srq->toggle_entry->rdma_entry.ref);
> +		toggle_entry = srq->toggle_entry;
> +		goto alloc_tmem;
> +	}
> +
>  	err = uverbs_get_const(&res_type, attrs, BNXT_RE_TOGGLE_MEM_TYPE);
>  	if (err)
>  		return err;
> -
> -	uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
>  	err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
>  	if (err)
>  		return err;
>  
>  	/*
> +	 * Legacy path: old libbnxt_re sends TYPE + RES_ID.
>  	 * Hold xa_lock across xa_load + kref_get so that a concurrent
>  	 * bnxt_re_destroy_cq/srq cannot call __xa_erase and remove the
>  	 * toggle_entry between our load and our reference on it.
> @@ -297,6 +333,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
>  	if (!mmap_offset)
>  		return -EOPNOTSUPP;
>  
> +alloc_tmem:
>  	tmem = kzalloc_obj(*tmem);
>  	if (!tmem) {
>  		rdma_user_mmap_entry_put(&toggle_entry->rdma_entry);
> @@ -343,10 +380,10 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
>  					    UA_MANDATORY),
>  			    UVERBS_ATTR_CONST_IN(BNXT_RE_TOGGLE_MEM_TYPE,
>  						 enum bnxt_re_get_toggle_mem_type,
> -						 UA_MANDATORY),
> +						 UA_OPTIONAL),
>  			    UVERBS_ATTR_PTR_IN(BNXT_RE_TOGGLE_MEM_RES_ID,
>  					       UVERBS_ATTR_TYPE(u32),
> -					       UA_MANDATORY),
> +					       UA_OPTIONAL),
>  			    UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
>  						UVERBS_ATTR_TYPE(u64),
>  						UA_MANDATORY),
> @@ -355,7 +392,15 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
>  						UA_MANDATORY),
>  			    UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
>  						UVERBS_ATTR_TYPE(u32),
> -						UA_MANDATORY));
> +						UA_MANDATORY),
> +			    UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> +					    UVERBS_OBJECT_CQ,
> +					    UVERBS_ACCESS_READ,
> +					    UA_OPTIONAL),
> +			    UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
> +					    UVERBS_OBJECT_SRQ,
> +					    UVERBS_ACCESS_READ,
> +					    UA_OPTIONAL));
>  
>  DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM,
>  				    UVERBS_ATTR_IDR(BNXT_RE_RELEASE_TOGGLE_MEM_HANDLE,
> diff --git a/include/uapi/rdma/bnxt_re-abi.h b/include/uapi/rdma/bnxt_re-abi.h
> index a4599d7b736a..c0ee9ce389ac 100644
> --- a/include/uapi/rdma/bnxt_re-abi.h
> +++ b/include/uapi/rdma/bnxt_re-abi.h
> @@ -57,6 +57,8 @@ enum {
>  	BNXT_RE_UCNTX_CMASK_POW2_DISABLED = 0x10ULL,
>  	BNXT_RE_UCNTX_CMASK_MSN_TABLE_ENABLED = 0x40,
>  	BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED = 0x80ULL,
> +	 /* Some reserved fields to manage compatibility with Out of tree drivers */

Selvin,

What did you mean with this comment?

Thanks

> +	BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT = 0x400000ULL,
>  };
>  
>  enum bnxt_re_wqe_mode {
> @@ -218,6 +220,8 @@ enum bnxt_re_var_toggle_mem_attrs {
>  	BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
>  	BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
>  	BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
> +	BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> +	BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
>  };
>  
>  enum bnxt_re_toggle_mem_attrs {
> -- 
> 2.39.3
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page
  2026-07-27  6:21   ` Leon Romanovsky
@ 2026-07-27  6:56     ` Selvin Xavier
  2026-07-27  9:07       ` Leon Romanovsky
  0 siblings, 1 reply; 11+ messages in thread
From: Selvin Xavier @ 2026-07-27  6:56 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: jgg, linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Jason Gunthorpe

[-- Attachment #1: Type: text/plain, Size: 9316 bytes --]

On Mon, Jul 27, 2026 at 11:51 AM Leon Romanovsky <leon@kernel.org> wrote:
>
> On Tue, Jul 21, 2026 at 04:54:39AM -0700, Selvin Xavier wrote:
> > The current GET_TOGGLE_MEM ioctl requires the caller to supply
> > a type enum and a raw hardware queue ID (RES_ID). The kernel
> > looks up the CQ or SRQ by that ID without verifying that the
> > caller owns the resource.
> >
> > Add a new, preferred code path that accepts standard uverbs
> > object handles (BNXT_RE_TOGGLE_MEM_CQ_HANDLE /
> > BNXT_RE_TOGGLE_MEM_SRQ_HANDLE) instead. The uverbs core validates
> > that the handle belongs to the calling context as part of resolving
> > it, so this path no longer needs the driver's own XArray lookup for
> > ownership checking. As with the legacy path, the toggle_entry's own
> > mmap-entry refcount (not a CQ/SRQ uobject reference) is what pins
> > the toggle page for the life of the GET_TOGGLE_MEM handle.
> >
> > Only newer rdma-core versions support this path, if the
> > driver reports the supported resp mask
> > (BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT).
> > The existing TYPE + RES_ID path is retained for backward
> > compatibility with older rdma-core.
> >
> > Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> > Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
> > ---
> >  drivers/infiniband/hw/bnxt_re/ib_verbs.c |  2 +
> >  drivers/infiniband/hw/bnxt_re/uapi.c     | 55 +++++++++++++++++++++---
> >  include/uapi/rdma/bnxt_re-abi.h          |  4 ++
> >  3 files changed, 56 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > index 0ff862ca982c..a14b17d4261f 100644
> > --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > @@ -4872,6 +4872,8 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
> >       if (_is_modify_qp_rate_limit_supported(dev_attr->dev_cap_flags2))
> >               resp.comp_mask |= BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED;
> >
> > +     resp.comp_mask |= BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT;
> > +
> >       if (udata->inlen) {
> >               rc = ib_copy_validate_udata_in_cm(
> >                       udata, ureq, comp_mask,
> > diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
> > index 97bc0e755511..feaf98631fc5 100644
> > --- a/drivers/infiniband/hw/bnxt_re/uapi.c
> > +++ b/drivers/infiniband/hw/bnxt_re/uapi.c
> > @@ -237,16 +237,52 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
> >       if (IS_ERR(ib_uctx))
> >               return PTR_ERR(ib_uctx);
> >
> > +     uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
> > +
> > +     /* New path: updated libbnxt_re passes the CQ or SRQ uverbs handle */
> > +     if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_CQ_HANDLE)) {
> > +             struct bnxt_re_cq *cq;
> > +
> > +             res_uobj = uverbs_attr_get_uobject(attrs,
> > +                                                BNXT_RE_TOGGLE_MEM_CQ_HANDLE);
> > +             if (IS_ERR(res_uobj))
> > +                     return PTR_ERR(res_uobj);
> > +             cq = container_of(res_uobj->object, struct bnxt_re_cq, ib_cq);
> > +             if (!cq->toggle_entry)
> > +                     return -EOPNOTSUPP;
> > +             mmap_offset = rdma_user_mmap_get_offset(&cq->toggle_entry->rdma_entry);
> > +             if (!mmap_offset)
> > +                     return -EOPNOTSUPP;
> > +             kref_get(&cq->toggle_entry->rdma_entry.ref);
> > +             toggle_entry = cq->toggle_entry;
> > +             goto alloc_tmem;
> > +     } else if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_SRQ_HANDLE)) {
> > +             struct bnxt_re_srq *srq;
> > +
> > +             res_uobj = uverbs_attr_get_uobject(attrs,
> > +                                                BNXT_RE_TOGGLE_MEM_SRQ_HANDLE);
> > +             if (IS_ERR(res_uobj))
> > +                     return PTR_ERR(res_uobj);
> > +             srq = container_of(res_uobj->object, struct bnxt_re_srq, ib_srq);
> > +             if (!srq->toggle_entry)
> > +                     return -EOPNOTSUPP;
> > +             mmap_offset = rdma_user_mmap_get_offset(&srq->toggle_entry->rdma_entry);
> > +             if (!mmap_offset)
> > +                     return -EOPNOTSUPP;
> > +             kref_get(&srq->toggle_entry->rdma_entry.ref);
> > +             toggle_entry = srq->toggle_entry;
> > +             goto alloc_tmem;
> > +     }
> > +
> >       err = uverbs_get_const(&res_type, attrs, BNXT_RE_TOGGLE_MEM_TYPE);
> >       if (err)
> >               return err;
> > -
> > -     uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
> >       err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
> >       if (err)
> >               return err;
> >
> >       /*
> > +      * Legacy path: old libbnxt_re sends TYPE + RES_ID.
> >        * Hold xa_lock across xa_load + kref_get so that a concurrent
> >        * bnxt_re_destroy_cq/srq cannot call __xa_erase and remove the
> >        * toggle_entry between our load and our reference on it.
> > @@ -297,6 +333,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
> >       if (!mmap_offset)
> >               return -EOPNOTSUPP;
> >
> > +alloc_tmem:
> >       tmem = kzalloc_obj(*tmem);
> >       if (!tmem) {
> >               rdma_user_mmap_entry_put(&toggle_entry->rdma_entry);
> > @@ -343,10 +380,10 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
> >                                           UA_MANDATORY),
> >                           UVERBS_ATTR_CONST_IN(BNXT_RE_TOGGLE_MEM_TYPE,
> >                                                enum bnxt_re_get_toggle_mem_type,
> > -                                              UA_MANDATORY),
> > +                                              UA_OPTIONAL),
> >                           UVERBS_ATTR_PTR_IN(BNXT_RE_TOGGLE_MEM_RES_ID,
> >                                              UVERBS_ATTR_TYPE(u32),
> > -                                            UA_MANDATORY),
> > +                                            UA_OPTIONAL),
> >                           UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
> >                                               UVERBS_ATTR_TYPE(u64),
> >                                               UA_MANDATORY),
> > @@ -355,7 +392,15 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
> >                                               UA_MANDATORY),
> >                           UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
> >                                               UVERBS_ATTR_TYPE(u32),
> > -                                             UA_MANDATORY));
> > +                                             UA_MANDATORY),
> > +                         UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> > +                                         UVERBS_OBJECT_CQ,
> > +                                         UVERBS_ACCESS_READ,
> > +                                         UA_OPTIONAL),
> > +                         UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
> > +                                         UVERBS_OBJECT_SRQ,
> > +                                         UVERBS_ACCESS_READ,
> > +                                         UA_OPTIONAL));
> >
> >  DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM,
> >                                   UVERBS_ATTR_IDR(BNXT_RE_RELEASE_TOGGLE_MEM_HANDLE,
> > diff --git a/include/uapi/rdma/bnxt_re-abi.h b/include/uapi/rdma/bnxt_re-abi.h
> > index a4599d7b736a..c0ee9ce389ac 100644
> > --- a/include/uapi/rdma/bnxt_re-abi.h
> > +++ b/include/uapi/rdma/bnxt_re-abi.h
> > @@ -57,6 +57,8 @@ enum {
> >       BNXT_RE_UCNTX_CMASK_POW2_DISABLED = 0x10ULL,
> >       BNXT_RE_UCNTX_CMASK_MSN_TABLE_ENABLED = 0x40,
> >       BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED = 0x80ULL,
> > +      /* Some reserved fields to manage compatibility with Out of tree drivers */
>
> Selvin,
>
> What did you mean with this comment?
This CMASK tracks the feature compatibility. Broadcom distributes an
out-of-tree driver
with some of the features that are not available in the upstream
driver. Some of these
features are debug only or features applicable for the next revision
of the chip (which is not
supported yet in the upstream driver). Since we want our inbox
libraries to work with
the out-of-tree drivers (and vice versa),  we are maintaining ABI
compatibility and I will
have to keep reserved/holes in the feature definition of this
compatibility mask.

Thanks
>
> Thanks
>
> > +     BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT = 0x400000ULL,
> >  };
> >
> >  enum bnxt_re_wqe_mode {
> > @@ -218,6 +220,8 @@ enum bnxt_re_var_toggle_mem_attrs {
> >       BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
> >       BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
> >       BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
> > +     BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> > +     BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
> >  };
> >
> >  enum bnxt_re_toggle_mem_attrs {
> > --
> > 2.39.3
> >

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5473 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page
  2026-07-27  6:56     ` Selvin Xavier
@ 2026-07-27  9:07       ` Leon Romanovsky
  2026-07-27  9:09         ` Selvin Xavier
  0 siblings, 1 reply; 11+ messages in thread
From: Leon Romanovsky @ 2026-07-27  9:07 UTC (permalink / raw)
  To: Selvin Xavier
  Cc: jgg, linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Jason Gunthorpe

On Mon, Jul 27, 2026 at 12:26:46PM +0530, Selvin Xavier wrote:
> On Mon, Jul 27, 2026 at 11:51 AM Leon Romanovsky <leon@kernel.org> wrote:
> >
> > On Tue, Jul 21, 2026 at 04:54:39AM -0700, Selvin Xavier wrote:
> > > The current GET_TOGGLE_MEM ioctl requires the caller to supply
> > > a type enum and a raw hardware queue ID (RES_ID). The kernel
> > > looks up the CQ or SRQ by that ID without verifying that the
> > > caller owns the resource.
> > >
> > > Add a new, preferred code path that accepts standard uverbs
> > > object handles (BNXT_RE_TOGGLE_MEM_CQ_HANDLE /
> > > BNXT_RE_TOGGLE_MEM_SRQ_HANDLE) instead. The uverbs core validates
> > > that the handle belongs to the calling context as part of resolving
> > > it, so this path no longer needs the driver's own XArray lookup for
> > > ownership checking. As with the legacy path, the toggle_entry's own
> > > mmap-entry refcount (not a CQ/SRQ uobject reference) is what pins
> > > the toggle page for the life of the GET_TOGGLE_MEM handle.
> > >
> > > Only newer rdma-core versions support this path, if the
> > > driver reports the supported resp mask
> > > (BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT).
> > > The existing TYPE + RES_ID path is retained for backward
> > > compatibility with older rdma-core.
> > >
> > > Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> > > Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
> > > ---
> > >  drivers/infiniband/hw/bnxt_re/ib_verbs.c |  2 +
> > >  drivers/infiniband/hw/bnxt_re/uapi.c     | 55 +++++++++++++++++++++---
> > >  include/uapi/rdma/bnxt_re-abi.h          |  4 ++
> > >  3 files changed, 56 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > > index 0ff862ca982c..a14b17d4261f 100644
> > > --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > > +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > > @@ -4872,6 +4872,8 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
> > >       if (_is_modify_qp_rate_limit_supported(dev_attr->dev_cap_flags2))
> > >               resp.comp_mask |= BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED;
> > >
> > > +     resp.comp_mask |= BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT;
> > > +
> > >       if (udata->inlen) {
> > >               rc = ib_copy_validate_udata_in_cm(
> > >                       udata, ureq, comp_mask,
> > > diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
> > > index 97bc0e755511..feaf98631fc5 100644
> > > --- a/drivers/infiniband/hw/bnxt_re/uapi.c
> > > +++ b/drivers/infiniband/hw/bnxt_re/uapi.c
> > > @@ -237,16 +237,52 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
> > >       if (IS_ERR(ib_uctx))
> > >               return PTR_ERR(ib_uctx);
> > >
> > > +     uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
> > > +
> > > +     /* New path: updated libbnxt_re passes the CQ or SRQ uverbs handle */
> > > +     if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_CQ_HANDLE)) {
> > > +             struct bnxt_re_cq *cq;
> > > +
> > > +             res_uobj = uverbs_attr_get_uobject(attrs,
> > > +                                                BNXT_RE_TOGGLE_MEM_CQ_HANDLE);
> > > +             if (IS_ERR(res_uobj))
> > > +                     return PTR_ERR(res_uobj);
> > > +             cq = container_of(res_uobj->object, struct bnxt_re_cq, ib_cq);
> > > +             if (!cq->toggle_entry)
> > > +                     return -EOPNOTSUPP;
> > > +             mmap_offset = rdma_user_mmap_get_offset(&cq->toggle_entry->rdma_entry);
> > > +             if (!mmap_offset)
> > > +                     return -EOPNOTSUPP;
> > > +             kref_get(&cq->toggle_entry->rdma_entry.ref);
> > > +             toggle_entry = cq->toggle_entry;
> > > +             goto alloc_tmem;
> > > +     } else if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_SRQ_HANDLE)) {
> > > +             struct bnxt_re_srq *srq;
> > > +
> > > +             res_uobj = uverbs_attr_get_uobject(attrs,
> > > +                                                BNXT_RE_TOGGLE_MEM_SRQ_HANDLE);
> > > +             if (IS_ERR(res_uobj))
> > > +                     return PTR_ERR(res_uobj);
> > > +             srq = container_of(res_uobj->object, struct bnxt_re_srq, ib_srq);
> > > +             if (!srq->toggle_entry)
> > > +                     return -EOPNOTSUPP;
> > > +             mmap_offset = rdma_user_mmap_get_offset(&srq->toggle_entry->rdma_entry);
> > > +             if (!mmap_offset)
> > > +                     return -EOPNOTSUPP;
> > > +             kref_get(&srq->toggle_entry->rdma_entry.ref);
> > > +             toggle_entry = srq->toggle_entry;
> > > +             goto alloc_tmem;
> > > +     }
> > > +
> > >       err = uverbs_get_const(&res_type, attrs, BNXT_RE_TOGGLE_MEM_TYPE);
> > >       if (err)
> > >               return err;
> > > -
> > > -     uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
> > >       err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
> > >       if (err)
> > >               return err;
> > >
> > >       /*
> > > +      * Legacy path: old libbnxt_re sends TYPE + RES_ID.
> > >        * Hold xa_lock across xa_load + kref_get so that a concurrent
> > >        * bnxt_re_destroy_cq/srq cannot call __xa_erase and remove the
> > >        * toggle_entry between our load and our reference on it.
> > > @@ -297,6 +333,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
> > >       if (!mmap_offset)
> > >               return -EOPNOTSUPP;
> > >
> > > +alloc_tmem:
> > >       tmem = kzalloc_obj(*tmem);
> > >       if (!tmem) {
> > >               rdma_user_mmap_entry_put(&toggle_entry->rdma_entry);
> > > @@ -343,10 +380,10 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
> > >                                           UA_MANDATORY),
> > >                           UVERBS_ATTR_CONST_IN(BNXT_RE_TOGGLE_MEM_TYPE,
> > >                                                enum bnxt_re_get_toggle_mem_type,
> > > -                                              UA_MANDATORY),
> > > +                                              UA_OPTIONAL),
> > >                           UVERBS_ATTR_PTR_IN(BNXT_RE_TOGGLE_MEM_RES_ID,
> > >                                              UVERBS_ATTR_TYPE(u32),
> > > -                                            UA_MANDATORY),
> > > +                                            UA_OPTIONAL),
> > >                           UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
> > >                                               UVERBS_ATTR_TYPE(u64),
> > >                                               UA_MANDATORY),
> > > @@ -355,7 +392,15 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
> > >                                               UA_MANDATORY),
> > >                           UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
> > >                                               UVERBS_ATTR_TYPE(u32),
> > > -                                             UA_MANDATORY));
> > > +                                             UA_MANDATORY),
> > > +                         UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> > > +                                         UVERBS_OBJECT_CQ,
> > > +                                         UVERBS_ACCESS_READ,
> > > +                                         UA_OPTIONAL),
> > > +                         UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
> > > +                                         UVERBS_OBJECT_SRQ,
> > > +                                         UVERBS_ACCESS_READ,
> > > +                                         UA_OPTIONAL));
> > >
> > >  DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM,
> > >                                   UVERBS_ATTR_IDR(BNXT_RE_RELEASE_TOGGLE_MEM_HANDLE,
> > > diff --git a/include/uapi/rdma/bnxt_re-abi.h b/include/uapi/rdma/bnxt_re-abi.h
> > > index a4599d7b736a..c0ee9ce389ac 100644
> > > --- a/include/uapi/rdma/bnxt_re-abi.h
> > > +++ b/include/uapi/rdma/bnxt_re-abi.h
> > > @@ -57,6 +57,8 @@ enum {
> > >       BNXT_RE_UCNTX_CMASK_POW2_DISABLED = 0x10ULL,
> > >       BNXT_RE_UCNTX_CMASK_MSN_TABLE_ENABLED = 0x40,
> > >       BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED = 0x80ULL,
> > > +      /* Some reserved fields to manage compatibility with Out of tree drivers */
> >
> > Selvin,
> >
> > What did you mean with this comment?
> This CMASK tracks the feature compatibility. Broadcom distributes an
> out-of-tree driver
> with some of the features that are not available in the upstream
> driver. Some of these
> features are debug only or features applicable for the next revision
> of the chip (which is not
> supported yet in the upstream driver). Since we want our inbox
> libraries to work with
> the out-of-tree drivers (and vice versa),  we are maintaining ABI
> compatibility and I will
> have to keep reserved/holes in the feature definition of this
> compatibility mask.

There are still plenty of numbers available, and the numbering is
entirely up to you. We do not want any association with OOT code.
Once you run out of available numbers, we will ask you to use those
reserved in the hole.

I will remove this line when applying the patch. Is that OK?

Thanks

> 
> Thanks
> >
> > Thanks
> >
> > > +     BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT = 0x400000ULL,
> > >  };
> > >
> > >  enum bnxt_re_wqe_mode {
> > > @@ -218,6 +220,8 @@ enum bnxt_re_var_toggle_mem_attrs {
> > >       BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
> > >       BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
> > >       BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
> > > +     BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> > > +     BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
> > >  };
> > >
> > >  enum bnxt_re_toggle_mem_attrs {
> > > --
> > > 2.39.3
> > >



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page
  2026-07-27  9:07       ` Leon Romanovsky
@ 2026-07-27  9:09         ` Selvin Xavier
  0 siblings, 0 replies; 11+ messages in thread
From: Selvin Xavier @ 2026-07-27  9:09 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: jgg, linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef, Jason Gunthorpe

[-- Attachment #1: Type: text/plain, Size: 10575 bytes --]

On Mon, Jul 27, 2026 at 2:37 PM Leon Romanovsky <leon@kernel.org> wrote:
>
> On Mon, Jul 27, 2026 at 12:26:46PM +0530, Selvin Xavier wrote:
> > On Mon, Jul 27, 2026 at 11:51 AM Leon Romanovsky <leon@kernel.org> wrote:
> > >
> > > On Tue, Jul 21, 2026 at 04:54:39AM -0700, Selvin Xavier wrote:
> > > > The current GET_TOGGLE_MEM ioctl requires the caller to supply
> > > > a type enum and a raw hardware queue ID (RES_ID). The kernel
> > > > looks up the CQ or SRQ by that ID without verifying that the
> > > > caller owns the resource.
> > > >
> > > > Add a new, preferred code path that accepts standard uverbs
> > > > object handles (BNXT_RE_TOGGLE_MEM_CQ_HANDLE /
> > > > BNXT_RE_TOGGLE_MEM_SRQ_HANDLE) instead. The uverbs core validates
> > > > that the handle belongs to the calling context as part of resolving
> > > > it, so this path no longer needs the driver's own XArray lookup for
> > > > ownership checking. As with the legacy path, the toggle_entry's own
> > > > mmap-entry refcount (not a CQ/SRQ uobject reference) is what pins
> > > > the toggle page for the life of the GET_TOGGLE_MEM handle.
> > > >
> > > > Only newer rdma-core versions support this path, if the
> > > > driver reports the supported resp mask
> > > > (BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT).
> > > > The existing TYPE + RES_ID path is retained for backward
> > > > compatibility with older rdma-core.
> > > >
> > > > Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> > > > Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
> > > > ---
> > > >  drivers/infiniband/hw/bnxt_re/ib_verbs.c |  2 +
> > > >  drivers/infiniband/hw/bnxt_re/uapi.c     | 55 +++++++++++++++++++++---
> > > >  include/uapi/rdma/bnxt_re-abi.h          |  4 ++
> > > >  3 files changed, 56 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > > > index 0ff862ca982c..a14b17d4261f 100644
> > > > --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > > > +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> > > > @@ -4872,6 +4872,8 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
> > > >       if (_is_modify_qp_rate_limit_supported(dev_attr->dev_cap_flags2))
> > > >               resp.comp_mask |= BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED;
> > > >
> > > > +     resp.comp_mask |= BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT;
> > > > +
> > > >       if (udata->inlen) {
> > > >               rc = ib_copy_validate_udata_in_cm(
> > > >                       udata, ureq, comp_mask,
> > > > diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
> > > > index 97bc0e755511..feaf98631fc5 100644
> > > > --- a/drivers/infiniband/hw/bnxt_re/uapi.c
> > > > +++ b/drivers/infiniband/hw/bnxt_re/uapi.c
> > > > @@ -237,16 +237,52 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
> > > >       if (IS_ERR(ib_uctx))
> > > >               return PTR_ERR(ib_uctx);
> > > >
> > > > +     uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
> > > > +
> > > > +     /* New path: updated libbnxt_re passes the CQ or SRQ uverbs handle */
> > > > +     if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_CQ_HANDLE)) {
> > > > +             struct bnxt_re_cq *cq;
> > > > +
> > > > +             res_uobj = uverbs_attr_get_uobject(attrs,
> > > > +                                                BNXT_RE_TOGGLE_MEM_CQ_HANDLE);
> > > > +             if (IS_ERR(res_uobj))
> > > > +                     return PTR_ERR(res_uobj);
> > > > +             cq = container_of(res_uobj->object, struct bnxt_re_cq, ib_cq);
> > > > +             if (!cq->toggle_entry)
> > > > +                     return -EOPNOTSUPP;
> > > > +             mmap_offset = rdma_user_mmap_get_offset(&cq->toggle_entry->rdma_entry);
> > > > +             if (!mmap_offset)
> > > > +                     return -EOPNOTSUPP;
> > > > +             kref_get(&cq->toggle_entry->rdma_entry.ref);
> > > > +             toggle_entry = cq->toggle_entry;
> > > > +             goto alloc_tmem;
> > > > +     } else if (uverbs_attr_is_valid(attrs, BNXT_RE_TOGGLE_MEM_SRQ_HANDLE)) {
> > > > +             struct bnxt_re_srq *srq;
> > > > +
> > > > +             res_uobj = uverbs_attr_get_uobject(attrs,
> > > > +                                                BNXT_RE_TOGGLE_MEM_SRQ_HANDLE);
> > > > +             if (IS_ERR(res_uobj))
> > > > +                     return PTR_ERR(res_uobj);
> > > > +             srq = container_of(res_uobj->object, struct bnxt_re_srq, ib_srq);
> > > > +             if (!srq->toggle_entry)
> > > > +                     return -EOPNOTSUPP;
> > > > +             mmap_offset = rdma_user_mmap_get_offset(&srq->toggle_entry->rdma_entry);
> > > > +             if (!mmap_offset)
> > > > +                     return -EOPNOTSUPP;
> > > > +             kref_get(&srq->toggle_entry->rdma_entry.ref);
> > > > +             toggle_entry = srq->toggle_entry;
> > > > +             goto alloc_tmem;
> > > > +     }
> > > > +
> > > >       err = uverbs_get_const(&res_type, attrs, BNXT_RE_TOGGLE_MEM_TYPE);
> > > >       if (err)
> > > >               return err;
> > > > -
> > > > -     uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
> > > >       err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
> > > >       if (err)
> > > >               return err;
> > > >
> > > >       /*
> > > > +      * Legacy path: old libbnxt_re sends TYPE + RES_ID.
> > > >        * Hold xa_lock across xa_load + kref_get so that a concurrent
> > > >        * bnxt_re_destroy_cq/srq cannot call __xa_erase and remove the
> > > >        * toggle_entry between our load and our reference on it.
> > > > @@ -297,6 +333,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
> > > >       if (!mmap_offset)
> > > >               return -EOPNOTSUPP;
> > > >
> > > > +alloc_tmem:
> > > >       tmem = kzalloc_obj(*tmem);
> > > >       if (!tmem) {
> > > >               rdma_user_mmap_entry_put(&toggle_entry->rdma_entry);
> > > > @@ -343,10 +380,10 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
> > > >                                           UA_MANDATORY),
> > > >                           UVERBS_ATTR_CONST_IN(BNXT_RE_TOGGLE_MEM_TYPE,
> > > >                                                enum bnxt_re_get_toggle_mem_type,
> > > > -                                              UA_MANDATORY),
> > > > +                                              UA_OPTIONAL),
> > > >                           UVERBS_ATTR_PTR_IN(BNXT_RE_TOGGLE_MEM_RES_ID,
> > > >                                              UVERBS_ATTR_TYPE(u32),
> > > > -                                            UA_MANDATORY),
> > > > +                                            UA_OPTIONAL),
> > > >                           UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
> > > >                                               UVERBS_ATTR_TYPE(u64),
> > > >                                               UA_MANDATORY),
> > > > @@ -355,7 +392,15 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
> > > >                                               UA_MANDATORY),
> > > >                           UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
> > > >                                               UVERBS_ATTR_TYPE(u32),
> > > > -                                             UA_MANDATORY));
> > > > +                                             UA_MANDATORY),
> > > > +                         UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> > > > +                                         UVERBS_OBJECT_CQ,
> > > > +                                         UVERBS_ACCESS_READ,
> > > > +                                         UA_OPTIONAL),
> > > > +                         UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
> > > > +                                         UVERBS_OBJECT_SRQ,
> > > > +                                         UVERBS_ACCESS_READ,
> > > > +                                         UA_OPTIONAL));
> > > >
> > > >  DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM,
> > > >                                   UVERBS_ATTR_IDR(BNXT_RE_RELEASE_TOGGLE_MEM_HANDLE,
> > > > diff --git a/include/uapi/rdma/bnxt_re-abi.h b/include/uapi/rdma/bnxt_re-abi.h
> > > > index a4599d7b736a..c0ee9ce389ac 100644
> > > > --- a/include/uapi/rdma/bnxt_re-abi.h
> > > > +++ b/include/uapi/rdma/bnxt_re-abi.h
> > > > @@ -57,6 +57,8 @@ enum {
> > > >       BNXT_RE_UCNTX_CMASK_POW2_DISABLED = 0x10ULL,
> > > >       BNXT_RE_UCNTX_CMASK_MSN_TABLE_ENABLED = 0x40,
> > > >       BNXT_RE_UCNTX_CMASK_QP_RATE_LIMIT_ENABLED = 0x80ULL,
> > > > +      /* Some reserved fields to manage compatibility with Out of tree drivers */
> > >
> > > Selvin,
> > >
> > > What did you mean with this comment?
> > This CMASK tracks the feature compatibility. Broadcom distributes an
> > out-of-tree driver
> > with some of the features that are not available in the upstream
> > driver. Some of these
> > features are debug only or features applicable for the next revision
> > of the chip (which is not
> > supported yet in the upstream driver). Since we want our inbox
> > libraries to work with
> > the out-of-tree drivers (and vice versa),  we are maintaining ABI
> > compatibility and I will
> > have to keep reserved/holes in the feature definition of this
> > compatibility mask.
>
> There are still plenty of numbers available, and the numbering is
> entirely up to you. We do not want any association with OOT code.
> Once you run out of available numbers, we will ask you to use those
> reserved in the hole.
>
> I will remove this line when applying the patch. Is that OK?
Sure. I am fine with that.

Thanks,

>
> Thanks
>
> >
> > Thanks
> > >
> > > Thanks
> > >
> > > > +     BNXT_RE_UCNTX_CMASK_TOGGLE_MEM_UOBJ_SUPPORT = 0x400000ULL,
> > > >  };
> > > >
> > > >  enum bnxt_re_wqe_mode {
> > > > @@ -218,6 +220,8 @@ enum bnxt_re_var_toggle_mem_attrs {
> > > >       BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
> > > >       BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
> > > >       BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
> > > > +     BNXT_RE_TOGGLE_MEM_CQ_HANDLE,
> > > > +     BNXT_RE_TOGGLE_MEM_SRQ_HANDLE,
> > > >  };
> > > >
> > > >  enum bnxt_re_toggle_mem_attrs {
> > > > --
> > > > 2.39.3
> > > >
>
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5473 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: (subset) [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ
  2026-07-21 11:54 [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Selvin Xavier
                   ` (4 preceding siblings ...)
  2026-07-22 16:20 ` (subset) [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Leon Romanovsky
@ 2026-07-27  9:52 ` Leon Romanovsky
  5 siblings, 0 replies; 11+ messages in thread
From: Leon Romanovsky @ 2026-07-27  9:52 UTC (permalink / raw)
  To: jgg, Selvin Xavier
  Cc: linux-rdma, andrew.gospodarek, kalesh-anakkur.purayil,
	sriharsha.basavapatna, alhouseenyousef


On Tue, 21 Jul 2026 04:54:36 -0700, Selvin Xavier wrote:
> Based on the suggestion from Jason (
> https://patchwork.kernel.org/project/linux-rdma/patch/20260615224751.232802-5-selvin.xavier@broadcom.com/)
> , adding the uverb object to retrieve the CQ an SRQ structures while getting the
> toggle mem. To work with older rdma-core, retain the existing code with
> modification.
> The rdma-core pull request is here: https://github.com/linux-rdma/rdma-core/pull/1761
> Please review and apply the series.
> Thanks,
> Selvin Xavier
> 
> [...]

Applied, thanks!

[1/4] RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays
      https://git.kernel.org/rdma/rdma/c/2b248ac9c95bf0
[2/4] RDMA/bnxt_re: Defer toggle page free to rdma_user_mmap_entry teardown
      https://git.kernel.org/rdma/rdma/c/bc12898e33f52d
[3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page
      https://git.kernel.org/rdma/rdma/c/fbdb3dcef8440a

Best regards,
-- 
Leon Romanovsky <leon@kernel.org>


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-07-27  9:52 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21 11:54 [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Selvin Xavier
2026-07-21 11:54 ` [PATCH for-next v4 1/4] RDMA/bnxt_re: Replace per-device hash tables with per-context XArrays Selvin Xavier
2026-07-21 11:54 ` [PATCH for-next v4 2/4] RDMA/bnxt_re: Defer toggle page free to rdma_user_mmap_entry teardown Selvin Xavier
2026-07-21 11:54 ` [PATCH for-next v4 3/4] RDMA/bnxt_re: Add uverbs object handle path for CQ/SRQ toggle page Selvin Xavier
2026-07-27  6:21   ` Leon Romanovsky
2026-07-27  6:56     ` Selvin Xavier
2026-07-27  9:07       ` Leon Romanovsky
2026-07-27  9:09         ` Selvin Xavier
2026-07-21 11:54 ` [PATCH for-next v4 4/4] RDMA/bnxt_re: Clear VM_MAYWRITE on DBR/toggle page mmap Selvin Xavier
2026-07-22 16:20 ` (subset) [PATCH for-next v4 0/4] RDMA/bnxt_re: Update the toggle page handling of CQ and SRQ Leon Romanovsky
2026-07-27  9:52 ` Leon Romanovsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox