|
@@ -227,12 +227,9 @@ static int __ethtool_get_sset_count(struct net_device *dev, int sset)
|
|
|
if (sset == ETH_SS_PHY_TUNABLES)
|
|
|
return ARRAY_SIZE(phy_tunable_strings);
|
|
|
|
|
|
- if (sset == ETH_SS_PHY_STATS) {
|
|
|
- if (dev->phydev)
|
|
|
- return phy_ethtool_get_sset_count(dev->phydev);
|
|
|
- else
|
|
|
- return -EOPNOTSUPP;
|
|
|
- }
|
|
|
+ if (sset == ETH_SS_PHY_STATS && dev->phydev &&
|
|
|
+ !ops->get_ethtool_phy_stats)
|
|
|
+ return phy_ethtool_get_sset_count(dev->phydev);
|
|
|
|
|
|
if (ops->get_sset_count && ops->get_strings)
|
|
|
return ops->get_sset_count(dev, sset);
|
|
@@ -255,12 +252,10 @@ static void __ethtool_get_strings(struct net_device *dev,
|
|
|
memcpy(data, tunable_strings, sizeof(tunable_strings));
|
|
|
else if (stringset == ETH_SS_PHY_TUNABLES)
|
|
|
memcpy(data, phy_tunable_strings, sizeof(phy_tunable_strings));
|
|
|
- else if (stringset == ETH_SS_PHY_STATS) {
|
|
|
- if (dev->phydev)
|
|
|
- phy_ethtool_get_strings(dev->phydev, data);
|
|
|
- else
|
|
|
- return;
|
|
|
- } else
|
|
|
+ else if (stringset == ETH_SS_PHY_STATS && dev->phydev &&
|
|
|
+ !ops->get_ethtool_phy_stats)
|
|
|
+ phy_ethtool_get_strings(dev->phydev, data);
|
|
|
+ else
|
|
|
/* ops->get_strings is valid because checked earlier */
|
|
|
ops->get_strings(dev, stringset, data);
|
|
|
}
|
|
@@ -1972,15 +1967,19 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
|
|
|
|
|
|
static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
|
|
|
{
|
|
|
- struct ethtool_stats stats;
|
|
|
+ const struct ethtool_ops *ops = dev->ethtool_ops;
|
|
|
struct phy_device *phydev = dev->phydev;
|
|
|
+ struct ethtool_stats stats;
|
|
|
u64 *data;
|
|
|
int ret, n_stats;
|
|
|
|
|
|
- if (!phydev)
|
|
|
+ if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count))
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- n_stats = phy_ethtool_get_sset_count(dev->phydev);
|
|
|
+ if (dev->phydev && !ops->get_ethtool_phy_stats)
|
|
|
+ n_stats = phy_ethtool_get_sset_count(dev->phydev);
|
|
|
+ else
|
|
|
+ n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
|
|
|
if (n_stats < 0)
|
|
|
return n_stats;
|
|
|
if (n_stats > S32_MAX / sizeof(u64))
|
|
@@ -1995,9 +1994,13 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
|
|
|
if (n_stats && !data)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- ret = phy_ethtool_get_stats(dev->phydev, &stats, data);
|
|
|
- if (ret < 0)
|
|
|
- return ret;
|
|
|
+ if (dev->phydev && !ops->get_ethtool_phy_stats) {
|
|
|
+ ret = phy_ethtool_get_stats(dev->phydev, &stats, data);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ } else {
|
|
|
+ ops->get_ethtool_phy_stats(dev, &stats, data);
|
|
|
+ }
|
|
|
|
|
|
ret = -EFAULT;
|
|
|
if (copy_to_user(useraddr, &stats, sizeof(stats)))
|