diff options
author | Philippe De Muyter <phdm@macqel.be> | 2005-10-28 06:23:47 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-28 16:40:33 -0400 |
commit | b71b95efa5abca33e1bfb85d55162c7f99f54c23 (patch) | |
tree | e6b22bf428cc83cd54f10e9ea6551c4cea09fdb8 /drivers/net | |
parent | 89358f90ab6f6657d386e77e19c805d7ab88694f (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.c | 62 |
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 | |||
263 | IVb. References | 266 | IVb. References |
264 | 267 | ||
265 | The Sundance ST201 datasheet, preliminary version. | 268 | The Sundance ST201 datasheet, preliminary version. |
266 | http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html | 269 | The Kendin KS8723 datasheet, preliminary version. |
267 | http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html | 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 | IVc. Errata | 274 | IVc. Errata |
270 | 275 | ||
@@ -500,6 +505,25 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | |||
500 | static int netdev_close(struct net_device *dev); | 505 | static int netdev_close(struct net_device *dev); |
501 | static struct ethtool_ops ethtool_ops; | 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 | static int __devinit sundance_probe1 (struct pci_dev *pdev, | 527 | static 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); |