Messages in this thread Patch in this message | | | From | Sean Anderson <> | Subject | [PATCH net-next v3 09/47] net: phylink: Adjust advertisement based on rate adaptation | Date | Fri, 15 Jul 2022 17:59:16 -0400 |
| |
This adds support for adjusting the advertisement for pause-based rate adaptation. This may result in a lossy link, since the final link settings are not adjusted. Asymmetric pause support is necessary. It would be possible for a MAC supporting only symmetric pause to use pause-based rate adaptation, but only if pause reception was enabled as well.
Signed-off-by: Sean Anderson <sean.anderson@seco.com> ---
Changes in v3: - New
drivers/net/phy/phylink.c | 41 ++++++++++++++++++++++++++++++++++++--- include/linux/phylink.h | 6 +++++- 2 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index a952cdc7c96e..7fa21941878e 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -370,13 +370,15 @@ static int phy_interface_speed(phy_interface_t interface, int link_speed) * @linkmodes: ethtool linkmode mask (must be already initialised) * @interface: phy interface mode defined by &typedef phy_interface_t * @mac_capabilities: bitmask of MAC capabilities + * @rate_adaptation: type of rate adaptation being performed * * Set all possible pause, speed and duplex linkmodes in @linkmodes that * are supported by the @interface mode and @mac_capabilities. @linkmodes * must have been initialised previously. */ void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface, - unsigned long mac_capabilities) + unsigned long mac_capabilities, + enum rate_adaptation rate_adaptation) { unsigned long caps = MAC_SYM_PAUSE | MAC_ASYM_PAUSE; @@ -451,7 +453,38 @@ void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface, break; } - phylink_caps_to_linkmodes(linkmodes, caps & mac_capabilities); + caps = caps & mac_capabilities; + + switch (rate_adaptation) { + case RATE_ADAPT_NONE: + break; + case RATE_ADAPT_PAUSE: { + unsigned long adapted_caps; + + /* The mac must support pause for this */ + if (!(caps & MAC_ASYM_PAUSE)) + goto open_loop; + + /* Can't adapt if there's nothing slower */ + if (__fls(caps) <= __fls(MAC_10)) + break; + + adapted_caps = GENMASK(__fls(caps), __fls(MAC_10HD)); + /* We can't use pause frames in half-duplex mode */ + adapted_caps &= ~(MAC_1000HD | MAC_100HD | MAC_10HD); + caps |= adapted_caps; + break; + } + case RATE_ADAPT_CRS: + /* TODO */ + break; + case RATE_ADAPT_OPEN_LOOP: +open_loop: + /* TODO */ + break; + } + + phylink_caps_to_linkmodes(linkmodes, caps); } EXPORT_SYMBOL_GPL(phylink_get_linkmodes); @@ -473,7 +506,8 @@ void phylink_generic_validate(struct phylink_config *config, phylink_set_port_modes(mask); phylink_set(mask, Autoneg); - phylink_get_linkmodes(mask, state->interface, config->mac_capabilities); + phylink_get_linkmodes(mask, state->interface, config->mac_capabilities, + state->rate_adaptation); linkmode_and(supported, supported, mask); linkmode_and(state->advertising, state->advertising, mask); @@ -1462,6 +1496,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, config.interface = PHY_INTERFACE_MODE_NA; else config.interface = interface; + config.rate_adaptation = phy_get_rate_adaptation(phy, config.interface); ret = phylink_validate(pl, supported, &config); if (ret) { diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 30e3fbe19fb4..f990f8eab655 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -65,6 +65,8 @@ static inline bool phylink_autoneg_inband(unsigned int mode) * @link: true if the link is up. * @an_enabled: true if autonegotiation is enabled/desired. * @an_complete: true if autonegotiation has completed. + * @rate_adaptation: method of throttling @interface_speed to @speed, one of + * RATE_ADAPT_* constants. */ struct phylink_link_state { __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); @@ -74,6 +76,7 @@ struct phylink_link_state { int link_speed; int duplex; int pause; + enum rate_adaptation rate_adaptation; unsigned int link:1; unsigned int an_enabled:1; unsigned int an_complete:1; @@ -523,7 +526,8 @@ void pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, #endif void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface, - unsigned long mac_capabilities); + unsigned long mac_capabilities, + enum rate_adaptation rate_adaptation); void phylink_generic_validate(struct phylink_config *config, unsigned long *supported, struct phylink_link_state *state); -- 2.35.1.1320.gc452695387.dirty
| |