Commit 15e14b1f authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] 8139too: be sure to progress during rtl8139_rx()

From: Francois Romieu <romieu@fr.zoreil.com>

If the Rx buffer gets corrupted or the FIFO hangs in new interesting ways,
this code prevents the driver from looping in ksoftirqd context without
making any progress.
Signed-off-by: default avatarFrancois Romieu <romieu@fr.zoreil.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
parent 4f3cf06d
...@@ -593,6 +593,7 @@ struct rtl8139_private { ...@@ -593,6 +593,7 @@ struct rtl8139_private {
int time_to_die; int time_to_die;
struct mii_if_info mii; struct mii_if_info mii;
unsigned int regs_len; unsigned int regs_len;
unsigned long fifo_copy_timeout;
}; };
MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>"); MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
...@@ -1955,7 +1956,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, ...@@ -1955,7 +1956,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
unsigned int rx_size = 0; unsigned int rx_size = 0;
DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
" free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx,
RTL_R16 (RxBufAddr), RTL_R16 (RxBufAddr),
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
...@@ -1993,10 +1994,24 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, ...@@ -1993,10 +1994,24 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
* since EarlyRx is disabled. * since EarlyRx is disabled.
*/ */
if (unlikely(rx_size == 0xfff0)) { if (unlikely(rx_size == 0xfff0)) {
if (!tp->fifo_copy_timeout)
tp->fifo_copy_timeout = jiffies + 2;
else if (time_after(jiffies, tp->fifo_copy_timeout)) {
DPRINTK ("%s: hung FIFO. Reset.", dev->name);
rx_size = 0;
goto no_early_rx;
}
if (netif_msg_intr(tp)) {
printk(KERN_DEBUG "%s: fifo copy in progress.",
dev->name);
}
tp->xstats.early_rx++; tp->xstats.early_rx++;
break; break;
} }
no_early_rx:
tp->fifo_copy_timeout = 0;
/* If Rx err or invalid rx_size/rx_status received /* If Rx err or invalid rx_size/rx_status received
* (which happens if we get lost in the ring), * (which happens if we get lost in the ring),
* Rx process gets reset, so we abort any further * Rx process gets reset, so we abort any further
...@@ -2057,6 +2072,14 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, ...@@ -2057,6 +2072,14 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
#endif #endif
tp->cur_rx = cur_rx; tp->cur_rx = cur_rx;
/*
* The receive buffer should be mostly empty.
* Tell NAPI to reenable the Rx irq.
*/
if (tp->fifo_copy_timeout)
received = budget;
out: out:
return received; return received;
} }
......
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