From 962950a1e31193a5c96d8a2e6aaec80e6b552ebf Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 10 Mar 2026 13:06:40 -0700 Subject: [PATCH] cndm: Use event queues in driver Signed-off-by: Alex Forencich --- src/cndm/modules/cndm/Makefile | 1 + src/cndm/modules/cndm/cndm.h | 45 +++++++++++++++++++++++++++-- src/cndm/modules/cndm/cndm_cq.c | 42 +++++++++++++++++++-------- src/cndm/modules/cndm/cndm_hw.h | 8 ++--- src/cndm/modules/cndm/cndm_netdev.c | 20 +++++++++++-- src/cndm/modules/cndm/cndm_rq.c | 10 +++++-- src/cndm/modules/cndm/cndm_sq.c | 10 +++++-- 7 files changed, 110 insertions(+), 26 deletions(-) diff --git a/src/cndm/modules/cndm/Makefile b/src/cndm/modules/cndm/Makefile index f54dbdb..bc7c168 100644 --- a/src/cndm/modules/cndm/Makefile +++ b/src/cndm/modules/cndm/Makefile @@ -12,6 +12,7 @@ cndm-y += cndm_dev.o cndm-y += cndm_netdev.o cndm-y += cndm_ethtool.o cndm-y += cndm_ptp.o +cndm-y += cndm_eq.o cndm-y += cndm_cq.o cndm-y += cndm_sq.o cndm-y += cndm_rq.o diff --git a/src/cndm/modules/cndm/cndm.h b/src/cndm/modules/cndm/cndm.h index bfa533d..0afd31a 100644 --- a/src/cndm/modules/cndm/cndm.h +++ b/src/cndm/modules/cndm/cndm.h @@ -173,7 +173,7 @@ struct cndm_cq { int enabled; struct cndm_ring *src_ring; - + struct cndm_eq *eq; struct cndm_irq *irq; struct notifier_block irq_nb; @@ -183,6 +183,35 @@ struct cndm_cq { u8 __iomem *db_addr; }; +struct cndm_eq { + u32 cons_ptr; + + u32 size; + u32 size_mask; + u32 stride; + + size_t buf_size; + u8 *buf; + dma_addr_t buf_dma_addr; + + struct device *dev; + struct cndm_dev *cdev; + struct cndm_priv *priv; + int eqn; + int enabled; + + struct cndm_irq *irq; + struct notifier_block irq_nb; + + void (*handler)(struct cndm_eq *eq); + + spinlock_t table_lock; + struct radix_tree_root cq_table; + + u32 db_offset; + u8 __iomem *db_addr; +}; + struct cndm_priv { struct device *dev; struct net_device *ndev; @@ -198,6 +227,8 @@ struct cndm_priv { int rxq_count; int txq_count; + struct cndm_eq *eq; + struct cndm_ring *txq; struct cndm_ring *rxq; }; @@ -230,10 +261,20 @@ ktime_t cndm_read_cpl_ts(struct cndm_ring *ring, const struct cndm_cpl *cpl); void cndm_register_phc(struct cndm_dev *cdev); void cndm_unregister_phc(struct cndm_dev *cdev); +// cndm_eq.c +struct cndm_eq *cndm_create_eq(struct cndm_priv *priv); +void cndm_destroy_eq(struct cndm_eq *eq); +int cndm_open_eq(struct cndm_eq *eq, struct cndm_irq *irq, int size); +void cndm_close_eq(struct cndm_eq *eq); +int cndm_eq_attach_cq(struct cndm_eq *eq, struct cndm_cq *cq); +void cndm_eq_detach_cq(struct cndm_eq *eq, struct cndm_cq *cq); +void cndm_eq_write_cons_ptr(const struct cndm_eq *eq); +void cndm_eq_write_cons_ptr_arm(const struct cndm_eq *eq); + // cndm_cq.c struct cndm_cq *cndm_create_cq(struct cndm_priv *priv); void cndm_destroy_cq(struct cndm_cq *cq); -int cndm_open_cq(struct cndm_cq *cq, struct cndm_irq *irq, int size); +int cndm_open_cq(struct cndm_cq *cq, struct cndm_eq *eq, struct cndm_irq *irq, int size); void cndm_close_cq(struct cndm_cq *cq); void cndm_cq_write_cons_ptr(const struct cndm_cq *cq); void cndm_cq_write_cons_ptr_arm(const struct cndm_cq *cq); diff --git a/src/cndm/modules/cndm/cndm_cq.c b/src/cndm/modules/cndm/cndm_cq.c index 90e3741..81aff72 100644 --- a/src/cndm/modules/cndm/cndm_cq.c +++ b/src/cndm/modules/cndm/cndm_cq.c @@ -10,14 +10,7 @@ Authors: #include "cndm.h" -static int cndm_cq_int(struct notifier_block *nb, unsigned long action, void *data) -{ - struct cndm_cq *cq = container_of(nb, struct cndm_cq, irq_nb); - - napi_schedule_irqoff(&cq->napi); - - return NOTIFY_DONE; -} +static int cndm_cq_int(struct notifier_block *nb, unsigned long action, void *data); struct cndm_cq *cndm_create_cq(struct cndm_priv *priv) { @@ -51,14 +44,15 @@ void cndm_destroy_cq(struct cndm_cq *cq) kfree(cq); } -int cndm_open_cq(struct cndm_cq *cq, struct cndm_irq *irq, int size) +int cndm_open_cq(struct cndm_cq *cq, struct cndm_eq *eq, struct cndm_irq *irq, int size) { + u32 dqn; int ret = 0; struct cndm_cmd_queue cmd; struct cndm_cmd_queue rsp; - if (cq->enabled || cq->buf || !irq) + if (cq->enabled || cq->buf || (!irq && !eq)) return -EINVAL; cq->size = roundup_pow_of_two(size); @@ -70,12 +64,17 @@ int cndm_open_cq(struct cndm_cq *cq, struct cndm_irq *irq, int size) if (!cq->buf) return -ENOMEM; - if (irq) { + // can use either EQ or IRQ, but prefer EQ if both are specified + if (eq) { + cq->eq = eq; + dqn = eq->eqn; + } else if (irq) { ret = atomic_notifier_chain_register(&irq->nh, &cq->irq_nb); if (ret) goto fail; cq->irq = irq; + dqn = irq->index | 0x80000000; } cq->cons_ptr = 0; @@ -87,7 +86,7 @@ int cndm_open_cq(struct cndm_cq *cq, struct cndm_irq *irq, int size) cmd.flags = 0x00000000; cmd.port = cq->priv->ndev->dev_port; cmd.qn = 0; - cmd.qn2 = irq->index; // TODO + cmd.qn2 = dqn; cmd.pd = 0; cmd.size = ilog2(cq->size); cmd.dboffs = 0; @@ -106,6 +105,10 @@ int cndm_open_cq(struct cndm_cq *cq, struct cndm_irq *irq, int size) cq->db_offset = rsp.dboffs; cq->db_addr = cq->cdev->hw_addr + rsp.dboffs; + if (eq) { + cndm_eq_attach_cq(eq, cq); + } + cq->enabled = 1; cndm_cq_write_cons_ptr_arm(cq); @@ -140,6 +143,11 @@ void cndm_close_cq(struct cndm_cq *cq) cq->db_addr = NULL; } + if (cq->eq) { + cndm_eq_detach_cq(cq->eq, cq); + cq->eq = NULL; + } + if (cq->irq) { atomic_notifier_chain_unregister(&cq->irq->nh, &cq->irq_nb); cq->irq = NULL; @@ -161,3 +169,13 @@ void cndm_cq_write_cons_ptr_arm(const struct cndm_cq *cq) { iowrite32((cq->cons_ptr & 0xffff) | 0x80000000, cq->db_addr); } + +static int cndm_cq_int(struct notifier_block *nb, unsigned long action, void *data) +{ + struct cndm_cq *cq = container_of(nb, struct cndm_cq, irq_nb); + + if (likely(cq->handler)) + cq->handler(cq); + + return NOTIFY_DONE; +} diff --git a/src/cndm/modules/cndm/cndm_hw.h b/src/cndm/modules/cndm/cndm_hw.h index 1b7c68d..2ffc012 100644 --- a/src/cndm/modules/cndm/cndm_hw.h +++ b/src/cndm/modules/cndm/cndm_hw.h @@ -202,14 +202,10 @@ struct cndm_cpl { }; struct cndm_event { + __le16 rsvd0; __le16 type; - __le16 source; - __le32 rsvd0; + __le32 source; __le32 rsvd1; - __le32 rsvd2; - __le32 rsvd3; - __le32 rsvd4; - __le32 rsvd5; __le32 phase; }; diff --git a/src/cndm/modules/cndm/cndm_netdev.c b/src/cndm/modules/cndm/cndm_netdev.c index 02a7e7a..b61a6d8 100644 --- a/src/cndm/modules/cndm/cndm_netdev.c +++ b/src/cndm/modules/cndm/cndm_netdev.c @@ -38,7 +38,7 @@ static int cndm_open(struct net_device *ndev) goto fail; } - ret = cndm_open_cq(cq, &priv->cdev->irq[0], 256); + ret = cndm_open_cq(cq, priv->eq, &priv->cdev->irq[0], 256); if (ret) { cndm_destroy_cq(cq); goto fail; @@ -75,7 +75,7 @@ static int cndm_open(struct net_device *ndev) goto fail; } - ret = cndm_open_cq(cq, &priv->cdev->irq[0], 256); + ret = cndm_open_cq(cq, priv->eq, &priv->cdev->irq[0], 256); if (ret) { cndm_destroy_cq(cq); goto fail; @@ -326,6 +326,19 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port) ndev->min_mtu = ETH_MIN_MTU; ndev->max_mtu = 1500; + priv->eq = cndm_create_eq(priv); + if (IS_ERR_OR_NULL(priv->eq)) { + ret = PTR_ERR(priv->eq); + priv->eq = NULL; + goto fail; + } + + ret = cndm_open_eq(priv->eq, &priv->cdev->irq[0], 256); + if (ret) { + cndm_destroy_eq(priv->eq); + goto fail; + } + netif_carrier_off(ndev); ret = register_netdev(ndev); @@ -350,5 +363,8 @@ void cndm_destroy_netdev(struct net_device *ndev) if (priv->registered) unregister_netdev(ndev); + if (priv->eq) + cndm_destroy_eq(priv->eq); + free_netdev(ndev); } diff --git a/src/cndm/modules/cndm/cndm_rq.c b/src/cndm/modules/cndm/cndm_rq.c index 512619a..4025a0e 100644 --- a/src/cndm/modules/cndm/cndm_rq.c +++ b/src/cndm/modules/cndm/cndm_rq.c @@ -10,6 +10,8 @@ Authors: #include "cndm.h" +static void cndm_rq_cq_handler(struct cndm_cq *cq); + struct cndm_ring *cndm_create_rq(struct cndm_priv *priv) { struct cndm_ring *rq; @@ -69,7 +71,7 @@ int cndm_open_rq(struct cndm_ring *rq, struct cndm_priv *priv, struct cndm_cq *c rq->priv = priv; rq->cq = cq; cq->src_ring = rq; - // cq->handler = cndm_rx_irq; + cq->handler = cndm_rq_cq_handler; rq->prod_ptr = 0; rq->cons_ptr = 0; @@ -352,6 +354,11 @@ rx_drop: return done; } +static void cndm_rq_cq_handler(struct cndm_cq *cq) +{ + napi_schedule_irqoff(&cq->napi); +} + int cndm_poll_rx_cq(struct napi_struct *napi, int budget) { struct cndm_cq *cq = container_of(napi, struct cndm_cq, napi); @@ -364,7 +371,6 @@ int cndm_poll_rx_cq(struct napi_struct *napi, int budget) napi_complete(napi); - // TODO re-enable interrupts cndm_cq_write_cons_ptr_arm(cq); return done; diff --git a/src/cndm/modules/cndm/cndm_sq.c b/src/cndm/modules/cndm/cndm_sq.c index d2e1d3f..442ee2e 100644 --- a/src/cndm/modules/cndm/cndm_sq.c +++ b/src/cndm/modules/cndm/cndm_sq.c @@ -10,6 +10,8 @@ Authors: #include "cndm.h" +static void cndm_sq_cq_handler(struct cndm_cq *cq); + struct cndm_ring *cndm_create_sq(struct cndm_priv *priv) { struct cndm_ring *sq; @@ -69,7 +71,7 @@ int cndm_open_sq(struct cndm_ring *sq, struct cndm_priv *priv, struct cndm_cq *c sq->priv = priv; sq->cq = cq; cq->src_ring = sq; - // cq->handler = cndm_tx_irq; + cq->handler = cndm_sq_cq_handler; sq->prod_ptr = 0; sq->cons_ptr = 0; @@ -252,6 +254,11 @@ static int cndm_process_tx_cq(struct cndm_cq *cq, int napi_budget) return done; } +static void cndm_sq_cq_handler(struct cndm_cq *cq) +{ + napi_schedule_irqoff(&cq->napi); +} + int cndm_poll_tx_cq(struct napi_struct *napi, int budget) { struct cndm_cq *cq = container_of(napi, struct cndm_cq, napi); @@ -264,7 +271,6 @@ int cndm_poll_tx_cq(struct napi_struct *napi, int budget) napi_complete(napi); - // TODO re-enable interrupts cndm_cq_write_cons_ptr_arm(cq); return done;