Merge branch 'net-phy-let-phy_speed_down-up-support-speeds-1Gbps'
Heiner says: ==================== So far phy_speed_down/up can be used up to 1Gbps only. Remove this restriction and add needed helpers to phy-core.c v2: - remove unused parameter in patch 1 - rename __phy_speed_down to phy_speed_down_core in patch 2 ==================== Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
This commit is contained in:
commit
e070ca371f
|
@ -207,14 +207,14 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
|
static int __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)
|
||||||
{
|
{
|
||||||
const struct phy_setting *p;
|
const struct phy_setting *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
|
for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
|
||||||
if (p->speed > max_speed)
|
if (p->speed > max_speed)
|
||||||
linkmode_clear_bit(p->bit, phydev->supported);
|
linkmode_clear_bit(p->bit, addr);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,11 @@ static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
|
||||||
|
{
|
||||||
|
return __set_linkmode_max_speed(max_speed, phydev->supported);
|
||||||
|
}
|
||||||
|
|
||||||
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
|
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -310,6 +315,34 @@ void phy_resolve_aneg_linkmode(struct phy_device *phydev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);
|
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,
|
static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
|
||||||
u16 regnum)
|
u16 regnum)
|
||||||
{
|
{
|
||||||
|
|
|
@ -608,38 +608,21 @@ static int phy_poll_aneg_done(struct phy_device *phydev)
|
||||||
*/
|
*/
|
||||||
int phy_speed_down(struct phy_device *phydev, bool sync)
|
int phy_speed_down(struct phy_device *phydev, bool sync)
|
||||||
{
|
{
|
||||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
|
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
|
||||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv);
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (phydev->autoneg != AUTONEG_ENABLE)
|
if (phydev->autoneg != AUTONEG_ENABLE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
linkmode_copy(adv_old, phydev->advertising);
|
linkmode_copy(adv_tmp, phydev->advertising);
|
||||||
linkmode_copy(adv, phydev->lp_advertising);
|
|
||||||
linkmode_and(adv, adv, phydev->supported);
|
|
||||||
|
|
||||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, adv) ||
|
ret = phy_speed_down_core(phydev);
|
||||||
linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, adv)) {
|
if (ret)
|
||||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
|
return ret;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linkmode_equal(phydev->advertising, adv_old))
|
linkmode_copy(phydev->adv_old, adv_tmp);
|
||||||
|
|
||||||
|
if (linkmode_equal(phydev->advertising, adv_tmp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = phy_config_aneg(phydev);
|
ret = phy_config_aneg(phydev);
|
||||||
|
@ -658,30 +641,19 @@ EXPORT_SYMBOL_GPL(phy_speed_down);
|
||||||
*/
|
*/
|
||||||
int phy_speed_up(struct phy_device *phydev)
|
int phy_speed_up(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(all_speeds) = { 0, };
|
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
|
||||||
__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);
|
|
||||||
|
|
||||||
if (phydev->autoneg != AUTONEG_ENABLE)
|
if (phydev->autoneg != AUTONEG_ENABLE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, all_speeds);
|
if (linkmode_empty(phydev->adv_old))
|
||||||
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, all_speeds);
|
return 0;
|
||||||
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);
|
|
||||||
|
|
||||||
linkmode_andnot(not_speeds, adv_old, all_speeds);
|
linkmode_copy(adv_tmp, phydev->advertising);
|
||||||
linkmode_copy(supported, phydev->supported);
|
linkmode_copy(phydev->advertising, phydev->adv_old);
|
||||||
linkmode_and(speeds, supported, all_speeds);
|
linkmode_zero(phydev->adv_old);
|
||||||
linkmode_or(phydev->advertising, not_speeds, speeds);
|
|
||||||
|
|
||||||
if (linkmode_equal(phydev->advertising, adv_old))
|
if (linkmode_equal(phydev->advertising, adv_tmp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return phy_config_aneg(phydev);
|
return phy_config_aneg(phydev);
|
||||||
|
|
|
@ -403,6 +403,8 @@ struct phy_device {
|
||||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
|
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
|
||||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
|
__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
|
||||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_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 */
|
/* Energy efficient ethernet modes which should be prohibited */
|
||||||
u32 eee_broken_modes;
|
u32 eee_broken_modes;
|
||||||
|
@ -665,6 +667,7 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
|
||||||
unsigned long *mask);
|
unsigned long *mask);
|
||||||
void of_set_phy_supported(struct phy_device *phydev);
|
void of_set_phy_supported(struct phy_device *phydev);
|
||||||
void of_set_phy_eee_broken(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
|
* phy_is_started - Convenience function to check whether PHY is started
|
||||||
|
|
Loading…
Reference in New Issue