diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2019-12-09 23:13:51 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2020-03-30 12:38:58 +0100 |
commit | 5510b32e3bc38585cbdeb73a1b49f9337ec5f772 (patch) | |
tree | 147e3a617aeeaf86a384b8eae8b51616f8932e40 /drivers/net/phy/phy_device.c | |
parent | 406e21b10db69e05bd909727fd8b6f4f4866e810 (diff) |
net: add helpers to resolve negotiated flow control
Add a couple of helpers to resolve negotiated flow control. Two helpers
are provided:
- linkmode_resolve_pause() which takes the link partner and local
advertisements, and decodes whether we should enable TX or RX pause
at the MAC. This is useful outside of phylib, e.g. in phylink.
- phy_get_pause(), which returns the TX/RX enablement status for the
current negotiation results of the PHY.
This allows us to centralise the flow control resolution, rather than
spreading it around.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r-- | drivers/net/phy/phy_device.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 28e3c5c0e3c3..651eff5127df 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2414,6 +2414,32 @@ bool phy_validate_pause(struct phy_device *phydev, } EXPORT_SYMBOL(phy_validate_pause); +/** + * phy_get_pause - resolve negotiated pause modes + * @phydev: phy_device struct + * @tx_pause: pointer to bool to indicate whether transmit pause should be + * enabled. + * @rx_pause: pointer to bool to indicate whether receive pause should be + * enabled. + * + * Resolve and return the flow control modes according to the negotiation + * result. This includes checking that we are operating in full duplex mode. + * See linkmode_resolve_pause() for further details. + */ +void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause) +{ + if (phydev->duplex != DUPLEX_FULL) { + *tx_pause = false; + *rx_pause = false; + return; + } + + return linkmode_resolve_pause(phydev->advertising, + phydev->lp_advertising, + tx_pause, rx_pause); +} +EXPORT_SYMBOL(phy_get_pause); + static bool phy_drv_supports_irq(struct phy_driver *phydrv) { return phydrv->config_intr && phydrv->ack_interrupt; |