linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* problem with via-rhine driver and VT6103 chipset
@ 2002-07-20 16:20 damsnet
  2002-07-20 16:43 ` Roger Luethi
  0 siblings, 1 reply; 3+ messages in thread
From: damsnet @ 2002-07-20 16:20 UTC (permalink / raw)
  To: ivangurdiev, rl, ShingChuang; +Cc: linux-kernel

Hello

I would like to report a bug, appearing in kernels 2.4.18 
to 2.4.19-rc3 (I have not tested with previous ones). 

It concerns the VIA-Rhine (ethernet) driver. I use it with
a VT6103 ethernet adaptator, which seems not to be supported
by the driver, but almost works.

When I use this driver in 10Mbps mode (not 100Mbps), it resets the
ethernet card every few seconds and at the ends I have to reboot, 
because the card does not work anymore. These are the messages
I see with repetition:

NETDEV WATCHDOG: eth0: transmit timed out
eth0: Transmit timed out, status 0000, PHY status 786d, resetting...
NETDEV WATCHDOG: eth0: transmit timed out
eth0: Transmit timed out, status 0000, PHY status 786d, resetting...
[etc, etc, ...]


In 100Mbps mode, everything work perfectly. But the problem appears
all the time in 10Mbps mode. I made many tests, with differents 
motherboards (the card is integrated in it) in different situations, 
and it always appens.

The weird thing is that it only happens when the data go to this 
card, I mean if I copy a file *to* the computer with this card, it 
happens. If I copy a file *from* it (to an other computer), it does
not happen. I tested with ftp (proftpd running on the computer) by 
uploading files, and with scp.

My ethernet card is integrated to the VIA Mini-ITX motherboard, aimed
at embedded systems. The manual says it is a "VIA VT6103 Ethernet PHY".

lspci shows this:

00:12.0 Ethernet controller: VIA Technologies, Inc. Ethernet Controller (rev 51)
        Subsystem: VIA Technologies, Inc.: Unknown device 0102
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
        Status: Cap+ 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
        Latency: 32 (750ns min, 2000ns max), cache line size 08
        Interrupt: pin A routed to IRQ 11
        Region 0: I/O ports at e800 [size=256]
        Region 1: Memory at d4000000 (32-bit, non-prefetchable) [size=256]
        Capabilities: [40] Power Management version 2
                Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
                Status: D0 PME-Enable- DSel=0 DScale=0 PME-



The processor is:

processor       : 0
vendor_id       : CentaurHauls
cpu family      : 6
model           : 7
model name      : VIA Ezra
stepping        : 8
cpu MHz         : 800.047
cache size      : 64 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 1
wp              : yes
flags           : fpu de tsc msr cx8 mtrr pge mmx 3dnow
bogomips        : 1595.80


I compiled everything into the kernel, no modules support.
I tested with and without MMIO support, and the result is the same.



Thanks in advance,
regards.

Damien

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: problem with via-rhine driver and VT6103 chipset
  2002-07-20 16:20 problem with via-rhine driver and VT6103 chipset damsnet
@ 2002-07-20 16:43 ` Roger Luethi
  2002-07-20 19:16   ` damsnet
  0 siblings, 1 reply; 3+ messages in thread
From: Roger Luethi @ 2002-07-20 16:43 UTC (permalink / raw)
  To: damsnet; +Cc: linux-kernel

On Sat, 20 Jul 2002 18:20:44 +0200, damsnet@free.fr wrote:
> I would like to report a bug, appearing in kernels 2.4.18 
> to 2.4.19-rc3 (I have not tested with previous ones). 
> 
> It concerns the VIA-Rhine (ethernet) driver. I use it with
> a VT6103 ethernet adaptator, which seems not to be supported
> by the driver, but almost works.
> 
> When I use this driver in 10Mbps mode (not 100Mbps), it resets the
> ethernet card every few seconds and at the ends I have to reboot, 
> because the card does not work anymore. These are the messages
> I see with repetition:
> 
> NETDEV WATCHDOG: eth0: transmit timed out
> eth0: Transmit timed out, status 0000, PHY status 786d, resetting...
> NETDEV WATCHDOG: eth0: transmit timed out
> eth0: Transmit timed out, status 0000, PHY status 786d, resetting...
> [etc, etc, ...]

Try a recent ac kernel (2.4.19rc1-ac6 or later) or the patch below.

Roger

--- drivers/net/bk_11Jul.c	Mon Jul 15 14:53:27 2002
+++ drivers/net/via-rhine.c	Mon Jul 15 14:53:53 2002
@@ -93,7 +93,10 @@
 	- transmit frame queue message is off by one - fixed
 	- adds IntrNormalSummary to "Something Wicked" exclusion list
 	  so normal interrupts will not trigger the message (src: Donald Becker)
-	(Roger Lahti)
+	(Roger Luethi)
+	- show confused chip where to continue after Tx error
+	- location of collision counter is chip specific
+	- allow selecting backoff algorithm (module parameter)
 	- cosmetic cleanups, remove 3 unused members of struct netdev_private
 
 */
@@ -113,6 +116,9 @@ static int max_interrupt_work = 20;
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak;
 
+/* Select a backoff algorithm (Ethernet capture effect) */
+static int backoff;
+
 /* Used to pass the media type, etc.
    Both 'options[]' and 'full_duplex[]' should exist for driver
    interoperability.
@@ -215,11 +221,13 @@ MODULE_LICENSE("GPL");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(backoff, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(backoff, "VIA Rhine: Bits 0-3: backoff algorithm");
 MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex");
 MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)");
 
@@ -236,7 +244,8 @@ II. Board-specific settings
 Boards with this chip are functional only in a bus-master PCI slot.
 
 Many operational settings are loaded from the EEPROM to the Config word at
-offset 0x78.  This driver assumes that they are correct.
+offset 0x78. For most of these settings, this driver assumes that they are
+correct.
 If this driver is compiled to use PCI memory space operations the EEPROM
 must be configured to enable memory ops.
 
@@ -388,9 +397,10 @@ enum register_offsets {
 	StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC,
 };
 
-/* Bits in ConfigD (select backoff algorithm (Ethernet capture effect)) */
+/* Bits in ConfigD */
 enum backoff_bits {
-	BackOpt=0x01, BackAMD=0x02, BackDEC=0x04, BackRandom=0x08
+	BackOptional=0x01, BackModify=0x02,
+	BackCaptureEffect=0x04, BackRandom=0x08
 };
 
 #ifdef USE_MEM
@@ -404,7 +414,7 @@ int mmio_verify_registers[] = {
 /* Bits in the interrupt status/mask registers. */
 enum intr_status_bits {
 	IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
-	IntrTxDone=0x0002, IntrTxAbort=0x0008, IntrTxUnderrun=0x0010,
+	IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0010,
 	IntrPCIErr=0x0040,
 	IntrStatsMax=0x0080, IntrRxEarly=0x0100, IntrMIIChange=0x0200,
 	IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
@@ -430,24 +440,27 @@ enum mii_status_bits {
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
 	s32 rx_status;
-	u32 desc_length;
+	u32 desc_length; /* Chain flag, Buffer/frame length */
 	u32 addr;
 	u32 next_desc;
 };
 struct tx_desc {
 	s32 tx_status;
-	u32 desc_length;
+	u32 desc_length; /* Chain flag, Tx Config, Frame length */
 	u32 addr;
 	u32 next_desc;
 };
 
+/* Initial value for tx_desc.desc_length, Buffer size goes to bits 0-10 */
+#define TXDESC 0x00e08000
+
 enum rx_status_bits {
 	RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F
 };
 
-/* Bits in *_desc.status */
+/* Bits in *_desc.*_status */
 enum desc_status_bits {
-	DescOwn=0x80000000, DescEndPacket=0x4000, DescIntr=0x1000,
+	DescOwn=0x80000000
 };
 
 /* Bits in ChipCmd. */
@@ -519,6 +532,7 @@ static struct net_device_stats *via_rhin
 static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  via_rhine_close(struct net_device *dev);
 static inline void clear_tally_counters(long ioaddr);
+static inline void via_restart_tx(struct net_device *dev);
 
 static void wait_for_reset(struct net_device *dev, int chip_id, char *name)
 {
@@ -705,6 +719,11 @@ static int __devinit via_rhine_init_one 
 		writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA);
 	}
 
+	/* Select backoff algorithm */
+	if (backoff)
+		writeb(readb(ioaddr + ConfigD) & (0xF0 | backoff),
+			ioaddr + ConfigD);
+
 	dev->irq = pdev->irq;
 
 	np = dev->priv;
@@ -939,7 +958,7 @@ static void alloc_tbufs(struct net_devic
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_skbuff[i] = 0;
 		np->tx_ring[i].tx_status = 0;
-		np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000);
+		np->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
 		next += sizeof(struct tx_desc);
 		np->tx_ring[i].next_desc = cpu_to_le32(next);
 		np->tx_buf[i] = &np->tx_bufs[i * PKT_BUF_SZ];
@@ -955,7 +974,7 @@ static void free_tbufs(struct net_device
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_ring[i].tx_status = 0;
-		np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000);
+		np->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
 		np->tx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
 		if (np->tx_skbuff[i]) {
 			if (np->tx_skbuff_dma[i]) {
@@ -980,7 +999,7 @@ static void init_registers(struct net_de
 		writeb(dev->dev_addr[i], ioaddr + StationAddr + i);
 
 	/* Initialize other registers. */
-	writew(0x0006, ioaddr + PCIBusConfig);	/* Store & forward */
+	writew(0x0006, ioaddr + PCIBusConfig);	/* Tune configuration??? */
 	/* Configure initial FIFO thresholds. */
 	writeb(0x20, ioaddr + TxConfig);
 	np->tx_thresh = 0x20;
@@ -995,8 +1014,9 @@ static void init_registers(struct net_de
 	via_rhine_set_rx_mode(dev);
 
 	/* Enable interrupts by setting the interrupt mask. */
-	writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow| IntrRxDropped|
-		   IntrTxDone | IntrTxAbort | IntrTxUnderrun |
+	writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
+		   IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
+		   IntrTxDone | IntrTxError | IntrTxUnderrun |
 		   IntrPCIErr | IntrStatsMax | IntrLinkChange | IntrMIIChange,
 		   ioaddr + IntrEnable);
 
@@ -1239,7 +1259,7 @@ static int via_rhine_start_tx(struct sk_
 	}
 
 	np->tx_ring[entry].desc_length = 
-		cpu_to_le32(0x00E08000 | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+		cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
 	/* lock eth irq */
 	spin_lock_irq (&np->lock);
@@ -1291,13 +1311,14 @@ static void via_rhine_interrupt(int irq,
 						   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
 			via_rhine_rx(dev);
 
-		if (intr_status & (IntrTxDone | IntrTxAbort | IntrTxUnderrun |
+		if (intr_status & (IntrTxDone | IntrTxError | IntrTxUnderrun |
 						   IntrTxAborted))
 			via_rhine_tx(dev);
 
 		/* Abnormal error summary/uncommon events handlers. */
 		if (intr_status & (IntrPCIErr | IntrLinkChange | IntrMIIChange |
-						   IntrStatsMax | IntrTxAbort | IntrTxUnderrun))
+				   IntrStatsMax | IntrTxError | IntrTxAborted |
+				   IntrTxUnderrun))
 			via_rhine_error(dev, intr_status);
 
 		if (--boguscnt < 0) {
@@ -1309,7 +1330,7 @@ static void via_rhine_interrupt(int irq,
 	}
 
 	if (debug > 3)
-		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
+		printk(KERN_DEBUG "%s: exiting interrupt, status=%4.4x.\n",
 			   dev->name, readw(ioaddr + IntrStatus));
 }
 
@@ -1325,11 +1346,11 @@ static void via_rhine_tx(struct net_devi
 	/* find and cleanup dirty tx descriptors */
 	while (np->dirty_tx != np->cur_tx) {
 		txstatus = le32_to_cpu(np->tx_ring[entry].tx_status);
-		if (txstatus & DescOwn)
-			break;
 		if (debug > 6)
 			printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n",
 				   entry, txstatus);
+		if (txstatus & DescOwn)
+			break;
 		if (txstatus & 0x8000) {
 			if (debug > 1)
 				printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
@@ -1339,10 +1360,22 @@ static void via_rhine_tx(struct net_devi
 			if (txstatus & 0x0200) np->stats.tx_window_errors++;
 			if (txstatus & 0x0100) np->stats.tx_aborted_errors++;
 			if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++;
-			if (txstatus & 0x0002) np->stats.tx_fifo_errors++;
+			if (((np->chip_id == VT86C100A) && txstatus & 0x0002) ||
+				(txstatus & 0x0800) || (txstatus & 0x1000)) {
+				np->stats.tx_fifo_errors++;
+				np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
+				break; /* Keep the skb - we try again */
+			}
 			/* Transmitter restarted in 'abnormal' handler. */
 		} else {
-			np->stats.collisions += (txstatus >> 3) & 15;
+			if (np->chip_id == VT86C100A)
+				np->stats.collisions += (txstatus >> 3) & 0x0F;
+			else
+				np->stats.collisions += txstatus & 0x0F;
+			if (debug > 6)
+				printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n",
+					(txstatus >> 3) & 0xF,
+					txstatus & 0xF);
 			np->stats.tx_bytes += np->tx_skbuff[entry]->len;
 			np->stats.tx_packets++;
 		}
@@ -1478,6 +1511,17 @@ static void via_rhine_rx(struct net_devi
 	writew(CmdRxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
 }
 
+static inline void via_restart_tx(struct net_device *dev) {
+	struct netdev_private *np = dev->priv;
+	int entry = np->dirty_tx % TX_RING_SIZE;
+
+	/* We know better than the chip where it should continue */
+	writel(np->tx_ring_dma + entry * sizeof(struct tx_desc),
+		   dev->base_addr + TxRingPtr);
+
+	writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
+}
+
 static void via_rhine_error(struct net_device *dev, int intr_status)
 {
 	struct netdev_private *np = dev->priv;
@@ -1503,19 +1547,23 @@ static void via_rhine_error(struct net_d
 		np->stats.rx_missed_errors	+= readw(ioaddr + RxMissed);
 		clear_tally_counters(ioaddr);
 	}
-	if (intr_status & IntrTxAbort) {
-		/* Stats counted in Tx-done handler, just restart Tx. */
-		writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
+	if (intr_status & IntrTxError) {
+		if (debug > 1)
+			printk(KERN_INFO "%s: Abort %4.4x, frame dropped.\n",
+				   dev->name, intr_status);
+		via_restart_tx(dev);
 	}
 	if (intr_status & IntrTxUnderrun) {
 		if (np->tx_thresh < 0xE0)
 			writeb(np->tx_thresh += 0x20, ioaddr + TxConfig);
 		if (debug > 1)
-			printk(KERN_INFO "%s: Transmitter underrun, increasing Tx "
-				   "threshold setting to %2.2x.\n", dev->name, np->tx_thresh);
+			printk(KERN_INFO "%s: Transmitter underrun, Tx "
+				   "threshold now %2.2x.\n",
+				   dev->name, np->tx_thresh);
+		via_restart_tx(dev);
 	}
 	if (intr_status & ~( IntrLinkChange | IntrStatsMax |
- 						 IntrTxAbort | IntrTxAborted | IntrNormalSummary)) {
+ 						 IntrTxError | IntrTxAborted | IntrNormalSummary)) {
 		if (debug > 1)
 			printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
 			   dev->name, intr_status);

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: problem with via-rhine driver and VT6103 chipset
  2002-07-20 16:43 ` Roger Luethi
@ 2002-07-20 19:16   ` damsnet
  0 siblings, 0 replies; 3+ messages in thread
From: damsnet @ 2002-07-20 19:16 UTC (permalink / raw)
  To: Roger Luethi; +Cc: linux-kernel

On Sat, 20 Jul 2002 18:43:21 +0200
Roger Luethi <rl@hellgate.ch> wrote:

> On Sat, 20 Jul 2002 18:20:44 +0200, damsnet@free.fr wrote:
> > I would like to report a bug, appearing in kernels 2.4.18 
> > to 2.4.19-rc3 (I have not tested with previous ones). 
> > 
> > It concerns the VIA-Rhine (ethernet) driver. I use it with
> > a VT6103 ethernet adaptator, which seems not to be supported
> > by the driver, but almost works.
> > 
> > When I use this driver in 10Mbps mode (not 100Mbps), it resets the
> > ethernet card every few seconds and at the ends I have to reboot, 
> > because the card does not work anymore. These are the messages
> > I see with repetition:
> > 
> > NETDEV WATCHDOG: eth0: transmit timed out
> > eth0: Transmit timed out, status 0000, PHY status 786d, resetting...
> > NETDEV WATCHDOG: eth0: transmit timed out
> > eth0: Transmit timed out, status 0000, PHY status 786d, resetting...
> > [etc, etc, ...]
> 
> Try a recent ac kernel (2.4.19rc1-ac6 or later) or the patch below.
> 
> Roger
> 
> [...]


I tested with 2.4.19-rc2-ac2 and it is effectively far far better.

With previous kernels, it used to reset the card every few (2 or 3) 
megabytes transferred.

With this one, the reset happened only one time in a 600MBytes 
transfer, so it is incomparable.

(and I had to make several tests to eventually see this bug happen)


Thanks a lot for your support.

Damien

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-07-20 19:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-07-20 16:20 problem with via-rhine driver and VT6103 chipset damsnet
2002-07-20 16:43 ` Roger Luethi
2002-07-20 19:16   ` damsnet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).