diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2018-04-25 15:12:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-27 11:53:03 -0400 |
commit | cf963573039a333eff7156629e61a06e59da61cf (patch) | |
tree | 78375bd5f5d00dab15a09c64c962b59ed93601ab /net/dsa/master.c | |
parent | 6207a78c098a183df1620c1e2cbf620a4cc7c3e3 (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.c | 47 |
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 | ||
34 | static 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 | |||
34 | static int dsa_master_get_sset_count(struct net_device *dev, int sset) | 60 | static 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 | ||