mirror of https://gitee.com/openkylin/linux.git
net: phy: let phy_speed_down/up support speeds >1Gbps
So far phy_speed_down/up can be used up to 1Gbps only. Remove this restriction by using new helper __phy_speed_down. New member adv_old in struct phy_device is used by phy_speed_up to restore the advertised modes before calling phy_speed_down. Don't simply advertise what is supported because a user may have intentionally removed modes from advertisement. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
This commit is contained in:
parent
331c56ac73
commit
65b27995a4
|
@ -608,38 +608,21 @@ static int phy_poll_aneg_done(struct phy_device *phydev)
|
|||
*/
|
||||
int phy_speed_down(struct phy_device *phydev, bool sync)
|
||||
{
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
|
||||
int ret;
|
||||
|
||||
if (phydev->autoneg != AUTONEG_ENABLE)
|
||||
return 0;
|
||||
|
||||
linkmode_copy(adv_old, phydev->advertising);
|
||||
linkmode_copy(adv, phydev->lp_advertising);
|
||||
linkmode_and(adv, adv, phydev->supported);
|
||||
linkmode_copy(adv_tmp, phydev->advertising);
|
||||
|
||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, adv) ||
|
||||
linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, adv)) {
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
|
||||
phydev->advertising);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
phydev->advertising);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
|
||||
phydev->advertising);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
phydev->advertising);
|
||||
} else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
|
||||
adv) ||
|
||||
linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
adv)) {
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
|
||||
phydev->advertising);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
phydev->advertising);
|
||||
}
|
||||
ret = phy_speed_down_core(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (linkmode_equal(phydev->advertising, adv_old))
|
||||
linkmode_copy(phydev->adv_old, adv_tmp);
|
||||
|
||||
if (linkmode_equal(phydev->advertising, adv_tmp))
|
||||
return 0;
|
||||
|
||||
ret = phy_config_aneg(phydev);
|
||||
|
@ -658,30 +641,19 @@ EXPORT_SYMBOL_GPL(phy_speed_down);
|
|||
*/
|
||||
int phy_speed_up(struct phy_device *phydev)
|
||||
{
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(all_speeds) = { 0, };
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(not_speeds);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(speeds);
|
||||
|
||||
linkmode_copy(adv_old, phydev->advertising);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
|
||||
|
||||
if (phydev->autoneg != AUTONEG_ENABLE)
|
||||
return 0;
|
||||
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, all_speeds);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, all_speeds);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, all_speeds);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, all_speeds);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, all_speeds);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, all_speeds);
|
||||
if (linkmode_empty(phydev->adv_old))
|
||||
return 0;
|
||||
|
||||
linkmode_andnot(not_speeds, adv_old, all_speeds);
|
||||
linkmode_copy(supported, phydev->supported);
|
||||
linkmode_and(speeds, supported, all_speeds);
|
||||
linkmode_or(phydev->advertising, not_speeds, speeds);
|
||||
linkmode_copy(adv_tmp, phydev->advertising);
|
||||
linkmode_copy(phydev->advertising, phydev->adv_old);
|
||||
linkmode_zero(phydev->adv_old);
|
||||
|
||||
if (linkmode_equal(phydev->advertising, adv_old))
|
||||
if (linkmode_equal(phydev->advertising, adv_tmp))
|
||||
return 0;
|
||||
|
||||
return phy_config_aneg(phydev);
|
||||
|
|
|
@ -403,6 +403,8 @@ struct phy_device {
|
|||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
|
||||
/* used with phy_speed_down */
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
|
||||
|
||||
/* Energy efficient ethernet modes which should be prohibited */
|
||||
u32 eee_broken_modes;
|
||||
|
|
Loading…
Reference in New Issue