123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- From: Florian Fainelli <f.fainelli@gmail.com>
- Date: Tue, 29 Nov 2016 09:57:17 -0800
- Subject: [PATCH] net: phy: broadcom: Add support code for reading PHY counters
- Broadcom PHYs expose a number of PHY error counters: receive errors,
- false carrier sense, SerDes BER count, local and remote receive errors.
- Add support code to allow retrieving these error counters. Since the
- Broadcom PHY library code is used by several drivers, make it possible
- for them to specify the storage for the software copy of the statistics.
- Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
- Signed-off-by: David S. Miller <davem@davemloft.net>
- ---
- --- a/drivers/net/phy/bcm-phy-lib.c
- +++ b/drivers/net/phy/bcm-phy-lib.c
- @@ -17,6 +17,7 @@
- #include <linux/mdio.h>
- #include <linux/module.h>
- #include <linux/phy.h>
- +#include <linux/ethtool.h>
-
- #define MII_BCM_CHANNEL_WIDTH 0x2000
- #define BCM_CL45VEN_EEE_ADV 0x3c
- @@ -231,6 +232,75 @@ int bcm_phy_set_eee(struct phy_device *p
- }
- EXPORT_SYMBOL_GPL(bcm_phy_set_eee);
-
- +struct bcm_phy_hw_stat {
- + const char *string;
- + u8 reg;
- + u8 shift;
- + u8 bits;
- +};
- +
- +/* Counters freeze at either 0xffff or 0xff, better than nothing */
- +static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = {
- + { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 },
- + { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 },
- + { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 },
- + { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 },
- + { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 },
- +};
- +
- +int bcm_phy_get_sset_count(struct phy_device *phydev)
- +{
- + return ARRAY_SIZE(bcm_phy_hw_stats);
- +}
- +EXPORT_SYMBOL_GPL(bcm_phy_get_sset_count);
- +
- +void bcm_phy_get_strings(struct phy_device *phydev, u8 *data)
- +{
- + unsigned int i;
- +
- + for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
- + memcpy(data + i * ETH_GSTRING_LEN,
- + bcm_phy_hw_stats[i].string, ETH_GSTRING_LEN);
- +}
- +EXPORT_SYMBOL_GPL(bcm_phy_get_strings);
- +
- +#ifndef UINT64_MAX
- +#define UINT64_MAX (u64)(~((u64)0))
- +#endif
- +
- +/* Caller is supposed to provide appropriate storage for the library code to
- + * access the shadow copy
- + */
- +static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow,
- + unsigned int i)
- +{
- + struct bcm_phy_hw_stat stat = bcm_phy_hw_stats[i];
- + int val;
- + u64 ret;
- +
- + val = phy_read(phydev, stat.reg);
- + if (val < 0) {
- + ret = UINT64_MAX;
- + } else {
- + val >>= stat.shift;
- + val = val & ((1 << stat.bits) - 1);
- + shadow[i] += val;
- + ret = shadow[i];
- + }
- +
- + return ret;
- +}
- +
- +void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
- + struct ethtool_stats *stats, u64 *data)
- +{
- + unsigned int i;
- +
- + for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
- + data[i] = bcm_phy_get_stat(phydev, shadow, i);
- +}
- +EXPORT_SYMBOL_GPL(bcm_phy_get_stats);
- +
- MODULE_DESCRIPTION("Broadcom PHY Library");
- MODULE_LICENSE("GPL v2");
- MODULE_AUTHOR("Broadcom Corporation");
- --- a/drivers/net/phy/bcm-phy-lib.h
- +++ b/drivers/net/phy/bcm-phy-lib.h
- @@ -44,4 +44,10 @@ int bcm_phy_config_intr(struct phy_devic
- int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
-
- int bcm_phy_set_eee(struct phy_device *phydev, bool enable);
- +
- +int bcm_phy_get_sset_count(struct phy_device *phydev);
- +void bcm_phy_get_strings(struct phy_device *phydev, u8 *data);
- +void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
- + struct ethtool_stats *stats, u64 *data);
- +
- #endif /* _LINUX_BCM_PHY_LIB_H */
- --- a/include/linux/brcmphy.h
- +++ b/include/linux/brcmphy.h
- @@ -234,6 +234,9 @@
- #define LPI_FEATURE_EN_DIG1000X 0x4000
-
- /* Core register definitions*/
- +#define MII_BRCM_CORE_BASE12 0x12
- +#define MII_BRCM_CORE_BASE13 0x13
- +#define MII_BRCM_CORE_BASE14 0x14
- #define MII_BRCM_CORE_BASE1E 0x1E
- #define MII_BRCM_CORE_EXPB0 0xB0
- #define MII_BRCM_CORE_EXPB1 0xB1
|