Re: ksoftirqd uses 99% CPU triggered by network traffic (maybe RLT-8139 related)
From: Francois Romieu
Date: Sat Jul 31 2004 - 07:39:57 EST
Pasi Sjoholm <ptsjohol@xxxxxxxxx> :
[interesting report]
> The hardest part is to tell where the problem is but I think that
> rtl8139_poll-function would be good place to start looking for the bug?
>
> readprofile didn't tell much.. Where to go next? I'm not so good
> programmer that I could find the right place to fix..
In case it could make a difference: did you check if CONFIG_8139_OLD_RX_RESET
changes the behavior or not ?
If it does not, I'd welcome a test report + log with the two attached patch
applied. The first one is just a placebo but the second one could help.
Btw, you are probably right that the issue is not related to ksoftirqd at all.
--
Ueimor
drivers/net/8139too.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff -puN drivers/net/8139too.c~r8139-10 drivers/net/8139too.c
--- linux-2.6.8-rc2/drivers/net/8139too.c~r8139-10 2004-07-31 12:43:44.000000000 +0200
+++ linux-2.6.8-rc2-romieu/drivers/net/8139too.c 2004-07-31 12:43:44.000000000 +0200
@@ -1934,6 +1934,7 @@ static int rtl8139_rx(struct net_device
int received = 0;
unsigned char *rx_ring = tp->rx_ring;
unsigned int cur_rx = tp->cur_rx;
+ u16 status;
DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
" free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
@@ -1947,7 +1948,6 @@ static int rtl8139_rx(struct net_device
unsigned int rx_size;
unsigned int pkt_size;
struct sk_buff *skb;
- u16 status;
rmb();
@@ -2024,17 +2024,17 @@ static int rtl8139_rx(struct net_device
cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
RTL_W16 (RxBufPtr, (u16) (cur_rx - 16));
+ }
- /* Clear out errors and receive interrupts */
- status = RTL_R16 (IntrStatus) & RxAckBits;
- if (likely(status != 0)) {
- if (unlikely(status & (RxFIFOOver | RxOverflow))) {
- tp->stats.rx_errors++;
- if (status & RxFIFOOver)
- tp->stats.rx_fifo_errors++;
- }
- RTL_W16_F (IntrStatus, RxAckBits);
+ /* Clear out errors and receive interrupts */
+ status = RTL_R16 (IntrStatus) & RxAckBits;
+ if (likely(status != 0)) {
+ if (unlikely(status & (RxFIFOOver | RxOverflow))) {
+ tp->stats.rx_errors++;
+ if (status & RxFIFOOver)
+ tp->stats.rx_fifo_errors++;
}
+ RTL_W16_F (IntrStatus, RxAckBits);
}
done:
_
drivers/net/8139too.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletion(-)
diff -puN drivers/net/8139too.c~r8139-20 drivers/net/8139too.c
--- linux-2.6.8-rc2/drivers/net/8139too.c~r8139-20 2004-07-31 12:44:12.000000000 +0200
+++ linux-2.6.8-rc2-romieu/drivers/net/8139too.c 2004-07-31 14:20:36.000000000 +0200
@@ -593,6 +593,7 @@ struct rtl8139_private {
int time_to_die;
struct mii_if_info mii;
unsigned int regs_len;
+ unsigned long fifo_copy_timeout;
};
MODULE_AUTHOR ("Jeff Garzik <jgarzik@xxxxxxxxx>");
@@ -1937,7 +1938,7 @@ static int rtl8139_rx(struct net_device
u16 status;
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 (RxBufPtr), RTL_R8 (ChipCmd));
@@ -1977,6 +1978,14 @@ static int rtl8139_rx(struct net_device
*/
if (unlikely(rx_size == 0xfff0)) {
tp->xstats.early_rx++;
+ 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);
+ tp->fifo_copy_timeout = 0;
+ rtl8139_rx_err (rx_status, dev, tp, ioaddr);
+ return -1;
+ }
goto done;
}
_