Commit 6a98afbb authored by David S. Miller's avatar David S. Miller

Merge branch 'net-phy-register-modifying-helpers'

Heiner Kallweit says:

====================
net: phy: add and use register modifying helpers returning 1 on change

Add and use register modifying helpers returning 1 on change.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 193dad2a 4f9744ed
...@@ -141,10 +141,9 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable) ...@@ -141,10 +141,9 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
return ret; return ret;
val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE; val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
MV_V2_TEMP_CTRL_MASK, val);
return ret < 0 ? ret : 0; return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
MV_V2_TEMP_CTRL_MASK, val);
} }
static void mv3310_hwmon_disable(void *data) static void mv3310_hwmon_disable(void *data)
...@@ -345,7 +344,7 @@ static int mv3310_config_aneg(struct phy_device *phydev) ...@@ -345,7 +344,7 @@ static int mv3310_config_aneg(struct phy_device *phydev)
linkmode_and(phydev->advertising, phydev->advertising, linkmode_and(phydev->advertising, phydev->advertising,
phydev->supported); phydev->supported);
ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_ALL | ADVERTISE_100BASE4 |
ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
linkmode_adv_to_mii_adv_t(phydev->advertising)); linkmode_adv_to_mii_adv_t(phydev->advertising));
...@@ -355,7 +354,7 @@ static int mv3310_config_aneg(struct phy_device *phydev) ...@@ -355,7 +354,7 @@ static int mv3310_config_aneg(struct phy_device *phydev)
changed = true; changed = true;
reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MV_AN_CTRL1000, ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg); ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -369,8 +368,8 @@ static int mv3310_config_aneg(struct phy_device *phydev) ...@@ -369,8 +368,8 @@ static int mv3310_config_aneg(struct phy_device *phydev)
else else
reg = 0; reg = 0;
ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
MDIO_AN_10GBT_CTRL_ADV10G, reg); MDIO_AN_10GBT_CTRL_ADV10G, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret > 0) if (ret > 0)
......
...@@ -531,7 +531,7 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) ...@@ -531,7 +531,7 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
EXPORT_SYMBOL(phy_write_mmd); EXPORT_SYMBOL(phy_write_mmd);
/** /**
* __phy_modify() - Convenience function for modifying a PHY register * __phy_modify_changed() - Convenience function for modifying a PHY register
* @phydev: a pointer to a &struct phy_device * @phydev: a pointer to a &struct phy_device
* @regnum: register number * @regnum: register number
* @mask: bit mask of bits to clear * @mask: bit mask of bits to clear
...@@ -539,16 +539,69 @@ EXPORT_SYMBOL(phy_write_mmd); ...@@ -539,16 +539,69 @@ EXPORT_SYMBOL(phy_write_mmd);
* *
* Unlocked helper function which allows a PHY register to be modified as * Unlocked helper function which allows a PHY register to be modified as
* new register value = (old register value & ~mask) | set * new register value = (old register value & ~mask) | set
*
* Returns negative errno, 0 if there was no change, and 1 in case of change
*/ */
int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
u16 set)
{ {
int ret; int new, ret;
ret = __phy_read(phydev, regnum); ret = __phy_read(phydev, regnum);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = __phy_write(phydev, regnum, (ret & ~mask) | set); new = (ret & ~mask) | set;
if (new == ret)
return 0;
ret = __phy_write(phydev, regnum, new);
return ret < 0 ? ret : 1;
}
EXPORT_SYMBOL_GPL(__phy_modify_changed);
/**
* phy_modify_changed - Function for modifying a PHY register
* @phydev: the phy_device struct
* @regnum: register number to modify
* @mask: bit mask of bits to clear
* @set: new value of bits set in mask to write to @regnum
*
* NOTE: MUST NOT be called from interrupt context,
* because the bus read/write functions may wait for an interrupt
* to conclude the operation.
*
* Returns negative errno, 0 if there was no change, and 1 in case of change
*/
int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
{
int ret;
mutex_lock(&phydev->mdio.bus->mdio_lock);
ret = __phy_modify_changed(phydev, regnum, mask, set);
mutex_unlock(&phydev->mdio.bus->mdio_lock);
return ret;
}
EXPORT_SYMBOL_GPL(phy_modify_changed);
/**
* __phy_modify - Convenience function for modifying a PHY register
* @phydev: the phy_device struct
* @regnum: register number to modify
* @mask: bit mask of bits to clear
* @set: new value of bits set in mask to write to @regnum
*
* NOTE: MUST NOT be called from interrupt context,
* because the bus read/write functions may wait for an interrupt
* to conclude the operation.
*/
int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
{
int ret;
ret = __phy_modify_changed(phydev, regnum, mask, set);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
...@@ -578,7 +631,7 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) ...@@ -578,7 +631,7 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
EXPORT_SYMBOL_GPL(phy_modify); EXPORT_SYMBOL_GPL(phy_modify);
/** /**
* __phy_modify_mmd - Convenience function for modifying a register on MMD * __phy_modify_mmd_changed - Function for modifying a register on MMD
* @phydev: the phy_device struct * @phydev: the phy_device struct
* @devad: the MMD containing register to modify * @devad: the MMD containing register to modify
* @regnum: register number to modify * @regnum: register number to modify
...@@ -587,17 +640,73 @@ EXPORT_SYMBOL_GPL(phy_modify); ...@@ -587,17 +640,73 @@ EXPORT_SYMBOL_GPL(phy_modify);
* *
* Unlocked helper function which allows a MMD register to be modified as * Unlocked helper function which allows a MMD register to be modified as
* new register value = (old register value & ~mask) | set * new register value = (old register value & ~mask) | set
*
* Returns negative errno, 0 if there was no change, and 1 in case of change
*/ */
int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set) u16 mask, u16 set)
{ {
int ret; int new, ret;
ret = __phy_read_mmd(phydev, devad, regnum); ret = __phy_read_mmd(phydev, devad, regnum);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set); new = (ret & ~mask) | set;
if (new == ret)
return 0;
ret = __phy_write_mmd(phydev, devad, regnum, new);
return ret < 0 ? ret : 1;
}
EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed);
/**
* phy_modify_mmd_changed - Function for modifying a register on MMD
* @phydev: the phy_device struct
* @devad: the MMD containing register to modify
* @regnum: register number to modify
* @mask: bit mask of bits to clear
* @set: new value of bits set in mask to write to @regnum
*
* NOTE: MUST NOT be called from interrupt context,
* because the bus read/write functions may wait for an interrupt
* to conclude the operation.
*
* Returns negative errno, 0 if there was no change, and 1 in case of change
*/
int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set)
{
int ret;
mutex_lock(&phydev->mdio.bus->mdio_lock);
ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
mutex_unlock(&phydev->mdio.bus->mdio_lock);
return ret;
}
EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);
/**
* __phy_modify_mmd - Convenience function for modifying a register on MMD
* @phydev: the phy_device struct
* @devad: the MMD containing register to modify
* @regnum: register number to modify
* @mask: bit mask of bits to clear
* @set: new value of bits set in mask to write to @regnum
*
* NOTE: MUST NOT be called from interrupt context,
* because the bus read/write functions may wait for an interrupt
* to conclude the operation.
*/
int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set)
{
int ret;
ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
......
...@@ -1516,7 +1516,7 @@ EXPORT_SYMBOL(phy_reset_after_clk_enable); ...@@ -1516,7 +1516,7 @@ EXPORT_SYMBOL(phy_reset_after_clk_enable);
static int genphy_config_advert(struct phy_device *phydev) static int genphy_config_advert(struct phy_device *phydev)
{ {
u32 advertise; u32 advertise;
int oldadv, adv, bmsr; int bmsr, adv;
int err, changed = 0; int err, changed = 0;
/* Only allow advertising what this PHY supports */ /* Only allow advertising what this PHY supports */
...@@ -1529,22 +1529,14 @@ static int genphy_config_advert(struct phy_device *phydev) ...@@ -1529,22 +1529,14 @@ static int genphy_config_advert(struct phy_device *phydev)
phydev->advertising); phydev->advertising);
/* Setup standard advertisement */ /* Setup standard advertisement */
adv = phy_read(phydev, MII_ADVERTISE); err = phy_modify_changed(phydev, MII_ADVERTISE,
if (adv < 0) ADVERTISE_ALL | ADVERTISE_100BASE4 |
return adv; ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
ethtool_adv_to_mii_adv_t(advertise));
oldadv = adv; if (err < 0)
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | return err;
ADVERTISE_PAUSE_ASYM); if (err > 0)
adv |= ethtool_adv_to_mii_adv_t(advertise);
if (adv != oldadv) {
err = phy_write(phydev, MII_ADVERTISE, adv);
if (err < 0)
return err;
changed = 1; changed = 1;
}
bmsr = phy_read(phydev, MII_BMSR); bmsr = phy_read(phydev, MII_BMSR);
if (bmsr < 0) if (bmsr < 0)
...@@ -1558,25 +1550,20 @@ static int genphy_config_advert(struct phy_device *phydev) ...@@ -1558,25 +1550,20 @@ static int genphy_config_advert(struct phy_device *phydev)
return changed; return changed;
/* Configure gigabit if it's supported */ /* Configure gigabit if it's supported */
adv = phy_read(phydev, MII_CTRL1000); adv = 0;
if (adv < 0)
return adv;
oldadv = adv;
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported) || phydev->supported) ||
linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported)) phydev->supported))
adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); adv = ethtool_adv_to_mii_ctrl1000_t(advertise);
if (adv != oldadv) err = phy_modify_changed(phydev, MII_CTRL1000,
changed = 1; ADVERTISE_1000FULL | ADVERTISE_1000HALF,
adv);
err = phy_write(phydev, MII_CTRL1000, adv);
if (err < 0) if (err < 0)
return err; return err;
if (err > 0)
changed = 1;
return changed; return changed;
} }
......
...@@ -799,13 +799,21 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); ...@@ -799,13 +799,21 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
*/ */
int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
u16 set);
int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
u16 set);
int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set);
int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set);
int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set); u16 mask, u16 set);
int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set); u16 mask, u16 set);
/** /**
* __phy_set_bits - Convenience function for setting bits in a PHY register * __phy_set_bits - Convenience function for setting bits in a PHY register
......
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