Commit d43a396a authored by LEROY Christophe's avatar LEROY Christophe Committed by David S. Miller

net: fs_enet: Add NAPI TX

When using a MPC8xx as a router, 'perf' shows a significant time spent in
fs_enet_interrupt() and fs_enet_start_xmit().
'perf annotate' shows that the time spent in fs_enet_start_xmit is indeed spent
between spin_unlock_irqrestore() and the following instruction, hence in
interrupt handling. This is due to the TX complete interrupt that fires after
each transmitted packet.
This patch modifies the handling of TX complete to use NAPI.
With this patch, my NAT router offers a throughput improved by 21%

Original performance:

[root@localhost tmp]# scp toto pgs:/tmp
toto                                          100%  256MB   2.8MB/s   01:31

Performance with the patch:

[root@localhost tmp]# scp toto pgs:/tmp
toto                                          100%  256MB   3.4MB/s   01:16
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 583d4a68
...@@ -215,17 +215,23 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) ...@@ -215,17 +215,23 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
return received; return received;
} }
static void fs_enet_tx(struct net_device *dev) static int fs_enet_tx_napi(struct napi_struct *napi, int budget)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = container_of(napi, struct fs_enet_private,
napi_tx);
struct net_device *dev = fep->ndev;
cbd_t __iomem *bdp; cbd_t __iomem *bdp;
struct sk_buff *skb; struct sk_buff *skb;
int dirtyidx, do_wake, do_restart; int dirtyidx, do_wake, do_restart;
u16 sc; u16 sc;
int has_tx_work = 0;
spin_lock(&fep->tx_lock); spin_lock(&fep->tx_lock);
bdp = fep->dirty_tx; bdp = fep->dirty_tx;
/* clear TX status bits for napi*/
(*fep->ops->napi_clear_tx_event)(dev);
do_wake = do_restart = 0; do_wake = do_restart = 0;
while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) { while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
dirtyidx = bdp - fep->tx_bd_base; dirtyidx = bdp - fep->tx_bd_base;
...@@ -278,7 +284,7 @@ static void fs_enet_tx(struct net_device *dev) ...@@ -278,7 +284,7 @@ static void fs_enet_tx(struct net_device *dev)
/* /*
* Free the sk buffer associated with this last transmit. * Free the sk buffer associated with this last transmit.
*/ */
dev_kfree_skb_irq(skb); dev_kfree_skb(skb);
fep->tx_skbuff[dirtyidx] = NULL; fep->tx_skbuff[dirtyidx] = NULL;
/* /*
...@@ -295,6 +301,7 @@ static void fs_enet_tx(struct net_device *dev) ...@@ -295,6 +301,7 @@ static void fs_enet_tx(struct net_device *dev)
*/ */
if (!fep->tx_free++) if (!fep->tx_free++)
do_wake = 1; do_wake = 1;
has_tx_work = 1;
} }
fep->dirty_tx = bdp; fep->dirty_tx = bdp;
...@@ -302,10 +309,19 @@ static void fs_enet_tx(struct net_device *dev) ...@@ -302,10 +309,19 @@ static void fs_enet_tx(struct net_device *dev)
if (do_restart) if (do_restart)
(*fep->ops->tx_restart)(dev); (*fep->ops->tx_restart)(dev);
if (!has_tx_work) {
napi_complete(napi);
(*fep->ops->napi_enable_tx)(dev);
}
spin_unlock(&fep->tx_lock); spin_unlock(&fep->tx_lock);
if (do_wake) if (do_wake)
netif_wake_queue(dev); netif_wake_queue(dev);
if (has_tx_work)
return budget;
return 0;
} }
/* /*
...@@ -350,8 +366,17 @@ fs_enet_interrupt(int irq, void *dev_id) ...@@ -350,8 +366,17 @@ fs_enet_interrupt(int irq, void *dev_id)
__napi_schedule(&fep->napi); __napi_schedule(&fep->napi);
} }
if (int_events & fep->ev_tx) if (int_events & fep->ev_tx) {
fs_enet_tx(dev); napi_ok = napi_schedule_prep(&fep->napi_tx);
(*fep->ops->napi_disable_tx)(dev);
(*fep->ops->clear_int_events)(dev, fep->ev_napi_tx);
/* NOTE: it is possible for FCCs in NAPI mode */
/* to submit a spurious interrupt while in poll */
if (napi_ok)
__napi_schedule(&fep->napi_tx);
}
} }
handled = nr > 0; handled = nr > 0;
...@@ -484,7 +509,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -484,7 +509,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
cbd_t __iomem *bdp; cbd_t __iomem *bdp;
int curidx; int curidx;
u16 sc; u16 sc;
unsigned long flags;
#ifdef CONFIG_FS_ENET_MPC5121_FEC #ifdef CONFIG_FS_ENET_MPC5121_FEC
if (((unsigned long)skb->data) & 0x3) { if (((unsigned long)skb->data) & 0x3) {
...@@ -499,7 +523,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -499,7 +523,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
} }
} }
#endif #endif
spin_lock_irqsave(&fep->tx_lock, flags); spin_lock(&fep->tx_lock);
/* /*
* Fill in a Tx ring entry * Fill in a Tx ring entry
...@@ -508,7 +532,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -508,7 +532,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) { if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
netif_stop_queue(dev); netif_stop_queue(dev);
spin_unlock_irqrestore(&fep->tx_lock, flags); spin_unlock(&fep->tx_lock);
/* /*
* Ooops. All transmit buffers are full. Bail out. * Ooops. All transmit buffers are full. Bail out.
...@@ -564,7 +588,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -564,7 +588,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
(*fep->ops->tx_kickstart)(dev); (*fep->ops->tx_kickstart)(dev);
spin_unlock_irqrestore(&fep->tx_lock, flags); spin_unlock(&fep->tx_lock);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
...@@ -685,6 +709,7 @@ static int fs_enet_open(struct net_device *dev) ...@@ -685,6 +709,7 @@ static int fs_enet_open(struct net_device *dev)
fs_init_bds(fep->ndev); fs_init_bds(fep->ndev);
napi_enable(&fep->napi); napi_enable(&fep->napi);
napi_enable(&fep->napi_tx);
/* Install our interrupt handler. */ /* Install our interrupt handler. */
r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED, r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED,
...@@ -692,6 +717,7 @@ static int fs_enet_open(struct net_device *dev) ...@@ -692,6 +717,7 @@ static int fs_enet_open(struct net_device *dev)
if (r != 0) { if (r != 0) {
dev_err(fep->dev, "Could not allocate FS_ENET IRQ!"); dev_err(fep->dev, "Could not allocate FS_ENET IRQ!");
napi_disable(&fep->napi); napi_disable(&fep->napi);
napi_disable(&fep->napi_tx);
return -EINVAL; return -EINVAL;
} }
...@@ -699,6 +725,7 @@ static int fs_enet_open(struct net_device *dev) ...@@ -699,6 +725,7 @@ static int fs_enet_open(struct net_device *dev)
if (err) { if (err) {
free_irq(fep->interrupt, dev); free_irq(fep->interrupt, dev);
napi_disable(&fep->napi); napi_disable(&fep->napi);
napi_disable(&fep->napi_tx);
return err; return err;
} }
phy_start(fep->phydev); phy_start(fep->phydev);
...@@ -716,6 +743,7 @@ static int fs_enet_close(struct net_device *dev) ...@@ -716,6 +743,7 @@ static int fs_enet_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
netif_carrier_off(dev); netif_carrier_off(dev);
napi_disable(&fep->napi); napi_disable(&fep->napi);
napi_disable(&fep->napi_tx);
phy_stop(fep->phydev); phy_stop(fep->phydev);
spin_lock_irqsave(&fep->lock, flags); spin_lock_irqsave(&fep->lock, flags);
...@@ -971,6 +999,7 @@ static int fs_enet_probe(struct platform_device *ofdev) ...@@ -971,6 +999,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
ndev->netdev_ops = &fs_enet_netdev_ops; ndev->netdev_ops = &fs_enet_netdev_ops;
ndev->watchdog_timeo = 2 * HZ; ndev->watchdog_timeo = 2 * HZ;
netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight); netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight);
netif_napi_add(ndev, &fep->napi_tx, fs_enet_tx_napi, 2);
ndev->ethtool_ops = &fs_ethtool_ops; ndev->ethtool_ops = &fs_ethtool_ops;
......
...@@ -84,6 +84,9 @@ struct fs_ops { ...@@ -84,6 +84,9 @@ struct fs_ops {
void (*napi_clear_rx_event)(struct net_device *dev); void (*napi_clear_rx_event)(struct net_device *dev);
void (*napi_enable_rx)(struct net_device *dev); void (*napi_enable_rx)(struct net_device *dev);
void (*napi_disable_rx)(struct net_device *dev); void (*napi_disable_rx)(struct net_device *dev);
void (*napi_clear_tx_event)(struct net_device *dev);
void (*napi_enable_tx)(struct net_device *dev);
void (*napi_disable_tx)(struct net_device *dev);
void (*rx_bd_done)(struct net_device *dev); void (*rx_bd_done)(struct net_device *dev);
void (*tx_kickstart)(struct net_device *dev); void (*tx_kickstart)(struct net_device *dev);
u32 (*get_int_events)(struct net_device *dev); u32 (*get_int_events)(struct net_device *dev);
...@@ -119,6 +122,7 @@ struct phy_info { ...@@ -119,6 +122,7 @@ struct phy_info {
struct fs_enet_private { struct fs_enet_private {
struct napi_struct napi; struct napi_struct napi;
struct napi_struct napi_tx;
struct device *dev; /* pointer back to the device (must be initialized first) */ struct device *dev; /* pointer back to the device (must be initialized first) */
struct net_device *ndev; struct net_device *ndev;
spinlock_t lock; /* during all ops except TX pckt processing */ spinlock_t lock; /* during all ops except TX pckt processing */
...@@ -149,6 +153,7 @@ struct fs_enet_private { ...@@ -149,6 +153,7 @@ struct fs_enet_private {
/* event masks */ /* event masks */
u32 ev_napi_rx; /* mask of NAPI rx events */ u32 ev_napi_rx; /* mask of NAPI rx events */
u32 ev_napi_tx; /* mask of NAPI rx events */
u32 ev_rx; /* rx event mask */ u32 ev_rx; /* rx event mask */
u32 ev_tx; /* tx event mask */ u32 ev_tx; /* tx event mask */
u32 ev_err; /* error event mask */ u32 ev_err; /* error event mask */
...@@ -191,8 +196,8 @@ void fs_cleanup_bds(struct net_device *dev); ...@@ -191,8 +196,8 @@ void fs_cleanup_bds(struct net_device *dev);
#define DRV_MODULE_NAME "fs_enet" #define DRV_MODULE_NAME "fs_enet"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.0" #define DRV_MODULE_VERSION "1.1"
#define DRV_MODULE_RELDATE "Aug 8, 2005" #define DRV_MODULE_RELDATE "Sep 22, 2014"
/***************************************************************************/ /***************************************************************************/
......
...@@ -125,6 +125,7 @@ static int do_pd_setup(struct fs_enet_private *fep) ...@@ -125,6 +125,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
} }
#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB) #define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
#define FCC_NAPI_TX_EVENT_MSK (FCC_ENET_TXF | FCC_ENET_TXB)
#define FCC_RX_EVENT (FCC_ENET_RXF) #define FCC_RX_EVENT (FCC_ENET_RXF)
#define FCC_TX_EVENT (FCC_ENET_TXB) #define FCC_TX_EVENT (FCC_ENET_TXB)
#define FCC_ERR_EVENT_MSK (FCC_ENET_TXE) #define FCC_ERR_EVENT_MSK (FCC_ENET_TXE)
...@@ -137,6 +138,7 @@ static int setup_data(struct net_device *dev) ...@@ -137,6 +138,7 @@ static int setup_data(struct net_device *dev)
return -EINVAL; return -EINVAL;
fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK; fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK;
fep->ev_napi_tx = FCC_NAPI_TX_EVENT_MSK;
fep->ev_rx = FCC_RX_EVENT; fep->ev_rx = FCC_RX_EVENT;
fep->ev_tx = FCC_TX_EVENT; fep->ev_tx = FCC_TX_EVENT;
fep->ev_err = FCC_ERR_EVENT_MSK; fep->ev_err = FCC_ERR_EVENT_MSK;
...@@ -446,6 +448,30 @@ static void napi_disable_rx(struct net_device *dev) ...@@ -446,6 +448,30 @@ static void napi_disable_rx(struct net_device *dev)
C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK); C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
} }
static void napi_clear_tx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
fcc_t __iomem *fccp = fep->fcc.fccp;
W16(fccp, fcc_fcce, FCC_NAPI_TX_EVENT_MSK);
}
static void napi_enable_tx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
fcc_t __iomem *fccp = fep->fcc.fccp;
S16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK);
}
static void napi_disable_tx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
fcc_t __iomem *fccp = fep->fcc.fccp;
C16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK);
}
static void rx_bd_done(struct net_device *dev) static void rx_bd_done(struct net_device *dev)
{ {
/* nothing */ /* nothing */
...@@ -572,6 +598,9 @@ const struct fs_ops fs_fcc_ops = { ...@@ -572,6 +598,9 @@ const struct fs_ops fs_fcc_ops = {
.napi_clear_rx_event = napi_clear_rx_event, .napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx, .napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx, .napi_disable_rx = napi_disable_rx,
.napi_clear_tx_event = napi_clear_tx_event,
.napi_enable_tx = napi_enable_tx,
.napi_disable_tx = napi_disable_tx,
.rx_bd_done = rx_bd_done, .rx_bd_done = rx_bd_done,
.tx_kickstart = tx_kickstart, .tx_kickstart = tx_kickstart,
.get_int_events = get_int_events, .get_int_events = get_int_events,
......
...@@ -110,6 +110,7 @@ static int do_pd_setup(struct fs_enet_private *fep) ...@@ -110,6 +110,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
} }
#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB) #define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
#define FEC_NAPI_TX_EVENT_MSK (FEC_ENET_TXF | FEC_ENET_TXB)
#define FEC_RX_EVENT (FEC_ENET_RXF) #define FEC_RX_EVENT (FEC_ENET_RXF)
#define FEC_TX_EVENT (FEC_ENET_TXF) #define FEC_TX_EVENT (FEC_ENET_TXF)
#define FEC_ERR_EVENT_MSK (FEC_ENET_HBERR | FEC_ENET_BABR | \ #define FEC_ERR_EVENT_MSK (FEC_ENET_HBERR | FEC_ENET_BABR | \
...@@ -126,6 +127,7 @@ static int setup_data(struct net_device *dev) ...@@ -126,6 +127,7 @@ static int setup_data(struct net_device *dev)
fep->fec.htlo = 0; fep->fec.htlo = 0;
fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK; fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK;
fep->ev_napi_tx = FEC_NAPI_TX_EVENT_MSK;
fep->ev_rx = FEC_RX_EVENT; fep->ev_rx = FEC_RX_EVENT;
fep->ev_tx = FEC_TX_EVENT; fep->ev_tx = FEC_TX_EVENT;
fep->ev_err = FEC_ERR_EVENT_MSK; fep->ev_err = FEC_ERR_EVENT_MSK;
...@@ -415,6 +417,30 @@ static void napi_disable_rx(struct net_device *dev) ...@@ -415,6 +417,30 @@ static void napi_disable_rx(struct net_device *dev)
FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
} }
static void napi_clear_tx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct fec __iomem *fecp = fep->fec.fecp;
FW(fecp, ievent, FEC_NAPI_TX_EVENT_MSK);
}
static void napi_enable_tx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct fec __iomem *fecp = fep->fec.fecp;
FS(fecp, imask, FEC_NAPI_TX_EVENT_MSK);
}
static void napi_disable_tx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct fec __iomem *fecp = fep->fec.fecp;
FC(fecp, imask, FEC_NAPI_TX_EVENT_MSK);
}
static void rx_bd_done(struct net_device *dev) static void rx_bd_done(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
...@@ -487,6 +513,9 @@ const struct fs_ops fs_fec_ops = { ...@@ -487,6 +513,9 @@ const struct fs_ops fs_fec_ops = {
.napi_clear_rx_event = napi_clear_rx_event, .napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx, .napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx, .napi_disable_rx = napi_disable_rx,
.napi_clear_tx_event = napi_clear_tx_event,
.napi_enable_tx = napi_enable_tx,
.napi_disable_tx = napi_disable_tx,
.rx_bd_done = rx_bd_done, .rx_bd_done = rx_bd_done,
.tx_kickstart = tx_kickstart, .tx_kickstart = tx_kickstart,
.get_int_events = get_int_events, .get_int_events = get_int_events,
......
...@@ -116,6 +116,7 @@ static int do_pd_setup(struct fs_enet_private *fep) ...@@ -116,6 +116,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
} }
#define SCC_NAPI_RX_EVENT_MSK (SCCE_ENET_RXF | SCCE_ENET_RXB) #define SCC_NAPI_RX_EVENT_MSK (SCCE_ENET_RXF | SCCE_ENET_RXB)
#define SCC_NAPI_TX_EVENT_MSK (SCCE_ENET_TXF | SCCE_ENET_TXB)
#define SCC_RX_EVENT (SCCE_ENET_RXF) #define SCC_RX_EVENT (SCCE_ENET_RXF)
#define SCC_TX_EVENT (SCCE_ENET_TXB) #define SCC_TX_EVENT (SCCE_ENET_TXB)
#define SCC_ERR_EVENT_MSK (SCCE_ENET_TXE | SCCE_ENET_BSY) #define SCC_ERR_EVENT_MSK (SCCE_ENET_TXE | SCCE_ENET_BSY)
...@@ -130,6 +131,7 @@ static int setup_data(struct net_device *dev) ...@@ -130,6 +131,7 @@ static int setup_data(struct net_device *dev)
fep->scc.htlo = 0; fep->scc.htlo = 0;
fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK; fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
fep->ev_napi_tx = SCC_NAPI_TX_EVENT_MSK;
fep->ev_rx = SCC_RX_EVENT; fep->ev_rx = SCC_RX_EVENT;
fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE; fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE;
fep->ev_err = SCC_ERR_EVENT_MSK; fep->ev_err = SCC_ERR_EVENT_MSK;
...@@ -398,6 +400,30 @@ static void napi_disable_rx(struct net_device *dev) ...@@ -398,6 +400,30 @@ static void napi_disable_rx(struct net_device *dev)
C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK); C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
} }
static void napi_clear_tx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
scc_t __iomem *sccp = fep->scc.sccp;
W16(sccp, scc_scce, SCC_NAPI_TX_EVENT_MSK);
}
static void napi_enable_tx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
scc_t __iomem *sccp = fep->scc.sccp;
S16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK);
}
static void napi_disable_tx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
scc_t __iomem *sccp = fep->scc.sccp;
C16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK);
}
static void rx_bd_done(struct net_device *dev) static void rx_bd_done(struct net_device *dev)
{ {
/* nothing */ /* nothing */
...@@ -471,6 +497,9 @@ const struct fs_ops fs_scc_ops = { ...@@ -471,6 +497,9 @@ const struct fs_ops fs_scc_ops = {
.napi_clear_rx_event = napi_clear_rx_event, .napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx, .napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx, .napi_disable_rx = napi_disable_rx,
.napi_clear_tx_event = napi_clear_tx_event,
.napi_enable_tx = napi_enable_tx,
.napi_disable_tx = napi_disable_tx,
.rx_bd_done = rx_bd_done, .rx_bd_done = rx_bd_done,
.tx_kickstart = tx_kickstart, .tx_kickstart = tx_kickstart,
.get_int_events = get_int_events, .get_int_events = get_int_events,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment