[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);