aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sundance.c95
1 files changed, 62 insertions, 33 deletions
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 7d5561b8241c..f860ea150395 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -409,6 +409,7 @@ static int change_mtu(struct net_device *dev, int new_mtu);
409static int eeprom_read(void __iomem *ioaddr, int location); 409static int eeprom_read(void __iomem *ioaddr, int location);
410static int mdio_read(struct net_device *dev, int phy_id, int location); 410static int mdio_read(struct net_device *dev, int phy_id, int location);
411static void mdio_write(struct net_device *dev, int phy_id, int location, int value); 411static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
412static int mdio_wait_link(struct net_device *dev, int wait);
412static int netdev_open(struct net_device *dev); 413static int netdev_open(struct net_device *dev);
413static void check_duplex(struct net_device *dev); 414static void check_duplex(struct net_device *dev);
414static void netdev_timer(unsigned long data); 415static void netdev_timer(unsigned long data);
@@ -785,6 +786,24 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
785 return; 786 return;
786} 787}
787 788
789static int mdio_wait_link(struct net_device *dev, int wait)
790{
791 int bmsr;
792 int phy_id;
793 struct netdev_private *np;
794
795 np = netdev_priv(dev);
796 phy_id = np->phys[0];
797
798 do {
799 bmsr = mdio_read(dev, phy_id, MII_BMSR);
800 if (bmsr & 0x0004)
801 return 0;
802 mdelay(1);
803 } while (--wait > 0);
804 return -1;
805}
806
788static int netdev_open(struct net_device *dev) 807static int netdev_open(struct net_device *dev)
789{ 808{
790 struct netdev_private *np = netdev_priv(dev); 809 struct netdev_private *np = netdev_priv(dev);
@@ -1393,41 +1412,51 @@ static void netdev_error(struct net_device *dev, int intr_status)
1393 int speed; 1412 int speed;
1394 1413
1395 if (intr_status & LinkChange) { 1414 if (intr_status & LinkChange) {
1396 if (np->an_enable) { 1415 if (mdio_wait_link(dev, 10) == 0) {
1397 mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE); 1416 printk(KERN_INFO "%s: Link up\n", dev->name);
1398 mii_lpa= mdio_read (dev, np->phys[0], MII_LPA); 1417 if (np->an_enable) {
1399 mii_advertise &= mii_lpa; 1418 mii_advertise = mdio_read(dev, np->phys[0],
1400 printk (KERN_INFO "%s: Link changed: ", dev->name); 1419 MII_ADVERTISE);
1401 if (mii_advertise & ADVERTISE_100FULL) { 1420 mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
1402 np->speed = 100; 1421 mii_advertise &= mii_lpa;
1403 printk ("100Mbps, full duplex\n"); 1422 printk(KERN_INFO "%s: Link changed: ",
1404 } else if (mii_advertise & ADVERTISE_100HALF) { 1423 dev->name);
1405 np->speed = 100; 1424 if (mii_advertise & ADVERTISE_100FULL) {
1406 printk ("100Mbps, half duplex\n"); 1425 np->speed = 100;
1407 } else if (mii_advertise & ADVERTISE_10FULL) { 1426 printk("100Mbps, full duplex\n");
1408 np->speed = 10; 1427 } else if (mii_advertise & ADVERTISE_100HALF) {
1409 printk ("10Mbps, full duplex\n"); 1428 np->speed = 100;
1410 } else if (mii_advertise & ADVERTISE_10HALF) { 1429 printk("100Mbps, half duplex\n");
1411 np->speed = 10; 1430 } else if (mii_advertise & ADVERTISE_10FULL) {
1412 printk ("10Mbps, half duplex\n"); 1431 np->speed = 10;
1413 } else 1432 printk("10Mbps, full duplex\n");
1414 printk ("\n"); 1433 } else if (mii_advertise & ADVERTISE_10HALF) {
1434 np->speed = 10;
1435 printk("10Mbps, half duplex\n");
1436 } else
1437 printk("\n");
1415 1438
1439 } else {
1440 mii_ctl = mdio_read(dev, np->phys[0], MII_BMCR);
1441 speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
1442 np->speed = speed;
1443 printk(KERN_INFO "%s: Link changed: %dMbps ,",
1444 dev->name, speed);
1445 printk("%s duplex.\n",
1446 (mii_ctl & BMCR_FULLDPLX) ?
1447 "full" : "half");
1448 }
1449 check_duplex(dev);
1450 if (np->flowctrl && np->mii_if.full_duplex) {
1451 iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
1452 ioaddr + MulticastFilter1+2);
1453 iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
1454 ioaddr + MACCtrl0);
1455 }
1456 netif_carrier_on(dev);
1416 } else { 1457 } else {
1417 mii_ctl = mdio_read (dev, np->phys[0], MII_BMCR); 1458 printk(KERN_INFO "%s: Link down\n", dev->name);
1418 speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10; 1459 netif_carrier_off(dev);
1419 np->speed = speed;
1420 printk (KERN_INFO "%s: Link changed: %dMbps ,",
1421 dev->name, speed);
1422 printk ("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
1423 "full" : "half");
1424 }
1425 check_duplex (dev);
1426 if (np->flowctrl && np->mii_if.full_duplex) {
1427 iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
1428 ioaddr + MulticastFilter1+2);
1429 iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
1430 ioaddr + MACCtrl0);
1431 } 1460 }
1432 } 1461 }
1433 if (intr_status & StatsMax) { 1462 if (intr_status & StatsMax) {