aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sundance.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sundance.c')
-rw-r--r--drivers/net/sundance.c111
1 files changed, 73 insertions, 38 deletions
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index d500a5771dbc..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{
@@ -518,6 +542,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
518#else 542#else
519 int bar = 1; 543 int bar = 1;
520#endif 544#endif
545 int phy, phy_idx = 0;
521 546
522 547
523/* when built into the kernel, we only print version if device is found */ 548/* when built into the kernel, we only print version if device is found */
@@ -549,6 +574,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
549 for (i = 0; i < 3; i++) 574 for (i = 0; i < 3; i++)
550 ((u16 *)dev->dev_addr)[i] = 575 ((u16 *)dev->dev_addr)[i] =
551 le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET)); 576 le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
577 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
552 578
553 dev->base_addr = (unsigned long)ioaddr; 579 dev->base_addr = (unsigned long)ioaddr;
554 dev->irq = irq; 580 dev->irq = irq;
@@ -605,33 +631,31 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
605 printk("%2.2x:", dev->dev_addr[i]); 631 printk("%2.2x:", dev->dev_addr[i]);
606 printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); 632 printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
607 633
608 if (1) { 634 np->phys[0] = 1; /* Default setting */
609 int phy, phy_idx = 0; 635 np->mii_preamble_required++;
610 np->phys[0] = 1; /* Default setting */ 636 for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
611 np->mii_preamble_required++; 637 int mii_status = mdio_read(dev, phy, MII_BMSR);
612 for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) { 638 int phyx = phy & 0x1f;
613 int mii_status = mdio_read(dev, phy, MII_BMSR); 639 if (mii_status != 0xffff && mii_status != 0x0000) {
614 if (mii_status != 0xffff && mii_status != 0x0000) { 640 np->phys[phy_idx++] = phyx;
615 np->phys[phy_idx++] = phy; 641 np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
616 np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE); 642 if ((mii_status & 0x0040) == 0)
617 if ((mii_status & 0x0040) == 0) 643 np->mii_preamble_required++;
618 np->mii_preamble_required++; 644 printk(KERN_INFO "%s: MII PHY found at address %d, status "
619 printk(KERN_INFO "%s: MII PHY found at address %d, status " 645 "0x%4.4x advertising %4.4x.\n",
620 "0x%4.4x advertising %4.4x.\n", 646 dev->name, phyx, mii_status, np->mii_if.advertising);
621 dev->name, phy, mii_status, np->mii_if.advertising);
622 }
623 }
624 np->mii_preamble_required--;
625
626 if (phy_idx == 0) {
627 printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
628 dev->name, ioread32(ioaddr + ASICCtrl));
629 goto err_out_unregister;
630 } 647 }
648 }
649 np->mii_preamble_required--;
631 650
632 np->mii_if.phy_id = np->phys[0]; 651 if (phy_idx == 0) {
652 printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
653 dev->name, ioread32(ioaddr + ASICCtrl));
654 goto err_out_unregister;
633 } 655 }
634 656
657 np->mii_if.phy_id = np->phys[0];
658
635 /* Parse override configuration */ 659 /* Parse override configuration */
636 np->an_enable = 1; 660 np->an_enable = 1;
637 if (card_idx < MAX_UNITS) { 661 if (card_idx < MAX_UNITS) {
@@ -692,7 +716,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
692 /* Reset the chip to erase previous misconfiguration. */ 716 /* Reset the chip to erase previous misconfiguration. */
693 if (netif_msg_hw(np)) 717 if (netif_msg_hw(np))
694 printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl)); 718 printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
695 iowrite16(0x007f, ioaddr + ASICCtrl + 2); 719 iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
696 if (netif_msg_hw(np)) 720 if (netif_msg_hw(np))
697 printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl)); 721 printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
698 722
@@ -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);
@@ -1619,6 +1653,7 @@ static struct ethtool_ops ethtool_ops = {
1619 .get_link = get_link, 1653 .get_link = get_link,
1620 .get_msglevel = get_msglevel, 1654 .get_msglevel = get_msglevel,
1621 .set_msglevel = set_msglevel, 1655 .set_msglevel = set_msglevel,
1656 .get_perm_addr = ethtool_op_get_perm_addr,
1622}; 1657};
1623 1658
1624static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 1659static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)