[PATCH] 3c59x-txreset.patch
Sang-yong Suh
sysuh@kigam.re.kr
Fri Aug 20 03:20:01 1999
I think I have a solution, though not perfect, on the Transmit error
problem. During my previous analyses, it is obvious that the TX
is not properly resetted. Therefore, I assumed that TxReset can
not be done too early, probably within interrupt loop.
I modified the source not to try reset during the interrupt loop,
instead remembered the status in a word, tx_need_reset. The status
is checked at the start of vortex_start_xmit(), and if it is set,
the real TxReset is attempted.
With this modification, the NIC is operating continuoulsy.
The NFS did not detected the net failure, and no more complains. :-)
I have tested my patched version on a PPRO-200 Linux news server,
nntp.kreonet.re.kr. The server is one of the busiest news servers
in the world. I made kernel-2.2.10 with this patch, and rebooted.
And I don't have to downgrade the kernel to old 2.0.36...
I am including three materials:
1. copy of /proc/net/dev
2. selected copy of syslog
3. 3c59x.c-txreset.patch against v0.99L
--
sysuh
PART 1. /proc/net/dev
---------------------
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 1260 18 0 0 0 0 0 0 1260 18 0 0 0 0 0 0
eth0:890581376 1517270 0 0 0 0 0 0 1088060189 1622659 0 0 26 19588 31 0
PART 2. selected syslog message
-------------------------------
Aug 20 14:55:57 nntp kernel: eth0: 3Com 3c595 Vortex 100baseTx at 0xe000, 00:a0:24:c5:f8:15, IRQ 12
Aug 20 14:55:57 nntp kernel: eth0: Overriding PCI latency timer (CFLT) setting of 32, new value is 248.
Aug 20 14:57:12 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 14:57:30 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 14:59:13 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:01:31 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:03:16 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:06:13 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:13:43 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:16:34 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:17:06 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:18:12 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:21:39 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:26:40 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:29:02 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:30:29 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:36:45 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:38:55 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:39:45 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:44:04 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:45:24 nntp kernel: eth0: Transmit error, Tx status register 90.
Aug 20 15:48:02 nntp kernel: eth0: Transmit error, Tx status register 90.
PART 3. 3c59x-txreset.patch
---------------------------
*** 3c59x.c-0.99L Thu Aug 19 16:43:09 1999
--- 3c59x.c Fri Aug 20 14:15:04 1999
***************
*** 473,478 ****
--- 473,489 ----
u16 capabilities, info1, info2; /* Various, from EEPROM. */
u16 advertising; /* NWay media advertisement */
unsigned char phys[2]; /* MII device addresses. */
+
+ #define SUH_HACK
+ /*
+ ** I think that tx_reset should be done outside of the interrupt.
+ ** If you network is jammed during heavy load and syslog shows
+ ** "Transmit error" message, pls try me.
+ */
+ #ifdef SUH_HACK
+ /* tx_reset seems to be done outside of interrupt. */
+ u16 tx_need_reset;
+ #endif
};
/* The action to take with a media selection timer tick.
***************
*** 1440,1445 ****
--- 1451,1457 ----
}
}
if (do_tx_reset) {
+ #ifndef SUH_HACK
int j;
outw(TxReset, ioaddr + EL3_CMD);
for (j = 200; j >= 0 ; j--)
***************
*** 1447,1455 ****
break;
outw(TxEnable, ioaddr + EL3_CMD);
}
!
}
static int
vortex_start_xmit(struct sk_buff *skb, struct device *dev)
--- 1459,1480 ----
break;
outw(TxEnable, ioaddr + EL3_CMD);
}
! }
! #else
! vp->tx_need_reset = 1;
! }
}
+ static void vortex_tx_reset(long ioaddr)
+ {
+ int j;
+ outw(TxReset, ioaddr + EL3_CMD);
+ for (j = 200; j >= 0 ; j--)
+ if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ break;
+ outw(TxEnable, ioaddr + EL3_CMD);
+ }
+ #endif
static int
vortex_start_xmit(struct sk_buff *skb, struct device *dev)
***************
*** 1457,1462 ****
--- 1482,1494 ----
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
+ #ifdef SUH_HACK
+ if (vp->tx_need_reset) {
+ vp->tx_need_reset = 0;
+ vortex_tx_reset(ioaddr);
+ return 1;
+ }
+ #endif
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
if (jiffies - dev->trans_start >= TX_TIMEOUT)
vortex_tx_timeout(dev);