From: Abhijit Gangurde <abhijit.gangurde@amd.com>
To: <jgg@ziepe.ca>, <leon@kernel.org>, <brett.creeley@amd.com>,
<andrew+netdev@lunn.ch>, <davem@davemloft.net>,
<edumazet@google.com>, <kuba@kernel.org>, <pabeni@redhat.com>
Cc: <allen.hubbe@amd.com>, <nikhil.agarwal@amd.com>,
<linux-rdma@vger.kernel.org>, <netdev@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
Abhijit Gangurde <abhijit.gangurde@amd.com>
Subject: [for-next v1 2/5] RDMA/ionic: support firmware-assigned CQ IDs
Date: Tue, 8 Sep 2026 14:37:58 +0530 [thread overview]
Message-ID: <20260908090802.152142-3-abhijit.gangurde@amd.com> (raw)
In-Reply-To: <20260908090802.152142-1-abhijit.gangurde@amd.com>
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
next prev parent reply other threads:[~2026-09-08 9:09 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
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-09 9:10 ` sashiko-bot
2026-09-08 9:07 ` Abhijit Gangurde [this message]
2026-09-09 9:10 ` [for-next v1 2/5] RDMA/ionic: support firmware-assigned CQ IDs sashiko-bot
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-09 9:10 ` sashiko-bot
2026-09-08 9:08 ` [for-next v1 4/5] RDMA/ionic: add Shared receive queue (SRQ) support Abhijit Gangurde
2026-09-09 9:10 ` sashiko-bot
2026-09-08 9:08 ` [for-next v1 5/5] RDMA/ionic: implement SRQ event handling support Abhijit Gangurde
2026-09-09 9:10 ` sashiko-bot
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=20260908090802.152142-3-abhijit.gangurde@amd.com \
--to=abhijit.gangurde@amd.com \
--cc=allen.hubbe@amd.com \
--cc=andrew+netdev@lunn.ch \
--cc=brett.creeley@amd.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jgg@ziepe.ca \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nikhil.agarwal@amd.com \
--cc=pabeni@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.