Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+78 −30
Original line number Diff line number Diff line
@@ -2516,8 +2516,16 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
	if (!netif_running(dev)) {
		/* We do not track link speed / duplex setting if the
		 * 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);
		}
	}

	if (netif_carrier_ok(dev)) {
		switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
		case NVREG_LINKSPEED_10:
			ecmd->speed = SPEED_10;
@@ -2532,6 +2540,10 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
		ecmd->duplex = DUPLEX_HALF;
		if (np->duplex)
			ecmd->duplex = DUPLEX_FULL;
	} else {
		ecmd->speed = -1;
		ecmd->duplex = -1;
	}

	ecmd->autoneg = np->autoneg;

@@ -2539,9 +2551,6 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
	if (np->autoneg) {
		ecmd->advertising |= ADVERTISED_Autoneg;
		adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
	} else {
		adv = np->fixed_mode;
	}
		if (adv & ADVERTISE_10HALF)
			ecmd->advertising |= ADVERTISED_10baseT_Half;
		if (adv & ADVERTISE_10FULL)
@@ -2550,12 +2559,12 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
			ecmd->advertising |= ADVERTISED_100baseT_Half;
		if (adv & ADVERTISE_100FULL)
			ecmd->advertising |= ADVERTISED_100baseT_Full;
	if (np->autoneg && np->gigabit == PHY_GIGABIT) {
		if (np->gigabit == PHY_GIGABIT) {
			adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
			if (adv & ADVERTISE_1000FULL)
				ecmd->advertising |= ADVERTISED_1000baseT_Full;
		}

	}
	ecmd->supported = (SUPPORTED_Autoneg |
		SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
		SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
@@ -2607,7 +2616,18 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
		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) {
		int adv, bmcr;

@@ -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);
		}

		if (netif_running(dev))
			printk(KERN_INFO "%s: link down.\n", dev->name);
		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
		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)
		}

		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
		bmcr |= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_FULLDPLX);
		if (adv & (ADVERTISE_10FULL|ADVERTISE_100FULL))
		bmcr &= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_SPEED1000|BMCR_FULLDPLX);
		if (np->fixed_mode & (ADVERTISE_10FULL|ADVERTISE_100FULL))
			bmcr |= BMCR_FULLDPLX;
		if (adv & (ADVERTISE_100HALF|ADVERTISE_100FULL))
		if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL))
			bmcr |= BMCR_SPEED100;
		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);

		if (netif_running(dev)) {
		if (np->phy_oui == PHY_OUI_MARVELL) {
			/* 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. */
			udelay(10);
			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;
}
@@ -2721,19 +2753,35 @@ static int nv_nway_reset(struct net_device *dev)
	struct fe_priv *np = netdev_priv(dev);
	int ret;

	spin_lock_irq(&np->lock);
	if (np->autoneg) {
		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 |= (BMCR_ANENABLE | BMCR_ANRESTART);
		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;
	} else {
		ret = -EINVAL;
	}
	spin_unlock_irq(&np->lock);

	return ret;
}