Skip to content

Commit

Permalink
net: phy: add phy_speed_down_core and phy_resolve_min_speed
Browse files Browse the repository at this point in the history
phy_speed_down_core provides most of the functionality for
phy_speed_down. It makes use of new helper phy_resolve_min_speed that is
based on the sorting of the settings[] array. In certain cases it may be
helpful to be able to exclude legacy half duplex modes, therefore
prepare phy_resolve_min_speed() for it.

v2:
- rename __phy_speed_down to phy_speed_down_core

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
  • Loading branch information
Heiner Kallweit authored and Jakub Kicinski committed Aug 14, 2019
1 parent 7b261e0 commit 331c56a
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
28 changes: 28 additions & 0 deletions drivers/net/phy/phy-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,34 @@ void phy_resolve_aneg_linkmode(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);

static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
int i = ARRAY_SIZE(settings);

linkmode_and(common, phydev->lp_advertising, phydev->advertising);

while (--i >= 0) {
if (test_bit(settings[i].bit, common)) {
if (fdx_only && settings[i].duplex != DUPLEX_FULL)
continue;
return settings[i].speed;
}
}

return SPEED_UNKNOWN;
}

int phy_speed_down_core(struct phy_device *phydev)
{
int min_common_speed = phy_resolve_min_speed(phydev, true);

if (min_common_speed == SPEED_UNKNOWN)
return -EINVAL;

return __set_linkmode_max_speed(min_common_speed, phydev->advertising);
}

static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
u16 regnum)
{
Expand Down
1 change: 1 addition & 0 deletions include/linux/phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
unsigned long *mask);
void of_set_phy_supported(struct phy_device *phydev);
void of_set_phy_eee_broken(struct phy_device *phydev);
int phy_speed_down_core(struct phy_device *phydev);

/**
* phy_is_started - Convenience function to check whether PHY is started
Expand Down

0 comments on commit 331c56a

Please sign in to comment.