mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 04:38:42 -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_netdev.o
|
||||||
cndm-y += cndm_ethtool.o
|
cndm-y += cndm_ethtool.o
|
||||||
cndm-y += cndm_ptp.o
|
cndm-y += cndm_ptp.o
|
||||||
|
cndm-y += cndm_eq.o
|
||||||
cndm-y += cndm_cq.o
|
cndm-y += cndm_cq.o
|
||||||
cndm-y += cndm_sq.o
|
cndm-y += cndm_sq.o
|
||||||
cndm-y += cndm_rq.o
|
cndm-y += cndm_rq.o
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ struct cndm_cq {
|
|||||||
int enabled;
|
int enabled;
|
||||||
|
|
||||||
struct cndm_ring *src_ring;
|
struct cndm_ring *src_ring;
|
||||||
|
struct cndm_eq *eq;
|
||||||
struct cndm_irq *irq;
|
struct cndm_irq *irq;
|
||||||
struct notifier_block irq_nb;
|
struct notifier_block irq_nb;
|
||||||
|
|
||||||
@@ -183,6 +183,35 @@ struct cndm_cq {
|
|||||||
u8 __iomem *db_addr;
|
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 cndm_priv {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct net_device *ndev;
|
struct net_device *ndev;
|
||||||
@@ -198,6 +227,8 @@ struct cndm_priv {
|
|||||||
int rxq_count;
|
int rxq_count;
|
||||||
int txq_count;
|
int txq_count;
|
||||||
|
|
||||||
|
struct cndm_eq *eq;
|
||||||
|
|
||||||
struct cndm_ring *txq;
|
struct cndm_ring *txq;
|
||||||
struct cndm_ring *rxq;
|
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_register_phc(struct cndm_dev *cdev);
|
||||||
void cndm_unregister_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
|
// 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, 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_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);
|
||||||
|
|||||||
@@ -10,14 +10,7 @@ Authors:
|
|||||||
|
|
||||||
#include "cndm.h"
|
#include "cndm.h"
|
||||||
|
|
||||||
static int cndm_cq_int(struct notifier_block *nb, unsigned long action, void *data)
|
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)
|
||||||
{
|
{
|
||||||
@@ -51,14 +44,15 @@ void cndm_destroy_cq(struct cndm_cq *cq)
|
|||||||
kfree(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;
|
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 || !irq)
|
if (cq->enabled || cq->buf || (!irq && !eq))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cq->size = roundup_pow_of_two(size);
|
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)
|
if (!cq->buf)
|
||||||
return -ENOMEM;
|
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);
|
ret = atomic_notifier_chain_register(&irq->nh, &cq->irq_nb);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
cq->irq = irq;
|
cq->irq = irq;
|
||||||
|
dqn = irq->index | 0x80000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
cq->cons_ptr = 0;
|
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.flags = 0x00000000;
|
||||||
cmd.port = cq->priv->ndev->dev_port;
|
cmd.port = cq->priv->ndev->dev_port;
|
||||||
cmd.qn = 0;
|
cmd.qn = 0;
|
||||||
cmd.qn2 = irq->index; // TODO
|
cmd.qn2 = dqn;
|
||||||
cmd.pd = 0;
|
cmd.pd = 0;
|
||||||
cmd.size = ilog2(cq->size);
|
cmd.size = ilog2(cq->size);
|
||||||
cmd.dboffs = 0;
|
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_offset = rsp.dboffs;
|
||||||
cq->db_addr = cq->cdev->hw_addr + rsp.dboffs;
|
cq->db_addr = cq->cdev->hw_addr + rsp.dboffs;
|
||||||
|
|
||||||
|
if (eq) {
|
||||||
|
cndm_eq_attach_cq(eq, cq);
|
||||||
|
}
|
||||||
|
|
||||||
cq->enabled = 1;
|
cq->enabled = 1;
|
||||||
|
|
||||||
cndm_cq_write_cons_ptr_arm(cq);
|
cndm_cq_write_cons_ptr_arm(cq);
|
||||||
@@ -140,6 +143,11 @@ void cndm_close_cq(struct cndm_cq *cq)
|
|||||||
cq->db_addr = NULL;
|
cq->db_addr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cq->eq) {
|
||||||
|
cndm_eq_detach_cq(cq->eq, cq);
|
||||||
|
cq->eq = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (cq->irq) {
|
if (cq->irq) {
|
||||||
atomic_notifier_chain_unregister(&cq->irq->nh, &cq->irq_nb);
|
atomic_notifier_chain_unregister(&cq->irq->nh, &cq->irq_nb);
|
||||||
cq->irq = NULL;
|
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);
|
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 {
|
struct cndm_event {
|
||||||
|
__le16 rsvd0;
|
||||||
__le16 type;
|
__le16 type;
|
||||||
__le16 source;
|
__le32 source;
|
||||||
__le32 rsvd0;
|
|
||||||
__le32 rsvd1;
|
__le32 rsvd1;
|
||||||
__le32 rsvd2;
|
|
||||||
__le32 rsvd3;
|
|
||||||
__le32 rsvd4;
|
|
||||||
__le32 rsvd5;
|
|
||||||
__le32 phase;
|
__le32 phase;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ static int cndm_open(struct net_device *ndev)
|
|||||||
goto fail;
|
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) {
|
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, &priv->cdev->irq[0], 256);
|
ret = cndm_open_cq(cq, priv->eq, &priv->cdev->irq[0], 256);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
cndm_destroy_cq(cq);
|
cndm_destroy_cq(cq);
|
||||||
goto fail;
|
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->min_mtu = ETH_MIN_MTU;
|
||||||
ndev->max_mtu = 1500;
|
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);
|
netif_carrier_off(ndev);
|
||||||
|
|
||||||
ret = register_netdev(ndev);
|
ret = register_netdev(ndev);
|
||||||
@@ -350,5 +363,8 @@ void cndm_destroy_netdev(struct net_device *ndev)
|
|||||||
if (priv->registered)
|
if (priv->registered)
|
||||||
unregister_netdev(ndev);
|
unregister_netdev(ndev);
|
||||||
|
|
||||||
|
if (priv->eq)
|
||||||
|
cndm_destroy_eq(priv->eq);
|
||||||
|
|
||||||
free_netdev(ndev);
|
free_netdev(ndev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ Authors:
|
|||||||
|
|
||||||
#include "cndm.h"
|
#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 *cndm_create_rq(struct cndm_priv *priv)
|
||||||
{
|
{
|
||||||
struct cndm_ring *rq;
|
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->priv = priv;
|
||||||
rq->cq = cq;
|
rq->cq = cq;
|
||||||
cq->src_ring = rq;
|
cq->src_ring = rq;
|
||||||
// cq->handler = cndm_rx_irq;
|
cq->handler = cndm_rq_cq_handler;
|
||||||
|
|
||||||
rq->prod_ptr = 0;
|
rq->prod_ptr = 0;
|
||||||
rq->cons_ptr = 0;
|
rq->cons_ptr = 0;
|
||||||
@@ -352,6 +354,11 @@ rx_drop:
|
|||||||
return done;
|
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)
|
int cndm_poll_rx_cq(struct napi_struct *napi, int budget)
|
||||||
{
|
{
|
||||||
struct cndm_cq *cq = container_of(napi, struct cndm_cq, napi);
|
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);
|
napi_complete(napi);
|
||||||
|
|
||||||
// TODO re-enable interrupts
|
|
||||||
cndm_cq_write_cons_ptr_arm(cq);
|
cndm_cq_write_cons_ptr_arm(cq);
|
||||||
|
|
||||||
return done;
|
return done;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ Authors:
|
|||||||
|
|
||||||
#include "cndm.h"
|
#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 *cndm_create_sq(struct cndm_priv *priv)
|
||||||
{
|
{
|
||||||
struct cndm_ring *sq;
|
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->priv = priv;
|
||||||
sq->cq = cq;
|
sq->cq = cq;
|
||||||
cq->src_ring = sq;
|
cq->src_ring = sq;
|
||||||
// cq->handler = cndm_tx_irq;
|
cq->handler = cndm_sq_cq_handler;
|
||||||
|
|
||||||
sq->prod_ptr = 0;
|
sq->prod_ptr = 0;
|
||||||
sq->cons_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;
|
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)
|
int cndm_poll_tx_cq(struct napi_struct *napi, int budget)
|
||||||
{
|
{
|
||||||
struct cndm_cq *cq = container_of(napi, struct cndm_cq, napi);
|
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);
|
napi_complete(napi);
|
||||||
|
|
||||||
// TODO re-enable interrupts
|
|
||||||
cndm_cq_write_cons_ptr_arm(cq);
|
cndm_cq_write_cons_ptr_arm(cq);
|
||||||
|
|
||||||
return done;
|
return done;
|
||||||
|
|||||||
Reference in New Issue
Block a user