@@ -1616,8 +1616,17 @@ fec_enet_rx(struct net_device *ndev, int budget)
}
static bool
-fec_enet_collect_events(struct fec_enet_private *fep, uint int_events)
+fec_enet_collect_events(struct fec_enet_private *fep)
{
+ uint int_events;
+
+ int_events = readl(fep->hwp + FEC_IEVENT);
+
+ /* Don't clear MDIO events, we poll for those */
+ int_events &= ~FEC_ENET_MII;
+
+ writel(int_events, fep->hwp + FEC_IEVENT);
+
if (int_events == 0)
return false;
@@ -1643,16 +1652,9 @@ fec_enet_interrupt(int irq, void *dev_id)
{
struct net_device *ndev = dev_id;
struct fec_enet_private *fep = netdev_priv(ndev);
- uint int_events;
irqreturn_t ret = IRQ_NONE;
- int_events = readl(fep->hwp + FEC_IEVENT);
-
- /* Don't clear MDIO events, we poll for those */
- int_events &= ~FEC_ENET_MII;
-
- writel(int_events, fep->hwp + FEC_IEVENT);
- fec_enet_collect_events(fep, int_events);
+ fec_enet_collect_events(fep);
if ((fep->work_tx || fep->work_rx) && fep->link) {
ret = IRQ_HANDLED;
@@ -1673,6 +1675,8 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
struct fec_enet_private *fep = netdev_priv(ndev);
int pkts;
+ fec_enet_collect_events(fep);
+
pkts = fec_enet_rx(ndev, budget);
fec_enet_tx(ndev);
In the ISR, we poll the event register for the queues in need of service and then enter polled mode. After this point, the event register will never be read again until we exit polled mode. In a scenario where a UDP flow is routed back out through the same interface, i.e. "router-on-a-stick" we'll typically only see an rx queue event initially. Once we start to process the incoming flow we'll be locked polled mode, but we'll never clean the tx rings since that event is never caught. Eventually the netdev watchdog will trip, causing all buffers to be dropped and then the process starts over again. By adding a poll of the active events at each NAPI call, we avoid the starvation. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> --- drivers/net/ethernet/freescale/fec_main.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)