]> git.neil.brown.name Git - history.git/commitdiff
[netdrvr r8169] TX irq handler looping fix
authorFrançois Romieu <romieu@fr.zoreil.com>
Tue, 6 Apr 2004 04:21:48 +0000 (00:21 -0400)
committerJeff Garzik <jgarzik@redhat.com>
Tue, 6 Apr 2004 04:21:48 +0000 (00:21 -0400)
If a few packets have been scheduled for Tx, it is possible to keep looping
in the Tx irq handler as soon as the irq for the first packet has been
received until the descriptor of the last packet has been sent (with
interrupts disabled btw).

drivers/net/r8169.c

index 52458d93ed211390a6c7f0e1e73b14f2f7b1748f..97e3e1e7f59eb5404a15664b94f716890cc71392 100644 (file)
@@ -1394,22 +1394,24 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 
        while (tx_left > 0) {
                int entry = dirty_tx % NUM_TX_DESC;
+               struct sk_buff *skb = tp->Tx_skbuff[entry];
+               u32 status;
 
                rmb();
-               if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
-                       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 + entry,
-                                            tp->TxDescArray + entry);
-                       dev_kfree_skb_irq(skb);
-                       tp->Tx_skbuff[entry] = NULL;
-                       dirty_tx++;
-                       tx_left--;
-               }
+               status = le32_to_cpu(tp->TxDescArray[entry].status);
+               if (status & OWNbit)
+                       break;
+
+               /* 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 + entry,
+                                    tp->TxDescArray + entry);
+               dev_kfree_skb_irq(skb);
+               tp->Tx_skbuff[entry] = NULL;
+               dirty_tx++;
+               tx_left--;
        }
 
        if (tp->dirty_tx != dirty_tx) {