diff options
| author | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
|---|---|---|
| committer | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
| commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
| tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /drivers/net/phy/phy.c | |
| parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
| parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) | |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'drivers/net/phy/phy.c')
| -rw-r--r-- | drivers/net/phy/phy.c | 39 | 
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index b2197b506acb..adb48abafc87 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -353,6 +353,8 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)  	phydev->duplex = cmd->duplex; +	phydev->mdix = cmd->eth_tp_mdix_ctrl; +  	/* Restart the PHY */  	phy_start_aneg(phydev); @@ -377,6 +379,7 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)  	cmd->transceiver = phy_is_internal(phydev) ?  		XCVR_INTERNAL : XCVR_EXTERNAL;  	cmd->autoneg = phydev->autoneg; +	cmd->eth_tp_mdix_ctrl = phydev->mdix;  	return 0;  } @@ -811,6 +814,7 @@ void phy_state_machine(struct work_struct *work)  	bool needs_aneg = false, do_suspend = false;  	enum phy_state old_state;  	int err = 0; +	int old_link;  	mutex_lock(&phydev->lock); @@ -896,11 +900,18 @@ void phy_state_machine(struct work_struct *work)  		phydev->adjust_link(phydev->attached_dev);  		break;  	case PHY_RUNNING: -		/* Only register a CHANGE if we are -		 * polling or ignoring interrupts +		/* Only register a CHANGE if we are polling or ignoring +		 * interrupts and link changed since latest checking.  		 */ -		if (!phy_interrupt_is_valid(phydev)) -			phydev->state = PHY_CHANGELINK; +		if (!phy_interrupt_is_valid(phydev)) { +			old_link = phydev->link; +			err = phy_read_status(phydev); +			if (err) +				break; + +			if (old_link != phydev->link) +				phydev->state = PHY_CHANGELINK; +		}  		break;  	case PHY_CHANGELINK:  		err = phy_read_status(phydev); @@ -1029,11 +1040,15 @@ int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,  	struct phy_driver *phydrv = phydev->drv;  	int value = -1; -	if (phydrv->read_mmd_indirect == NULL) { -		mmd_phy_indirect(phydev->bus, prtad, devad, addr); +	if (!phydrv->read_mmd_indirect) { +		struct mii_bus *bus = phydev->bus; + +		mutex_lock(&bus->mdio_lock); +		mmd_phy_indirect(bus, prtad, devad, addr);  		/* Read the content of the MMD's selected register */ -		value = phydev->bus->read(phydev->bus, addr, MII_MMD_DATA); +		value = bus->read(bus, addr, MII_MMD_DATA); +		mutex_unlock(&bus->mdio_lock);  	} else {  		value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);  	} @@ -1062,11 +1077,15 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,  {  	struct phy_driver *phydrv = phydev->drv; -	if (phydrv->write_mmd_indirect == NULL) { -		mmd_phy_indirect(phydev->bus, prtad, devad, addr); +	if (!phydrv->write_mmd_indirect) { +		struct mii_bus *bus = phydev->bus; + +		mutex_lock(&bus->mdio_lock); +		mmd_phy_indirect(bus, prtad, devad, addr);  		/* Write the data into MMD's selected register */ -		phydev->bus->write(phydev->bus, addr, MII_MMD_DATA, data); +		bus->write(bus, addr, MII_MMD_DATA, data); +		mutex_unlock(&bus->mdio_lock);  	} else {  		phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);  	}  |