netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery
@ 2004-08-05 21:43 Francois Romieu
  2004-08-05 21:45 ` [PATCH 2.6.8-rc3-mm1 2/2] 8139too: be sure to progress durin rtl8139_rx() Francois Romieu
  2004-08-11 19:17 ` [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery Jeff Garzik
  0 siblings, 2 replies; 7+ messages in thread
From: Francois Romieu @ 2004-08-05 21:43 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andrew Morton, Pasi Sjoholm, Hector Martin, OGAWA Hirofumi,
	netdev

This patch allows to update the interrupt status register after an 
Rx overflow or a Rx fifo error even when the Rx buffer contains no packet.
As a side effect it saves a few heavy (i.e. flushed) pci ops per received
packet when several packets are received at the same time.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>

diff -puN drivers/net/8139too.c~r8139-10 drivers/net/8139too.c
--- linux-2.6.8-rc3/drivers/net/8139too.c~r8139-10	2004-08-05 23:09:26.000000000 +0200
+++ linux-2.6.8-rc3-romieu/drivers/net/8139too.c	2004-08-05 23:14:31.000000000 +0200
@@ -1934,12 +1934,15 @@ 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,
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
+	status = RTL_R16 (IntrStatus) & RxAckBits;
+
 	while (netif_running(dev) && received < budget 
 	       && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
 		u32 ring_offset = cur_rx % RX_BUF_LEN;
@@ -1947,7 +1950,6 @@ static int rtl8139_rx(struct net_device 
 		unsigned int rx_size;
 		unsigned int pkt_size;
 		struct sk_buff *skb;
-		u16 status;
 
 		rmb();
 
@@ -1977,7 +1979,7 @@ static int rtl8139_rx(struct net_device 
 		 */
 		if (unlikely(rx_size == 0xfff0)) {
 			tp->xstats.early_rx++;
-			goto done;
+			break;
 		}
 
 		/* If Rx err or invalid rx_size/rx_status received
@@ -1989,7 +1991,8 @@ static int rtl8139_rx(struct net_device 
 			     (rx_size < 8) ||
 			     (!(rx_status & RxStatusOK)))) {
 			rtl8139_rx_err (rx_status, dev, tp, ioaddr);
-			return -1;
+			received = -1;
+			goto out;
 		}
 
 		/* Malloc up new buffer, compatible with net-2e. */
@@ -2024,21 +2027,18 @@ 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 */
+	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:
-
 #if RTL8139_DEBUG > 1
 	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
 		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
@@ -2047,6 +2047,7 @@ static int rtl8139_rx(struct net_device 
 #endif
 
 	tp->cur_rx = cur_rx;
+out:
 	return received;
 }
 

_

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

* [PATCH 2.6.8-rc3-mm1 2/2] 8139too: be sure to progress durin rtl8139_rx()
  2004-08-05 21:43 [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery Francois Romieu
@ 2004-08-05 21:45 ` Francois Romieu
  2004-08-11 19:17 ` [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery Jeff Garzik
  1 sibling, 0 replies; 7+ messages in thread
From: Francois Romieu @ 2004-08-05 21:45 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andrew Morton, Pasi Sjoholm, Hector Martin, OGAWA Hirofumi,
	netdev

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: Francois Romieu <romieu@fr.zoreil.com>

diff -puN drivers/net/8139too.c~r8139-20 drivers/net/8139too.c
--- linux-2.6.8-rc3/drivers/net/8139too.c~r8139-20	2004-08-05 23:24:47.000000000 +0200
+++ linux-2.6.8-rc3-romieu/drivers/net/8139too.c	2004-08-05 23:24:47.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@pobox.com>");
@@ -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));
 
@@ -1978,10 +1979,24 @@ static int rtl8139_rx(struct net_device 
 		 * since EarlyRx is disabled.
 		 */
 		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++;
 			break;
 		}
 
+no_early_rx:
+		tp->fifo_copy_timeout = 0;
+
 		/* If Rx err or invalid rx_size/rx_status received
 		 * (which happens if we get lost in the ring),
 		 * Rx process gets reset, so we abort any further
@@ -2047,6 +2062,14 @@ static int rtl8139_rx(struct net_device 
 #endif
 
 	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:
 	return received;
 }

_

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

* Re: [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery
  2004-08-05 21:43 [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery Francois Romieu
  2004-08-05 21:45 ` [PATCH 2.6.8-rc3-mm1 2/2] 8139too: be sure to progress durin rtl8139_rx() Francois Romieu
@ 2004-08-11 19:17 ` Jeff Garzik
  2004-08-11 22:32   ` Francois Romieu
  1 sibling, 1 reply; 7+ messages in thread
From: Jeff Garzik @ 2004-08-11 19:17 UTC (permalink / raw)
  To: Francois Romieu
  Cc: Andrew Morton, Pasi Sjoholm, Hector Martin, OGAWA Hirofumi,
	netdev

Francois Romieu wrote:
> This patch allows to update the interrupt status register after an 
> Rx overflow or a Rx fifo error even when the Rx buffer contains no packet.
> As a side effect it saves a few heavy (i.e. flushed) pci ops per received
> packet when several packets are received at the same time.


You _want_ to update those registers on every packet.  Otherwise the 
crappy 8139 chip breaks.

	Jeff

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

* Re: [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery
  2004-08-11 19:17 ` [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery Jeff Garzik
@ 2004-08-11 22:32   ` Francois Romieu
  2004-08-11 22:56     ` Jeff Garzik
  0 siblings, 1 reply; 7+ messages in thread
From: Francois Romieu @ 2004-08-11 22:32 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andrew Morton, Pasi Sjoholm, Hector Martin, OGAWA Hirofumi,
	netdev

Jeff Garzik <jgarzik@pobox.com> :
[...]
> You _want_ to update those registers on every packet.  Otherwise the 
> crappy 8139 chip breaks.

The affected users noticed a clear difference when the update was in
the no-packet branch instead of the packet processing loop. Btw the
excerpt of the documentation outlined by Hirofumi san suggests that
this update makes sense.

Any objection/suggestion regarding a patch which would allow the update
in both branches ?

--
Ueimor

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

* Re: [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery
  2004-08-11 22:32   ` Francois Romieu
@ 2004-08-11 22:56     ` Jeff Garzik
  2004-08-12 20:28       ` Francois Romieu
  0 siblings, 1 reply; 7+ messages in thread
From: Jeff Garzik @ 2004-08-11 22:56 UTC (permalink / raw)
  To: Francois Romieu
  Cc: Andrew Morton, Pasi Sjoholm, Hector Martin, OGAWA Hirofumi,
	netdev

Francois Romieu wrote:
> Jeff Garzik <jgarzik@pobox.com> :
> [...]
> 
>>You _want_ to update those registers on every packet.  Otherwise the 
>>crappy 8139 chip breaks.
> 
> 
> The affected users noticed a clear difference when the update was in
> the no-packet branch instead of the packet processing loop. Btw the
> excerpt of the documentation outlined by Hirofumi san suggests that
> this update makes sense.
> 
> Any objection/suggestion regarding a patch which would allow the update
> in both branches ?

Both branches is fine.

You'll quickly hit the RX-error-requiring-reset condition if you don't 
update on each packet, though.

	Jeff

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

* Re: [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery
  2004-08-11 22:56     ` Jeff Garzik
@ 2004-08-12 20:28       ` Francois Romieu
  2004-08-14 18:58         ` Pasi Sjoholm
  0 siblings, 1 reply; 7+ messages in thread
From: Francois Romieu @ 2004-08-12 20:28 UTC (permalink / raw)
  To: Pasi Sjoholm
  Cc: Jeff Garzik, Andrew Morton, Hector Martin, OGAWA Hirofumi, netdev

[-- Attachment #1: Type: text/plain, Size: 652 bytes --]

Jeff Garzik <jgarzik@pobox.com> :
[...]
> Both branches is fine.
> 
> You'll quickly hit the RX-error-requiring-reset condition if you don't 
> update on each packet, though.

M. Sjoholm, can you apply the attached patch below to a vanilla 2.6.8-rc4
and report if the former bug reappears ?

If the bug is (partially) back, 8139too-20.patch on top of -10 may help.

If you want to test against 2.6.8-rc4-mm1:
http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.8-rc4-mm1/8139too-mm-revert.patch
http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.8-rc4-mm1/8139too-10.patch
http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.8-rc4-mm1/8139too-20.patch

--
Ueimor

[-- Attachment #2: 8139too-10.patch --]
[-- Type: text/plain, Size: 3298 bytes --]


This patch allows to update the interrupt status register after an 
Rx overflow or a Rx fifo error even when the Rx buffer contains no packet.
The update must be kept in the packet processing loop to prevent an Rx
error storm.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>


 drivers/net/8139too.c |   45 ++++++++++++++++++++++++++++++---------------
 1 files changed, 30 insertions(+), 15 deletions(-)

diff -puN drivers/net/8139too.c~8139too-10 drivers/net/8139too.c
--- linux-2.6.8-rc4/drivers/net/8139too.c~8139too-10	2004-08-12 21:37:18.000000000 +0200
+++ linux-2.6.8-rc4-romieu/drivers/net/8139too.c	2004-08-12 22:10:21.000000000 +0200
@@ -1927,6 +1927,23 @@ static __inline__ void wrap_copy(struct 
 }
 #endif
 
+static void rtl8139_isr_ack(struct rtl8139_private *tp, u16 status)
+{
+	void *ioaddr = tp->mmio_addr;
+
+	status &= RxAckBits;
+
+	/* Clear out errors and receive interrupts */
+	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);
+	}
+}
+
 static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		      int budget)
 {
@@ -1934,20 +1951,22 @@ static int rtl8139_rx(struct net_device 
 	int received = 0;
 	unsigned char *rx_ring = tp->rx_ring;
 	unsigned int cur_rx = tp->cur_rx;
+	unsigned int rx_size = 0;
+	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,
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
+	status = RTL_R16 (IntrStatus);
+
 	while (netif_running(dev) && received < budget 
 	       && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
 		u32 ring_offset = cur_rx % RX_BUF_LEN;
 		u32 rx_status;
-		unsigned int rx_size;
 		unsigned int pkt_size;
 		struct sk_buff *skb;
-		u16 status;
 
 		rmb();
 
@@ -1977,7 +1996,7 @@ static int rtl8139_rx(struct net_device 
 		 */
 		if (unlikely(rx_size == 0xfff0)) {
 			tp->xstats.early_rx++;
-			goto done;
+			break;
 		}
 
 		/* If Rx err or invalid rx_size/rx_status received
@@ -1989,7 +2008,8 @@ static int rtl8139_rx(struct net_device 
 			     (rx_size < 8) ||
 			     (!(rx_status & RxStatusOK)))) {
 			rtl8139_rx_err (rx_status, dev, tp, ioaddr);
-			return -1;
+			received = -1;
+			goto out;
 		}
 
 		/* Malloc up new buffer, compatible with net-2e. */
@@ -2025,19 +2045,13 @@ 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);
-		}
+		rtl8139_isr_ack(tp, status);
+
+		status = RTL_R16 (IntrStatus);
 	}
 
- done:
+	if (unlikely(!received || rx_size == 0xfff0))
+		rtl8139_isr_ack(tp, status);
 
 #if RTL8139_DEBUG > 1
 	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
@@ -2047,6 +2061,7 @@ static int rtl8139_rx(struct net_device 
 #endif
 
 	tp->cur_rx = cur_rx;
+out:
 	return received;
 }
 

_

[-- Attachment #3: 8139too-20.patch --]
[-- Type: text/plain, Size: 2123 bytes --]


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: Francois Romieu <romieu@fr.zoreil.com>


 drivers/net/8139too.c |   25 ++++++++++++++++++++++++-
 1 files changed, 24 insertions(+), 1 deletion(-)

diff -puN drivers/net/8139too.c~8139too-20 drivers/net/8139too.c
--- linux-2.6.8-rc4/drivers/net/8139too.c~8139too-20	2004-08-12 22:13:18.000000000 +0200
+++ linux-2.6.8-rc4-romieu/drivers/net/8139too.c	2004-08-12 22:13:18.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@pobox.com>");
@@ -1955,7 +1956,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));
 
@@ -1995,10 +1996,24 @@ static int rtl8139_rx(struct net_device 
 		 * since EarlyRx is disabled.
 		 */
 		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++;
 			break;
 		}
 
+no_early_rx:
+		tp->fifo_copy_timeout = 0;
+
 		/* If Rx err or invalid rx_size/rx_status received
 		 * (which happens if we get lost in the ring),
 		 * Rx process gets reset, so we abort any further
@@ -2061,6 +2076,14 @@ static int rtl8139_rx(struct net_device 
 #endif
 
 	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:
 	return received;
 }

_

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

* Re: [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery
  2004-08-12 20:28       ` Francois Romieu
@ 2004-08-14 18:58         ` Pasi Sjoholm
  0 siblings, 0 replies; 7+ messages in thread
From: Pasi Sjoholm @ 2004-08-14 18:58 UTC (permalink / raw)
  To: Francois Romieu
  Cc: Jeff Garzik, Andrew Morton, Hector Martin, OGAWA Hirofumi, netdev

On Thu, 12 Aug 2004, Francois Romieu wrote:

> Jeff Garzik <jgarzik@pobox.com> :
> [...]
> > Both branches is fine.
> > You'll quickly hit the RX-error-requiring-reset condition if you don't 
> > update on each packet, though.
> M. Sjoholm, can you apply the attached patch below to a vanilla 2.6.8-rc4
> and report if the former bug reappears ?

Hello Francois, 

I only tested 8139too-10.patch against vanilla 2.6.8.1 and it seems
that the 8139too-driver is working ok. I tested it for three hours 
but I guess it's enough. =) 

--
Pasi Sjöholm

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

end of thread, other threads:[~2004-08-14 18:58 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-05 21:43 [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery Francois Romieu
2004-08-05 21:45 ` [PATCH 2.6.8-rc3-mm1 2/2] 8139too: be sure to progress durin rtl8139_rx() Francois Romieu
2004-08-11 19:17 ` [PATCH 2.6.8-rc3-mm1 1/2] 8139too: Rx fifo/overflow recovery Jeff Garzik
2004-08-11 22:32   ` Francois Romieu
2004-08-11 22:56     ` Jeff Garzik
2004-08-12 20:28       ` Francois Romieu
2004-08-14 18:58         ` Pasi Sjoholm

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).