summaryrefslogtreecommitdiff
path: root/target/linux/generic/patches-4.9/076-v4.11-0002-net-phy-broadcom-Add-support-code-for-reading-PHY-co.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-4.9/076-v4.11-0002-net-phy-broadcom-Add-support-code-for-reading-PHY-co.patch')
-rw-r--r--target/linux/generic/patches-4.9/076-v4.11-0002-net-phy-broadcom-Add-support-code-for-reading-PHY-co.patch125
1 files changed, 125 insertions, 0 deletions
diff --git a/target/linux/generic/patches-4.9/076-v4.11-0002-net-phy-broadcom-Add-support-code-for-reading-PHY-co.patch b/target/linux/generic/patches-4.9/076-v4.11-0002-net-phy-broadcom-Add-support-code-for-reading-PHY-co.patch
new file mode 100644
index 0000000..1bdecf5
--- /dev/null
+++ b/target/linux/generic/patches-4.9/076-v4.11-0002-net-phy-broadcom-Add-support-code-for-reading-PHY-co.patch
@@ -0,0 +1,125 @@
+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
+@@ -37,4 +37,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