076-v4.11-0002-net-phy-broadcom-Add-support-code-for-reading-PHY-co.patch 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. From: Florian Fainelli <f.fainelli@gmail.com>
  2. Date: Tue, 29 Nov 2016 09:57:17 -0800
  3. Subject: [PATCH] net: phy: broadcom: Add support code for reading PHY counters
  4. Broadcom PHYs expose a number of PHY error counters: receive errors,
  5. false carrier sense, SerDes BER count, local and remote receive errors.
  6. Add support code to allow retrieving these error counters. Since the
  7. Broadcom PHY library code is used by several drivers, make it possible
  8. for them to specify the storage for the software copy of the statistics.
  9. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
  10. Signed-off-by: David S. Miller <davem@davemloft.net>
  11. ---
  12. --- a/drivers/net/phy/bcm-phy-lib.c
  13. +++ b/drivers/net/phy/bcm-phy-lib.c
  14. @@ -17,6 +17,7 @@
  15. #include <linux/mdio.h>
  16. #include <linux/module.h>
  17. #include <linux/phy.h>
  18. +#include <linux/ethtool.h>
  19. #define MII_BCM_CHANNEL_WIDTH 0x2000
  20. #define BCM_CL45VEN_EEE_ADV 0x3c
  21. @@ -231,6 +232,75 @@ int bcm_phy_set_eee(struct phy_device *p
  22. }
  23. EXPORT_SYMBOL_GPL(bcm_phy_set_eee);
  24. +struct bcm_phy_hw_stat {
  25. + const char *string;
  26. + u8 reg;
  27. + u8 shift;
  28. + u8 bits;
  29. +};
  30. +
  31. +/* Counters freeze at either 0xffff or 0xff, better than nothing */
  32. +static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = {
  33. + { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 },
  34. + { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 },
  35. + { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 },
  36. + { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 },
  37. + { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 },
  38. +};
  39. +
  40. +int bcm_phy_get_sset_count(struct phy_device *phydev)
  41. +{
  42. + return ARRAY_SIZE(bcm_phy_hw_stats);
  43. +}
  44. +EXPORT_SYMBOL_GPL(bcm_phy_get_sset_count);
  45. +
  46. +void bcm_phy_get_strings(struct phy_device *phydev, u8 *data)
  47. +{
  48. + unsigned int i;
  49. +
  50. + for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
  51. + memcpy(data + i * ETH_GSTRING_LEN,
  52. + bcm_phy_hw_stats[i].string, ETH_GSTRING_LEN);
  53. +}
  54. +EXPORT_SYMBOL_GPL(bcm_phy_get_strings);
  55. +
  56. +#ifndef UINT64_MAX
  57. +#define UINT64_MAX (u64)(~((u64)0))
  58. +#endif
  59. +
  60. +/* Caller is supposed to provide appropriate storage for the library code to
  61. + * access the shadow copy
  62. + */
  63. +static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow,
  64. + unsigned int i)
  65. +{
  66. + struct bcm_phy_hw_stat stat = bcm_phy_hw_stats[i];
  67. + int val;
  68. + u64 ret;
  69. +
  70. + val = phy_read(phydev, stat.reg);
  71. + if (val < 0) {
  72. + ret = UINT64_MAX;
  73. + } else {
  74. + val >>= stat.shift;
  75. + val = val & ((1 << stat.bits) - 1);
  76. + shadow[i] += val;
  77. + ret = shadow[i];
  78. + }
  79. +
  80. + return ret;
  81. +}
  82. +
  83. +void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
  84. + struct ethtool_stats *stats, u64 *data)
  85. +{
  86. + unsigned int i;
  87. +
  88. + for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
  89. + data[i] = bcm_phy_get_stat(phydev, shadow, i);
  90. +}
  91. +EXPORT_SYMBOL_GPL(bcm_phy_get_stats);
  92. +
  93. MODULE_DESCRIPTION("Broadcom PHY Library");
  94. MODULE_LICENSE("GPL v2");
  95. MODULE_AUTHOR("Broadcom Corporation");
  96. --- a/drivers/net/phy/bcm-phy-lib.h
  97. +++ b/drivers/net/phy/bcm-phy-lib.h
  98. @@ -44,4 +44,10 @@ int bcm_phy_config_intr(struct phy_devic
  99. int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
  100. int bcm_phy_set_eee(struct phy_device *phydev, bool enable);
  101. +
  102. +int bcm_phy_get_sset_count(struct phy_device *phydev);
  103. +void bcm_phy_get_strings(struct phy_device *phydev, u8 *data);
  104. +void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
  105. + struct ethtool_stats *stats, u64 *data);
  106. +
  107. #endif /* _LINUX_BCM_PHY_LIB_H */
  108. --- a/include/linux/brcmphy.h
  109. +++ b/include/linux/brcmphy.h
  110. @@ -234,6 +234,9 @@
  111. #define LPI_FEATURE_EN_DIG1000X 0x4000
  112. /* Core register definitions*/
  113. +#define MII_BRCM_CORE_BASE12 0x12
  114. +#define MII_BRCM_CORE_BASE13 0x13
  115. +#define MII_BRCM_CORE_BASE14 0x14
  116. #define MII_BRCM_CORE_BASE1E 0x1E
  117. #define MII_BRCM_CORE_EXPB0 0xB0
  118. #define MII_BRCM_CORE_EXPB1 0xB1