--- v1
+++ v2
@@ -6,6 +6,7 @@
Handling of the budget in association with TX interrupts is based on
indications provided at https://wiki.linuxfoundation.org/networking/napi
+We never proceed more than the complete TX ring on a single run.
At the same time, we fix an issue in the handling of fep->tx_free:
@@ -15,18 +16,31 @@
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
- .../net/ethernet/freescale/fs_enet/fs_enet-main.c | 259 +++++++++------------
+v2: Limitation of TX completion loop to the size of the TX ring to avoid
+infinite loop.
+
+ .../net/ethernet/freescale/fs_enet/fs_enet-main.c | 268 +++++++++------------
drivers/net/ethernet/freescale/fs_enet/fs_enet.h | 16 +-
- drivers/net/ethernet/freescale/fs_enet/mac-fcc.c | 57 ++---
- drivers/net/ethernet/freescale/fs_enet/mac-fec.c | 57 ++---
- drivers/net/ethernet/freescale/fs_enet/mac-scc.c | 57 ++---
- 5 files changed, 153 insertions(+), 293 deletions(-)
+ drivers/net/ethernet/freescale/fs_enet/mac-fcc.c | 57 +----
+ drivers/net/ethernet/freescale/fs_enet/mac-fec.c | 57 +----
+ drivers/net/ethernet/freescale/fs_enet/mac-scc.c | 57 +----
+ 5 files changed, 160 insertions(+), 295 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
-index 61fd486..7cd3ef9 100644
+index 61fd486..37574a9 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
-@@ -79,8 +79,8 @@ static void skb_align(struct sk_buff *skb, int align)
+@@ -60,6 +60,9 @@ module_param(fs_enet_debug, int, 0);
+ MODULE_PARM_DESC(fs_enet_debug,
+ "Freescale bitmapped debugging message enable value");
+
++#define RX_RING_SIZE 32
++#define TX_RING_SIZE 64
++
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void fs_enet_netpoll(struct net_device *dev);
+ #endif
+@@ -79,8 +82,8 @@ static void skb_align(struct sk_buff *skb, int align)
skb_reserve(skb, align - off);
}
@@ -37,11 +51,12 @@
{
struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi);
struct net_device *dev = fep->ndev;
-@@ -90,9 +90,100 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
+@@ -90,9 +93,102 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
int received = 0;
u16 pkt_len, sc;
int curidx;
+ int dirtyidx, do_wake, do_restart;
++ int tx_left = TX_RING_SIZE;
- if (budget <= 0)
- return received;
@@ -52,7 +67,7 @@
+ (*fep->ops->napi_clear_event)(dev);
+
+ 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 && tx_left) {
+ dirtyidx = bdp - fep->tx_bd_base;
+
+ if (fep->tx_free == fep->tx_ring)
@@ -126,6 +141,7 @@
+ */
+ if (++fep->tx_free == MAX_SKB_FRAGS)
+ do_wake = 1;
++ tx_left--;
+ }
+
+ fep->dirty_tx = bdp;
@@ -140,7 +156,7 @@
/*
* First, grab all of the stats for the incoming packet.
-@@ -100,10 +191,8 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
+@@ -100,10 +196,8 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
*/
bdp = fep->cur_rx;
@@ -153,7 +169,7 @@
curidx = bdp - fep->rx_bd_base;
/*
-@@ -197,134 +286,19 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
+@@ -197,134 +291,19 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
bdp = fep->rx_bd_base;
(*fep->ops->rx_bd_done)(dev);
@@ -165,14 +181,15 @@
fep->cur_rx = bdp;
- if (received < budget) {
-+ if (received < budget && !do_wake) {
++ if (received < budget && tx_left) {
/* done */
napi_complete(napi);
- (*fep->ops->napi_enable_rx)(dev);
- }
- return received;
-}
--
++ (*fep->ops->napi_enable)(dev);
+
-static int fs_enet_tx_napi(struct napi_struct *napi, int budget)
-{
- struct fs_enet_private *fep = container_of(napi, struct fs_enet_private,
@@ -234,8 +251,7 @@
- */
- if (sc & BD_ENET_TX_DEF)
- fep->stats.collisions++;
-+ (*fep->ops->napi_enable)(dev);
-
+-
- /* unmap */
- if (fep->mapped_as_page[dirtyidx])
- dma_unmap_page(fep->dev, CBDR_BUFADDR(bdp),
@@ -292,7 +308,7 @@
}
/*
-@@ -350,18 +324,18 @@ fs_enet_interrupt(int irq, void *dev_id)
+@@ -350,18 +329,18 @@ fs_enet_interrupt(int irq, void *dev_id)
nr++;
int_clr_events = int_events;
@@ -315,7 +331,7 @@
/* NOTE: it is possible for FCCs in NAPI mode */
/* to submit a spurious interrupt while in poll */
-@@ -369,17 +343,6 @@ fs_enet_interrupt(int irq, void *dev_id)
+@@ -369,17 +348,6 @@ fs_enet_interrupt(int irq, void *dev_id)
__napi_schedule(&fep->napi);
}
@@ -333,7 +349,7 @@
}
handled = nr > 0;
-@@ -659,7 +622,8 @@ static void fs_timeout(struct net_device *dev)
+@@ -659,7 +627,8 @@ static void fs_timeout(struct net_device *dev)
}
phy_start(dev->phydev);
@@ -343,7 +359,7 @@
spin_unlock_irqrestore(&fep->lock, flags);
if (wake)
-@@ -751,11 +715,10 @@ static int fs_enet_open(struct net_device *dev)
+@@ -751,11 +720,10 @@ static int fs_enet_open(struct net_device *dev)
int err;
/* to initialize the fep->cur_rx,... */
@@ -356,7 +372,7 @@
/* Install our interrupt handler. */
r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED,
-@@ -763,7 +726,6 @@ static int fs_enet_open(struct net_device *dev)
+@@ -763,7 +731,6 @@ static int fs_enet_open(struct net_device *dev)
if (r != 0) {
dev_err(fep->dev, "Could not allocate FS_ENET IRQ!");
napi_disable(&fep->napi);
@@ -364,7 +380,7 @@
return -EINVAL;
}
-@@ -771,7 +733,6 @@ static int fs_enet_open(struct net_device *dev)
+@@ -771,7 +738,6 @@ static int fs_enet_open(struct net_device *dev)
if (err) {
free_irq(fep->interrupt, dev);
napi_disable(&fep->napi);
@@ -372,7 +388,7 @@
return err;
}
phy_start(dev->phydev);
-@@ -789,7 +750,6 @@ static int fs_enet_close(struct net_device *dev)
+@@ -789,7 +755,6 @@ static int fs_enet_close(struct net_device *dev)
netif_stop_queue(dev);
netif_carrier_off(dev);
napi_disable(&fep->napi);
@@ -380,7 +396,18 @@
phy_stop(dev->phydev);
spin_lock_irqsave(&fep->lock, flags);
-@@ -1024,8 +984,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
+@@ -939,8 +904,8 @@ static int fs_enet_probe(struct platform_device *ofdev)
+ fpi->cp_command = *data;
+ }
+
+- fpi->rx_ring = 32;
+- fpi->tx_ring = 64;
++ fpi->rx_ring = RX_RING_SIZE;
++ fpi->tx_ring = TX_RING_SIZE;
+ fpi->rx_copybreak = 240;
+ fpi->napi_weight = 17;
+ fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
+@@ -1024,8 +989,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
ndev->netdev_ops = &fs_enet_netdev_ops;
ndev->watchdog_timeo = 2 * HZ;