Commit f9430a01 authored by Ayaz Abdulla's avatar Ayaz Abdulla Committed by Jeff Garzik

[PATCH] forcedeth config: phy

This patch fixes configuration bugs when modifying phy settings.
Signed-Off-By: default avatarAyaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent b6d0773f
...@@ -2516,9 +2516,17 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2516,9 +2516,17 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
if (!netif_running(dev)) { if (!netif_running(dev)) {
/* We do not track link speed / duplex setting if the /* We do not track link speed / duplex setting if the
* interface is disabled. Force a link check */ * interface is disabled. Force a link check */
nv_update_linkspeed(dev); if (nv_update_linkspeed(dev)) {
if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
} else {
if (netif_carrier_ok(dev))
netif_carrier_off(dev);
}
} }
switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
if (netif_carrier_ok(dev)) {
switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
case NVREG_LINKSPEED_10: case NVREG_LINKSPEED_10:
ecmd->speed = SPEED_10; ecmd->speed = SPEED_10;
break; break;
...@@ -2528,10 +2536,14 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2528,10 +2536,14 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
case NVREG_LINKSPEED_1000: case NVREG_LINKSPEED_1000:
ecmd->speed = SPEED_1000; ecmd->speed = SPEED_1000;
break; break;
}
ecmd->duplex = DUPLEX_HALF;
if (np->duplex)
ecmd->duplex = DUPLEX_FULL;
} else {
ecmd->speed = -1;
ecmd->duplex = -1;
} }
ecmd->duplex = DUPLEX_HALF;
if (np->duplex)
ecmd->duplex = DUPLEX_FULL;
ecmd->autoneg = np->autoneg; ecmd->autoneg = np->autoneg;
...@@ -2539,23 +2551,20 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2539,23 +2551,20 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
if (np->autoneg) { if (np->autoneg) {
ecmd->advertising |= ADVERTISED_Autoneg; ecmd->advertising |= ADVERTISED_Autoneg;
adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
} else { if (adv & ADVERTISE_10HALF)
adv = np->fixed_mode; ecmd->advertising |= ADVERTISED_10baseT_Half;
} if (adv & ADVERTISE_10FULL)
if (adv & ADVERTISE_10HALF) ecmd->advertising |= ADVERTISED_10baseT_Full;
ecmd->advertising |= ADVERTISED_10baseT_Half; if (adv & ADVERTISE_100HALF)
if (adv & ADVERTISE_10FULL) ecmd->advertising |= ADVERTISED_100baseT_Half;
ecmd->advertising |= ADVERTISED_10baseT_Full; if (adv & ADVERTISE_100FULL)
if (adv & ADVERTISE_100HALF) ecmd->advertising |= ADVERTISED_100baseT_Full;
ecmd->advertising |= ADVERTISED_100baseT_Half; if (np->gigabit == PHY_GIGABIT) {
if (adv & ADVERTISE_100FULL) adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
ecmd->advertising |= ADVERTISED_100baseT_Full; if (adv & ADVERTISE_1000FULL)
if (np->autoneg && np->gigabit == PHY_GIGABIT) { ecmd->advertising |= ADVERTISED_1000baseT_Full;
adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); }
if (adv & ADVERTISE_1000FULL)
ecmd->advertising |= ADVERTISED_1000baseT_Full;
} }
ecmd->supported = (SUPPORTED_Autoneg | ecmd->supported = (SUPPORTED_Autoneg |
SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
...@@ -2607,7 +2616,18 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2607,7 +2616,18 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return -EINVAL; return -EINVAL;
} }
spin_lock_irq(&np->lock); netif_carrier_off(dev);
if (netif_running(dev)) {
nv_disable_irq(dev);
spin_lock_bh(&dev->xmit_lock);
spin_lock(&np->lock);
/* stop engines */
nv_stop_rx(dev);
nv_stop_tx(dev);
spin_unlock(&np->lock);
spin_unlock_bh(&dev->xmit_lock);
}
if (ecmd->autoneg == AUTONEG_ENABLE) { if (ecmd->autoneg == AUTONEG_ENABLE) {
int adv, bmcr; int adv, bmcr;
...@@ -2638,6 +2658,8 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2638,6 +2658,8 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
mii_rw(dev, np->phyaddr, MII_CTRL1000, adv); mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
} }
if (netif_running(dev))
printk(KERN_INFO "%s: link down.\n", dev->name);
bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
...@@ -2676,20 +2698,30 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2676,20 +2698,30 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} }
bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
bmcr |= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_FULLDPLX); bmcr &= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_SPEED1000|BMCR_FULLDPLX);
if (adv & (ADVERTISE_10FULL|ADVERTISE_100FULL)) if (np->fixed_mode & (ADVERTISE_10FULL|ADVERTISE_100FULL))
bmcr |= BMCR_FULLDPLX; bmcr |= BMCR_FULLDPLX;
if (adv & (ADVERTISE_100HALF|ADVERTISE_100FULL)) if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL))
bmcr |= BMCR_SPEED100; bmcr |= BMCR_SPEED100;
mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
if (np->phy_oui == PHY_OUI_MARVELL) {
if (netif_running(dev)) { /* reset the phy */
if (phy_reset(dev)) {
printk(KERN_INFO "%s: phy reset failed\n", dev->name);
return -EINVAL;
}
} else if (netif_running(dev)) {
/* Wait a bit and then reconfigure the nic. */ /* Wait a bit and then reconfigure the nic. */
udelay(10); udelay(10);
nv_linkchange(dev); nv_linkchange(dev);
} }
} }
spin_unlock_irq(&np->lock);
if (netif_running(dev)) {
nv_start_rx(dev);
nv_start_tx(dev);
nv_enable_irq(dev);
}
return 0; return 0;
} }
...@@ -2721,19 +2753,35 @@ static int nv_nway_reset(struct net_device *dev) ...@@ -2721,19 +2753,35 @@ static int nv_nway_reset(struct net_device *dev)
struct fe_priv *np = netdev_priv(dev); struct fe_priv *np = netdev_priv(dev);
int ret; int ret;
spin_lock_irq(&np->lock);
if (np->autoneg) { if (np->autoneg) {
int bmcr; int bmcr;
netif_carrier_off(dev);
if (netif_running(dev)) {
nv_disable_irq(dev);
spin_lock_bh(&dev->xmit_lock);
spin_lock(&np->lock);
/* stop engines */
nv_stop_rx(dev);
nv_stop_tx(dev);
spin_unlock(&np->lock);
spin_unlock_bh(&dev->xmit_lock);
printk(KERN_INFO "%s: link down.\n", dev->name);
}
bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
if (netif_running(dev)) {
nv_start_rx(dev);
nv_start_tx(dev);
nv_enable_irq(dev);
}
ret = 0; ret = 0;
} else { } else {
ret = -EINVAL; ret = -EINVAL;
} }
spin_unlock_irq(&np->lock);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment