Commit b71b95efa5abca33e1bfb85d55162c7f99f54c23

Authored by Philippe De Muyter
Committed by Jeff Garzik
1 parent 89358f90ab

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

Showing 1 changed file with 48 additions and 14 deletions Side-by-side Diff

drivers/net/sundance.c
... ... @@ -80,7 +80,7 @@
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  
87 87  
... ... @@ -91,11 +91,14 @@
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.
... ... @@ -263,8 +266,10 @@
263 266 IVb. References
264 267  
265 268 The Sundance ST201 datasheet, preliminary version.
266   -http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
267   -http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
  269 +The Kendin KS8723 datasheet, preliminary version.
  270 +The ICplus IP100 datasheet, preliminary version.
  271 +http://www.scyld.com/expert/100mbps.html
  272 +http://www.scyld.com/expert/NWay.html
268 273  
269 274 IVc. Errata
270 275  
... ... @@ -500,6 +505,25 @@
500 505 static int netdev_close(struct net_device *dev);
501 506 static struct ethtool_ops ethtool_ops;
502 507  
  508 +static 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 +
503 527 static int __devinit sundance_probe1 (struct pci_dev *pdev,
504 528 const struct pci_device_id *ent)
505 529 {
506 530  
507 531  
508 532  
... ... @@ -1190,23 +1214,33 @@
1190 1214 ("%s: Transmit status is %2.2x.\n",
1191 1215 dev->name, tx_status);
1192 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 1220 np->stats.tx_errors++;
1194 1221 if (tx_status & 0x10)
1195 1222 np->stats.tx_fifo_errors++;
1196 1223 if (tx_status & 0x08)
1197 1224 np->stats.collisions++;
  1225 + if (tx_status & 0x04)
  1226 + np->stats.tx_fifo_errors++;
1198 1227 if (tx_status & 0x02)
1199 1228 np->stats.tx_window_errors++;
1200   - /* This reset has not been verified!. */
1201   - if (tx_status & 0x10) { /* Reset the Tx. */
1202   - np->stats.tx_fifo_errors++;
1203   - spin_lock(&np->lock);
1204   - reset_tx(dev);
1205   - spin_unlock(&np->lock);
  1229 + /*
  1230 + ** This reset has been verified on
  1231 + ** DFE-580TX boards ! phdm@macqel.be.
  1232 + */
  1233 + if (tx_status & 0x10) { /* TxUnderrun */
  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. */
1208   - iowrite16 (TxEnable,
1209   - ioaddr + MACCtrl1);
  1242 + /* Restart the Tx. */
  1243 + iowrite16 (TxEnable, ioaddr + MACCtrl1);
1210 1244 }
1211 1245 /* Yup, this is a documentation bug. It cost me *hours*. */
1212 1246 iowrite16 (0, ioaddr + TxStatus);