|
@@ -31,6 +31,32 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,
|
|
|
ds->ops->get_ethtool_stats(ds, port, data + count);
|
|
|
}
|
|
|
|
|
|
+static void dsa_master_get_ethtool_phy_stats(struct net_device *dev,
|
|
|
+ struct ethtool_stats *stats,
|
|
|
+ uint64_t *data)
|
|
|
+{
|
|
|
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
|
|
|
+ const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
|
|
|
+ struct dsa_switch *ds = cpu_dp->ds;
|
|
|
+ int port = cpu_dp->index;
|
|
|
+ int count = 0;
|
|
|
+
|
|
|
+ if (dev->phydev && !ops->get_ethtool_phy_stats) {
|
|
|
+ count = phy_ethtool_get_sset_count(dev->phydev);
|
|
|
+ if (count >= 0)
|
|
|
+ phy_ethtool_get_stats(dev->phydev, stats, data);
|
|
|
+ } else if (ops->get_sset_count && ops->get_ethtool_phy_stats) {
|
|
|
+ count = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
|
|
|
+ ops->get_ethtool_phy_stats(dev, stats, data);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (count < 0)
|
|
|
+ count = 0;
|
|
|
+
|
|
|
+ if (ds->ops->get_ethtool_phy_stats)
|
|
|
+ ds->ops->get_ethtool_phy_stats(ds, port, data + count);
|
|
|
+}
|
|
|
+
|
|
|
static int dsa_master_get_sset_count(struct net_device *dev, int sset)
|
|
|
{
|
|
|
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)
|
|
|
struct dsa_switch *ds = cpu_dp->ds;
|
|
|
int count = 0;
|
|
|
|
|
|
- if (ops->get_sset_count) {
|
|
|
+ if (sset == ETH_SS_PHY_STATS && dev->phydev &&
|
|
|
+ !ops->get_ethtool_phy_stats)
|
|
|
+ count = phy_ethtool_get_sset_count(dev->phydev);
|
|
|
+ else if (ops->get_sset_count)
|
|
|
count = ops->get_sset_count(dev, sset);
|
|
|
- if (count < 0)
|
|
|
- count = 0;
|
|
|
- }
|
|
|
+
|
|
|
+ if (count < 0)
|
|
|
+ count = 0;
|
|
|
|
|
|
if (ds->ops->get_sset_count)
|
|
|
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,
|
|
|
/* We do not want to be NULL-terminated, since this is a prefix */
|
|
|
pfx[sizeof(pfx) - 1] = '_';
|
|
|
|
|
|
- if (ops->get_sset_count && ops->get_strings) {
|
|
|
+ if (stringset == ETH_SS_PHY_STATS && dev->phydev &&
|
|
|
+ !ops->get_ethtool_phy_stats) {
|
|
|
+ mcount = phy_ethtool_get_sset_count(dev->phydev);
|
|
|
+ if (mcount < 0)
|
|
|
+ mcount = 0;
|
|
|
+ else
|
|
|
+ phy_ethtool_get_strings(dev->phydev, data);
|
|
|
+ } else if (ops->get_sset_count && ops->get_strings) {
|
|
|
mcount = ops->get_sset_count(dev, stringset);
|
|
|
if (mcount < 0)
|
|
|
mcount = 0;
|
|
@@ -107,6 +143,7 @@ static int dsa_master_ethtool_setup(struct net_device *dev)
|
|
|
ops->get_sset_count = dsa_master_get_sset_count;
|
|
|
ops->get_ethtool_stats = dsa_master_get_ethtool_stats;
|
|
|
ops->get_strings = dsa_master_get_strings;
|
|
|
+ ops->get_ethtool_phy_stats = dsa_master_get_ethtool_phy_stats;
|
|
|
|
|
|
dev->ethtool_ops = ops;
|
|
|
|