mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 12:38:44 -07:00
cndm: Use event queues in driver
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user