Add an optional polling interface for PHY statistics to simplify driver implementation. Drivers can request the PHYlib to handle the polling task by explicitly setting the `PHY_POLL_STATS` flag in their driver configuration. Signed-off-by: Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx> --- drivers/net/phy/phy.c | 15 +++++++++++++++ include/linux/phy.h | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 0d20b534122b..b10ee9223fc9 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1346,6 +1346,18 @@ static int phy_enable_interrupts(struct phy_device *phydev) return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); } +/** + * phy_update_stats - update the PHY statistics + * @phydev: target phy_device struct + */ +static int phy_update_stats(struct phy_device *phydev) +{ + if (!phydev->drv->update_stats) + return 0; + + return phydev->drv->update_stats(phydev); +} + /** * phy_request_interrupt - request and enable interrupt for a PHY device * @phydev: target phy_device struct @@ -1415,6 +1427,9 @@ static enum phy_state_work _phy_state_machine(struct phy_device *phydev) case PHY_RUNNING: err = phy_check_link_status(phydev); func = &phy_check_link_status; + + if (!err) + err = phy_update_stats(phydev); break; case PHY_CABLETEST: err = phydev->drv->cable_test_get_status(phydev, &finished); diff --git a/include/linux/phy.h b/include/linux/phy.h index a6c47b0675af..21cd44d177d2 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -90,6 +90,7 @@ extern const int phy_10gbit_features_array[1]; #define PHY_RST_AFTER_CLK_EN BIT(1) #define PHY_POLL_CABLE_TEST BIT(2) #define PHY_ALWAYS_CALL_SUSPEND BIT(3) +#define PHY_POLL_STATS BIT(4) #define MDIO_DEVICE_IS_PHY BIT(31) /** @@ -1101,6 +1102,8 @@ struct phy_driver { struct ethtool_phy_stats *stats); void (*get_link_stats)(struct phy_device *dev, struct ethtool_link_ext_stats *link_stats); + int (*update_stats)(struct phy_device *dev); + /** @get_sset_count: Number of statistic counters */ int (*get_sset_count)(struct phy_device *dev); /** @get_strings: Names of the statistic counters */ @@ -1591,6 +1594,9 @@ static inline bool phy_polling_mode(struct phy_device *phydev) if (phydev->drv->flags & PHY_POLL_CABLE_TEST) return true; + if (phydev->drv->update_stats && phydev->drv->flags & PHY_POLL_STATS) + return true; + return phydev->irq == PHY_POLL; } -- 2.39.5