Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Philippe De Muyter and committed by
Jeff Garzik
b71b95ef 89358f90

+48 -14
+48 -14
drivers/net/sundance.c
··· 80 80 I/O access could affect performance in ARM-based system 81 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 84 - Fix bug of custom mac address 85 85 (StationAddr register only accept word write) 86 86 ··· 91 91 Version LK1.09a (ICPlus): 92 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 99 #define DRV_NAME "sundance" 97 - #define DRV_VERSION "1.01+LK1.09a" 98 - #define DRV_RELDATE "10-Jul-2003" 100 + #define DRV_VERSION "1.01+LK1.10" 101 + #define DRV_RELDATE "28-Oct-2005" 99 102 100 103 101 104 /* The user-configurable values. ··· 266 263 IVb. References 267 264 268 265 The Sundance ST201 datasheet, preliminary version. 269 - http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html 270 - http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html 266 + The Kendin KS8723 datasheet, preliminary version. 267 + The ICplus IP100 datasheet, preliminary version. 268 + http://www.scyld.com/expert/100mbps.html 269 + http://www.scyld.com/expert/NWay.html 271 270 272 271 IVc. Errata 273 272 ··· 504 499 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 505 500 static int netdev_close(struct net_device *dev); 506 501 static struct ethtool_ops ethtool_ops; 502 + 503 + static void sundance_reset(struct net_device *dev, unsigned long reset_cmd) 504 + { 505 + struct netdev_private *np = netdev_priv(dev); 506 + void __iomem *ioaddr = np->base + ASICCtrl; 507 + int countdown; 508 + 509 + /* ST201 documentation states ASICCtrl is a 32bit register */ 510 + iowrite32 (reset_cmd | ioread32 (ioaddr), ioaddr); 511 + /* ST201 documentation states reset can take up to 1 ms */ 512 + countdown = 10 + 1; 513 + while (ioread32 (ioaddr) & (ResetBusy << 16)) { 514 + if (--countdown == 0) { 515 + printk(KERN_WARNING "%s : reset not completed !!\n", dev->name); 516 + break; 517 + } 518 + udelay(100); 519 + } 520 + } 507 521 508 522 static int __devinit sundance_probe1 (struct pci_dev *pdev, 509 523 const struct pci_device_id *ent) ··· 1214 1190 ("%s: Transmit status is %2.2x.\n", 1215 1191 dev->name, tx_status); 1216 1192 if (tx_status & 0x1e) { 1193 + if (netif_msg_tx_err(np)) 1194 + printk("%s: Transmit error status %4.4x.\n", 1195 + dev->name, tx_status); 1217 1196 np->stats.tx_errors++; 1218 1197 if (tx_status & 0x10) 1219 1198 np->stats.tx_fifo_errors++; 1220 1199 if (tx_status & 0x08) 1221 1200 np->stats.collisions++; 1201 + if (tx_status & 0x04) 1202 + np->stats.tx_fifo_errors++; 1222 1203 if (tx_status & 0x02) 1223 1204 np->stats.tx_window_errors++; 1224 - /* This reset has not been verified!. */ 1225 - if (tx_status & 0x10) { /* Reset the Tx. */ 1226 - np->stats.tx_fifo_errors++; 1227 - spin_lock(&np->lock); 1228 - reset_tx(dev); 1229 - spin_unlock(&np->lock); 1205 + /* 1206 + ** This reset has been verified on 1207 + ** DFE-580TX boards ! phdm@macqel.be. 1208 + */ 1209 + if (tx_status & 0x10) { /* TxUnderrun */ 1210 + unsigned short txthreshold; 1211 + 1212 + txthreshold = ioread16 (ioaddr + TxStartThresh); 1213 + /* Restart Tx FIFO and transmitter */ 1214 + sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16); 1215 + iowrite16 (txthreshold, ioaddr + TxStartThresh); 1216 + /* No need to reset the Tx pointer here */ 1230 1217 } 1231 - if (tx_status & 0x1e) /* Restart the Tx. */ 1232 - iowrite16 (TxEnable, 1233 - ioaddr + MACCtrl1); 1218 + /* Restart the Tx. */ 1219 + iowrite16 (TxEnable, ioaddr + MACCtrl1); 1234 1220 } 1235 1221 /* Yup, this is a documentation bug. It cost me *hours*. */ 1236 1222 iowrite16 (0, ioaddr + TxStatus);