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

Commit 65b27995 authored by Heiner Kallweit's avatar Heiner Kallweit Committed by Jakub Kicinski
Browse files

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: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
parent 331c56ac
Loading
Loading
Loading
Loading
+16 −44
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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;