aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy.c
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2019-08-12 17:52:19 -0400
committerJakub Kicinski <jakub.kicinski@netronome.com>2019-08-13 20:14:06 -0400
commit65b27995a4ab8fc51b4adc6b4dcdca20f7a595bb (patch)
tree7b8814cf8b7bd2767af3c3080b20c9b9c4a2b70f /drivers/net/phy/phy.c
parent331c56ac73846fa267c04ee6aa9a00bb5fed9440 (diff)
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>
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c60
1 files changed, 16 insertions, 44 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef7aa738e0dc..f3adea9ef400 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -608,38 +608,21 @@ static int phy_poll_aneg_done(struct phy_device *phydev)
608 */ 608 */
609int phy_speed_down(struct phy_device *phydev, bool sync) 609int phy_speed_down(struct phy_device *phydev, bool sync)
610{ 610{
611 __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); 611 __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
612 __ETHTOOL_DECLARE_LINK_MODE_MASK(adv);
613 int ret; 612 int ret;
614 613
615 if (phydev->autoneg != AUTONEG_ENABLE) 614 if (phydev->autoneg != AUTONEG_ENABLE)
616 return 0; 615 return 0;
617 616
618 linkmode_copy(adv_old, phydev->advertising); 617 linkmode_copy(adv_tmp, phydev->advertising);
619 linkmode_copy(adv, phydev->lp_advertising); 618
620 linkmode_and(adv, adv, phydev->supported); 619 ret = phy_speed_down_core(phydev);
621 620 if (ret)
622 if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, adv) || 621 return ret;
623 linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, adv)) {
624 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
625 phydev->advertising);
626 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
627 phydev->advertising);
628 linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
629 phydev->advertising);
630 linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
631 phydev->advertising);
632 } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
633 adv) ||
634 linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
635 adv)) {
636 linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
637 phydev->advertising);
638 linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
639 phydev->advertising);
640 }
641 622
642 if (linkmode_equal(phydev->advertising, adv_old)) 623 linkmode_copy(phydev->adv_old, adv_tmp);
624
625 if (linkmode_equal(phydev->advertising, adv_tmp))
643 return 0; 626 return 0;
644 627
645 ret = phy_config_aneg(phydev); 628 ret = phy_config_aneg(phydev);
@@ -658,30 +641,19 @@ EXPORT_SYMBOL_GPL(phy_speed_down);
658 */ 641 */
659int phy_speed_up(struct phy_device *phydev) 642int phy_speed_up(struct phy_device *phydev)
660{ 643{
661 __ETHTOOL_DECLARE_LINK_MODE_MASK(all_speeds) = { 0, }; 644 __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
662 __ETHTOOL_DECLARE_LINK_MODE_MASK(not_speeds);
663 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
664 __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
665 __ETHTOOL_DECLARE_LINK_MODE_MASK(speeds);
666
667 linkmode_copy(adv_old, phydev->advertising);
668 645
669 if (phydev->autoneg != AUTONEG_ENABLE) 646 if (phydev->autoneg != AUTONEG_ENABLE)
670 return 0; 647 return 0;
671 648
672 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, all_speeds); 649 if (linkmode_empty(phydev->adv_old))
673 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, all_speeds); 650 return 0;
674 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, all_speeds);
675 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, all_speeds);
676 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, all_speeds);
677 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, all_speeds);
678 651
679 linkmode_andnot(not_speeds, adv_old, all_speeds); 652 linkmode_copy(adv_tmp, phydev->advertising);
680 linkmode_copy(supported, phydev->supported); 653 linkmode_copy(phydev->advertising, phydev->adv_old);
681 linkmode_and(speeds, supported, all_speeds); 654 linkmode_zero(phydev->adv_old);
682 linkmode_or(phydev->advertising, not_speeds, speeds);
683 655
684 if (linkmode_equal(phydev->advertising, adv_old)) 656 if (linkmode_equal(phydev->advertising, adv_tmp))
685 return 0; 657 return 0;
686 658
687 return phy_config_aneg(phydev); 659 return phy_config_aneg(phydev);