* [for-next v1 0/5] RDMA/ionic: add SRQ support and firmware assigned CQ and SRQ IDs
@ 2026-09-08 9:07 Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 1/5] net: ionic: Fetch qid allocation and SRQ capability from firmware Abhijit Gangurde
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Abhijit Gangurde @ 2026-09-08 9:07 UTC (permalink / raw)
To: jgg, leon, brett.creeley, andrew+netdev, davem, edumazet, kuba,
pabeni
Cc: allen.hubbe, nikhil.agarwal, linux-rdma, netdev, linux-kernel,
Abhijit Gangurde
This series adds ionic Shared Receive Queue support and lets firmware assign
CQ/SRQ IDs when the LIF advertises qid-allocation capability.
Patch 1: extends the RDMA LIF identity with SRQ qtype and alloc_qid_cap.
Patch 2: uses that for firmware-assigned CQ IDs and splits CQ create/destroy
so cq_tbl is updated only after the ID is known, and removed before the ID
is returned to firmware.
Patches 3: Refactor RQ state into ionic_rq so QP RQ and SRQ share init/destroy.
Patches 4-5: add SRQ verbs and EQ events. Userspace ABI field srqid is new
with this series;
rdma-core PR: https://github.com/linux-rdma/rdma-core/pull/1799
Net changes pull request:
The following changes since commit df2908090cda368b01ff43709f51890076c56157:
Linux 7.3-rc2 (2026-09-06 15:07:20 -0700)
are available in the Git repository at:
https://github.com/abhijitG-xlnx/linux.git ionic-shared
for you to fetch changes up to 4d77450be558f140997fe23b362e4049c0ff0d74:
net: ionic: Fetch qid allocation and SRQ capability from firmware
Abhijit Gangurde (2):
net: ionic: Fetch qid allocation and SRQ capability from firmware
RDMA/ionic: support firmware-assigned CQ IDs
Amit Kumar (3):
RDMA/ionic: segregate rq related fields from ionic_qp into a new
ionic_rq struct
RDMA/ionic: add Shared receive queue (SRQ) support
RDMA/ionic: implement SRQ event handling support
drivers/infiniband/hw/ionic/ionic_admin.c | 117 ++-
.../infiniband/hw/ionic/ionic_controlpath.c | 771 +++++++++++++-----
drivers/infiniband/hw/ionic/ionic_datapath.c | 82 +-
drivers/infiniband/hw/ionic/ionic_fw.h | 74 +-
drivers/infiniband/hw/ionic/ionic_ibdev.c | 20 +
drivers/infiniband/hw/ionic/ionic_ibdev.h | 87 +-
drivers/infiniband/hw/ionic/ionic_lif_cfg.c | 2 +
drivers/infiniband/hw/ionic/ionic_lif_cfg.h | 2 +
.../net/ethernet/pensando/ionic/ionic_if.h | 31 +-
include/uapi/rdma/ionic-abi.h | 2 +-
10 files changed, 907 insertions(+), 281 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [for-next v1 1/5] net: ionic: Fetch qid allocation and SRQ capability from firmware
2026-09-08 9:07 [for-next v1 0/5] RDMA/ionic: add SRQ support and firmware assigned CQ and SRQ IDs Abhijit Gangurde
@ 2026-09-08 9:07 ` Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 2/5] RDMA/ionic: support firmware-assigned CQ IDs Abhijit Gangurde
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Abhijit Gangurde @ 2026-09-08 9:07 UTC (permalink / raw)
To: jgg, leon, brett.creeley, andrew+netdev, davem, edumazet, kuba,
pabeni
Cc: allen.hubbe, nikhil.agarwal, linux-rdma, netdev, linux-kernel,
Abhijit Gangurde
Read the qid allocation and SRQ capability from the RDMA LIF identity
reported by firmware.
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
---
.../net/ethernet/pensando/ionic/ionic_if.h | 31 +++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h
index 15f2bc3f4043..9bd5f7a29fc4 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_if.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h
@@ -7,6 +7,7 @@
#define IONIC_DEV_INFO_SIGNATURE 0x44455649 /* 'DEVI' */
#define IONIC_DEV_INFO_VERSION 1
#define IONIC_IFNAMSIZ 16
+#define IONIC_CREATE_CQ_CMD_V2_MAGIC -1
/*
* enum ionic_cmd_opcode - Device commands
@@ -513,6 +514,23 @@ enum ionic_lif_rdma_cap_stats {
IONIC_LIF_RDMA_STAT_QP = BIT(1),
};
+/**
+ * enum ionic_lif_rdma_alloc_qid - RDMA QID allocation capability
+ *
+ * Bitmask of RDMA queue types for which firmware can automatically
+ * allocate queue IDs. When a bit is set, the driver can request the
+ * firmware to allocate QIDs for that queue type during creation.
+ *
+ * @IONIC_LIF_RDMA_ALLOC_QID_CQ: Firmware can allocate QIDs for
+ * Completion Queues
+ * @IONIC_LIF_RDMA_ALLOC_QID_SRQ: Firmware can allocate QIDs for
+ * Shared Receive Queues
+ */
+enum ionic_lif_rdma_alloc_qid {
+ IONIC_LIF_RDMA_ALLOC_QID_CQ = BIT(0),
+ IONIC_LIF_RDMA_ALLOC_QID_SRQ = BIT(1),
+};
+
/**
* struct ionic_lif_identity - LIF identity information (type-specific)
*
@@ -557,6 +575,10 @@ enum ionic_lif_rdma_cap_stats {
* (enum ionic_lif_rdma_cap_stats)
* @rdma.rsvd: Reserved byte
* @rdma.rcq_sign_bit: RCQ sign bit
+ * @rdma.srq_qtype: RDMA Shared Receive Qtype
+ * @rdma.rsvd2: Reserved byte(s)
+ * @rdma.alloc_qid_cap: RDMA queue type QID allocation capability
+ * (bitmask of enum ionic_lif_rdma_alloc_qid)
* @rdma.rsvd1: Reserved byte(s)
* @words: word access to struct contents
*/
@@ -604,7 +626,10 @@ union ionic_lif_identity {
__le16 stats_type;
u8 rsvd;
u8 rcq_sign_bit;
- u8 rsvd1[160];
+ struct ionic_lif_logical_qtype srq_qtype;
+ u8 rsvd2[5];
+ u8 alloc_qid_cap;
+ u8 rsvd1[142];
} __packed rdma;
} __packed;
__le32 words[478];
@@ -2608,6 +2633,7 @@ struct ionic_rdma_reset_cmd {
* @depth_log2: log base two of queue depth
* @stride_log2: log base two of queue stride
* @dma_addr: address of the queue memory
+ * @udma_mask: udma index
* @rsvd2: reserved byte(s)
*
* The same command struct is used to create an RDMA event queue, completion
@@ -2637,7 +2663,8 @@ struct ionic_rdma_queue_cmd {
u8 depth_log2;
u8 stride_log2;
__le64 dma_addr;
- u8 rsvd2[40];
+ u8 udma_mask;
+ u8 rsvd2[39];
};
/******************************************************************
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [for-next v1 2/5] RDMA/ionic: support firmware-assigned CQ IDs
2026-09-08 9:07 [for-next v1 0/5] RDMA/ionic: add SRQ support and firmware assigned CQ and SRQ IDs Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 1/5] net: ionic: Fetch qid allocation and SRQ capability from firmware Abhijit Gangurde
@ 2026-09-08 9:07 ` Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 3/5] RDMA/ionic: segregate rq related fields from ionic_qp into a new ionic_rq struct Abhijit Gangurde
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Abhijit Gangurde @ 2026-09-08 9:07 UTC (permalink / raw)
To: jgg, leon, brett.creeley, andrew+netdev, davem, edumazet, kuba,
pabeni
Cc: allen.hubbe, nikhil.agarwal, linux-rdma, netdev, linux-kernel,
Abhijit Gangurde
When the LIF advertises qid allocation for CQ, let firmware return
the completion queue ID instead of allocating it in the driver bitmap.
Split CQ create/destroy into distinct phases so cq_tbl is updated only
after the ID is known and removed before the destroy admin command
returns the ID to firmware, avoiding a race where a concurrent create
reusing the same cqid could have its xarray entry erased by a stale
destroy.
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
---
drivers/infiniband/hw/ionic/ionic_admin.c | 70 ++++++++--
.../infiniband/hw/ionic/ionic_controlpath.c | 121 ++++++++++++++----
drivers/infiniband/hw/ionic/ionic_fw.h | 15 ++-
drivers/infiniband/hw/ionic/ionic_ibdev.h | 12 +-
drivers/infiniband/hw/ionic/ionic_lif_cfg.c | 1 +
drivers/infiniband/hw/ionic/ionic_lif_cfg.h | 1 +
6 files changed, 181 insertions(+), 39 deletions(-)
diff --git a/drivers/infiniband/hw/ionic/ionic_admin.c b/drivers/infiniband/hw/ionic/ionic_admin.c
index 37e24450d129..cda48c36c047 100644
--- a/drivers/infiniband/hw/ionic/ionic_admin.c
+++ b/drivers/infiniband/hw/ionic/ionic_admin.c
@@ -489,6 +489,49 @@ static int ionic_rdma_queue_devcmd(struct ionic_ibdev *dev,
return ionic_rdma_devcmd(dev, &admin);
}
+static int ionic_rdma_cq_devcmd(struct ionic_vcq *vcq,
+ struct ionic_queue *q,
+ u32 *qid, u32 cid, u16 opcode,
+ u8 udma_mask)
+{
+ struct ionic_ibdev *dev = to_ionic_ibdev(vcq->ibcq.device);
+ struct ionic_admin_ctx admin = {
+ .work = COMPLETION_INITIALIZER_ONSTACK(admin.work),
+ .cmd.rdma_queue = {
+ .opcode = opcode,
+ .lif_index = cpu_to_le16(dev->lif_cfg.lif_index),
+ .qid_ver = cpu_to_le32(*qid),
+ .cid = cpu_to_le32(cid),
+ .dbid = cpu_to_le16(dev->lif_cfg.dbid),
+ .depth_log2 = q->depth_log2,
+ .stride_log2 = q->stride_log2,
+ .dma_addr = cpu_to_le64(q->dma),
+ },
+ };
+ int rc;
+
+ if (ionic_fw_has_qid_alloc(dev, IONIC_LIF_RDMA_ALLOC_QID_CQ)) {
+ struct ionic_admin_create_cq_resp resp_buf;
+
+ /* Indicates use of CQ create V2 response format. */
+ admin.cmd.rdma_queue.qid_ver = cpu_to_le32(IONIC_CREATE_CQ_CMD_V2_MAGIC);
+ admin.cmd.rdma_queue.udma_mask = udma_mask;
+
+ rc = ionic_rdma_devcmd(dev, &admin);
+ if (rc)
+ return rc;
+
+ memcpy(&resp_buf, admin.comp.comp.cmd_data, sizeof(resp_buf));
+ *qid = le32_to_cpu(resp_buf.id);
+ } else {
+ rc = ionic_rdma_devcmd(dev, &admin);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
static void ionic_rdma_admincq_comp(struct ib_cq *ibcq, void *cq_context)
{
struct ionic_aq *aq = cq_context;
@@ -533,12 +576,16 @@ static struct ionic_vcq *ionic_create_rdma_admincq(struct ionic_ibdev *dev,
cq = &vcq->cq[0];
rc = ionic_create_cq_common(vcq, &buf, &attr, NULL, NULL,
- NULL, NULL, 0);
+ NULL, 0);
if (rc)
goto err_init;
- rc = ionic_rdma_queue_devcmd(dev, &cq->q, cq->cqid, cq->eqid,
- IONIC_CMD_RDMA_CREATE_CQ);
+ rc = ionic_rdma_cq_devcmd(vcq, &cq->q, &cq->cqid, cq->eqid,
+ IONIC_CMD_RDMA_CREATE_CQ, 0);
+ if (rc)
+ goto err_cmd;
+
+ rc = ionic_post_create_cq_cmd(cq, &buf, NULL, NULL);
if (rc)
goto err_cmd;
@@ -552,6 +599,14 @@ static struct ionic_vcq *ionic_create_rdma_admincq(struct ionic_ibdev *dev,
return ERR_PTR(rc);
}
+static void ionic_destroy_rdma_admincq(struct ionic_ibdev *dev,
+ struct ionic_vcq *vcq)
+{
+ ionic_pre_destroy_cq_cmd(dev, &vcq->cq[0]);
+ ionic_destroy_cq_common(dev, &vcq->cq[0]);
+ kfree(vcq);
+}
+
static struct ionic_aq *__ionic_create_rdma_adminq(struct ionic_ibdev *dev,
u32 aqid, u32 cqid)
{
@@ -1153,8 +1208,7 @@ int ionic_create_rdma_admin(struct ionic_ibdev *dev)
vcq->cq[0].cqid);
if (IS_ERR(aq)) {
/* Clean up the dangling CQ */
- ionic_destroy_cq_common(dev, &vcq->cq[0]);
- kfree(vcq);
+ ionic_destroy_rdma_admincq(dev, vcq);
rc = PTR_ERR(aq);
@@ -1207,10 +1261,8 @@ void ionic_destroy_rdma_admin(struct ionic_ibdev *dev)
cancel_work_sync(&aq->work);
__ionic_destroy_rdma_adminq(dev, aq);
- if (vcq) {
- ionic_destroy_cq_common(dev, &vcq->cq[0]);
- kfree(vcq);
- }
+ if (vcq)
+ ionic_destroy_rdma_admincq(dev, vcq);
}
kfree(dev->aq_vec);
diff --git a/drivers/infiniband/hw/ionic/ionic_controlpath.c b/drivers/infiniband/hw/ionic/ionic_controlpath.c
index 37f71fb43811..57103c1a464d 100644
--- a/drivers/infiniband/hw/ionic/ionic_controlpath.c
+++ b/drivers/infiniband/hw/ionic/ionic_controlpath.c
@@ -79,12 +79,10 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
struct ionic_ctx *ctx,
struct ib_udata *udata,
struct ionic_qdesc *req_cq,
- __u32 *resp_cqid,
int udma_idx)
{
struct ionic_ibdev *dev = to_ionic_ibdev(vcq->ibcq.device);
struct ionic_cq *cq = &vcq->cq[udma_idx];
- void *entry;
int rc;
cq->vcq = vcq;
@@ -94,9 +92,11 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
goto err_args;
}
- rc = ionic_get_cqid(dev, &cq->cqid, udma_idx);
- if (rc)
- goto err_args;
+ if (!ionic_fw_has_qid_alloc(dev, IONIC_LIF_RDMA_ALLOC_QID_CQ)) {
+ rc = ionic_get_cqid(dev, &cq->cqid, udma_idx);
+ if (rc)
+ goto err_args;
+ }
cq->eqid = ionic_get_eqid(dev, attr->comp_vector, udma_idx);
@@ -122,8 +122,6 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
cq->q.mask = req_cq->mask;
cq->q.depth_log2 = req_cq->depth_log2;
cq->q.stride_log2 = req_cq->stride_log2;
-
- *resp_cqid = cq->cqid;
} else {
rc = ionic_queue_init(&cq->q, dev->lif_cfg.hwdev,
attr->cqe + IONIC_CQ_GRACE,
@@ -131,7 +129,6 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
if (rc)
goto err_q_init;
- ionic_queue_dbell_init(&cq->q, cq->cqid);
cq->color = true;
cq->credit = cq->q.mask;
}
@@ -143,20 +140,8 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
init_completion(&cq->cq_rel_comp);
kref_init(&cq->cq_kref);
- entry = xa_store_irq(&dev->cq_tbl, cq->cqid, cq, GFP_KERNEL);
- if (entry) {
- if (!xa_is_err(entry))
- rc = -EINVAL;
- else
- rc = xa_err(entry);
-
- goto err_xa;
- }
-
return 0;
-err_xa:
- ionic_pgtbl_unbuf(dev, buf);
err_pgtbl_init:
if (!udata)
ionic_queue_destroy(&cq->q, dev->lif_cfg.hwdev);
@@ -164,14 +149,30 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
if (cq->umem)
ib_umem_release(cq->umem);
err_qdesc:
- ionic_put_cqid(dev, cq->cqid);
+ if (!ionic_fw_has_qid_alloc(dev, IONIC_LIF_RDMA_ALLOC_QID_CQ))
+ ionic_put_cqid(dev, cq->cqid);
err_args:
cq->vcq = NULL;
return rc;
}
-void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq)
+int ionic_post_create_cq_cmd(struct ionic_cq *cq,
+ struct ionic_tbl_buf *buf,
+ struct ib_udata *udata,
+ __u32 *resp_cqid)
+{
+ struct ionic_ibdev *dev = to_ionic_ibdev(cq->vcq->ibcq.device);
+
+ if (udata && resp_cqid)
+ *resp_cqid = cq->cqid;
+ else
+ ionic_queue_dbell_init(&cq->q, cq->cqid);
+
+ return xa_insert_irq(&dev->cq_tbl, cq->cqid, cq, GFP_KERNEL);
+}
+
+void ionic_pre_destroy_cq_cmd(struct ionic_ibdev *dev, struct ionic_cq *cq)
{
if (!cq->vcq)
return;
@@ -180,13 +181,20 @@ void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq)
kref_put(&cq->cq_kref, ionic_cq_complete);
wait_for_completion(&cq->cq_rel_comp);
+}
+
+void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq)
+{
+ if (!cq->vcq)
+ return;
if (cq->umem)
ib_umem_release(cq->umem);
else
ionic_queue_destroy(&cq->q, dev->lif_cfg.hwdev);
- ionic_put_cqid(dev, cq->cqid);
+ if (!ionic_fw_has_qid_alloc(dev, IONIC_LIF_RDMA_ALLOC_QID_CQ))
+ ionic_put_cqid(dev, cq->cqid);
cq->vcq = NULL;
}
@@ -1222,8 +1230,11 @@ int ionic_dealloc_mw(struct ib_mw *ibmw)
static int ionic_create_cq_cmd(struct ionic_ibdev *dev,
struct ionic_ctx *ctx,
struct ionic_cq *cq,
- struct ionic_tbl_buf *buf)
+ struct ionic_tbl_buf *buf,
+ int udma_mask,
+ int *out_udma_idx)
{
+ struct ionic_admin_create_cq_resp *resp_buf;
const u16 dbid = ionic_ctx_dbid(dev, ctx);
struct ionic_admin_wr wr = {
.work = COMPLETION_INITIALIZER_ONSTACK(wr.work),
@@ -1243,13 +1254,55 @@ static int ionic_create_cq_cmd(struct ionic_ibdev *dev,
}
}
};
+ dma_addr_t resp_buf_dma;
+ int rc;
if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_CREATE_CQ)
return -EBADRQC;
+ if (!ionic_fw_has_qid_alloc(dev, IONIC_LIF_RDMA_ALLOC_QID_CQ)) {
+ ionic_admin_post(dev, &wr);
+ return ionic_admin_wait(dev, &wr, 0);
+ }
+
+ resp_buf = kzalloc_obj(*resp_buf);
+ if (!resp_buf)
+ return -ENOMEM;
+
+ resp_buf_dma = dma_map_single(dev->lif_cfg.hwdev, resp_buf,
+ sizeof(*resp_buf),
+ DMA_FROM_DEVICE);
+
+ rc = dma_mapping_error(dev->lif_cfg.hwdev, resp_buf_dma);
+ if (rc)
+ goto err_dma;
+
+ wr.wqe.len = cpu_to_le16(IONIC_ADMIN_CREATE_CQ_IN_V2_LEN);
+ wr.wqe.cmd.create_cq.udma_mask = udma_mask;
+ wr.wqe.cmd.create_cq.resp_dma_addr = cpu_to_le64(resp_buf_dma);
+ wr.wqe.cmd.create_cq.resp_buf_len = cpu_to_le32(IONIC_ADMIN_CREATE_CQ_OUT_V1_LEN);
+
ionic_admin_post(dev, &wr);
+ rc = ionic_admin_wait(dev, &wr, 0);
+ if (rc)
+ goto err_admin;
- return ionic_admin_wait(dev, &wr, 0);
+ if (be32_to_cpu(wr.cqe.status_length) < IONIC_ADMIN_CREATE_CQ_OUT_V1_LEN) {
+ rc = -EOPNOTSUPP;
+ goto err_admin;
+ }
+
+ cq->cqid = le32_to_cpu(resp_buf->id);
+ if (out_udma_idx)
+ *out_udma_idx = resp_buf->udma_idx;
+
+err_admin:
+ dma_unmap_single(dev->lif_cfg.hwdev, resp_buf_dma, sizeof(*resp_buf),
+ DMA_FROM_DEVICE);
+err_dma:
+ kfree(resp_buf);
+
+ return rc;
}
static int ionic_destroy_cq_cmd(struct ionic_ibdev *dev, u32 cqid)
@@ -1308,16 +1361,21 @@ int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
rc = ionic_create_cq_common(vcq, &buf, attr, ctx, udata,
&req.cq[udma_idx],
- &resp.cqid[udma_idx],
udma_idx);
if (rc)
goto err_init;
- rc = ionic_create_cq_cmd(dev, ctx, &vcq->cq[udma_idx], &buf);
+ rc = ionic_create_cq_cmd(dev, ctx, &vcq->cq[udma_idx], &buf,
+ udma_idx, NULL);
if (rc)
goto err_cmd;
ionic_pgtbl_unbuf(dev, &buf);
+
+ rc = ionic_post_create_cq_cmd(&vcq->cq[udma_idx], &buf, udata,
+ &resp.cqid[udma_idx]);
+ if (rc)
+ goto err_post;
}
vcq->ibcq.cqe = attr->cqe;
@@ -1337,6 +1395,8 @@ int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
--udma_idx;
if (!(vcq->udma_mask & BIT(udma_idx)))
continue;
+ ionic_pre_destroy_cq_cmd(dev, &vcq->cq[udma_idx]);
+err_post:
ionic_destroy_cq_cmd(dev, vcq->cq[udma_idx].cqid);
err_cmd:
ionic_pgtbl_unbuf(dev, &buf);
@@ -1364,6 +1424,13 @@ int ionic_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
if (!(vcq->udma_mask & BIT(udma_idx)))
continue;
+ /*
+ * 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.
+ */
+ ionic_pre_destroy_cq_cmd(dev, &vcq->cq[udma_idx]);
+
rc_tmp = ionic_destroy_cq_cmd(dev, vcq->cq[udma_idx].cqid);
if (rc_tmp) {
if (!rc)
diff --git a/drivers/infiniband/hw/ionic/ionic_fw.h b/drivers/infiniband/hw/ionic/ionic_fw.h
index d0a5bce85ed8..7a02e799de2b 100644
--- a/drivers/infiniband/hw/ionic/ionic_fw.h
+++ b/drivers/infiniband/hw/ionic/ionic_fw.h
@@ -746,11 +746,22 @@ struct ionic_admin_create_cq {
__le32 map_count;
__le64 dma_addr;
__le16 dbid_flags;
+ __u8 udma_mask;
+ __le32 resp_buf_len;
+ __le64 resp_dma_addr;
} __packed;
#define IONIC_ADMIN_CREATE_CQ_IN_V1_LEN 34
-static_assert(sizeof(struct ionic_admin_create_cq) ==
- IONIC_ADMIN_CREATE_CQ_IN_V1_LEN);
+#define IONIC_ADMIN_CREATE_CQ_IN_V2_LEN 47
+static_assert(sizeof(struct ionic_admin_create_cq) == IONIC_ADMIN_CREATE_CQ_IN_V2_LEN);
+
+struct ionic_admin_create_cq_resp {
+ __le32 id;
+ __u8 udma_idx;
+} __packed;
+
+#define IONIC_ADMIN_CREATE_CQ_OUT_V1_LEN 5
+static_assert(sizeof(struct ionic_admin_create_cq_resp) == IONIC_ADMIN_CREATE_CQ_OUT_V1_LEN);
struct ionic_admin_destroy_cq {
__le32 cq_id;
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.h b/drivers/infiniband/hw/ionic/ionic_ibdev.h
index 32b6a8a45fa2..d7358e63f678 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.h
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.h
@@ -438,6 +438,12 @@ static inline void ionic_cq_complete(struct kref *kref)
complete(&cq->cq_rel_comp);
}
+static inline bool ionic_fw_has_qid_alloc(struct ionic_ibdev *dev,
+ enum ionic_lif_rdma_alloc_qid qtype)
+{
+ return dev->lif_cfg.alloc_qid_cap & qtype;
+}
+
/* ionic_admin.c */
extern struct workqueue_struct *ionic_evt_workq;
void ionic_admin_post(struct ionic_ibdev *dev, struct ionic_admin_wr *wr);
@@ -457,8 +463,12 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
struct ionic_ctx *ctx,
struct ib_udata *udata,
struct ionic_qdesc *req_cq,
- __u32 *resp_cqid,
int udma_idx);
+int ionic_post_create_cq_cmd(struct ionic_cq *cq,
+ struct ionic_tbl_buf *buf,
+ struct ib_udata *udata,
+ __u32 *resp_cqid);
+void ionic_pre_destroy_cq_cmd(struct ionic_ibdev *dev, struct ionic_cq *cq);
void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq);
void ionic_flush_qp(struct ionic_ibdev *dev, struct ionic_qp *qp);
void ionic_notify_flush_cq(struct ionic_cq *cq);
diff --git a/drivers/infiniband/hw/ionic/ionic_lif_cfg.c b/drivers/infiniband/hw/ionic/ionic_lif_cfg.c
index 1e37bd09490f..c381bda4360d 100644
--- a/drivers/infiniband/hw/ionic/ionic_lif_cfg.c
+++ b/drivers/infiniband/hw/ionic/ionic_lif_cfg.c
@@ -93,6 +93,7 @@ void ionic_fill_lif_cfg(struct ionic_lif *lif, struct ionic_lif_cfg *cfg)
!!(lif->qtype_info[IONIC_QTYPE_TXQ].features & IONIC_QIDENT_F_EXPDB);
cfg->rq_expdb =
!!(lif->qtype_info[IONIC_QTYPE_RXQ].features & IONIC_QIDENT_F_EXPDB);
+ cfg->alloc_qid_cap = ident->rdma.alloc_qid_cap;
}
struct net_device *ionic_lif_netdev(struct ionic_lif *lif)
diff --git a/drivers/infiniband/hw/ionic/ionic_lif_cfg.h b/drivers/infiniband/hw/ionic/ionic_lif_cfg.h
index d7835ac27896..68aec06908ca 100644
--- a/drivers/infiniband/hw/ionic/ionic_lif_cfg.h
+++ b/drivers/infiniband/hw/ionic/ionic_lif_cfg.h
@@ -58,6 +58,7 @@ struct ionic_lif_cfg {
bool rq_expdb;
u8 expdb_mask;
u8 rcq_sign_bit;
+ u8 alloc_qid_cap;
};
void ionic_fill_lif_cfg(struct ionic_lif *lif, struct ionic_lif_cfg *cfg);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [for-next v1 3/5] RDMA/ionic: segregate rq related fields from ionic_qp into a new ionic_rq struct
2026-09-08 9:07 [for-next v1 0/5] RDMA/ionic: add SRQ support and firmware assigned CQ and SRQ IDs Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 1/5] net: ionic: Fetch qid allocation and SRQ capability from firmware Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 2/5] RDMA/ionic: support firmware-assigned CQ IDs Abhijit Gangurde
@ 2026-09-08 9:07 ` Abhijit Gangurde
2026-09-08 9:08 ` [for-next v1 4/5] RDMA/ionic: add Shared receive queue (SRQ) support Abhijit Gangurde
2026-09-08 9:08 ` [for-next v1 5/5] RDMA/ionic: implement SRQ event handling support Abhijit Gangurde
4 siblings, 0 replies; 6+ messages in thread
From: Abhijit Gangurde @ 2026-09-08 9:07 UTC (permalink / raw)
To: jgg, leon, brett.creeley, andrew+netdev, davem, edumazet, kuba,
pabeni
Cc: allen.hubbe, nikhil.agarwal, linux-rdma, netdev, linux-kernel,
Amit Kumar, Abhijit Gangurde
From: Amit Kumar <a.k@amd.com>
In preparation for SRQ support, segregate rq related fields from ionic_qp
into a new ionic_rq struct. This refactoring enables both non-SRQ and
future SRQ code to leverage the common rq init/destroy infrastructure
around ionic_qp_rq_init/_destroy with no functional changes.
Signed-off-by: Amit Kumar <a.k@amd.com>
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
---
.../infiniband/hw/ionic/ionic_controlpath.c | 300 +++++++++---------
drivers/infiniband/hw/ionic/ionic_datapath.c | 80 ++---
drivers/infiniband/hw/ionic/ionic_ibdev.h | 41 ++-
3 files changed, 215 insertions(+), 206 deletions(-)
diff --git a/drivers/infiniband/hw/ionic/ionic_controlpath.c b/drivers/infiniband/hw/ionic/ionic_controlpath.c
index 57103c1a464d..884f5665e7a0 100644
--- a/drivers/infiniband/hw/ionic/ionic_controlpath.c
+++ b/drivers/infiniband/hw/ionic/ionic_controlpath.c
@@ -1463,8 +1463,8 @@ static int ionic_create_qp_cmd(struct ionic_ibdev *dev,
const u16 dbid = ionic_obj_dbid(dev, pd->ibpd.uobject);
const u32 flags = to_ionic_qp_flags(0, 0,
qp->sq_cmb & IONIC_CMB_ENABLE,
- qp->rq_cmb & IONIC_CMB_ENABLE,
- qp->sq_spec, qp->rq_spec,
+ qp->rq.cmb & IONIC_CMB_ENABLE,
+ qp->sq_spec, qp->rq.spec,
pd->flags & IONIC_QPF_PRIVILEGED,
pd_remote_privileged(&pd->ibpd));
struct ionic_admin_wr wr = {
@@ -1503,8 +1503,8 @@ static int ionic_create_qp_cmd(struct ionic_ibdev *dev,
if (qp->has_rq) {
wr.wqe.cmd.create_qp.rq_cq_id = cpu_to_le32(recv_cq->cqid);
- wr.wqe.cmd.create_qp.rq_depth_log2 = qp->rq.depth_log2;
- wr.wqe.cmd.create_qp.rq_stride_log2 = qp->rq.stride_log2;
+ wr.wqe.cmd.create_qp.rq_depth_log2 = qp->rq.q.depth_log2;
+ wr.wqe.cmd.create_qp.rq_stride_log2 = qp->rq.q.stride_log2;
wr.wqe.cmd.create_qp.rq_page_size_log2 = rq_buf->page_size_log2;
wr.wqe.cmd.create_qp.rq_tbl_index_srq_id = cpu_to_le32(~0);
wr.wqe.cmd.create_qp.rq_map_count =
@@ -1526,8 +1526,8 @@ static int ionic_modify_qp_cmd(struct ionic_ibdev *dev,
const u32 flags = to_ionic_qp_flags(attr->qp_access_flags,
attr->en_sqd_async_notify,
qp->sq_cmb & IONIC_CMB_ENABLE,
- qp->rq_cmb & IONIC_CMB_ENABLE,
- qp->sq_spec, qp->rq_spec,
+ qp->rq.cmb & IONIC_CMB_ENABLE,
+ qp->sq_spec, qp->rq.spec,
pd->flags & IONIC_QPF_PRIVILEGED,
pd_remote_privileged(qp->ibqp.pd));
const u8 state = to_ionic_qp_modify_state(attr->qp_state,
@@ -1697,9 +1697,9 @@ static int ionic_query_qp_cmd(struct ionic_ibdev *dev,
if (qp->has_rq) {
attr->cap.max_recv_sge =
- ionic_v1_recv_wqe_max_sge(qp->rq.stride_log2,
- qp->rq_spec,
- qp->rq_cmb & IONIC_CMB_EXPDB);
+ ionic_v1_recv_wqe_max_sge(qp->rq.q.stride_log2,
+ qp->rq.spec,
+ qp->rq.cmb & IONIC_CMB_EXPDB);
}
query_sqbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
@@ -2069,99 +2069,88 @@ static void ionic_qp_sq_destroy(struct ionic_ibdev *dev,
ionic_queue_destroy(&qp->sq, dev->lif_cfg.hwdev);
}
-static void ionic_qp_rq_init_cmb(struct ionic_ibdev *dev,
- struct ionic_qp *qp,
- struct ib_udata *udata)
+static void ionic_rq_init_cmb(struct ionic_ibdev *dev,
+ struct ionic_rq *rq,
+ struct ib_udata *udata)
{
u8 expdb_stride_log2 = 0;
bool expdb;
int rc;
- if (!(qp->rq_cmb & IONIC_CMB_ENABLE))
+ if (!(rq->cmb & IONIC_CMB_ENABLE))
goto not_in_cmb;
- if (qp->rq_cmb & ~IONIC_CMB_SUPPORTED) {
- if (qp->rq_cmb & IONIC_CMB_REQUIRE)
+ if (rq->cmb & ~IONIC_CMB_SUPPORTED) {
+ if (rq->cmb & IONIC_CMB_REQUIRE)
goto not_in_cmb;
- qp->rq_cmb &= IONIC_CMB_SUPPORTED;
+ rq->cmb &= IONIC_CMB_SUPPORTED;
}
- if ((qp->rq_cmb & IONIC_CMB_EXPDB) && !dev->lif_cfg.rq_expdb) {
- if (qp->rq_cmb & IONIC_CMB_REQUIRE)
+ if ((rq->cmb & IONIC_CMB_EXPDB) && !dev->lif_cfg.rq_expdb) {
+ if (rq->cmb & IONIC_CMB_REQUIRE)
goto not_in_cmb;
- qp->rq_cmb &= ~IONIC_CMB_EXPDB;
+ rq->cmb &= ~IONIC_CMB_EXPDB;
}
- qp->rq_cmb_order = order_base_2(qp->rq.size / PAGE_SIZE);
+ rq->cmb_order = order_base_2(rq->q.size / PAGE_SIZE);
- if (qp->rq_cmb_order >= IONIC_RQCMB_ORDER)
+ if (rq->cmb_order >= IONIC_RQCMB_ORDER)
goto not_in_cmb;
- if (qp->rq_cmb & IONIC_CMB_EXPDB)
- expdb_stride_log2 = qp->rq.stride_log2;
+ if (rq->cmb & IONIC_CMB_EXPDB)
+ expdb_stride_log2 = rq->q.stride_log2;
- rc = ionic_get_cmb(dev->lif_cfg.lif, &qp->rq_cmb_pgid,
- &qp->rq_cmb_addr, qp->rq_cmb_order,
+ rc = ionic_get_cmb(dev->lif_cfg.lif, &rq->cmb_pgid,
+ &rq->cmb_addr, rq->cmb_order,
expdb_stride_log2, &expdb);
if (rc)
goto not_in_cmb;
- if ((qp->rq_cmb & IONIC_CMB_EXPDB) && !expdb) {
- if (qp->rq_cmb & IONIC_CMB_REQUIRE)
+ if ((rq->cmb & IONIC_CMB_EXPDB) && !expdb) {
+ if (rq->cmb & IONIC_CMB_REQUIRE)
goto err_map;
- qp->rq_cmb &= ~IONIC_CMB_EXPDB;
+ rq->cmb &= ~IONIC_CMB_EXPDB;
}
return;
err_map:
- ionic_put_cmb(dev->lif_cfg.lif, qp->rq_cmb_pgid, qp->rq_cmb_order);
+ ionic_put_cmb(dev->lif_cfg.lif, rq->cmb_pgid, rq->cmb_order);
not_in_cmb:
- if (qp->rq_cmb & IONIC_CMB_REQUIRE)
+ if (rq->cmb & IONIC_CMB_REQUIRE)
ibdev_dbg(&dev->ibdev, "could not place rq in cmb as required\n");
- qp->rq_cmb = 0;
- qp->rq_cmb_order = IONIC_RES_INVALID;
- qp->rq_cmb_pgid = 0;
- qp->rq_cmb_addr = 0;
+ rq->cmb = 0;
+ rq->cmb_order = IONIC_RES_INVALID;
+ rq->cmb_pgid = 0;
+ rq->cmb_addr = 0;
}
-static void ionic_qp_rq_destroy_cmb(struct ionic_ibdev *dev,
- struct ionic_ctx *ctx,
- struct ionic_qp *qp)
+static void ionic_rq_destroy_cmb(struct ionic_ibdev *dev,
+ struct ionic_ctx *ctx,
+ struct ionic_rq *rq)
{
- if (!(qp->rq_cmb & IONIC_CMB_ENABLE))
+ if (!(rq->cmb & IONIC_CMB_ENABLE))
return;
if (ctx)
- rdma_user_mmap_entry_remove(qp->mmap_rq_cmb);
+ rdma_user_mmap_entry_remove(rq->mmap_cmb);
- ionic_put_cmb(dev->lif_cfg.lif, qp->rq_cmb_pgid, qp->rq_cmb_order);
+ ionic_put_cmb(dev->lif_cfg.lif, rq->cmb_pgid, rq->cmb_order);
}
-static int ionic_qp_rq_init(struct ionic_ibdev *dev, struct ionic_ctx *ctx,
- struct ionic_qp *qp, struct ionic_qdesc *rq,
- struct ionic_tbl_buf *buf, int max_wr, int max_sge,
- int rq_spec, struct ib_udata *udata)
+static int ionic_rq_init(struct ionic_ibdev *dev, struct ionic_ctx *ctx,
+ struct ionic_rq *rq, struct ionic_qdesc *qdesc,
+ struct ionic_tbl_buf *buf, int max_wr, int max_sge,
+ int rq_spec, struct ib_udata *udata)
{
int rc = 0, i;
u32 wqe_size;
- if (!qp->has_rq) {
- if (buf) {
- buf->tbl_buf = NULL;
- buf->tbl_limit = 0;
- buf->tbl_pages = 0;
- }
- if (udata)
- rc = ionic_validate_qdesc_zero(rq);
-
- return rc;
- }
-
+ rq->cmb_prod = 0;
rc = -EINVAL;
if (max_wr < 0 || max_wr > 0xffff)
@@ -2175,105 +2164,102 @@ static int ionic_qp_rq_init(struct ionic_ibdev *dev, struct ionic_ctx *ctx,
return rc;
if (udata) {
- rc = ionic_validate_qdesc(rq);
+ rc = ionic_validate_qdesc(qdesc);
if (rc)
return rc;
- qp->rq_spec = rq_spec;
+ rq->spec = rq_spec;
- qp->rq.ptr = NULL;
- qp->rq.size = rq->size;
- qp->rq.mask = rq->mask;
- qp->rq.depth_log2 = rq->depth_log2;
- qp->rq.stride_log2 = rq->stride_log2;
+ rq->q.ptr = NULL;
+ rq->q.size = qdesc->size;
+ rq->q.mask = qdesc->mask;
+ rq->q.depth_log2 = qdesc->depth_log2;
+ rq->q.stride_log2 = qdesc->stride_log2;
- qp->rq_meta = NULL;
+ rq->meta = NULL;
- qp->rq_umem = ib_umem_get_va(&dev->ibdev, rq->addr, rq->size, 0);
- if (IS_ERR(qp->rq_umem))
- return PTR_ERR(qp->rq_umem);
+ rq->umem = ib_umem_get_va(&dev->ibdev, qdesc->addr, qdesc->size, 0);
+ if (IS_ERR(rq->umem))
+ return PTR_ERR(rq->umem);
} else {
- qp->rq_umem = NULL;
+ rq->umem = NULL;
- qp->rq_spec = ionic_v1_use_spec_sge(max_sge, rq_spec);
- if (rq_spec && !qp->rq_spec)
+ rq->spec = ionic_v1_use_spec_sge(max_sge, rq_spec);
+ if (rq_spec && !rq->spec)
ibdev_dbg(&dev->ibdev,
"init rq: max_sge %u disables spec\n",
max_sge);
- if (qp->rq_cmb & IONIC_CMB_EXPDB) {
+ if (rq->cmb & IONIC_CMB_EXPDB) {
wqe_size = ionic_v1_recv_wqe_min_size(max_sge,
- qp->rq_spec,
+ rq->spec,
true);
if (!ionic_expdb_wqe_size_supported(dev, wqe_size))
- qp->rq_cmb &= ~IONIC_CMB_EXPDB;
+ rq->cmb &= ~IONIC_CMB_EXPDB;
}
- if (!(qp->rq_cmb & IONIC_CMB_EXPDB))
+ if (!(rq->cmb & IONIC_CMB_EXPDB))
wqe_size = ionic_v1_recv_wqe_min_size(max_sge,
- qp->rq_spec,
+ rq->spec,
false);
- rc = ionic_queue_init(&qp->rq, dev->lif_cfg.hwdev,
+ rc = ionic_queue_init(&rq->q, dev->lif_cfg.hwdev,
max_wr, wqe_size);
if (rc)
return rc;
- ionic_queue_dbell_init(&qp->rq, qp->qpid);
+ ionic_queue_dbell_init(&rq->q, rq->qid);
- qp->rq_meta = kmalloc_objs(*qp->rq_meta, (u32)qp->rq.mask + 1);
- if (!qp->rq_meta) {
+ rq->meta = kmalloc_objs(*rq->meta, (u32)rq->q.mask + 1);
+ if (!rq->meta) {
rc = -ENOMEM;
goto err_rq_meta;
}
- for (i = 0; i < qp->rq.mask; ++i)
- qp->rq_meta[i].next = &qp->rq_meta[i + 1];
- qp->rq_meta[i].next = IONIC_META_LAST;
- qp->rq_meta_head = &qp->rq_meta[0];
+ for (i = 0; i < rq->q.mask; ++i)
+ rq->meta[i].next = &rq->meta[i + 1];
+ rq->meta[i].next = IONIC_META_LAST;
+ rq->meta_head = &rq->meta[0];
}
- ionic_qp_rq_init_cmb(dev, qp, udata);
+ ionic_rq_init_cmb(dev, rq, udata);
- if (qp->rq_cmb & IONIC_CMB_ENABLE)
+ if (rq->cmb & IONIC_CMB_ENABLE)
rc = ionic_pgtbl_init(dev, buf, NULL,
- (u64)qp->rq_cmb_pgid << PAGE_SHIFT,
+ (u64)rq->cmb_pgid << PAGE_SHIFT,
1, PAGE_SIZE);
else
- rc = ionic_pgtbl_init(dev, buf,
- qp->rq_umem, qp->rq.dma, 1, PAGE_SIZE);
+ rc = ionic_pgtbl_init(dev, buf, rq->umem,
+ rq->q.dma, 1, PAGE_SIZE);
if (rc)
goto err_rq_tbl;
return 0;
err_rq_tbl:
- ionic_qp_rq_destroy_cmb(dev, ctx, qp);
- kfree(qp->rq_meta);
+ ionic_rq_destroy_cmb(dev, ctx, rq);
+ kfree(rq->meta);
err_rq_meta:
- if (qp->rq_umem)
- ib_umem_release(qp->rq_umem);
+ if (rq->umem)
+ ib_umem_release(rq->umem);
else
- ionic_queue_destroy(&qp->rq, dev->lif_cfg.hwdev);
+ ionic_queue_destroy(&rq->q, dev->lif_cfg.hwdev);
return rc;
}
-static void ionic_qp_rq_destroy(struct ionic_ibdev *dev,
- struct ionic_ctx *ctx,
- struct ionic_qp *qp)
+static void ionic_rq_destroy(struct ionic_ibdev *dev,
+ struct ionic_ctx *ctx,
+ struct ionic_rq *rq)
{
- if (!qp->has_rq)
- return;
-
- ionic_qp_rq_destroy_cmb(dev, ctx, qp);
+ ionic_rq_destroy_cmb(dev, ctx, rq);
- kfree(qp->rq_meta);
+ kfree(rq->meta);
- if (qp->rq_umem)
- ib_umem_release(qp->rq_umem);
+ if (rq->umem)
+ ib_umem_release(rq->umem);
else
- ionic_queue_destroy(&qp->rq, dev->lif_cfg.hwdev);
+ ionic_queue_destroy(&rq->q, dev->lif_cfg.hwdev);
}
int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
@@ -2317,7 +2303,7 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
INIT_LIST_HEAD(&qp->cq_flush_rq);
spin_lock_init(&qp->sq_lock);
- spin_lock_init(&qp->rq_lock);
+ spin_lock_init(&qp->rq.lock);
qp->has_sq = 1;
qp->has_rq = 1;
@@ -2361,7 +2347,7 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
if (udata) {
if (req.rq_cmb & IONIC_CMB_ENABLE)
- qp->rq_cmb = req.rq_cmb;
+ qp->rq.cmb = req.rq_cmb;
if (req.sq_cmb & IONIC_CMB_ENABLE)
qp->sq_cmb = req.sq_cmb;
@@ -2373,11 +2359,22 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
if (rc)
goto err_sq;
- rc = ionic_qp_rq_init(dev, ctx, qp, &req.rq, &rq_buf,
- attr->cap.max_recv_wr, attr->cap.max_recv_sge,
- req.rq_spec, udata);
- if (rc)
- goto err_rq;
+ if (qp->has_rq) {
+ /* for non-srq qps, rq qid is same as qpid */
+ qp->rq.qid = qp->qpid;
+ rc = ionic_rq_init(dev, ctx, &qp->rq, &req.rq, &rq_buf,
+ attr->cap.max_recv_wr, attr->cap.max_recv_sge,
+ req.rq_spec, udata);
+ if (rc)
+ goto err_rq;
+ } else {
+ rq_buf.tbl_buf = NULL;
+ rq_buf.tbl_limit = 0;
+ rq_buf.tbl_pages = 0;
+
+ if (udata)
+ rc = ionic_validate_qdesc_zero(&req.rq);
+ }
rc = ionic_create_qp_cmd(dev, pd,
to_ionic_vcq_cq(attr->send_cq, qp->udma_idx),
@@ -2423,41 +2420,41 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
resp.sq_cmb = qp->sq_cmb;
}
- if (qp->rq_cmb & IONIC_CMB_ENABLE) {
+ if (qp->rq.cmb & IONIC_CMB_ENABLE) {
bool wc;
- if ((qp->rq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) ==
+ if ((qp->rq.cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) ==
(IONIC_CMB_WC | IONIC_CMB_UC)) {
ibdev_dbg(&dev->ibdev,
- "Both rq_cmb flags IONIC_CMB_WC and IONIC_CMB_UC are set, using default driver mapping\n");
- qp->rq_cmb &= ~(IONIC_CMB_WC | IONIC_CMB_UC);
+ "Both rq.cmb flags IONIC_CMB_WC and IONIC_CMB_UC are set, using default driver mapping\n");
+ qp->rq.cmb &= ~(IONIC_CMB_WC | IONIC_CMB_UC);
}
- if (qp->rq_cmb & IONIC_CMB_EXPDB)
- wc = (qp->rq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC))
+ if (qp->rq.cmb & IONIC_CMB_EXPDB)
+ wc = (qp->rq.cmb & (IONIC_CMB_WC | IONIC_CMB_UC))
== IONIC_CMB_WC;
else
- wc = (qp->rq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC))
+ wc = (qp->rq.cmb & (IONIC_CMB_WC | IONIC_CMB_UC))
!= IONIC_CMB_UC;
/* let userspace know the mapping */
if (wc)
- qp->rq_cmb |= IONIC_CMB_WC;
+ qp->rq.cmb |= IONIC_CMB_WC;
else
- qp->rq_cmb |= IONIC_CMB_UC;
+ qp->rq.cmb |= IONIC_CMB_UC;
- qp->mmap_rq_cmb =
+ qp->rq.mmap_cmb =
ionic_mmap_entry_insert(ctx,
- qp->rq.size,
- PHYS_PFN(qp->rq_cmb_addr),
+ qp->rq.q.size,
+ PHYS_PFN(qp->rq.cmb_addr),
wc ? IONIC_MMAP_WC : 0,
&resp.rq_cmb_offset);
- if (!qp->mmap_rq_cmb) {
+ if (!qp->rq.mmap_cmb) {
rc = -ENOMEM;
goto err_mmap_rq;
}
- resp.rq_cmb = qp->rq_cmb;
+ resp.rq_cmb = qp->rq.cmb;
}
rc = ib_respond_udata(udata, resp);
@@ -2501,19 +2498,19 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
if (qp->has_rq) {
cq = to_ionic_vcq_cq(attr->recv_cq, qp->udma_idx);
- attr->cap.max_recv_wr = qp->rq.mask;
+ attr->cap.max_recv_wr = qp->rq.q.mask;
attr->cap.max_recv_sge =
- ionic_v1_recv_wqe_max_sge(qp->rq.stride_log2,
- qp->rq_spec,
- qp->rq_cmb & IONIC_CMB_EXPDB);
- qp->rq_cqid = cq->cqid;
+ ionic_v1_recv_wqe_max_sge(qp->rq.q.stride_log2,
+ qp->rq.spec,
+ qp->rq.cmb & IONIC_CMB_EXPDB);
+ qp->rq.cqid = cq->cqid;
}
return 0;
err_resp:
- if (udata && (qp->rq_cmb & IONIC_CMB_ENABLE))
- rdma_user_mmap_entry_remove(qp->mmap_rq_cmb);
+ if (udata && (qp->rq.cmb & IONIC_CMB_ENABLE))
+ rdma_user_mmap_entry_remove(qp->rq.mmap_cmb);
err_mmap_rq:
if (udata && (qp->sq_cmb & IONIC_CMB_ENABLE))
rdma_user_mmap_entry_remove(qp->mmap_sq_cmb);
@@ -2521,7 +2518,8 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
ionic_destroy_qp_cmd(dev, qp->qpid);
err_cmd:
ionic_pgtbl_unbuf(dev, &rq_buf);
- ionic_qp_rq_destroy(dev, ctx, qp);
+ if (qp->has_rq)
+ ionic_rq_destroy(dev, ctx, &qp->rq);
err_rq:
ionic_pgtbl_unbuf(dev, &sq_buf);
ionic_qp_sq_destroy(dev, ctx, qp);
@@ -2575,15 +2573,15 @@ void ionic_flush_qp(struct ionic_ibdev *dev, struct ionic_qp *qp)
if (qp->ibqp.recv_cq) {
cq = to_ionic_vcq_cq(qp->ibqp.recv_cq, qp->udma_idx);
- /* Hold the CQ lock and QP rq_lock to set up flush */
+ /* Hold the CQ lock and QP rq.lock to set up flush */
spin_lock_irqsave(&cq->lock, irqflags);
- spin_lock(&qp->rq_lock);
- qp->rq_flush = true;
- if (!ionic_queue_empty(&qp->rq)) {
+ spin_lock(&qp->rq.lock);
+ qp->rq.flush = true;
+ if (!ionic_queue_empty(&qp->rq.q)) {
cq->flush = true;
list_move_tail(&qp->cq_flush_rq, &cq->flush_rq);
}
- spin_unlock(&qp->rq_lock);
+ spin_unlock(&qp->rq.lock);
spin_unlock_irqrestore(&cq->lock, irqflags);
}
}
@@ -2649,17 +2647,17 @@ static void ionic_reset_qp(struct ionic_ibdev *dev, struct ionic_qp *qp)
}
if (qp->has_rq) {
- spin_lock(&qp->rq_lock);
- qp->rq_flush = false;
- qp->rq.prod = 0;
- qp->rq.cons = 0;
- if (qp->rq_meta) {
- for (i = 0; i < qp->rq.mask; ++i)
- qp->rq_meta[i].next = &qp->rq_meta[i + 1];
- qp->rq_meta[i].next = IONIC_META_LAST;
+ spin_lock(&qp->rq.lock);
+ qp->rq.flush = false;
+ qp->rq.q.prod = 0;
+ qp->rq.q.cons = 0;
+ if (qp->rq.meta) {
+ for (i = 0; i < qp->rq.q.mask; ++i)
+ qp->rq.meta[i].next = &qp->rq.meta[i + 1];
+ qp->rq.meta[i].next = IONIC_META_LAST;
}
- qp->rq_meta_head = &qp->rq_meta[0];
- spin_unlock(&qp->rq_lock);
+ qp->rq.meta_head = &qp->rq.meta[0];
+ spin_unlock(&qp->rq.lock);
}
local_irq_restore(irqflags);
@@ -2777,7 +2775,7 @@ int ionic_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
attr->cap.max_send_wr = qp->sq.mask;
if (qp->has_rq)
- attr->cap.max_recv_wr = qp->rq.mask;
+ attr->cap.max_recv_wr = qp->rq.q.mask;
init_attr->event_handler = ibqp->event_handler;
init_attr->qp_context = ibqp->qp_context;
@@ -2837,7 +2835,9 @@ int ionic_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
spin_unlock_irqrestore(&cq->lock, irqflags);
}
- ionic_qp_rq_destroy(dev, ctx, qp);
+ if (qp->has_rq)
+ ionic_rq_destroy(dev, ctx, &qp->rq);
+
ionic_qp_sq_destroy(dev, ctx, qp);
if (qp->has_ah) {
ionic_put_ahid(dev, qp->ahid);
diff --git a/drivers/infiniband/hw/ionic/ionic_datapath.c b/drivers/infiniband/hw/ionic/ionic_datapath.c
index 3e2300f7ea10..9c40b54123d5 100644
--- a/drivers/infiniband/hw/ionic/ionic_datapath.c
+++ b/drivers/infiniband/hw/ionic/ionic_datapath.c
@@ -34,17 +34,17 @@ static int ionic_flush_recv(struct ionic_qp *qp, struct ib_wc *wc)
struct ionic_v1_wqe *wqe;
u64 wqe_idx;
- if (!qp->rq_flush)
+ if (!qp->rq.flush)
return 0;
- if (ionic_queue_empty(&qp->rq))
+ if (ionic_queue_empty(&qp->rq.q))
return 0;
- wqe = ionic_queue_at_cons(&qp->rq);
+ wqe = ionic_queue_at_cons(&qp->rq.q);
wqe_idx = le64_to_cpu(wqe->base.wqe_idx);
/* wqe_idx must be a valid queue index */
- if (unlikely(wqe_idx >> qp->rq.depth_log2)) {
+ if (unlikely(wqe_idx >> qp->rq.q.depth_log2)) {
ibdev_warn(qp->ibqp.device,
"flush qp %u recv index %llu invalid\n",
qp->qpid, (unsigned long long)wqe_idx);
@@ -52,7 +52,7 @@ static int ionic_flush_recv(struct ionic_qp *qp, struct ib_wc *wc)
}
/* wqe_idx must indicate a request that is outstanding */
- meta = &qp->rq_meta[wqe_idx];
+ meta = &qp->rq.meta[wqe_idx];
if (unlikely(meta->next != IONIC_META_POSTED)) {
ibdev_warn(qp->ibqp.device,
"flush qp %u recv index %llu not posted\n",
@@ -60,7 +60,7 @@ static int ionic_flush_recv(struct ionic_qp *qp, struct ib_wc *wc)
return -EIO;
}
- ionic_queue_consume(&qp->rq);
+ ionic_queue_consume(&qp->rq.q);
memset(wc, 0, sizeof(*wc));
@@ -68,8 +68,8 @@ static int ionic_flush_recv(struct ionic_qp *qp, struct ib_wc *wc)
wc->wr_id = meta->wrid;
wc->qp = &qp->ibqp;
- meta->next = qp->rq_meta_head;
- qp->rq_meta_head = meta;
+ meta->next = qp->rq.meta_head;
+ qp->rq.meta_head = meta;
return 1;
}
@@ -139,7 +139,7 @@ static int ionic_poll_recv(struct ionic_ibdev *dev, struct ionic_cq *cq,
u32 src_qpn, st_len;
u8 op;
- if (cqe_qp->rq_flush)
+ if (cqe_qp->rq.flush)
return 0;
qp = cqe_qp;
@@ -148,7 +148,7 @@ static int ionic_poll_recv(struct ionic_ibdev *dev, struct ionic_cq *cq,
/* ignore wqe_idx in case of flush error */
if (ionic_v1_cqe_error(cqe) && st_len == IONIC_STS_WQE_FLUSHED_ERR) {
- cqe_qp->rq_flush = true;
+ cqe_qp->rq.flush = true;
cq->flush = true;
list_move_tail(&qp->cq_flush_rq, &cq->flush_rq);
@@ -157,29 +157,29 @@ static int ionic_poll_recv(struct ionic_ibdev *dev, struct ionic_cq *cq,
}
/* there had better be something in the recv queue to complete */
- if (ionic_queue_empty(&qp->rq)) {
+ if (ionic_queue_empty(&qp->rq.q)) {
ibdev_warn(&dev->ibdev, "qp %u is empty\n", qp->qpid);
return -EIO;
}
wqe_idx = le64_to_cpu(cqe->recv.wqe_idx_timestamp) & IONIC_V1_CQE_WQE_IDX_MASK;
/* wqe_idx must be a valid queue index */
- if (unlikely(wqe_idx >> qp->rq.depth_log2)) {
+ if (unlikely(wqe_idx >> qp->rq.q.depth_log2)) {
ibdev_warn(&dev->ibdev,
"qp %u recv index %u invalid\n", qp->qpid, wqe_idx);
return -EIO;
}
/* wqe_idx must indicate a request that is outstanding */
- meta = &qp->rq_meta[wqe_idx];
+ meta = &qp->rq.meta[wqe_idx];
if (unlikely(meta->next != IONIC_META_POSTED)) {
ibdev_warn(&dev->ibdev,
"qp %u recv index %u not posted\n", qp->qpid, wqe_idx);
return -EIO;
}
- meta->next = qp->rq_meta_head;
- qp->rq_meta_head = meta;
+ meta->next = qp->rq.meta_head;
+ qp->rq.meta_head = meta;
memset(wc, 0, sizeof(*wc));
@@ -191,7 +191,7 @@ static int ionic_poll_recv(struct ionic_ibdev *dev, struct ionic_cq *cq,
wc->vendor_err = st_len;
wc->status = ionic_to_ib_status(st_len);
- cqe_qp->rq_flush = true;
+ cqe_qp->rq.flush = true;
cq->flush = true;
list_move_tail(&qp->cq_flush_rq, &cq->flush_rq);
@@ -255,7 +255,7 @@ static int ionic_poll_recv(struct ionic_ibdev *dev, struct ionic_cq *cq,
wc->port_num = 1;
out:
- ionic_queue_consume(&qp->rq);
+ ionic_queue_consume(&qp->rq.q);
return 1;
}
@@ -526,9 +526,9 @@ static int ionic_poll_vcq_cq(struct ionic_ibdev *dev,
switch (type) {
case IONIC_V1_CQE_TYPE_RECV:
- spin_lock(&qp->rq_lock);
+ spin_lock(&qp->rq.lock);
rc = ionic_poll_recv(dev, cq, qp, cqe, wc + npolled);
- spin_unlock(&qp->rq_lock);
+ spin_unlock(&qp->rq.lock);
if (rc < 0)
goto out;
@@ -616,9 +616,9 @@ static int ionic_poll_vcq_cq(struct ionic_ibdev *dev,
if (npolled == nwc)
goto out;
- spin_lock(&qp->rq_lock);
+ spin_lock(&qp->rq.lock);
rc = ionic_flush_recv_many(qp, wc + npolled, nwc - npolled);
- spin_unlock(&qp->rq_lock);
+ spin_unlock(&qp->rq.lock);
if (rc > 0)
npolled += rc;
@@ -881,7 +881,7 @@ static void ionic_prep_sq_wqe(struct ionic_qp *qp, void *wqe)
static void ionic_prep_rq_wqe(struct ionic_qp *qp, void *wqe)
{
- memset(wqe, 0, 1u << qp->rq.stride_log2);
+ memset(wqe, 0, 1u << qp->rq.q.stride_log2);
}
static int ionic_prep_send(struct ionic_qp *qp,
@@ -1183,38 +1183,38 @@ static int ionic_prep_recv(struct ionic_qp *qp,
s64 signed_len;
u32 mval;
- wqe = ionic_queue_at_prod(&qp->rq);
+ wqe = ionic_queue_at_prod(&qp->rq.q);
/* if wqe is owned by device, caller can try posting again soon */
if (wqe->base.flags & cpu_to_be16(IONIC_V1_FLAG_FENCE))
return -EAGAIN;
- meta = qp->rq_meta_head;
+ meta = qp->rq.meta_head;
if (unlikely(meta == IONIC_META_LAST) ||
unlikely(meta == IONIC_META_POSTED))
return -EIO;
ionic_prep_rq_wqe(qp, wqe);
- mval = ionic_v1_recv_wqe_max_sge(qp->rq.stride_log2, qp->rq_spec,
+ mval = ionic_v1_recv_wqe_max_sge(qp->rq.q.stride_log2, qp->rq.spec,
false);
signed_len = ionic_prep_pld(wqe, &wqe->recv.pld,
- qp->rq_spec, mval,
+ qp->rq.spec, mval,
wr->sg_list, wr->num_sge);
if (signed_len < 0)
return signed_len;
meta->wrid = wr->wr_id;
- wqe->base.wqe_idx = cpu_to_le64(meta - qp->rq_meta);
+ wqe->base.wqe_idx = cpu_to_le64(meta - qp->rq.meta);
wqe->base.num_sge_key = wr->num_sge;
/* total length for recv goes in base imm_data_key */
wqe->base.imm_data_key = cpu_to_be32(signed_len);
- ionic_queue_produce(&qp->rq);
+ ionic_queue_produce(&qp->rq.q);
- qp->rq_meta_head = meta->next;
+ qp->rq.meta_head = meta->next;
meta->next = IONIC_META_POSTED;
return 0;
@@ -1321,10 +1321,10 @@ static int ionic_post_recv_common(struct ionic_ibdev *dev,
return -EINVAL;
}
- spin_lock_irqsave(&qp->rq_lock, irqflags);
+ spin_lock_irqsave(&qp->rq.lock, irqflags);
while (wr) {
- if (ionic_queue_full(&qp->rq)) {
+ if (ionic_queue_full(&qp->rq.q)) {
ibdev_dbg(&dev->ibdev, "queue full");
rc = -ENOMEM;
goto out;
@@ -1339,32 +1339,32 @@ static int ionic_post_recv_common(struct ionic_ibdev *dev,
out:
if (!cq) {
- spin_unlock_irqrestore(&qp->rq_lock, irqflags);
+ spin_unlock_irqrestore(&qp->rq.lock, irqflags);
goto out_unlocked;
}
- spin_unlock_irqrestore(&qp->rq_lock, irqflags);
+ spin_unlock_irqrestore(&qp->rq.lock, irqflags);
spin_lock_irqsave(&cq->lock, irqflags);
- spin_lock(&qp->rq_lock);
+ spin_lock(&qp->rq.lock);
- if (likely(qp->rq.prod != qp->rq_old_prod)) {
+ if (likely(qp->rq.q.prod != qp->rq.old_prod)) {
/* ring cq doorbell just in time */
- spend = (qp->rq.prod - qp->rq_old_prod) & qp->rq.mask;
+ spend = (qp->rq.q.prod - qp->rq.old_prod) & qp->rq.q.mask;
ionic_reserve_cq(dev, cq, spend);
- qp->rq_old_prod = qp->rq.prod;
+ qp->rq.old_prod = qp->rq.q.prod;
ionic_dbell_ring(dev->lif_cfg.dbpage, dev->lif_cfg.rq_qtype,
- ionic_queue_dbell_val(&qp->rq));
+ ionic_queue_dbell_val(&qp->rq.q));
}
- if (qp->rq_flush) {
+ if (qp->rq.flush) {
notify = true;
cq->flush = true;
list_move_tail(&qp->cq_flush_rq, &cq->flush_rq);
}
- spin_unlock(&qp->rq_lock);
+ spin_unlock(&qp->rq.lock);
spin_unlock_irqrestore(&cq->lock, irqflags);
if (notify && vcq->ibcq.comp_handler)
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.h b/drivers/infiniband/hw/ionic/ionic_ibdev.h
index d7358e63f678..b73de5d25400 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.h
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.h
@@ -241,6 +241,30 @@ struct ionic_rq_meta {
u64 wrid;
};
+struct ionic_rq {
+ struct ionic_queue q;
+ u32 qid;
+ u32 cqid;
+ struct list_head cq_flush;
+ spinlock_t lock; /* for posting and polling */
+
+ phys_addr_t cmb_addr;
+ void __iomem *cmb_ptr;
+ struct rdma_user_mmap_entry *mmap_cmb;
+
+ struct ionic_rq_meta *meta;
+ struct ionic_rq_meta *meta_head;
+ struct ib_umem *umem;
+
+ int spec;
+ int cmb_order;
+ u32 cmb_pgid;
+ u16 cmb_prod;
+ u16 old_prod;
+ u8 cmb;
+ bool flush;
+};
+
struct ionic_qp {
struct ib_qp ibqp;
enum ib_qp_state state;
@@ -248,7 +272,6 @@ struct ionic_qp {
u32 qpid;
u32 ahid;
u32 sq_cqid;
- u32 rq_cqid;
u8 udma_idx;
u8 has_ah:1;
u8 has_sq:1;
@@ -274,14 +297,7 @@ struct ionic_qp {
bool sq_flush;
bool sq_flush_rcvd;
- spinlock_t rq_lock; /* for posting and polling */
- struct ionic_queue rq;
- struct ionic_rq_meta *rq_meta;
- struct ionic_rq_meta *rq_meta_head;
- int rq_spec;
- u16 rq_old_prod;
- u8 rq_cmb;
- bool rq_flush;
+ struct ionic_rq rq;
struct kref qp_kref;
struct completion qp_rel_comp;
@@ -295,13 +311,6 @@ struct ionic_qp {
struct ib_umem *sq_umem;
- int rq_cmb_order;
- u32 rq_cmb_pgid;
- phys_addr_t rq_cmb_addr;
- struct rdma_user_mmap_entry *mmap_rq_cmb;
-
- struct ib_umem *rq_umem;
-
int dcqcn_profile;
struct ib_ud_header *hdr;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [for-next v1 4/5] RDMA/ionic: add Shared receive queue (SRQ) support
2026-09-08 9:07 [for-next v1 0/5] RDMA/ionic: add SRQ support and firmware assigned CQ and SRQ IDs Abhijit Gangurde
` (2 preceding siblings ...)
2026-09-08 9:07 ` [for-next v1 3/5] RDMA/ionic: segregate rq related fields from ionic_qp into a new ionic_rq struct Abhijit Gangurde
@ 2026-09-08 9:08 ` Abhijit Gangurde
2026-09-08 9:08 ` [for-next v1 5/5] RDMA/ionic: implement SRQ event handling support Abhijit Gangurde
4 siblings, 0 replies; 6+ messages in thread
From: Abhijit Gangurde @ 2026-09-08 9:08 UTC (permalink / raw)
To: jgg, leon, brett.creeley, andrew+netdev, davem, edumazet, kuba,
pabeni
Cc: allen.hubbe, nikhil.agarwal, linux-rdma, netdev, linux-kernel,
Amit Kumar, Abhijit Gangurde
From: Amit Kumar <a.k@amd.com>
Implement device supported verb APIs for shared receive queue.
Signed-off-by: Amit Kumar <a.k@amd.com>
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
---
.../infiniband/hw/ionic/ionic_controlpath.c | 392 +++++++++++++++---
drivers/infiniband/hw/ionic/ionic_datapath.c | 2 +-
drivers/infiniband/hw/ionic/ionic_fw.h | 53 +++
drivers/infiniband/hw/ionic/ionic_ibdev.c | 16 +
drivers/infiniband/hw/ionic/ionic_ibdev.h | 24 +-
drivers/infiniband/hw/ionic/ionic_lif_cfg.c | 1 +
drivers/infiniband/hw/ionic/ionic_lif_cfg.h | 1 +
include/uapi/rdma/ionic-abi.h | 2 +-
8 files changed, 431 insertions(+), 60 deletions(-)
diff --git a/drivers/infiniband/hw/ionic/ionic_controlpath.c b/drivers/infiniband/hw/ionic/ionic_controlpath.c
index 884f5665e7a0..6979e0c5a25c 100644
--- a/drivers/infiniband/hw/ionic/ionic_controlpath.c
+++ b/drivers/infiniband/hw/ionic/ionic_controlpath.c
@@ -14,6 +14,8 @@
#define ionic_set_ecn(tos) (((tos) | 2u) & ~1u)
#define ionic_clear_ecn(tos) ((tos) & ~3u)
+#define QP_USES_SRQ(qp) ((qp)->srq)
+
static int ionic_validate_qdesc(struct ionic_qdesc *q)
{
if (!q->addr || !q->size || !q->mask ||
@@ -1501,7 +1503,7 @@ static int ionic_create_qp_cmd(struct ionic_ibdev *dev,
wr.wqe.cmd.create_qp.sq_dma_addr = ionic_pgtbl_dma(sq_buf, 0);
}
- if (qp->has_rq) {
+ if (!QP_USES_SRQ(qp)) {
wr.wqe.cmd.create_qp.rq_cq_id = cpu_to_le32(recv_cq->cqid);
wr.wqe.cmd.create_qp.rq_depth_log2 = qp->rq.q.depth_log2;
wr.wqe.cmd.create_qp.rq_stride_log2 = qp->rq.q.stride_log2;
@@ -1510,6 +1512,9 @@ static int ionic_create_qp_cmd(struct ionic_ibdev *dev,
wr.wqe.cmd.create_qp.rq_map_count =
cpu_to_le32(rq_buf->tbl_pages);
wr.wqe.cmd.create_qp.rq_dma_addr = ionic_pgtbl_dma(rq_buf, 0);
+ } else {
+ wr.wqe.cmd.create_qp.rq_tbl_index_srq_id = cpu_to_le32(qp->srq->rq.qid);
+ wr.wqe.cmd.create_qp.rq_cq_id = cpu_to_le32(recv_cq->cqid);
}
ionic_admin_post(dev, &wr);
@@ -1695,7 +1700,7 @@ static int ionic_query_qp_cmd(struct ionic_ibdev *dev,
ionic_v1_send_wqe_max_data(qp->sq.stride_log2, expdb);
}
- if (qp->has_rq) {
+ if (!QP_USES_SRQ(qp)) {
attr->cap.max_recv_sge =
ionic_v1_recv_wqe_max_sge(qp->rq.q.stride_log2,
qp->rq.spec,
@@ -2069,6 +2074,42 @@ static void ionic_qp_sq_destroy(struct ionic_ibdev *dev,
ionic_queue_destroy(&qp->sq, dev->lif_cfg.hwdev);
}
+static void ionic_rq_mmap_cmb(struct ionic_ibdev *dev,
+ struct ionic_ctx *ctx,
+ struct ionic_rq *rq,
+ u64 *cmb_offset)
+{
+ bool wc;
+
+ /* set mapping by default to uncached for
+ * expdb (to guarantee writes order) otherwise
+ * writecombine, unless this default is
+ * overridden by userspace
+ */
+ if ((rq->cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) ==
+ (IONIC_CMB_WC | IONIC_CMB_UC)) {
+ ibdev_warn(&dev->ibdev,
+ "Both rq_cmb flags IONIC_CMB_WC and IONIC_CMB_UC set, using default driver mapping\n");
+ rq->cmb &= ~(IONIC_CMB_WC | IONIC_CMB_UC);
+ }
+
+ if (rq->cmb & IONIC_CMB_EXPDB)
+ wc = (rq->cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) == IONIC_CMB_WC;
+ else
+ wc = (rq->cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) != IONIC_CMB_UC;
+
+ /* let userspace know the mapping */
+ if (wc)
+ rq->cmb |= IONIC_CMB_WC;
+ else
+ rq->cmb |= IONIC_CMB_UC;
+
+ rq->mmap_cmb = ionic_mmap_entry_insert(ctx, rq->q.size,
+ PHYS_PFN(rq->cmb_addr),
+ wc ? IONIC_MMAP_WC : 0,
+ cmb_offset);
+}
+
static void ionic_rq_init_cmb(struct ionic_ibdev *dev,
struct ionic_rq *rq,
struct ib_udata *udata)
@@ -2306,19 +2347,26 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
spin_lock_init(&qp->rq.lock);
qp->has_sq = 1;
- qp->has_rq = 1;
+
+ if (attr->srq)
+ qp->srq = to_ionic_srq(attr->srq);
+ else
+ qp->srq = NULL;
if (attr->qp_type == IB_QPT_GSI) {
rc = ionic_get_gsi_qpid(dev, &qp->qpid);
} else {
udma_mask = BIT(dev->lif_cfg.udma_count) - 1;
- if (qp->has_sq)
+ if (attr->send_cq)
udma_mask &= to_ionic_vcq(attr->send_cq)->udma_mask;
- if (qp->has_rq)
+ if (attr->recv_cq)
udma_mask &= to_ionic_vcq(attr->recv_cq)->udma_mask;
+ if (attr->srq)
+ udma_mask &= BIT(to_ionic_srq(attr->srq)->udma_idx);
+
if (udata && req.udma_mask)
udma_mask &= req.udma_mask;
@@ -2345,13 +2393,8 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
goto err_ahid;
}
- if (udata) {
- if (req.rq_cmb & IONIC_CMB_ENABLE)
- qp->rq.cmb = req.rq_cmb;
-
- if (req.sq_cmb & IONIC_CMB_ENABLE)
- qp->sq_cmb = req.sq_cmb;
- }
+ if (udata && (req.sq_cmb & IONIC_CMB_ENABLE))
+ qp->sq_cmb = req.sq_cmb;
rc = ionic_qp_sq_init(dev, ctx, qp, &req.sq, &sq_buf,
attr->cap.max_send_wr, attr->cap.max_send_sge,
@@ -2359,22 +2402,25 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
if (rc)
goto err_sq;
- if (qp->has_rq) {
- /* for non-srq qps, rq qid is same as qpid */
- qp->rq.qid = qp->qpid;
- rc = ionic_rq_init(dev, ctx, &qp->rq, &req.rq, &rq_buf,
- attr->cap.max_recv_wr, attr->cap.max_recv_sge,
- req.rq_spec, udata);
- if (rc)
- goto err_rq;
- } else {
+ if (QP_USES_SRQ(qp)) {
rq_buf.tbl_buf = NULL;
rq_buf.tbl_limit = 0;
rq_buf.tbl_pages = 0;
if (udata)
rc = ionic_validate_qdesc_zero(&req.rq);
+ } else {
+ if (udata && (req.rq_cmb & IONIC_CMB_ENABLE))
+ qp->rq.cmb = req.rq_cmb;
+
+ /* for non-srq qps, rq qid is same as qpid */
+ qp->rq.qid = qp->qpid;
+ rc = ionic_rq_init(dev, ctx, &qp->rq, &req.rq, &rq_buf,
+ attr->cap.max_recv_wr, attr->cap.max_recv_sge,
+ req.rq_spec, udata);
}
+ if (rc)
+ goto err_rq;
rc = ionic_create_qp_cmd(dev, pd,
to_ionic_vcq_cq(attr->send_cq, qp->udma_idx),
@@ -2420,35 +2466,9 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
resp.sq_cmb = qp->sq_cmb;
}
- if (qp->rq.cmb & IONIC_CMB_ENABLE) {
- bool wc;
-
- if ((qp->rq.cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) ==
- (IONIC_CMB_WC | IONIC_CMB_UC)) {
- ibdev_dbg(&dev->ibdev,
- "Both rq.cmb flags IONIC_CMB_WC and IONIC_CMB_UC are set, using default driver mapping\n");
- qp->rq.cmb &= ~(IONIC_CMB_WC | IONIC_CMB_UC);
- }
-
- if (qp->rq.cmb & IONIC_CMB_EXPDB)
- wc = (qp->rq.cmb & (IONIC_CMB_WC | IONIC_CMB_UC))
- == IONIC_CMB_WC;
- else
- wc = (qp->rq.cmb & (IONIC_CMB_WC | IONIC_CMB_UC))
- != IONIC_CMB_UC;
-
- /* let userspace know the mapping */
- if (wc)
- qp->rq.cmb |= IONIC_CMB_WC;
- else
- qp->rq.cmb |= IONIC_CMB_UC;
+ if (!QP_USES_SRQ(qp) && (qp->rq.cmb & IONIC_CMB_ENABLE)) {
+ ionic_rq_mmap_cmb(dev, ctx, &qp->rq, &resp.rq_cmb_offset);
- qp->rq.mmap_cmb =
- ionic_mmap_entry_insert(ctx,
- qp->rq.q.size,
- PHYS_PFN(qp->rq.cmb_addr),
- wc ? IONIC_MMAP_WC : 0,
- &resp.rq_cmb_offset);
if (!qp->rq.mmap_cmb) {
rc = -ENOMEM;
goto err_mmap_rq;
@@ -2495,7 +2515,7 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
qp->sq_cqid = cq->cqid;
}
- if (qp->has_rq) {
+ if (!QP_USES_SRQ(qp)) {
cq = to_ionic_vcq_cq(attr->recv_cq, qp->udma_idx);
attr->cap.max_recv_wr = qp->rq.q.mask;
@@ -2509,7 +2529,7 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
return 0;
err_resp:
- if (udata && (qp->rq.cmb & IONIC_CMB_ENABLE))
+ if (udata && !QP_USES_SRQ(qp) && (qp->rq.cmb & IONIC_CMB_ENABLE))
rdma_user_mmap_entry_remove(qp->rq.mmap_cmb);
err_mmap_rq:
if (udata && (qp->sq_cmb & IONIC_CMB_ENABLE))
@@ -2517,9 +2537,10 @@ int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
err_mmap_sq:
ionic_destroy_qp_cmd(dev, qp->qpid);
err_cmd:
- ionic_pgtbl_unbuf(dev, &rq_buf);
- if (qp->has_rq)
+ if (!QP_USES_SRQ(qp)) {
+ ionic_pgtbl_unbuf(dev, &rq_buf);
ionic_rq_destroy(dev, ctx, &qp->rq);
+ }
err_rq:
ionic_pgtbl_unbuf(dev, &sq_buf);
ionic_qp_sq_destroy(dev, ctx, qp);
@@ -2570,7 +2591,7 @@ void ionic_flush_qp(struct ionic_ibdev *dev, struct ionic_qp *qp)
spin_unlock_irqrestore(&cq->lock, irqflags);
}
- if (qp->ibqp.recv_cq) {
+ if (qp->ibqp.recv_cq && !QP_USES_SRQ(qp)) {
cq = to_ionic_vcq_cq(qp->ibqp.recv_cq, qp->udma_idx);
/* Hold the CQ lock and QP rq.lock to set up flush */
@@ -2646,7 +2667,7 @@ static void ionic_reset_qp(struct ionic_ibdev *dev, struct ionic_qp *qp)
spin_unlock(&qp->sq_lock);
}
- if (qp->has_rq) {
+ if (!QP_USES_SRQ(qp)) {
spin_lock(&qp->rq.lock);
qp->rq.flush = false;
qp->rq.q.prod = 0;
@@ -2774,7 +2795,7 @@ int ionic_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (qp->has_sq)
attr->cap.max_send_wr = qp->sq.mask;
- if (qp->has_rq)
+ if (!QP_USES_SRQ(qp))
attr->cap.max_recv_wr = qp->rq.q.mask;
init_attr->event_handler = ibqp->event_handler;
@@ -2835,7 +2856,7 @@ int ionic_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
spin_unlock_irqrestore(&cq->lock, irqflags);
}
- if (qp->has_rq)
+ if (!QP_USES_SRQ(qp))
ionic_rq_destroy(dev, ctx, &qp->rq);
ionic_qp_sq_destroy(dev, ctx, qp);
@@ -2847,3 +2868,260 @@ int ionic_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
return 0;
}
+
+static int ionic_create_srq_cmd(struct ionic_ibdev *dev,
+ struct ionic_ctx *ctx,
+ struct ionic_srq *srq,
+ struct ionic_pd *pd,
+ struct ionic_tbl_buf *buf,
+ u8 udma_mask)
+{
+ struct ionic_admin_create_srq_resp *resp_buf;
+ const u16 dbid = ionic_ctx_dbid(dev, ctx);
+ struct ionic_admin_wr wr = {
+ .work = COMPLETION_INITIALIZER_ONSTACK(wr.work),
+ .wqe = {
+ .op = IONIC_V1_ADMIN_CREATE_SRQ,
+ .len = cpu_to_le16(IONIC_ADMIN_CREATE_SRQ_IN_V1_LEN),
+ .cmd.create_srq = {
+ .pd_id = cpu_to_le32(pd->pdid),
+ .depth_log2 = srq->rq.q.depth_log2,
+ .stride_log2 = srq->rq.q.stride_log2,
+ .page_size_log2 = buf->page_size_log2,
+ .map_count = cpu_to_le32(buf->tbl_pages),
+ .dma_addr = ionic_pgtbl_dma(buf, 0),
+ .dbid = cpu_to_le16(dbid),
+ .qid = cpu_to_le32(srq->rq.qid),
+ .low_wqes_limit = cpu_to_le16(srq->srq_limit),
+ .udma_mask = udma_mask,
+ }
+ }
+ };
+ dma_addr_t resp_buf_dma;
+ int rc;
+
+ if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_CREATE_SRQ)
+ return -EOPNOTSUPP;
+
+ resp_buf = kzalloc_obj(*resp_buf);
+ if (!resp_buf)
+ return -ENOMEM;
+
+ resp_buf_dma = dma_map_single(dev->lif_cfg.hwdev, resp_buf,
+ sizeof(*resp_buf),
+ DMA_FROM_DEVICE);
+
+ rc = dma_mapping_error(dev->lif_cfg.hwdev, resp_buf_dma);
+ if (rc)
+ goto err_dma;
+
+ wr.wqe.cmd.create_srq.resp_dma_addr = cpu_to_le64(resp_buf_dma);
+ wr.wqe.cmd.create_srq.resp_buf_len = cpu_to_le32(IONIC_ADMIN_CREATE_SRQ_OUT_V1_LEN);
+
+ ionic_admin_post(dev, &wr);
+
+ rc = ionic_admin_wait(dev, &wr, 0);
+ if (rc)
+ goto err_admin;
+
+ if (be32_to_cpu(wr.cqe.status_length) < IONIC_ADMIN_CREATE_SRQ_OUT_V1_LEN) {
+ rc = -EOPNOTSUPP;
+ goto err_admin;
+ }
+
+ srq->rq.qid = le32_to_cpu(resp_buf->id);
+ srq->udma_idx = resp_buf->udma_idx;
+
+err_admin:
+ dma_unmap_single(dev->lif_cfg.hwdev, resp_buf_dma, sizeof(*resp_buf),
+ DMA_FROM_DEVICE);
+err_dma:
+ kfree(resp_buf);
+
+ return rc;
+}
+
+static int ionic_destroy_srq_cmd(struct ionic_ibdev *dev, u32 srqid)
+{
+ struct ionic_admin_wr wr = {
+ .work = COMPLETION_INITIALIZER_ONSTACK(wr.work),
+ .wqe = {
+ .op = IONIC_V1_ADMIN_DESTROY_SRQ,
+ .len = cpu_to_le16(IONIC_ADMIN_DESTROY_SRQ_IN_V1_LEN),
+ .cmd.destroy_srq = {
+ .qid = cpu_to_le32(srqid),
+ },
+ }
+ };
+
+ if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_DESTROY_SRQ)
+ return -EOPNOTSUPP;
+
+ ionic_admin_post(dev, &wr);
+
+ return ionic_admin_wait(dev, &wr, IONIC_ADMIN_F_TEARDOWN);
+}
+
+static int ionic_modify_srq_cmd(struct ionic_ibdev *dev, u32 srqid,
+ u16 srq_limit)
+{
+ struct ionic_admin_wr wr = {
+ .work = COMPLETION_INITIALIZER_ONSTACK(wr.work),
+ .wqe = {
+ .op = IONIC_V1_ADMIN_MODIFY_SRQ,
+ .len = cpu_to_le16(IONIC_ADMIN_MODIFY_SRQ_IN_V1_LEN),
+ .cmd.modify_srq = {
+ .qid = cpu_to_le32(srqid),
+ .low_wqes_limit = cpu_to_le16(srq_limit),
+ },
+ }
+ };
+
+ if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_MODIFY_SRQ)
+ return -EOPNOTSUPP;
+
+ ionic_admin_post(dev, &wr);
+
+ return ionic_admin_wait(dev, &wr, IONIC_ADMIN_F_TEARDOWN);
+}
+
+int ionic_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *attr,
+ struct ib_udata *udata)
+{
+ struct ionic_ibdev *dev = to_ionic_ibdev(ibsrq->device);
+ struct ionic_pd *pd = to_ionic_pd(ibsrq->pd);
+ struct ionic_srq *srq = to_ionic_srq(ibsrq);
+ struct ionic_ctx *ctx =
+ rdma_udata_to_drv_context(udata, struct ionic_ctx, ibctx);
+ struct ionic_srq_resp resp = {};
+ struct ionic_srq_req req = {};
+ struct ionic_tbl_buf buf = {};
+ u8 udma_mask;
+ int rc;
+
+ if (!ctx)
+ return -EOPNOTSUPP;
+
+ if (attr->srq_type != IB_SRQT_BASIC)
+ return -EOPNOTSUPP;
+
+ if (attr->attr.max_sge > IONIC_MAX_SRQ_SGES)
+ return -EINVAL;
+
+ if (attr->attr.srq_limit >= IONIC_MAX_SRQ_LIMIT)
+ return -EINVAL;
+
+ udma_mask = BIT(dev->lif_cfg.udma_count) - 1;
+ if (udata) {
+ rc = ib_copy_validate_udata_in(udata, req, rsvd);
+ if (rc)
+ return rc;
+
+ udma_mask &= req.udma_mask;
+ }
+
+ if (!udma_mask)
+ return -EINVAL;
+
+ rc = ionic_rq_init(dev, ctx, &srq->rq, &req.rq, &buf,
+ attr->attr.max_wr, attr->attr.max_sge,
+ req.rq_spec, udata);
+ if (rc)
+ return rc;
+
+ srq->srq_limit = attr->attr.srq_limit;
+
+ rc = ionic_create_srq_cmd(dev, ctx, srq, pd, &buf, udma_mask);
+ if (rc)
+ goto err_cmd;
+
+ ionic_queue_dbell_init(&srq->rq.q, srq->rq.qid);
+
+ if (udata) {
+ resp.srqid = srq->rq.qid;
+ resp.udma_idx = srq->udma_idx;
+
+ if (srq->rq.cmb & IONIC_CMB_ENABLE) {
+ ionic_rq_mmap_cmb(dev, ctx, &srq->rq, &resp.rq_cmb_offset);
+ if (!srq->rq.mmap_cmb) {
+ rc = -ENOMEM;
+ goto err_mmap_rq;
+ }
+
+ resp.rq_cmb = srq->rq.cmb;
+ }
+
+ rc = ib_respond_udata(udata, resp);
+ if (rc)
+ goto err_resp;
+ }
+
+ ionic_pgtbl_unbuf(dev, &buf);
+ attr->attr.max_wr = srq->rq.q.mask;
+
+ return 0;
+err_resp:
+ if (udata && (srq->rq.cmb & IONIC_CMB_ENABLE))
+ rdma_user_mmap_entry_remove(srq->rq.mmap_cmb);
+err_mmap_rq:
+ ionic_destroy_srq_cmd(dev, srq->rq.qid);
+err_cmd:
+ ionic_pgtbl_unbuf(dev, &buf);
+ ionic_rq_destroy(dev, ctx, &srq->rq);
+
+ return rc;
+}
+
+int ionic_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
+{
+ struct ionic_ctx *ctx =
+ rdma_udata_to_drv_context(udata, struct ionic_ctx, ibctx);
+ struct ionic_ibdev *dev = to_ionic_ibdev(ibsrq->device);
+ struct ionic_srq *srq = to_ionic_srq(ibsrq);
+ int rc;
+
+ rc = ionic_destroy_srq_cmd(dev, srq->rq.qid);
+ if (rc)
+ return rc;
+
+ ionic_rq_destroy(dev, ctx, &srq->rq);
+
+ return 0;
+}
+
+int ionic_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
+{
+ struct ionic_srq *srq = to_ionic_srq(ibsrq);
+
+ srq_attr->max_wr = srq->rq.q.mask;
+ srq_attr->max_sge =
+ ionic_v1_recv_wqe_max_sge(srq->rq.q.stride_log2, srq->rq.spec,
+ srq->rq.cmb & IONIC_CMB_EXPDB);
+ srq_attr->srq_limit = srq->srq_limit;
+
+ return 0;
+}
+
+int ionic_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask, struct ib_udata *udata)
+{
+ struct ionic_ibdev *dev = to_ionic_ibdev(ibsrq->device);
+ struct ionic_srq *srq = to_ionic_srq(ibsrq);
+ int rc;
+
+ if (attr_mask & IB_SRQ_MAX_WR)
+ return -EINVAL;
+
+ if (attr_mask & IB_SRQ_LIMIT) {
+ if (attr->srq_limit >= IONIC_MAX_SRQ_LIMIT)
+ return -EINVAL;
+
+ rc = ionic_modify_srq_cmd(dev, srq->rq.qid, attr->srq_limit);
+ if (rc)
+ return rc;
+
+ srq->srq_limit = attr->srq_limit;
+ }
+
+ return 0;
+}
diff --git a/drivers/infiniband/hw/ionic/ionic_datapath.c b/drivers/infiniband/hw/ionic/ionic_datapath.c
index 9c40b54123d5..e2d4d441052e 100644
--- a/drivers/infiniband/hw/ionic/ionic_datapath.c
+++ b/drivers/infiniband/hw/ionic/ionic_datapath.c
@@ -1311,7 +1311,7 @@ static int ionic_post_recv_common(struct ionic_ibdev *dev,
if (!bad)
return -EINVAL;
- if (!qp->has_rq) {
+ if (qp->srq) {
*bad = wr;
return -EINVAL;
}
diff --git a/drivers/infiniband/hw/ionic/ionic_fw.h b/drivers/infiniband/hw/ionic/ionic_fw.h
index 7a02e799de2b..a625149474e1 100644
--- a/drivers/infiniband/hw/ionic/ionic_fw.h
+++ b/drivers/infiniband/hw/ionic/ionic_fw.h
@@ -88,6 +88,10 @@ static inline int to_ionic_mr_flags(int access)
return flags;
}
+enum ionic_srq_flags {
+ IONIC_SRQF_CMB = BIT(0),
+};
+
enum ionic_qp_flags {
/* bits that determine qp access */
IONIC_QPF_REMOTE_WRITE = BIT(0),
@@ -857,6 +861,48 @@ struct ionic_admin_query_qp {
static_assert(sizeof(struct ionic_admin_query_qp) ==
IONIC_ADMIN_QUERY_QP_IN_V1_LEN);
+struct ionic_admin_create_srq {
+ __le64 dma_addr;
+ __le32 map_count;
+ __le32 pd_id;
+ __le32 qid;
+ __le16 dbid;
+ __le16 low_wqes_limit;
+ __le16 flags;
+ __u8 depth_log2;
+ __u8 stride_log2;
+ __u8 page_size_log2;
+ __u8 udma_mask;
+ __le32 resp_buf_len;
+ __le64 resp_dma_addr;
+} __packed;
+
+#define IONIC_ADMIN_CREATE_SRQ_IN_V1_LEN 42
+static_assert(sizeof(struct ionic_admin_create_srq) == IONIC_ADMIN_CREATE_SRQ_IN_V1_LEN);
+
+struct ionic_admin_create_srq_resp {
+ __le32 id;
+ __u8 udma_idx;
+} __packed;
+
+#define IONIC_ADMIN_CREATE_SRQ_OUT_V1_LEN 5
+static_assert(sizeof(struct ionic_admin_create_srq_resp) == IONIC_ADMIN_CREATE_SRQ_OUT_V1_LEN);
+
+struct ionic_admin_modify_srq {
+ __le32 qid;
+ __le16 low_wqes_limit;
+} __packed;
+
+#define IONIC_ADMIN_MODIFY_SRQ_IN_V1_LEN 6
+static_assert(sizeof(struct ionic_admin_modify_srq) == IONIC_ADMIN_MODIFY_SRQ_IN_V1_LEN);
+
+struct ionic_admin_destroy_srq {
+ __le32 qid;
+} __packed;
+
+#define IONIC_ADMIN_DESTROY_SRQ_IN_V1_LEN 4
+static_assert(sizeof(struct ionic_admin_destroy_srq) == IONIC_ADMIN_DESTROY_SRQ_IN_V1_LEN);
+
#define ADMIN_WQE_STRIDE 64
#define ADMIN_WQE_HDR_LEN 4
@@ -879,6 +925,9 @@ struct ionic_v1_admin_wqe {
struct ionic_admin_destroy_qp destroy_qp;
struct ionic_admin_mod_qp mod_qp;
struct ionic_admin_query_qp query_qp;
+ struct ionic_admin_create_srq create_srq;
+ struct ionic_admin_modify_srq modify_srq;
+ struct ionic_admin_destroy_srq destroy_srq;
} cmd;
};
@@ -925,6 +974,10 @@ enum ionic_v1_admin_op {
IONIC_V1_ADMIN_DESTROY_AH,
IONIC_V1_ADMIN_QP_STATS_HDRS,
IONIC_V1_ADMIN_QP_STATS_VALS,
+ IONIC_V1_ADMIN_CREATE_SRQ = 26,
+ IONIC_V1_ADMIN_MODIFY_SRQ,
+ IONIC_V1_ADMIN_QUERY_SRQ,
+ IONIC_V1_ADMIN_DESTROY_SRQ,
IONIC_V1_ADMIN_OPCODES_MAX,
};
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.c b/drivers/infiniband/hw/ionic/ionic_ibdev.c
index cba7809ec3d9..3187f6297946 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.c
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.c
@@ -73,6 +73,11 @@ static int ionic_query_device(struct ib_device *ibdev,
attr->max_ah = dev->lif_cfg.nahs_per_lif;
attr->max_fast_reg_page_list_len = dev->lif_cfg.npts_per_lif / 2;
attr->max_pkeys = IONIC_PKEY_TBL_LEN;
+ if (dev->lif_cfg.srq_count && ionic_fw_has_qid_alloc(dev, IONIC_LIF_RDMA_ALLOC_QID_SRQ)) {
+ attr->max_srq = dev->lif_cfg.srq_count;
+ attr->max_srq_wr = IONIC_MAX_SRQ_DEPTH;
+ attr->max_srq_sge = IONIC_MAX_SRQ_SGES;
+ }
return 0;
}
@@ -266,6 +271,15 @@ static const struct ib_device_ops ionic_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_mw, ionic_mr, ibmw),
};
+static const struct ib_device_ops ionic_srq_ops = {
+ .create_srq = ionic_create_srq,
+ .modify_srq = ionic_modify_srq,
+ .query_srq = ionic_query_srq,
+ .destroy_srq = ionic_destroy_srq,
+
+ INIT_RDMA_OBJ_SIZE(ib_srq, ionic_srq, ibsrq),
+};
+
static void ionic_init_resids(struct ionic_ibdev *dev)
{
ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count);
@@ -354,6 +368,8 @@ static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev)
goto err_admin;
ib_set_device_ops(&dev->ibdev, &ionic_dev_ops);
+ if (dev->lif_cfg.srq_count && ionic_fw_has_qid_alloc(dev, IONIC_LIF_RDMA_ALLOC_QID_SRQ))
+ ib_set_device_ops(&dev->ibdev, &ionic_srq_ops);
ionic_stats_init(dev);
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.h b/drivers/infiniband/hw/ionic/ionic_ibdev.h
index b73de5d25400..acc0382f2023 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.h
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.h
@@ -36,6 +36,10 @@
#define IONIC_SQCMB_ORDER 5
#define IONIC_RQCMB_ORDER 0
+#define IONIC_MAX_SRQ_SGES 2
+#define IONIC_MAX_SRQ_LIMIT 0xffff
+#define IONIC_MAX_SRQ_DEPTH 0xffff
+
#define IONIC_META_LAST ((void *)1ul)
#define IONIC_META_POSTED ((void *)2ul)
@@ -265,6 +269,13 @@ struct ionic_rq {
bool flush;
};
+struct ionic_srq {
+ struct ib_srq ibsrq;
+ struct ionic_rq rq;
+ u16 srq_limit;
+ u8 udma_idx;
+};
+
struct ionic_qp {
struct ib_qp ibqp;
enum ib_qp_state state;
@@ -275,7 +286,6 @@ struct ionic_qp {
u8 udma_idx;
u8 has_ah:1;
u8 has_sq:1;
- u8 has_rq:1;
u8 sig_all:1;
struct list_head qp_list_counter;
@@ -314,6 +324,7 @@ struct ionic_qp {
int dcqcn_profile;
struct ib_ud_header *hdr;
+ struct ionic_srq *srq;
};
struct ionic_ah {
@@ -408,6 +419,11 @@ static inline struct ionic_qp *to_ionic_qp(struct ib_qp *ibqp)
return container_of(ibqp, struct ionic_qp, ibqp);
}
+static inline struct ionic_srq *to_ionic_srq(struct ib_srq *ibsrq)
+{
+ return container_of(ibsrq, struct ionic_srq, ibsrq);
+}
+
static inline struct ionic_ah *to_ionic_ah(struct ib_ah *ibah)
{
return container_of(ibah, struct ionic_ah, ibah);
@@ -517,6 +533,12 @@ int ionic_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
int ionic_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
struct ib_qp_init_attr *init_attr);
int ionic_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
+int ionic_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *attr,
+ struct ib_udata *udata);
+int ionic_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata);
+int ionic_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr);
+int ionic_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
/* ionic_datapath.c */
int ionic_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
diff --git a/drivers/infiniband/hw/ionic/ionic_lif_cfg.c b/drivers/infiniband/hw/ionic/ionic_lif_cfg.c
index c381bda4360d..66cee57442e7 100644
--- a/drivers/infiniband/hw/ionic/ionic_lif_cfg.c
+++ b/drivers/infiniband/hw/ionic/ionic_lif_cfg.c
@@ -75,6 +75,7 @@ void ionic_fill_lif_cfg(struct ionic_lif *lif, struct ionic_lif_cfg *cfg)
cfg->eq_count = lif->ionic->neqs_per_lif;
cfg->cq_count = le32_to_cpu(ident->rdma.cq_qtype.qid_count);
cfg->qp_count = le32_to_cpu(ident->rdma.sq_qtype.qid_count);
+ cfg->srq_count = le32_to_cpu(ident->rdma.srq_qtype.qid_count);
cfg->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif);
cfg->aq_qtype = ident->rdma.aq_qtype.qtype;
diff --git a/drivers/infiniband/hw/ionic/ionic_lif_cfg.h b/drivers/infiniband/hw/ionic/ionic_lif_cfg.h
index 68aec06908ca..bc14fc0921da 100644
--- a/drivers/infiniband/hw/ionic/ionic_lif_cfg.h
+++ b/drivers/infiniband/hw/ionic/ionic_lif_cfg.h
@@ -38,6 +38,7 @@ struct ionic_lif_cfg {
int eq_count;
int cq_count;
int qp_count;
+ int srq_count;
u16 stats_type;
u8 aq_qtype;
diff --git a/include/uapi/rdma/ionic-abi.h b/include/uapi/rdma/ionic-abi.h
index 3d8d56922a93..ac48fcd19a4f 100644
--- a/include/uapi/rdma/ionic-abi.h
+++ b/include/uapi/rdma/ionic-abi.h
@@ -113,7 +113,7 @@ struct ionic_srq_req {
};
struct ionic_srq_resp {
- __u32 qpid;
+ __u32 srqid;
__u8 rq_cmb;
__u8 udma_idx;
__u8 rsvd[2];
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [for-next v1 5/5] RDMA/ionic: implement SRQ event handling support
2026-09-08 9:07 [for-next v1 0/5] RDMA/ionic: add SRQ support and firmware assigned CQ and SRQ IDs Abhijit Gangurde
` (3 preceding siblings ...)
2026-09-08 9:08 ` [for-next v1 4/5] RDMA/ionic: add Shared receive queue (SRQ) support Abhijit Gangurde
@ 2026-09-08 9:08 ` Abhijit Gangurde
4 siblings, 0 replies; 6+ messages in thread
From: Abhijit Gangurde @ 2026-09-08 9:08 UTC (permalink / raw)
To: jgg, leon, brett.creeley, andrew+netdev, davem, edumazet, kuba,
pabeni
Cc: allen.hubbe, nikhil.agarwal, linux-rdma, netdev, linux-kernel,
Amit Kumar, Abhijit Gangurde
From: Amit Kumar <a.k@amd.com>
Introduce SRQ event types and associated events. Report these events
through the SRQ event handler during event processing.
Signed-off-by: Amit Kumar <a.k@amd.com>
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
---
drivers/infiniband/hw/ionic/ionic_admin.c | 47 +++++++++++++++++++
.../infiniband/hw/ionic/ionic_controlpath.c | 12 +++++
drivers/infiniband/hw/ionic/ionic_fw.h | 6 ++-
drivers/infiniband/hw/ionic/ionic_ibdev.c | 4 ++
drivers/infiniband/hw/ionic/ionic_ibdev.h | 10 ++++
5 files changed, 78 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/ionic/ionic_admin.c b/drivers/infiniband/hw/ionic/ionic_admin.c
index cda48c36c047..4c76bc82e580 100644
--- a/drivers/infiniband/hw/ionic/ionic_admin.c
+++ b/drivers/infiniband/hw/ionic/ionic_admin.c
@@ -945,6 +945,49 @@ static void ionic_qp_event(struct ionic_ibdev *dev, u32 qpid, u8 code)
kref_put(&qp->qp_kref, ionic_qp_complete);
}
+static void ionic_srq_event(struct ionic_ibdev *dev, u32 srqid, u8 code)
+{
+ struct ionic_srq *srq;
+ struct ib_event ibev;
+ unsigned long irqflags;
+
+ xa_lock_irqsave(&dev->srq_tbl, irqflags);
+ srq = xa_load(&dev->srq_tbl, srqid);
+ if (srq)
+ kref_get(&srq->kref);
+ xa_unlock_irqrestore(&dev->srq_tbl, irqflags);
+
+ if (!srq) {
+ ibdev_dbg(&dev->ibdev,
+ "missing srqid %#x code %u\n", srqid, code);
+ return;
+ }
+
+ ibev.device = &dev->ibdev;
+ ibev.element.srq = &srq->ibsrq;
+
+ switch (code) {
+ case IONIC_V1_EQE_SRQ_LIMIT_REACHED:
+ ibev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ break;
+
+ case IONIC_V1_EQE_SRQ_ERR:
+ ibev.event = IB_EVENT_SRQ_ERR;
+ break;
+
+ default:
+ ibdev_dbg(&dev->ibdev,
+ "unrecognized srqid %#x code %u\n", srqid, code);
+ goto out;
+ }
+
+ if (srq->ibsrq.event_handler)
+ srq->ibsrq.event_handler(&ibev, srq->ibsrq.srq_context);
+
+out:
+ kref_put(&srq->kref, ionic_srq_complete);
+}
+
static u16 ionic_poll_eq(struct ionic_eq *eq, u16 budget)
{
struct ionic_ibdev *dev = eq->dev;
@@ -978,6 +1021,10 @@ static u16 ionic_poll_eq(struct ionic_eq *eq, u16 budget)
ionic_qp_event(dev, qid, code);
break;
+ case IONIC_V1_EQE_TYPE_SRQ:
+ ionic_srq_event(dev, qid, code);
+ break;
+
default:
ibdev_dbg(&dev->ibdev,
"unknown event %#x type %u\n", evt, type);
diff --git a/drivers/infiniband/hw/ionic/ionic_controlpath.c b/drivers/infiniband/hw/ionic/ionic_controlpath.c
index 6979e0c5a25c..de1b8aa1815c 100644
--- a/drivers/infiniband/hw/ionic/ionic_controlpath.c
+++ b/drivers/infiniband/hw/ionic/ionic_controlpath.c
@@ -3056,6 +3056,13 @@ int ionic_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *attr,
goto err_resp;
}
+ kref_init(&srq->kref);
+ init_completion(&srq->rel_comp);
+
+ rc = xa_insert_irq(&dev->srq_tbl, srq->rq.qid, srq, GFP_KERNEL);
+ if (rc)
+ goto err_resp;
+
ionic_pgtbl_unbuf(dev, &buf);
attr->attr.max_wr = srq->rq.q.mask;
@@ -3080,6 +3087,11 @@ int ionic_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
struct ionic_srq *srq = to_ionic_srq(ibsrq);
int rc;
+ xa_erase_irq(&dev->srq_tbl, srq->rq.qid);
+
+ kref_put(&srq->kref, ionic_srq_complete);
+ wait_for_completion(&srq->rel_comp);
+
rc = ionic_destroy_srq_cmd(dev, srq->rq.qid);
if (rc)
return rc;
diff --git a/drivers/infiniband/hw/ionic/ionic_fw.h b/drivers/infiniband/hw/ionic/ionic_fw.h
index a625149474e1..426add364898 100644
--- a/drivers/infiniband/hw/ionic/ionic_fw.h
+++ b/drivers/infiniband/hw/ionic/ionic_fw.h
@@ -1013,7 +1013,7 @@ enum ionic_v1_eqe_evt_bits {
/* cq error events */
IONIC_V1_EQE_CQ_ERR = 8,
- /* qp and srq events */
+ /* qp events */
IONIC_V1_EQE_TYPE_QP = 1,
/* qp normal events */
IONIC_V1_EQE_SRQ_LEVEL = 0,
@@ -1024,6 +1024,10 @@ enum ionic_v1_eqe_evt_bits {
IONIC_V1_EQE_QP_ERR = 8,
IONIC_V1_EQE_QP_ERR_REQUEST = 9,
IONIC_V1_EQE_QP_ERR_ACCESS = 10,
+ /* srq events */
+ IONIC_V1_EQE_TYPE_SRQ = 2,
+ IONIC_V1_EQE_SRQ_LIMIT_REACHED = 0,
+ IONIC_V1_EQE_SRQ_ERR = 1,
};
enum ionic_tfp_csum_profiles {
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.c b/drivers/infiniband/hw/ionic/ionic_ibdev.c
index 3187f6297946..b0206d34b6dc 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.c
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.c
@@ -318,6 +318,8 @@ static void ionic_destroy_ibdev(struct ionic_ibdev *dev)
xa_destroy(&dev->qp_tbl);
WARN_ON(!xa_empty(&dev->cq_tbl));
xa_destroy(&dev->cq_tbl);
+ WARN_ON(!xa_empty(&dev->srq_tbl));
+ xa_destroy(&dev->srq_tbl);
ib_dealloc_device(&dev->ibdev);
}
@@ -336,6 +338,7 @@ static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev)
xa_init_flags(&dev->qp_tbl, GFP_ATOMIC);
xa_init_flags(&dev->cq_tbl, GFP_ATOMIC);
+ xa_init_flags(&dev->srq_tbl, GFP_ATOMIC);
ionic_init_resids(dev);
@@ -388,6 +391,7 @@ static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev)
ionic_destroy_resids(dev);
xa_destroy(&dev->qp_tbl);
xa_destroy(&dev->cq_tbl);
+ xa_destroy(&dev->srq_tbl);
ib_dealloc_device(&dev->ibdev);
return ERR_PTR(rc);
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.h b/drivers/infiniband/hw/ionic/ionic_ibdev.h
index acc0382f2023..bab15b57d2bb 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.h
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.h
@@ -92,6 +92,7 @@ struct ionic_ibdev {
struct xarray qp_tbl;
struct xarray cq_tbl;
+ struct xarray srq_tbl;
struct ionic_resid_bits inuse_dbid;
struct ionic_resid_bits inuse_pdid;
@@ -272,6 +273,8 @@ struct ionic_rq {
struct ionic_srq {
struct ib_srq ibsrq;
struct ionic_rq rq;
+ struct kref kref;
+ struct completion rel_comp;
u16 srq_limit;
u8 udma_idx;
};
@@ -469,6 +472,13 @@ static inline bool ionic_fw_has_qid_alloc(struct ionic_ibdev *dev,
return dev->lif_cfg.alloc_qid_cap & qtype;
}
+static inline void ionic_srq_complete(struct kref *kref)
+{
+ struct ionic_srq *srq = container_of(kref, struct ionic_srq, kref);
+
+ complete(&srq->rel_comp);
+}
+
/* ionic_admin.c */
extern struct workqueue_struct *ionic_evt_workq;
void ionic_admin_post(struct ionic_ibdev *dev, struct ionic_admin_wr *wr);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-08 9:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 9:07 [for-next v1 0/5] RDMA/ionic: add SRQ support and firmware assigned CQ and SRQ IDs Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 1/5] net: ionic: Fetch qid allocation and SRQ capability from firmware Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 2/5] RDMA/ionic: support firmware-assigned CQ IDs Abhijit Gangurde
2026-09-08 9:07 ` [for-next v1 3/5] RDMA/ionic: segregate rq related fields from ionic_qp into a new ionic_rq struct Abhijit Gangurde
2026-09-08 9:08 ` [for-next v1 4/5] RDMA/ionic: add Shared receive queue (SRQ) support Abhijit Gangurde
2026-09-08 9:08 ` [for-next v1 5/5] RDMA/ionic: implement SRQ event handling support Abhijit Gangurde
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox