[PATCH] subdance: fix TX Pause bug (reset_tx, intr_handler)
authorJesse Huang <jesse@icplus.com.tw>
Fri, 20 Oct 2006 21:42:11 +0000 (14:42 -0700)
committerJeff Garzik <jeff@garzik.org>
Sat, 2 Dec 2006 05:12:02 +0000 (00:12 -0500)
Fix TX Pause bug (reset_tx, intr_handler).  When MaxCollisions occurred, need
to re-enable Tx.  But just after re-enable, MaxCollisions maybe occurred again
and with TxStatusOverflow.  This will cause driver can't check new
MaxCollisions to re-enable Tx again, because TxStatusOverflow.  For this
reason, after re-enable Tx, we need to make sure Tx was actually enabled.

Signed-off-by: Jesse Huang <jesse@icplus.com.tw>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/sundance.c

index be1faa0..91cd2f5 100644 (file)
@@ -1079,6 +1079,8 @@ reset_tx (struct net_device *dev)
 
        /* free all tx skbuff */
        for (i = 0; i < TX_RING_SIZE; i++) {
+               np->tx_ring[i].next_desc = 0;
+
                skb = np->tx_skbuff[i];
                if (skb) {
                        pci_unmap_single(np->pci_dev,
@@ -1094,6 +1096,10 @@ reset_tx (struct net_device *dev)
        }
        np->cur_tx = np->dirty_tx = 0;
        np->cur_task = 0;
+
+       np->last_tx = 0;
+       iowrite8(127, ioaddr + TxDMAPollPeriod);
+
        iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
        return 0;
 }
@@ -1162,8 +1168,14 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
                                                sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16);
                                                /* No need to reset the Tx pointer here */
                                        }
-                                       /* Restart the Tx. */
-                                       iowrite16 (TxEnable, ioaddr + MACCtrl1);
+                                       /* Restart the Tx. Need to make sure tx enabled */
+                                       i = 10;
+                                       do {
+                                               iowrite16(ioread16(ioaddr + MACCtrl1) | TxEnable, ioaddr + MACCtrl1);
+                                               if (ioread16(ioaddr + MACCtrl1) & TxEnabled)
+                                                       break;
+                                               mdelay(1);
+                                       } while (--i);
                                }
                                /* Yup, this is a documentation bug.  It cost me *hours*. */
                                iowrite16 (0, ioaddr + TxStatus);