[PATCH 4/4] RDMA/ionic: implement SRQ event handling support
From: Abhijit Gangurde
Date: Tue Jul 07 2026 - 05:57:39 EST
Introduce SRQ event types and associated events. Report these events
through the SRQ event handler during event processing.
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@xxxxxxx>
---
drivers/infiniband/hw/ionic/ionic_admin.c | 47 +++++++++++++++++++
.../infiniband/hw/ionic/ionic_controlpath.c | 19 ++++++++
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, 85 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/ionic/ionic_admin.c b/drivers/infiniband/hw/ionic/ionic_admin.c
index 2537aa55d12d..ad8a45d09252 100644
--- a/drivers/infiniband/hw/ionic/ionic_admin.c
+++ b/drivers/infiniband/hw/ionic/ionic_admin.c
@@ -890,6 +890,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;
@@ -923,6 +966,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 35eb08dd0761..2525deb7a229 100644
--- a/drivers/infiniband/hw/ionic/ionic_controlpath.c
+++ b/drivers/infiniband/hw/ionic/ionic_controlpath.c
@@ -2811,6 +2811,7 @@ int ionic_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *attr,
struct ionic_srq_req req = {};
struct ionic_tbl_buf buf = {};
u8 udma_mask;
+ void *entry;
int rc;
if (attr->srq_type != IB_SRQT_BASIC)
@@ -2869,6 +2870,19 @@ 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);
+
+ entry = xa_store_irq(&dev->srq_tbl, srq->rq.qid, srq, GFP_KERNEL);
+ if (entry) {
+ if (!xa_is_err(entry))
+ rc = -EINVAL;
+ else
+ rc = xa_err(entry);
+
+ goto err_resp;
+ }
+
ionic_pgtbl_unbuf(dev, &buf);
attr->attr.max_wr = srq->rq.q.mask;
return 0;
@@ -2897,6 +2911,11 @@ int ionic_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
if (rc)
return rc;
+ xa_erase_irq(&dev->srq_tbl, srq->rq.qid);
+
+ kref_put(&srq->kref, ionic_srq_complete);
+ wait_for_completion(&srq->rel_comp);
+
ionic_rq_destroy(dev, ctx, &srq->rq);
ionic_put_srqid(dev, srq->rq.qid);
return 0;
diff --git a/drivers/infiniband/hw/ionic/ionic_fw.h b/drivers/infiniband/hw/ionic/ionic_fw.h
index 632b16932844..eafadb0a16c7 100644
--- a/drivers/infiniband/hw/ionic/ionic_fw.h
+++ b/drivers/infiniband/hw/ionic/ionic_fw.h
@@ -983,7 +983,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,
@@ -994,6 +994,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 d8a8e74f56ac..3b4abfc41ca4 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.c
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.c
@@ -310,6 +310,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);
}
@@ -328,6 +330,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);
@@ -380,6 +383,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 895672283264..e29f11b38036 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.h
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.h
@@ -91,6 +91,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;
};
@@ -456,6 +459,13 @@ static inline void ionic_cq_complete(struct kref *kref)
complete(&cq->cq_rel_comp);
}
+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