From: Siva Reddy Kallam <siva.kallam@broadcom.com>
To: leonro@nvidia.com, jgg@nvidia.com, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
andrew+netdev@lunn.ch, horms@kernel.org
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-rdma@vger.kernel.org,
Suresh Rupanagudi <suresh.rupanagudi@broadcom.com>,
Siva Reddy Kallam <siva.kallam@broadcom.com>
Subject: [PATCH 09/15] RDMA/bng_re: Add MR verbs
Date: Fri, 4 Sep 2026 03:43:17 -0700 [thread overview]
Message-ID: <20260904104328.763768-10-siva.kallam@broadcom.com> (raw)
In-Reply-To: <20260904104328.763768-1-siva.kallam@broadcom.com>
From: Suresh Rupanagudi <suresh.rupanagudi@broadcom.com>
This patch adds below verbs.
- bng_re_get_dma_mr
- bng_re_alloc_mr
- bng_re_map_mr_sg
- bng_re_reg_user_mr
- bng_re_reg_user_mr_dmabuf
- bng_re_dereg_mr
Signed-off-by: Suresh Rupanagudi <suresh.rupanagudi@broadcom.com>
Signed-off-by: Siva Reddy Kallam <siva.kallam@broadcom.com>
---
drivers/infiniband/hw/bng_re/bng_dev.c | 8 +
drivers/infiniband/hw/bng_re/bng_res.h | 15 +-
drivers/infiniband/hw/bng_re/bng_sp.c | 210 ++++++++++++++
drivers/infiniband/hw/bng_re/bng_sp.h | 52 ++++
drivers/infiniband/hw/bng_re/bng_verbs.c | 333 +++++++++++++++++++++++
drivers/infiniband/hw/bng_re/bng_verbs.h | 27 ++
6 files changed, 640 insertions(+), 5 deletions(-)
diff --git a/drivers/infiniband/hw/bng_re/bng_dev.c b/drivers/infiniband/hw/bng_re/bng_dev.c
index b8a50c8cd299..44c278a93778 100644
--- a/drivers/infiniband/hw/bng_re/bng_dev.c
+++ b/drivers/infiniband/hw/bng_re/bng_dev.c
@@ -46,6 +46,12 @@ static const struct ib_device_ops bng_re_dev_ops = {
.del_gid = bng_re_del_gid,
.alloc_pd = bng_re_alloc_pd,
.dealloc_pd = bng_re_dealloc_pd,
+ .get_dma_mr = bng_re_get_dma_mr,
+ .alloc_mr = bng_re_alloc_mr,
+ .map_mr_sg = bng_re_map_mr_sg,
+ .reg_user_mr = bng_re_reg_user_mr,
+ .reg_user_mr_dmabuf = bng_re_reg_user_mr_dmabuf,
+ .dereg_mr = bng_re_dereg_mr,
INIT_RDMA_OBJ_SIZE(ib_pd, bng_re_pd, ib_pd),
INIT_RDMA_OBJ_SIZE(ib_ucontext, bng_re_ucontext, ib_uctx),
};
@@ -91,6 +97,7 @@ static void bng_re_destroy_chip_ctx(struct bng_re_dev *rdev)
chip_ctx = rdev->chip_ctx;
rdev->chip_ctx = NULL;
rdev->rcfw.res = NULL;
+ rdev->bng_res.rcfw = NULL;
rdev->bng_res.cctx = NULL;
rdev->bng_res.pdev = NULL;
kfree(chip_ctx);
@@ -117,6 +124,7 @@ static int bng_re_setup_chip_ctx(struct bng_re_dev *rdev)
aux_dev = rdev->aux_dev;
rdev->bng_res.pdev = aux_dev->pdev;
rdev->rcfw.res = &rdev->bng_res;
+ rdev->bng_res.rcfw = &rdev->rcfw;
chip_ctx = kzalloc_obj(*chip_ctx);
if (!chip_ctx)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/bng_re/bng_res.h b/drivers/infiniband/hw/bng_re/bng_res.h
index 72afe51c6bfa..cb0f302fc06a 100644
--- a/drivers/infiniband/hw/bng_re/bng_res.h
+++ b/drivers/infiniband/hw/bng_re/bng_res.h
@@ -38,6 +38,8 @@
#define RCFW_DBR_PCI_BAR_REGION 2
+#define BNG_RE_FR_PMR 0x80000000
+
struct bng_re_gid {
u8 data[16];
};
@@ -123,14 +125,16 @@ enum bng_re_pbl_lvl {
enum bng_re_hwq_type {
BNG_HWQ_TYPE_CTX,
- BNG_HWQ_TYPE_QUEUE
+ BNG_HWQ_TYPE_QUEUE,
+ BNG_HWQ_TYPE_MR
};
struct bng_re_sg_info {
- u32 npages;
- u32 pgshft;
- u32 pgsize;
- bool nopte;
+ u32 npages;
+ u32 pgshft;
+ u32 pgsize;
+ bool nopte;
+ struct ib_umem *umem;
};
struct bng_re_hwq_attr {
@@ -216,6 +220,7 @@ struct bng_re_res {
struct bng_re_pd_tbl pd_tbl;
/* Serialize access to PD table */
struct mutex pd_tbl_lock;
+ struct bng_re_rcfw *rcfw;
};
#define to_bng_re_res(ptr, member) container_of(ptr, struct bng_re_res, member)
diff --git a/drivers/infiniband/hw/bng_re/bng_sp.c b/drivers/infiniband/hw/bng_re/bng_sp.c
index 97768a25c0e4..cd33ff32845a 100644
--- a/drivers/infiniband/hw/bng_re/bng_sp.c
+++ b/drivers/infiniband/hw/bng_re/bng_sp.c
@@ -371,3 +371,213 @@ int bng_sp_dealloc_pd(struct bng_re_res *res,
mutex_unlock(&res->pd_tbl_lock);
return 0;
}
+
+/* MR allocation/de-allocation functions */
+int bng_sp_alloc_mrw(struct bng_re_res *res, struct bng_re_mrw *mrw)
+{
+ struct bng_re_rcfw *rcfw = res->rcfw;
+ struct creq_allocate_mrw_resp resp = {};
+ struct bng_re_cmdqmsg msg = {};
+ struct cmdq_allocate_mrw req = {};
+ int rc;
+
+ bng_re_rcfw_cmd_prep((struct cmdq_base *)&req,
+ CMDQ_BASE_OPCODE_ALLOCATE_MRW,
+ sizeof(req));
+
+ req.pd_id = cpu_to_le32(mrw->pd->id);
+ req.mrw_flags = mrw->type;
+
+ if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR &&
+ mrw->access_flags & BNG_RE_FR_PMR) ||
+ mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A ||
+ mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)
+ req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY;
+ req.mrw_handle = cpu_to_le64(mrw);
+
+ bng_re_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req),
+ sizeof(resp), 0);
+ rc = bng_re_rcfw_send_message(rcfw, &msg);
+ if (rc)
+ return rc;
+
+ if (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 ||
+ mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A ||
+ mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)
+ mrw->rkey = le32_to_cpu(resp.xid);
+ else
+ mrw->lkey = le32_to_cpu(resp.xid);
+
+ return 0;
+}
+
+int bng_sp_alloc_fast_reg_page_list(struct bng_re_res *res,
+ struct bng_re_frpl *frpl,
+ int max_pg_ptrs)
+{
+ struct bng_re_hwq_attr hwq_attr = {};
+ struct bng_re_sg_info sginfo = {};
+ struct bng_re_hwq *hwq;
+ int pg_ptrs, pages, rc;
+
+ pg_ptrs = roundup_pow_of_two(max_pg_ptrs);
+ pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT;
+ if (!pages)
+ pages++;
+
+ if (pages > MAX_PBL_LVL_1_PGS)
+ return -ENOMEM;
+
+ sginfo.pgsize = PAGE_SIZE;
+ sginfo.nopte = true;
+
+ hwq_attr.res = res;
+ hwq_attr.depth = pg_ptrs;
+ hwq_attr.stride = PAGE_SIZE;
+ hwq_attr.sginfo = &sginfo;
+ hwq_attr.type = BNG_HWQ_TYPE_CTX;
+
+ hwq = &frpl->hwq;
+ rc = bng_re_alloc_init_hwq(hwq, &hwq_attr);
+ if (!rc)
+ frpl->max_pg_ptrs = pg_ptrs;
+
+ return rc;
+}
+
+int bng_sp_free_mrw(struct bng_re_res *res,
+ struct bng_re_mrw *mrw)
+{
+ struct creq_deallocate_key_resp resp = {};
+ struct cmdq_deallocate_key req = {};
+ struct bng_re_rcfw *rcfw = res->rcfw;
+ struct bng_re_cmdqmsg msg = {};
+ struct bng_re_hwq *hwq;
+ int rc;
+
+ if (mrw->lkey == BNG_RE_RSVD_LKEY)
+ return 0;
+
+ bng_re_rcfw_cmd_prep((struct cmdq_base *)&req,
+ CMDQ_BASE_OPCODE_DEALLOCATE_KEY,
+ sizeof(req));
+
+ req.mrw_flags = mrw->type;
+
+ if (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 ||
+ mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A ||
+ mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)
+ req.key = cpu_to_le32(mrw->rkey);
+ else
+ req.key = cpu_to_le32(mrw->lkey);
+
+ bng_re_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req),
+ sizeof(resp), 0);
+ rc = bng_re_rcfw_send_message(rcfw, &msg);
+ if (rc)
+ return rc;
+
+ hwq = &mrw->hwq;
+ if (hwq->max_elements)
+ bng_re_free_hwq(res, hwq);
+
+ return 0;
+}
+
+int bng_sp_free_fast_reg_page_list(struct bng_re_res *res,
+ struct bng_re_frpl *frpl)
+{
+ struct bng_re_hwq *hwq;
+
+ hwq = &frpl->hwq;
+ bng_re_free_hwq(res, hwq);
+ return 0;
+}
+
+int bng_sp_reg_mr(struct bng_re_res *res, struct bng_re_mrw *mr,
+ struct ib_umem *umem, int num_pbls, u32 buf_pg_size,
+ bool unified_mr)
+{
+ struct bng_re_rcfw *rcfw = res->rcfw;
+ struct bng_re_hwq_attr hwq_attr = {};
+ struct bng_re_sg_info sginfo = {};
+ struct creq_register_mr_resp resp = {};
+ struct bng_re_cmdqmsg msg = {};
+ struct cmdq_register_mr req = {};
+ int pages, rc;
+ u32 pg_size;
+ u16 level;
+
+ if (num_pbls) {
+ pages = roundup_pow_of_two(num_pbls);
+ /* Allocate memory for the non-leaf pages to store buf ptrs.
+ * Non-leaf pages always uses system PAGE_SIZE
+ */
+ /* Free the hwq if it already exist, must be a rereg */
+ if (mr->hwq.max_elements)
+ bng_re_free_hwq(res, &mr->hwq);
+ hwq_attr.res = res;
+ hwq_attr.depth = pages;
+ hwq_attr.stride = sizeof(dma_addr_t);
+ hwq_attr.type = BNG_HWQ_TYPE_MR;
+ hwq_attr.sginfo = &sginfo;
+ hwq_attr.sginfo->umem = umem;
+ hwq_attr.sginfo->npages = pages;
+ hwq_attr.sginfo->pgsize = buf_pg_size;
+ hwq_attr.sginfo->pgshft = ilog2(buf_pg_size);
+ rc = bng_re_alloc_init_hwq(&mr->hwq, &hwq_attr);
+ if (rc) {
+ dev_err(&res->pdev->dev,
+ "SP: Reg MR memory allocation failed\n");
+ return -ENOMEM;
+ }
+ }
+
+ bng_re_rcfw_cmd_prep((struct cmdq_base *)&req,
+ CMDQ_BASE_OPCODE_REGISTER_MR,
+ sizeof(req));
+
+ /* Configure the request */
+ if (mr->hwq.level == BNG_PBL_LVL_MAX) {
+ /* No PBL provided, just use system PAGE_SIZE */
+ level = 0;
+ req.pbl = 0;
+ pg_size = PAGE_SIZE;
+ } else {
+ level = mr->hwq.level;
+ req.pbl = cpu_to_le64(mr->hwq.pbl[BNG_PBL_LVL_0].pg_map_arr[0]);
+ }
+ pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE;
+ req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) |
+ ((ilog2(pg_size) <<
+ CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) &
+ CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK);
+ req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) <<
+ CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) &
+ CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK));
+ req.access = (mr->access_flags & BNG_RE_MR_ACCESS_MASK);
+ req.va = cpu_to_le64(mr->va);
+ req.key = cpu_to_le32(mr->lkey);
+ if (unified_mr)
+ req.key = cpu_to_le32(mr->pd->id);
+ req.flags = cpu_to_le16(mr->flags);
+ req.mr_size = cpu_to_le64(mr->total_size);
+
+ bng_re_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req),
+ sizeof(resp), 0);
+ rc = bng_re_rcfw_send_message(rcfw, &msg);
+ if (rc)
+ goto free_hwq;
+
+ if (unified_mr) {
+ mr->lkey = le32_to_cpu(resp.xid);
+ mr->rkey = mr->lkey;
+ }
+
+ return 0;
+
+free_hwq:
+ if (mr->hwq.max_elements)
+ bng_re_free_hwq(res, &mr->hwq);
+ return rc;
+}
diff --git a/drivers/infiniband/hw/bng_re/bng_sp.h b/drivers/infiniband/hw/bng_re/bng_sp.h
index 136703942e1f..6dd3ff911548 100644
--- a/drivers/infiniband/hw/bng_re/bng_sp.h
+++ b/drivers/infiniband/hw/bng_re/bng_sp.h
@@ -4,6 +4,8 @@
#ifndef __BNG_SP_H__
#define __BNG_SP_H__
+#include <rdma/ib_umem.h>
+
#include "bng_fw.h"
#define BNG_VAR_MAX_WQE 4352
@@ -57,6 +59,45 @@ struct bng_sp_pd {
u32 id;
};
+/* Access flags */
+#define BNG_RE_ACCESS_LOCAL_WRITE BIT(0)
+#define BNG_RE_ACCESS_REMOTE_READ BIT(1)
+#define BNG_RE_ACCESS_REMOTE_WRITE BIT(2)
+#define BNG_RE_ACCESS_REMOTE_ATOMIC BIT(3)
+#define BNG_RE_ACCESS_MW_BIND BIT(4)
+#define BNG_RE_ACCESS_ZERO_BASED BIT(5)
+#define BNG_RE_ACCESS_ON_DEMAND BIT(6)
+
+struct bng_re_mrw {
+ struct bng_sp_pd *pd;
+ int type;
+ u32 access_flags;
+#define BNG_RE_MR_ACCESS_MASK 0xFF
+ u32 lkey;
+ u32 rkey;
+#define BNG_RE_RSVD_LKEY 0xFFFFFFFF
+ u64 va;
+ u64 total_size;
+ u32 npages;
+ u16 flags;
+ u64 mr_handle;
+ struct bng_re_hwq hwq;
+ u16 ctx_size_sb;
+};
+
+struct bng_re_frpl {
+ int max_pg_ptrs;
+ struct bng_re_hwq hwq;
+};
+
+struct bng_sp_mrinfo {
+ struct bng_re_mrw *mrw;
+ struct bng_re_sg_info sg;
+ u64 *ptes;
+ bool is_dma;
+ bool request_relax_order;
+};
+
int bng_re_get_dev_attr(struct bng_re_rcfw *rcfw);
int bng_sp_alloc_sgid_tbl(struct bng_re_sgid_tbl *sgid_tbl, u16 size);
@@ -76,4 +117,15 @@ int bng_sp_dealloc_pd(struct bng_re_res *res,
struct bng_re_pd_tbl *pdt,
struct bng_sp_pd *pd);
+int bng_sp_alloc_mrw(struct bng_re_res *res, struct bng_re_mrw *mrw);
+int bng_sp_alloc_fast_reg_page_list(struct bng_re_res *res,
+ struct bng_re_frpl *frpl,
+ int max_pg_ptrs);
+int bng_sp_free_fast_reg_page_list(struct bng_re_res *res,
+ struct bng_re_frpl *frpl);
+int bng_sp_free_mrw(struct bng_re_res *res, struct bng_re_mrw *mrw);
+int bng_sp_reg_mr(struct bng_re_res *res, struct bng_re_mrw *mr,
+ struct ib_umem *umem, int num_pbls, u32 buf_pg_size,
+ bool unified_mr);
+
#endif
diff --git a/drivers/infiniband/hw/bng_re/bng_verbs.c b/drivers/infiniband/hw/bng_re/bng_verbs.c
index 140a972a0316..fe227d20513a 100644
--- a/drivers/infiniband/hw/bng_re/bng_verbs.c
+++ b/drivers/infiniband/hw/bng_re/bng_verbs.c
@@ -560,3 +560,336 @@ int bng_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata)
}
return 0;
}
+
+/* Helper functions for MR operations */
+static inline bool _is_relaxed_ordering_supported(u16 dev_cap_ext_flags2)
+{
+ return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_MEMORY_REGION_RO_SUPPORTED;
+}
+
+static void bng_re_check_and_set_relaxed_ordering(struct bng_re_dev *rdev,
+ struct bng_re_mrw *mr)
+{
+ struct bng_re_dev_attr *dev_attr = rdev->dev_attr;
+
+ if (_is_relaxed_ordering_supported(dev_attr->dev_cap_flags2) &&
+ pcie_relaxed_ordering_enabled(rdev->aux_dev->pdev))
+ mr->flags |= CMDQ_REGISTER_MR_FLAGS_ENABLE_RO;
+}
+
+static int __from_ib_access_flags(int iflags)
+{
+ int qflags = 0;
+
+ if (iflags & IB_ACCESS_LOCAL_WRITE)
+ qflags |= BNG_RE_ACCESS_LOCAL_WRITE;
+ if (iflags & IB_ACCESS_REMOTE_READ)
+ qflags |= BNG_RE_ACCESS_REMOTE_READ;
+ if (iflags & IB_ACCESS_REMOTE_WRITE)
+ qflags |= BNG_RE_ACCESS_REMOTE_WRITE;
+ if (iflags & IB_ACCESS_REMOTE_ATOMIC)
+ qflags |= BNG_RE_ACCESS_REMOTE_ATOMIC;
+ if (iflags & IB_ACCESS_MW_BIND)
+ qflags |= BNG_RE_ACCESS_MW_BIND;
+ if (iflags & IB_ZERO_BASED)
+ qflags |= BNG_RE_ACCESS_ZERO_BASED;
+ if (iflags & IB_ACCESS_ON_DEMAND)
+ qflags |= BNG_RE_ACCESS_ON_DEMAND;
+
+ return qflags;
+}
+
+static inline bool _is_alloc_mr_unified(struct bng_re_dev_attr *dattr)
+{
+ return dattr->dev_cap_flags &
+ CREQ_QUERY_FUNC_RESP_SB_MR_REGISTER_ALLOC;
+}
+
+struct ib_mr *bng_re_get_dma_mr(struct ib_pd *ib_pd, int mr_access_flags)
+{
+ struct bng_re_pd *pd = container_of(ib_pd, struct bng_re_pd, ib_pd);
+ struct bng_re_dev *rdev = pd->rdev;
+ struct bng_re_mr *mr;
+ struct bng_re_res *sp_res;
+ int rc;
+
+ mr = kzalloc_obj(*mr, GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+
+ mr->rdev = rdev;
+ mr->sp_mr.pd = &pd->sp_pd;
+ mr->sp_mr.access_flags = __from_ib_access_flags(mr_access_flags);
+ mr->sp_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
+
+ if (mr_access_flags & IB_ACCESS_RELAXED_ORDERING)
+ bng_re_check_and_set_relaxed_ordering(rdev, &mr->sp_mr);
+
+ sp_res = &rdev->bng_res;
+ rc = bng_sp_alloc_mrw(sp_res, &mr->sp_mr);
+ if (rc) {
+ ibdev_err(&rdev->ibdev, "Allocate DMA MR failed: %d\n", rc);
+ goto free_mr;
+ }
+
+ mr->sp_mr.hwq.level = BNG_PBL_LVL_MAX;
+ /* Infinite length for DMA MR */
+ mr->sp_mr.total_size = -1;
+
+ /* Register the MR */
+ rc = bng_sp_reg_mr(sp_res, &mr->sp_mr, NULL, 0, PAGE_SIZE, false);
+ if (rc) {
+ ibdev_err(&rdev->ibdev, "Register DMA MR failed: %d\n", rc);
+ goto free_mrw;
+ }
+
+ /* Set the keys */
+ mr->ib_mr.lkey = mr->sp_mr.lkey;
+ if (mr_access_flags & (IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ |
+ IB_ACCESS_REMOTE_ATOMIC))
+ mr->ib_mr.rkey = mr->ib_mr.lkey;
+
+ return &mr->ib_mr;
+
+free_mrw:
+ bng_sp_free_mrw(sp_res, &mr->sp_mr);
+free_mr:
+ kfree(mr);
+ return ERR_PTR(rc);
+}
+
+struct ib_mr *bng_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type,
+ u32 max_num_sg)
+{
+ struct bng_re_pd *pd = container_of(ib_pd, struct bng_re_pd, ib_pd);
+ struct bng_re_dev *rdev = pd->rdev;
+ struct bng_re_res *sp_res;
+ struct bng_re_mr *mr = NULL;
+ int rc;
+
+ if (type != IB_MR_TYPE_MEM_REG) {
+ ibdev_dbg(&rdev->ibdev, "MR type 0x%x not supported\n", type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (max_num_sg > MAX_PBL_LVL_1_PGS) {
+ ibdev_dbg(&rdev->ibdev, "Max SG %u exceeds limit %d\n",
+ max_num_sg, MAX_PBL_LVL_1_PGS);
+ return ERR_PTR(-EINVAL);
+ }
+
+ mr = kzalloc_obj(*mr, GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+
+ mr->rdev = rdev;
+ mr->sp_mr.pd = &pd->sp_pd;
+ mr->sp_mr.access_flags = BNG_RE_FR_PMR;
+ mr->sp_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
+
+ sp_res = &rdev->bng_res;
+ rc = bng_sp_alloc_mrw(sp_res, &mr->sp_mr);
+ if (rc) {
+ ibdev_err(&rdev->ibdev, "Allocate MR failed: %d\n", rc);
+ goto free_mr;
+ }
+
+ mr->ib_mr.lkey = mr->sp_mr.lkey;
+ mr->ib_mr.rkey = mr->ib_mr.lkey;
+
+ rc = bng_sp_alloc_fast_reg_page_list(sp_res,
+ &mr->sp_frpl, max_num_sg);
+ if (rc) {
+ ibdev_err(&rdev->ibdev,
+ "Failed to allocate HW FR page list: %d\n", rc);
+ goto free_mrw;
+ }
+
+ mr->pages = kcalloc(mr->sp_frpl.max_pg_ptrs, sizeof(*mr->pages),
+ GFP_KERNEL);
+ if (!mr->pages) {
+ rc = -ENOMEM;
+ goto free_frpl;
+ }
+
+ return &mr->ib_mr;
+
+free_frpl:
+ bng_sp_free_fast_reg_page_list(sp_res, &mr->sp_frpl);
+free_mrw:
+ bng_sp_free_mrw(sp_res, &mr->sp_mr);
+free_mr:
+ kfree(mr);
+ return ERR_PTR(rc);
+}
+
+static int bng_re_set_page(struct ib_mr *ib_mr, u64 addr)
+{
+ struct bng_re_mr *mr = container_of(ib_mr, struct bng_re_mr, ib_mr);
+
+ if (unlikely(mr->npages == mr->sp_frpl.max_pg_ptrs))
+ return -ENOMEM;
+
+ mr->pages[mr->npages++] = addr;
+ return 0;
+}
+
+int bng_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
+ unsigned int *sg_offset)
+{
+ struct bng_re_mr *mr = container_of(ib_mr, struct bng_re_mr, ib_mr);
+
+ mr->npages = 0;
+ return ib_sg_to_pages(ib_mr, sg, sg_nents, sg_offset, bng_re_set_page);
+}
+
+static struct ib_mr *__bng_re_user_reg_mr(struct ib_pd *ib_pd, u64 length,
+ u64 virt_addr, int mr_access_flags,
+ struct ib_umem *umem)
+{
+ struct bng_re_pd *pd = container_of(ib_pd, struct bng_re_pd, ib_pd);
+ struct bng_re_dev *rdev = pd->rdev;
+ unsigned long page_size;
+ struct bng_re_mr *mr;
+ int umem_pgs, rc;
+
+ if (length > BNG_RE_MAX_MR_SIZE) {
+ ibdev_err(&rdev->ibdev, "MR Size: %llu > Max supported:%llu\n",
+ (unsigned long long)length,
+ (unsigned long long)BNG_RE_MAX_MR_SIZE);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ page_size = ib_umem_find_best_pgsz(umem, BNG_RE_PAGE_SIZE_SUPPORTED, virt_addr);
+ if (!page_size) {
+ ibdev_err(&rdev->ibdev, "umem page size unsupported!\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ mr = kzalloc_obj(*mr, GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+
+ mr->rdev = rdev;
+ mr->sp_mr.pd = &pd->sp_pd;
+ mr->sp_mr.access_flags = __from_ib_access_flags(mr_access_flags);
+ mr->sp_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR;
+
+ if (!_is_alloc_mr_unified(rdev->dev_attr)) {
+ rc = bng_sp_alloc_mrw(&rdev->bng_res, &mr->sp_mr);
+ if (rc) {
+ ibdev_err(&rdev->ibdev, "Failed to allocate MR rc = %d\n", rc);
+ rc = -EIO;
+ goto free_mr;
+ }
+ /* The fixed portion of the rkey is the same as the lkey */
+ mr->ib_mr.rkey = mr->sp_mr.rkey;
+ } else {
+ mr->sp_mr.flags = CMDQ_REGISTER_MR_FLAGS_ALLOC_MR;
+ }
+ mr->ib_umem = umem;
+ mr->sp_mr.va = virt_addr;
+ mr->sp_mr.total_size = length;
+
+ if (mr_access_flags & IB_ACCESS_RELAXED_ORDERING)
+ bng_re_check_and_set_relaxed_ordering(rdev, &mr->sp_mr);
+
+ umem_pgs = ib_umem_num_dma_blocks(umem, page_size);
+ rc = bng_sp_reg_mr(&rdev->bng_res, &mr->sp_mr, umem,
+ umem_pgs, page_size,
+ _is_alloc_mr_unified(rdev->dev_attr));
+ if (rc) {
+ ibdev_err(&rdev->ibdev, "Failed to register user MR - rc = %d\n", rc);
+ rc = -EIO;
+ goto free_mrw;
+ }
+
+ mr->ib_mr.lkey = mr->sp_mr.lkey;
+ mr->ib_mr.rkey = mr->sp_mr.lkey;
+
+ return &mr->ib_mr;
+
+free_mrw:
+ bng_sp_free_mrw(&rdev->bng_res, &mr->sp_mr);
+free_mr:
+ kfree(mr);
+ return ERR_PTR(rc);
+}
+
+struct ib_mr *bng_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,
+ u64 virt_addr, int mr_access_flags,
+ struct ib_dmah *dmah,
+ struct ib_udata *udata)
+{
+ struct bng_re_pd *pd = container_of(ib_pd, struct bng_re_pd, ib_pd);
+ struct bng_re_dev *rdev = pd->rdev;
+ struct ib_umem *umem;
+ struct ib_mr *ib_mr;
+
+ umem = ib_umem_get_va(&rdev->ibdev, start, length, mr_access_flags);
+ if (IS_ERR(umem))
+ return ERR_CAST(umem);
+
+ ib_mr = __bng_re_user_reg_mr(ib_pd, length, virt_addr, mr_access_flags, umem);
+ if (IS_ERR(ib_mr))
+ ib_umem_release(umem);
+ return ib_mr;
+}
+
+struct ib_mr *bng_re_reg_user_mr_dmabuf(struct ib_pd *ib_pd, u64 start,
+ u64 length, u64 virt_addr, int fd,
+ int mr_access_flags,
+ struct ib_dmah *dmah,
+ struct uverbs_attr_bundle *attrs)
+{
+ struct bng_re_pd *pd = container_of(ib_pd, struct bng_re_pd, ib_pd);
+ struct bng_re_dev *rdev = pd->rdev;
+ struct ib_umem_dmabuf *umem_dmabuf;
+ struct ib_umem *umem;
+ struct ib_mr *ib_mr;
+
+ ibdev_dbg(&rdev->ibdev, "Register user DMA-BUF MR\n");
+
+ umem_dmabuf = ib_umem_dmabuf_get_pinned(&rdev->ibdev, start, length,
+ fd, mr_access_flags);
+ if (IS_ERR(umem_dmabuf))
+ return ERR_CAST(umem_dmabuf);
+
+ umem = &umem_dmabuf->umem;
+
+ ib_mr = __bng_re_user_reg_mr(ib_pd, length, virt_addr, mr_access_flags, umem);
+ if (IS_ERR(ib_mr)) {
+ ib_umem_release(umem);
+ return ib_mr;
+ }
+
+ return ib_mr;
+}
+
+int bng_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
+{
+ struct bng_re_mr *mr = container_of(ib_mr, struct bng_re_mr, ib_mr);
+ struct bng_re_dev *rdev = mr->rdev;
+ struct bng_re_res *sp_res;
+ int rc;
+
+ sp_res = &rdev->bng_res;
+
+ rc = bng_sp_free_mrw(sp_res, &mr->sp_mr);
+ if (rc) {
+ ibdev_err(&rdev->ibdev, "Dereg MR failed: %d\n", rc);
+ return rc;
+ }
+
+ /* Free page list if it was allocated for fast registration */
+ if (mr->pages) {
+ bng_sp_free_fast_reg_page_list(sp_res, &mr->sp_frpl);
+ kfree(mr->pages);
+ }
+
+ ib_umem_release(mr->ib_umem);
+
+ kfree(mr);
+
+ return 0;
+}
diff --git a/drivers/infiniband/hw/bng_re/bng_verbs.h b/drivers/infiniband/hw/bng_re/bng_verbs.h
index ea017f70142e..0ef7a7535e87 100644
--- a/drivers/infiniband/hw/bng_re/bng_verbs.h
+++ b/drivers/infiniband/hw/bng_re/bng_verbs.h
@@ -37,6 +37,16 @@ struct bng_re_pd {
struct bng_sp_pd sp_pd;
};
+struct bng_re_mr {
+ struct bng_re_dev *rdev;
+ struct ib_mr ib_mr;
+ struct ib_umem *ib_umem;
+ struct bng_re_mrw sp_mr;
+ u32 npages;
+ u64 *pages;
+ struct bng_re_frpl sp_frpl;
+};
+
int bng_re_query_device(struct ib_device *ibdev, struct ib_device_attr *ib_attr,
struct ib_udata *udata);
int bng_re_modify_device(struct ib_device *ibdev, int device_modify_mask,
@@ -64,5 +74,22 @@ int bng_re_add_gid(const struct ib_gid_attr *attr, void **context);
int bng_re_del_gid(const struct ib_gid_attr *attr, void **context);
int bng_re_alloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata);
int bng_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata);
+
+struct ib_mr *bng_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type,
+ u32 max_num_sg);
+int bng_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
+ unsigned int *sg_offset);
+int bng_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata);
+struct ib_mr *bng_re_get_dma_mr(struct ib_pd *ib_pd, int mr_access_flags);
+struct ib_mr *bng_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,
+ u64 virt_addr, int mr_access_flags,
+ struct ib_dmah *dmah,
+ struct ib_udata *udata);
+struct ib_mr *bng_re_reg_user_mr_dmabuf(struct ib_pd *ib_pd, u64 start,
+ u64 length, u64 virt_addr,
+ int fd, int mr_access_flags,
+ struct ib_dmah *dmah,
+ struct uverbs_attr_bundle *attrs);
+
#endif /* __BNG_RE_VERBS_H__ */
--
2.43.5
next prev parent reply other threads:[~2026-09-04 10:52 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 10:43 [PATCH 00/15] Add BNG_RE control path verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 01/15] bnge: Add infrastructure support for RoCE MPC channels Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 02/15] bnge: Add HSI definitions for 64-bit doorbell and " Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 03/15] bnge: reserve TX/completion rings for the RoCE MPC channel Siva Reddy Kallam
2026-09-04 15:52 ` Jakub Kicinski
2026-09-04 10:43 ` [PATCH 04/15] RDMA/bng_re: Add MPC, XID management, doorbell infrastructure Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 05/15] RDMA/bng_re: Add support verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 06/15] RDMA/bng_re: Add ucontext/mmap verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 07/15] RDMA/bng_re: Add GID verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 08/15] RDMA/bng_re: Add PD verbs Siva Reddy Kallam
2026-09-04 10:43 ` Siva Reddy Kallam [this message]
2026-09-04 10:43 ` [PATCH 10/15] RDMA/bng_re: Add CQ verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 11/15] RDMA/bng_re: Add SRQ verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 12/15] RDMA/bng_re: Add Stats verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 13/15] RDMA/bng_re: Add AH verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 14/15] RDMA/bng_re: Add QP verbs Siva Reddy Kallam
2026-09-04 10:43 ` [PATCH 15/15] RDMA/bng_re: Register with ib-core Siva Reddy Kallam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260904104328.763768-10-siva.kallam@broadcom.com \
--to=siva.kallam@broadcom.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jgg@nvidia.com \
--cc=kuba@kernel.org \
--cc=leonro@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=suresh.rupanagudi@broadcom.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox