|
@@ -409,6 +409,7 @@ static int change_mtu(struct net_device *dev, int new_mtu);
|
|
|
static int eeprom_read(void __iomem *ioaddr, int location);
|
|
|
static int mdio_read(struct net_device *dev, int phy_id, int location);
|
|
|
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
|
|
|
+static int mdio_wait_link(struct net_device *dev, int wait);
|
|
|
static int netdev_open(struct net_device *dev);
|
|
|
static void check_duplex(struct net_device *dev);
|
|
|
static 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
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+static int mdio_wait_link(struct net_device *dev, int wait)
|
|
|
+{
|
|
|
+ int bmsr;
|
|
|
+ int phy_id;
|
|
|
+ struct netdev_private *np;
|
|
|
+
|
|
|
+ np = netdev_priv(dev);
|
|
|
+ phy_id = np->phys[0];
|
|
|
+
|
|
|
+ do {
|
|
|
+ bmsr = mdio_read(dev, phy_id, MII_BMSR);
|
|
|
+ if (bmsr & 0x0004)
|
|
|
+ return 0;
|
|
|
+ mdelay(1);
|
|
|
+ } while (--wait > 0);
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
static int netdev_open(struct net_device *dev)
|
|
|
{
|
|
|
struct netdev_private *np = netdev_priv(dev);
|
|
@@ -1393,41 +1412,51 @@ static void netdev_error(struct net_device *dev, int intr_status)
|
|
|
int speed;
|
|
|
|
|
|
if (intr_status & LinkChange) {
|
|
|
- if (np->an_enable) {
|
|
|
- mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE);
|
|
|
- mii_lpa= mdio_read (dev, np->phys[0], MII_LPA);
|
|
|
- mii_advertise &= mii_lpa;
|
|
|
- printk (KERN_INFO "%s: Link changed: ", dev->name);
|
|
|
- if (mii_advertise & ADVERTISE_100FULL) {
|
|
|
- np->speed = 100;
|
|
|
- printk ("100Mbps, full duplex\n");
|
|
|
- } else if (mii_advertise & ADVERTISE_100HALF) {
|
|
|
- np->speed = 100;
|
|
|
- printk ("100Mbps, half duplex\n");
|
|
|
- } else if (mii_advertise & ADVERTISE_10FULL) {
|
|
|
- np->speed = 10;
|
|
|
- printk ("10Mbps, full duplex\n");
|
|
|
- } else if (mii_advertise & ADVERTISE_10HALF) {
|
|
|
- np->speed = 10;
|
|
|
- printk ("10Mbps, half duplex\n");
|
|
|
- } else
|
|
|
- printk ("\n");
|
|
|
+ if (mdio_wait_link(dev, 10) == 0) {
|
|
|
+ printk(KERN_INFO "%s: Link up\n", dev->name);
|
|
|
+ if (np->an_enable) {
|
|
|
+ mii_advertise = mdio_read(dev, np->phys[0],
|
|
|
+ MII_ADVERTISE);
|
|
|
+ mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
|
|
|
+ mii_advertise &= mii_lpa;
|
|
|
+ printk(KERN_INFO "%s: Link changed: ",
|
|
|
+ dev->name);
|
|
|
+ if (mii_advertise & ADVERTISE_100FULL) {
|
|
|
+ np->speed = 100;
|
|
|
+ printk("100Mbps, full duplex\n");
|
|
|
+ } else if (mii_advertise & ADVERTISE_100HALF) {
|
|
|
+ np->speed = 100;
|
|
|
+ printk("100Mbps, half duplex\n");
|
|
|
+ } else if (mii_advertise & ADVERTISE_10FULL) {
|
|
|
+ np->speed = 10;
|
|
|
+ printk("10Mbps, full duplex\n");
|
|
|
+ } else if (mii_advertise & ADVERTISE_10HALF) {
|
|
|
+ np->speed = 10;
|
|
|
+ printk("10Mbps, half duplex\n");
|
|
|
+ } else
|
|
|
+ printk("\n");
|
|
|
|
|
|
+ } else {
|
|
|
+ mii_ctl = mdio_read(dev, np->phys[0], MII_BMCR);
|
|
|
+ speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
|
|
|
+ np->speed = speed;
|
|
|
+ printk(KERN_INFO "%s: Link changed: %dMbps ,",
|
|
|
+ dev->name, speed);
|
|
|
+ printk("%s duplex.\n",
|
|
|
+ (mii_ctl & BMCR_FULLDPLX) ?
|
|
|
+ "full" : "half");
|
|
|
+ }
|
|
|
+ check_duplex(dev);
|
|
|
+ if (np->flowctrl && np->mii_if.full_duplex) {
|
|
|
+ iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
|
|
|
+ ioaddr + MulticastFilter1+2);
|
|
|
+ iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
|
|
|
+ ioaddr + MACCtrl0);
|
|
|
+ }
|
|
|
+ netif_carrier_on(dev);
|
|
|
} else {
|
|
|
- mii_ctl = mdio_read (dev, np->phys[0], MII_BMCR);
|
|
|
- speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
|
|
|
- np->speed = speed;
|
|
|
- printk (KERN_INFO "%s: Link changed: %dMbps ,",
|
|
|
- dev->name, speed);
|
|
|
- printk ("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
|
|
|
- "full" : "half");
|
|
|
- }
|
|
|
- check_duplex (dev);
|
|
|
- if (np->flowctrl && np->mii_if.full_duplex) {
|
|
|
- iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
|
|
|
- ioaddr + MulticastFilter1+2);
|
|
|
- iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
|
|
|
- ioaddr + MACCtrl0);
|
|
|
+ printk(KERN_INFO "%s: Link down\n", dev->name);
|
|
|
+ netif_carrier_off(dev);
|
|
|
}
|
|
|
}
|
|
|
if (intr_status & StatsMax) {
|