aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorPhilippe De Muyter <phdm@macqel.be>2005-10-28 06:23:47 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-28 16:40:33 -0400
commitb71b95efa5abca33e1bfb85d55162c7f99f54c23 (patch)
treee6b22bf428cc83cd54f10e9ea6551c4cea09fdb8 /drivers/net
parent89358f90ab6f6657d386e77e19c805d7ab88694f (diff)
[PATCH] sundance: fix DFE-580TX Tx Underrun
Under heavy PCI bus load, ports of the DFE-580TX 4-ethernet port board stop working, with currently no other cure than a powercycle. Here is a tested fix. By the way, I also fixed some references and attribution. Signed-off-by: Philippe De Muyter <phdm@macqel.be> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sundance.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 5de0554fd7c6..0ab9c38b4a34 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -80,7 +80,7 @@
80 I/O access could affect performance in ARM-based system 80 I/O access could affect performance in ARM-based system
81 - Add Linux software VLAN support 81 - Add Linux software VLAN support
82 82
83 Version LK1.08 (D-Link): 83 Version LK1.08 (Philippe De Muyter phdm@macqel.be):
84 - Fix bug of custom mac address 84 - Fix bug of custom mac address
85 (StationAddr register only accept word write) 85 (StationAddr register only accept word write)
86 86
@@ -91,11 +91,14 @@
91 Version LK1.09a (ICPlus): 91 Version LK1.09a (ICPlus):
92 - Add the delay time in reading the contents of EEPROM 92 - Add the delay time in reading the contents of EEPROM
93 93
94 Version LK1.10 (Philippe De Muyter phdm@macqel.be):
95 - Make 'unblock interface after Tx underrun' work
96
94*/ 97*/
95 98
96#define DRV_NAME "sundance" 99#define DRV_NAME "sundance"
97#define DRV_VERSION "1.01+LK1.09a" 100#define DRV_VERSION "1.01+LK1.10"
98#define DRV_RELDATE "10-Jul-2003" 101#define DRV_RELDATE "28-Oct-2005"
99 102
100 103
101/* The user-configurable values. 104/* The user-configurable values.
@@ -263,8 +266,10 @@ IV. Notes
263IVb. References 266IVb. References
264 267
265The Sundance ST201 datasheet, preliminary version. 268The Sundance ST201 datasheet, preliminary version.
266http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html 269The Kendin KS8723 datasheet, preliminary version.
267http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html 270The ICplus IP100 datasheet, preliminary version.
271http://www.scyld.com/expert/100mbps.html
272http://www.scyld.com/expert/NWay.html
268 273
269IVc. Errata 274IVc. Errata
270 275
@@ -500,6 +505,25 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
500static int netdev_close(struct net_device *dev); 505static int netdev_close(struct net_device *dev);
501static struct ethtool_ops ethtool_ops; 506static struct ethtool_ops ethtool_ops;
502 507
508static void sundance_reset(struct net_device *dev, unsigned long reset_cmd)
509{
510 struct netdev_private *np = netdev_priv(dev);
511 void __iomem *ioaddr = np->base + ASICCtrl;
512 int countdown;
513
514 /* ST201 documentation states ASICCtrl is a 32bit register */
515 iowrite32 (reset_cmd | ioread32 (ioaddr), ioaddr);
516 /* ST201 documentation states reset can take up to 1 ms */
517 countdown = 10 + 1;
518 while (ioread32 (ioaddr) & (ResetBusy << 16)) {
519 if (--countdown == 0) {
520 printk(KERN_WARNING "%s : reset not completed !!\n", dev->name);
521 break;
522 }
523 udelay(100);
524 }
525}
526
503static int __devinit sundance_probe1 (struct pci_dev *pdev, 527static int __devinit sundance_probe1 (struct pci_dev *pdev,
504 const struct pci_device_id *ent) 528 const struct pci_device_id *ent)
505{ 529{
@@ -1190,23 +1214,33 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
1190 ("%s: Transmit status is %2.2x.\n", 1214 ("%s: Transmit status is %2.2x.\n",
1191 dev->name, tx_status); 1215 dev->name, tx_status);
1192 if (tx_status & 0x1e) { 1216 if (tx_status & 0x1e) {
1217 if (netif_msg_tx_err(np))
1218 printk("%s: Transmit error status %4.4x.\n",
1219 dev->name, tx_status);
1193 np->stats.tx_errors++; 1220 np->stats.tx_errors++;
1194 if (tx_status & 0x10) 1221 if (tx_status & 0x10)
1195 np->stats.tx_fifo_errors++; 1222 np->stats.tx_fifo_errors++;
1196 if (tx_status & 0x08) 1223 if (tx_status & 0x08)
1197 np->stats.collisions++; 1224 np->stats.collisions++;
1225 if (tx_status & 0x04)
1226 np->stats.tx_fifo_errors++;
1198 if (tx_status & 0x02) 1227 if (tx_status & 0x02)
1199 np->stats.tx_window_errors++; 1228 np->stats.tx_window_errors++;
1200 /* This reset has not been verified!. */ 1229 /*
1201 if (tx_status & 0x10) { /* Reset the Tx. */ 1230 ** This reset has been verified on
1202 np->stats.tx_fifo_errors++; 1231 ** DFE-580TX boards ! phdm@macqel.be.
1203 spin_lock(&np->lock); 1232 */
1204 reset_tx(dev); 1233 if (tx_status & 0x10) { /* TxUnderrun */
1205 spin_unlock(&np->lock); 1234 unsigned short txthreshold;
1235
1236 txthreshold = ioread16 (ioaddr + TxStartThresh);
1237 /* Restart Tx FIFO and transmitter */
1238 sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16);
1239 iowrite16 (txthreshold, ioaddr + TxStartThresh);
1240 /* No need to reset the Tx pointer here */
1206 } 1241 }
1207 if (tx_status & 0x1e) /* Restart the Tx. */ 1242 /* Restart the Tx. */
1208 iowrite16 (TxEnable, 1243 iowrite16 (TxEnable, ioaddr + MACCtrl1);
1209 ioaddr + MACCtrl1);
1210 } 1244 }
1211 /* Yup, this is a documentation bug. It cost me *hours*. */ 1245 /* Yup, this is a documentation bug. It cost me *hours*. */
1212 iowrite16 (0, ioaddr + TxStatus); 1246 iowrite16 (0, ioaddr + TxStatus);