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: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-02-10 12:53:19 -08:00
commit 6a98afbbb4
4 changed files with 150 additions and 47 deletions

View file

@ -141,10 +141,9 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
return ret;
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)
@ -345,7 +344,7 @@ static int mv3310_config_aneg(struct phy_device *phydev)
linkmode_and(phydev->advertising, phydev->advertising,
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_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
linkmode_adv_to_mii_adv_t(phydev->advertising));
@ -355,7 +354,7 @@ static int mv3310_config_aneg(struct phy_device *phydev)
changed = true;
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);
if (ret < 0)
return ret;
@ -369,8 +368,8 @@ static int mv3310_config_aneg(struct phy_device *phydev)
else
reg = 0;
ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
MDIO_AN_10GBT_CTRL_ADV10G, reg);
ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
MDIO_AN_10GBT_CTRL_ADV10G, reg);
if (ret < 0)
return ret;
if (ret > 0)

View file

@ -531,7 +531,7 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
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
* @regnum: register number
* @mask: bit mask of bits to clear
@ -539,16 +539,69 @@ EXPORT_SYMBOL(phy_write_mmd);
*
* Unlocked helper function which allows a PHY register to be modified as
* 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);
if (ret < 0)
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;
}
@ -578,7 +631,7 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
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
* @devad: the MMD containing register to modify
* @regnum: register number to modify
@ -587,17 +640,73 @@ EXPORT_SYMBOL_GPL(phy_modify);
*
* Unlocked helper function which allows a MMD register to be modified as
* 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_changed(struct phy_device *phydev, int devad, u32 regnum,
u16 mask, u16 set)
{
int new, ret;
ret = __phy_read_mmd(phydev, devad, regnum);
if (ret < 0)
return ret;
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_read_mmd(phydev, devad, regnum);
if (ret < 0)
return ret;
ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set);
ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
return ret < 0 ? ret : 0;
}

View file

@ -1516,7 +1516,7 @@ EXPORT_SYMBOL(phy_reset_after_clk_enable);
static int genphy_config_advert(struct phy_device *phydev)
{
u32 advertise;
int oldadv, adv, bmsr;
int bmsr, adv;
int err, changed = 0;
/* Only allow advertising what this PHY supports */
@ -1529,22 +1529,14 @@ static int genphy_config_advert(struct phy_device *phydev)
phydev->advertising);
/* Setup standard advertisement */
adv = phy_read(phydev, MII_ADVERTISE);
if (adv < 0)
return adv;
oldadv = adv;
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
ADVERTISE_PAUSE_ASYM);
adv |= ethtool_adv_to_mii_adv_t(advertise);
if (adv != oldadv) {
err = phy_write(phydev, MII_ADVERTISE, adv);
if (err < 0)
return err;
err = phy_modify_changed(phydev, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_100BASE4 |
ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
ethtool_adv_to_mii_adv_t(advertise));
if (err < 0)
return err;
if (err > 0)
changed = 1;
}
bmsr = phy_read(phydev, MII_BMSR);
if (bmsr < 0)
@ -1558,25 +1550,20 @@ static int genphy_config_advert(struct phy_device *phydev)
return changed;
/* Configure gigabit if it's supported */
adv = phy_read(phydev, MII_CTRL1000);
if (adv < 0)
return adv;
oldadv = adv;
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
adv = 0;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported) ||
linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported))
adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);
adv = ethtool_adv_to_mii_ctrl1000_t(advertise);
if (adv != oldadv)
changed = 1;
err = phy_write(phydev, MII_CTRL1000, adv);
err = phy_modify_changed(phydev, MII_CTRL1000,
ADVERTISE_1000FULL | ADVERTISE_1000HALF,
adv);
if (err < 0)
return err;
if (err > 0)
changed = 1;
return changed;
}

View file

@ -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_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_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,
u16 mask, u16 set);
u16 mask, u16 set);
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