From 030a89028db07a7987f1f3bd6ee43114e36f5060 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 3 Jun 2017 20:00:36 +0200 Subject: [PATCH] net: phy: smsc: Implement PHY statistics Most of the PHYs supported by the SMSC driver have a counter of symbol errors. This is 16 bit wide and wraps around when it reaches its maximum value. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Reviewed-By: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 67c9f2b26c8e..1b8204be064c 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -25,6 +25,16 @@ #include #include +struct smsc_hw_stat { + const char *string; + u8 reg; + u8 bits; +}; + +static struct smsc_hw_stat smsc_hw_stats[] = { + { "phy_symbol_errors", 26, 16}, +}; + struct smsc_phy_priv { bool energy_enable; }; @@ -143,6 +153,48 @@ static int lan87xx_read_status(struct phy_device *phydev) return err; } +static int smsc_get_sset_count(struct phy_device *phydev) +{ + return ARRAY_SIZE(smsc_hw_stats); +} + +static void smsc_get_strings(struct phy_device *phydev, u8 *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) { + memcpy(data + i * ETH_GSTRING_LEN, + smsc_hw_stats[i].string, ETH_GSTRING_LEN); + } +} + +#ifndef UINT64_MAX +#define UINT64_MAX (u64)(~((u64)0)) +#endif +static u64 smsc_get_stat(struct phy_device *phydev, int i) +{ + struct smsc_hw_stat stat = smsc_hw_stats[i]; + int val; + u64 ret; + + val = phy_read(phydev, stat.reg); + if (val < 0) + ret = UINT64_MAX; + else + ret = val; + + return ret; +} + +static void smsc_get_stats(struct phy_device *phydev, + struct ethtool_stats *stats, u64 *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) + data[i] = smsc_get_stat(phydev, i); +} + static int smsc_phy_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; @@ -206,6 +258,11 @@ static struct phy_driver smsc_phy_driver[] = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + /* Statistics */ + .get_sset_count = smsc_get_sset_count, + .get_strings = smsc_get_strings, + .get_stats = smsc_get_stats, + .suspend = genphy_suspend, .resume = genphy_resume, }, { @@ -228,6 +285,11 @@ static struct phy_driver smsc_phy_driver[] = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + /* Statistics */ + .get_sset_count = smsc_get_sset_count, + .get_strings = smsc_get_strings, + .get_stats = smsc_get_stats, + .suspend = genphy_suspend, .resume = genphy_resume, }, { @@ -271,6 +333,11 @@ static struct phy_driver smsc_phy_driver[] = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + /* Statistics */ + .get_sset_count = smsc_get_sset_count, + .get_strings = smsc_get_strings, + .get_stats = smsc_get_stats, + .suspend = genphy_suspend, .resume = genphy_resume, }, { @@ -293,6 +360,11 @@ static struct phy_driver smsc_phy_driver[] = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + /* Statistics */ + .get_sset_count = smsc_get_sset_count, + .get_strings = smsc_get_strings, + .get_stats = smsc_get_stats, + .suspend = genphy_suspend, .resume = genphy_resume, } }; -- 2.20.1