
From: Francois Romieu <romieu@fr.zoreil.com>

One of the r8169 tester would like to try -mm SMT scheduler with an
up-to-date r8169 driver wrt bug fixes.  The patch above is a merge of the
relevant patch of my r8169 serie.

In its original version, this patch has been sent on netdev and tested
against various kernel versions, including plain 2.4.2-rc1, without
noticeable regression.  In addition to this, nobody cared enough to say
that the analysis of the problem was wrong (or even badly written :o) ). 
It is not a silver bullet against the bugs of the r8169 driver under
load/SMP but this specific bug exists in any existing r8169 driver I have
heard of.

- possible tx descriptor index overflow (assume tp->dirty_tx = NUM_TX_DESC/2,
  tp->cur_tx = NUM_TX_DESC - 1 and watch TxDescArray for example);

- the status of an inadequate descriptor is checked.

NB: the bug will not necessarily noticed when tx_left == 1.



---

 drivers/net/r8169.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff -puN drivers/net/r8169.c~r8169-race-fix drivers/net/r8169.c
--- 25/drivers/net/r8169.c~r8169-race-fix	2004-01-24 13:05:53.000000000 -0800
+++ 25-akpm/drivers/net/r8169.c	2004-01-24 13:05:53.000000000 -0800
@@ -1341,8 +1341,7 @@ static void
 rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long dirty_tx, tx_left = 0;
-	int entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned long dirty_tx, tx_left;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -1352,20 +1351,21 @@ rtl8169_tx_interrupt(struct net_device *
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
+		int entry = dirty_tx % NUM_TX_DESC;
+
 		if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
-			int cur = dirty_tx % NUM_TX_DESC;
-			struct sk_buff *skb = tp->Tx_skbuff[cur];
+			struct sk_buff *skb = tp->Tx_skbuff[entry];
 
 			/* FIXME: is it really accurate for TxErr ? */
 			tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
 					      skb->len : ETH_ZLEN;
 			tp->stats.tx_packets++;
-			rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + cur,
-					     tp->TxDescArray + cur);
+			rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry,
+					     tp->TxDescArray + entry);
 			dev_kfree_skb_irq(skb);
+			tp->Tx_skbuff[entry] = NULL;
 			dirty_tx++;
 			tx_left--;
-			entry++;
 		}
 	}
 

_
