summaryrefslogtreecommitdiffstats
path: root/net/dsa/master.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2018-04-25 15:12:52 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-27 11:53:03 -0400
commitcf963573039a333eff7156629e61a06e59da61cf (patch)
tree78375bd5f5d00dab15a09c64c962b59ed93601ab /net/dsa/master.c
parent6207a78c098a183df1620c1e2cbf620a4cc7c3e3 (diff)
net: dsa: Allow providing PHY statistics from CPU port
Implement the same type of ethtool diversion that we have for ETH_SS_STATS and make it work with ETH_SS_PHY_STATS. This allows providing PHY level statistics for CPU ports that are directly connecting to a PHY device. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/master.c')
-rw-r--r--net/dsa/master.c47
1 files changed, 42 insertions, 5 deletions
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 8d27687fd0ca..c90ee3227dea 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -31,6 +31,32 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,
31 ds->ops->get_ethtool_stats(ds, port, data + count); 31 ds->ops->get_ethtool_stats(ds, port, data + count);
32} 32}
33 33
34static void dsa_master_get_ethtool_phy_stats(struct net_device *dev,
35 struct ethtool_stats *stats,
36 uint64_t *data)
37{
38 struct dsa_port *cpu_dp = dev->dsa_ptr;
39 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
40 struct dsa_switch *ds = cpu_dp->ds;
41 int port = cpu_dp->index;
42 int count = 0;
43
44 if (dev->phydev && !ops->get_ethtool_phy_stats) {
45 count = phy_ethtool_get_sset_count(dev->phydev);
46 if (count >= 0)
47 phy_ethtool_get_stats(dev->phydev, stats, data);
48 } else if (ops->get_sset_count && ops->get_ethtool_phy_stats) {
49 count = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
50 ops->get_ethtool_phy_stats(dev, stats, data);
51 }
52
53 if (count < 0)
54 count = 0;
55
56 if (ds->ops->get_ethtool_phy_stats)
57 ds->ops->get_ethtool_phy_stats(ds, port, data + count);
58}
59
34static int dsa_master_get_sset_count(struct net_device *dev, int sset) 60static int dsa_master_get_sset_count(struct net_device *dev, int sset)
35{ 61{
36 struct dsa_port *cpu_dp = dev->dsa_ptr; 62 struct dsa_port *cpu_dp = dev->dsa_ptr;
@@ -38,11 +64,14 @@ static int dsa_master_get_sset_count(struct net_device *dev, int sset)
38 struct dsa_switch *ds = cpu_dp->ds; 64 struct dsa_switch *ds = cpu_dp->ds;
39 int count = 0; 65 int count = 0;
40 66
41 if (ops->get_sset_count) { 67 if (sset == ETH_SS_PHY_STATS && dev->phydev &&
68 !ops->get_ethtool_phy_stats)
69 count = phy_ethtool_get_sset_count(dev->phydev);
70 else if (ops->get_sset_count)
42 count = ops->get_sset_count(dev, sset); 71 count = ops->get_sset_count(dev, sset);
43 if (count < 0) 72
44 count = 0; 73 if (count < 0)
45 } 74 count = 0;
46 75
47 if (ds->ops->get_sset_count) 76 if (ds->ops->get_sset_count)
48 count += ds->ops->get_sset_count(ds, cpu_dp->index, sset); 77 count += ds->ops->get_sset_count(ds, cpu_dp->index, sset);
@@ -67,7 +96,14 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
67 /* We do not want to be NULL-terminated, since this is a prefix */ 96 /* We do not want to be NULL-terminated, since this is a prefix */
68 pfx[sizeof(pfx) - 1] = '_'; 97 pfx[sizeof(pfx) - 1] = '_';
69 98
70 if (ops->get_sset_count && ops->get_strings) { 99 if (stringset == ETH_SS_PHY_STATS && dev->phydev &&
100 !ops->get_ethtool_phy_stats) {
101 mcount = phy_ethtool_get_sset_count(dev->phydev);
102 if (mcount < 0)
103 mcount = 0;
104 else
105 phy_ethtool_get_strings(dev->phydev, data);
106 } else if (ops->get_sset_count && ops->get_strings) {
71 mcount = ops->get_sset_count(dev, stringset); 107 mcount = ops->get_sset_count(dev, stringset);
72 if (mcount < 0) 108 if (mcount < 0)
73 mcount = 0; 109 mcount = 0;
@@ -107,6 +143,7 @@ static int dsa_master_ethtool_setup(struct net_device *dev)
107 ops->get_sset_count = dsa_master_get_sset_count; 143 ops->get_sset_count = dsa_master_get_sset_count;
108 ops->get_ethtool_stats = dsa_master_get_ethtool_stats; 144 ops->get_ethtool_stats = dsa_master_get_ethtool_stats;
109 ops->get_strings = dsa_master_get_strings; 145 ops->get_strings = dsa_master_get_strings;
146 ops->get_ethtool_phy_stats = dsa_master_get_ethtool_phy_stats;
110 147
111 dev->ethtool_ops = ops; 148 dev->ethtool_ops = ops;
112 149