cndm: Move interrupt handling out of CQ

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-03-09 22:23:56 -07:00
parent 2ea3c204de
commit ed61857bc3
3 changed files with 33 additions and 36 deletions

View File

@@ -174,6 +174,9 @@ struct cndm_cq {
struct cndm_ring *src_ring; struct cndm_ring *src_ring;
struct cndm_irq *irq;
struct notifier_block irq_nb;
void (*handler)(struct cndm_cq *cq); void (*handler)(struct cndm_cq *cq);
u32 db_offset; u32 db_offset;
@@ -190,9 +193,6 @@ struct cndm_priv {
void __iomem *hw_addr; void __iomem *hw_addr;
struct cndm_irq *irq;
struct notifier_block irq_nb;
struct hwtstamp_config hwts_config; struct hwtstamp_config hwts_config;
int rxq_count; int rxq_count;
@@ -233,7 +233,7 @@ void cndm_unregister_phc(struct cndm_dev *cdev);
// cndm_cq.c // cndm_cq.c
struct cndm_cq *cndm_create_cq(struct cndm_priv *priv); struct cndm_cq *cndm_create_cq(struct cndm_priv *priv);
void cndm_destroy_cq(struct cndm_cq *cq); void cndm_destroy_cq(struct cndm_cq *cq);
int cndm_open_cq(struct cndm_cq *cq, int irqn, int size); int cndm_open_cq(struct cndm_cq *cq, struct cndm_irq *irq, int size);
void cndm_close_cq(struct cndm_cq *cq); 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(const struct cndm_cq *cq);
void cndm_cq_write_cons_ptr_arm(const struct cndm_cq *cq); void cndm_cq_write_cons_ptr_arm(const struct cndm_cq *cq);

View File

@@ -10,6 +10,15 @@ Authors:
#include "cndm.h" #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;
}
struct cndm_cq *cndm_create_cq(struct cndm_priv *priv) struct cndm_cq *cndm_create_cq(struct cndm_priv *priv)
{ {
struct cndm_cq *cq; struct cndm_cq *cq;
@@ -25,6 +34,8 @@ struct cndm_cq *cndm_create_cq(struct cndm_priv *priv)
cq->cqn = -1; cq->cqn = -1;
cq->enabled = 0; cq->enabled = 0;
cq->irq_nb.notifier_call = cndm_cq_int;
cq->cons_ptr = 0; cq->cons_ptr = 0;
cq->db_offset = 0; cq->db_offset = 0;
@@ -40,14 +51,14 @@ void cndm_destroy_cq(struct cndm_cq *cq)
kfree(cq); kfree(cq);
} }
int cndm_open_cq(struct cndm_cq *cq, int irqn, int size) int cndm_open_cq(struct cndm_cq *cq, struct cndm_irq *irq, int size)
{ {
int ret = 0; int ret = 0;
struct cndm_cmd_queue cmd; struct cndm_cmd_queue cmd;
struct cndm_cmd_queue rsp; struct cndm_cmd_queue rsp;
if (cq->enabled || cq->buf) if (cq->enabled || cq->buf || !irq)
return -EINVAL; return -EINVAL;
cq->size = roundup_pow_of_two(size); cq->size = roundup_pow_of_two(size);
@@ -59,6 +70,14 @@ int cndm_open_cq(struct cndm_cq *cq, int irqn, int size)
if (!cq->buf) if (!cq->buf)
return -ENOMEM; return -ENOMEM;
if (irq) {
ret = atomic_notifier_chain_register(&irq->nh, &cq->irq_nb);
if (ret)
goto fail;
cq->irq = irq;
}
cq->cons_ptr = 0; cq->cons_ptr = 0;
// clear all phase tag bits // clear all phase tag bits
@@ -68,7 +87,7 @@ int cndm_open_cq(struct cndm_cq *cq, int irqn, int size)
cmd.flags = 0x00000000; cmd.flags = 0x00000000;
cmd.port = cq->priv->ndev->dev_port; cmd.port = cq->priv->ndev->dev_port;
cmd.qn = 0; cmd.qn = 0;
cmd.qn2 = irqn; // TODO cmd.qn2 = irq->index; // TODO
cmd.pd = 0; cmd.pd = 0;
cmd.size = ilog2(cq->size); cmd.size = ilog2(cq->size);
cmd.dboffs = 0; cmd.dboffs = 0;
@@ -121,6 +140,11 @@ void cndm_close_cq(struct cndm_cq *cq)
cq->db_addr = NULL; cq->db_addr = NULL;
} }
if (cq->irq) {
atomic_notifier_chain_unregister(&cq->irq->nh, &cq->irq_nb);
cq->irq = NULL;
}
if (cq->buf) { if (cq->buf) {
dma_free_coherent(cq->dev, cq->buf_size, cq->buf, cq->buf_dma_addr); dma_free_coherent(cq->dev, cq->buf_size, cq->buf, cq->buf_dma_addr);
cq->buf = NULL; cq->buf = NULL;

View File

@@ -38,7 +38,7 @@ static int cndm_open(struct net_device *ndev)
goto fail; goto fail;
} }
ret = cndm_open_cq(cq, 0, 256); ret = cndm_open_cq(cq, &priv->cdev->irq[0], 256);
if (ret) { if (ret) {
cndm_destroy_cq(cq); cndm_destroy_cq(cq);
goto fail; goto fail;
@@ -75,7 +75,7 @@ static int cndm_open(struct net_device *ndev)
goto fail; goto fail;
} }
ret = cndm_open_cq(cq, 0, 256); ret = cndm_open_cq(cq, &priv->cdev->irq[0], 256);
if (ret) { if (ret) {
cndm_destroy_cq(cq); cndm_destroy_cq(cq);
goto fail; goto fail;
@@ -278,20 +278,6 @@ static const struct net_device_ops cndm_netdev_ops = {
#endif #endif
}; };
static int cndm_netdev_irq(struct notifier_block *nb, unsigned long action, void *data)
{
struct cndm_priv *priv = container_of(nb, struct cndm_priv, irq_nb);
netdev_dbg(priv->ndev, "Interrupt");
if (priv->port_up) {
napi_schedule_irqoff(&priv->txq->cq->napi);
napi_schedule_irqoff(&priv->rxq->cq->napi);
}
return NOTIFY_DONE;
}
struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port) struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port)
{ {
struct device *dev = cdev->dev; struct device *dev = cdev->dev;
@@ -350,14 +336,6 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port)
priv->registered = 1; priv->registered = 1;
priv->irq_nb.notifier_call = cndm_netdev_irq;
priv->irq = &cdev->irq[port % cdev->irq_count];
ret = atomic_notifier_chain_register(&priv->irq->nh, &priv->irq_nb);
if (ret) {
priv->irq = NULL;
goto fail;
}
return ndev; return ndev;
fail: fail:
@@ -372,10 +350,5 @@ void cndm_destroy_netdev(struct net_device *ndev)
if (priv->registered) if (priv->registered)
unregister_netdev(ndev); unregister_netdev(ndev);
if (priv->irq)
atomic_notifier_chain_unregister(&priv->irq->nh, &priv->irq_nb);
priv->irq = NULL;
free_netdev(ndev); free_netdev(ndev);
} }