In order to make it possible for network device drivers that do not
necessarily have a phy_device attached, but still report PHY statistics,
have a preliminary refactoring consisting in creating helper functions
that encapsulate the PHY device driver knowledge within PHYLIB.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/phy/phy.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/phy.h   |  4 ++++
 net/core/ethtool.c    | 38 ++++++++------------------------------
 3 files changed, 60 insertions(+), 30 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 05c1e8ef15e6..a98ed12c0009 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1277,3 +1277,51 @@ int phy_ethtool_nway_reset(struct net_device *ndev)
        return phy_restart_aneg(phydev);
 }
 EXPORT_SYMBOL(phy_ethtool_nway_reset);
+
+int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data)
+{
+       if (!phydev->drv)
+               return -EIO;
+
+       mutex_lock(&phydev->lock);
+       phydev->drv->get_strings(phydev, data);
+       mutex_unlock(&phydev->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_get_strings);
+
+int phy_ethtool_get_sset_count(struct phy_device *phydev)
+{
+       int ret;
+
+       if (!phydev->drv)
+               return -EIO;
+
+       if (phydev->drv->get_sset_count &&
+           phydev->drv->get_strings &&
+           phydev->drv->get_stats) {
+               mutex_lock(&phydev->lock);
+               ret = phydev->drv->get_sset_count(phydev);
+               mutex_unlock(&phydev->lock);
+
+               return ret;
+       }
+
+       return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(phy_ethtool_get_sset_count);
+
+int phy_ethtool_get_stats(struct phy_device *phydev,
+                         struct ethtool_stats *stats, u64 *data)
+{
+       if (!phydev->drv)
+               return -EIO;
+
+       mutex_lock(&phydev->lock);
+       phydev->drv->get_stats(phydev, stats, data);
+       mutex_unlock(&phydev->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_get_stats);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index f0b5870a6d40..c16f6d90044f 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1062,6 +1062,10 @@ int phy_ethtool_get_link_ksettings(struct net_device 
*ndev,
 int phy_ethtool_set_link_ksettings(struct net_device *ndev,
                                   const struct ethtool_link_ksettings *cmd);
 int phy_ethtool_nway_reset(struct net_device *ndev);
+int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data);
+int phy_ethtool_get_sset_count(struct phy_device *phydev);
+int phy_ethtool_get_stats(struct phy_device *phydev,
+                         struct ethtool_stats *stats, u64 *data);
 
 #if IS_ENABLED(CONFIG_PHYLIB)
 int __init mdio_bus_init(void);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 03416e6dd5d7..f0d42e093c4a 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -210,23 +210,6 @@ static int ethtool_set_features(struct net_device *dev, 
void __user *useraddr)
        return ret;
 }
 
-static int phy_get_sset_count(struct phy_device *phydev)
-{
-       int ret;
-
-       if (phydev->drv->get_sset_count &&
-           phydev->drv->get_strings &&
-           phydev->drv->get_stats) {
-               mutex_lock(&phydev->lock);
-               ret = phydev->drv->get_sset_count(phydev);
-               mutex_unlock(&phydev->lock);
-
-               return ret;
-       }
-
-       return -EOPNOTSUPP;
-}
-
 static int __ethtool_get_sset_count(struct net_device *dev, int sset)
 {
        const struct ethtool_ops *ops = dev->ethtool_ops;
@@ -245,7 +228,7 @@ static int __ethtool_get_sset_count(struct net_device *dev, 
int sset)
 
        if (sset == ETH_SS_PHY_STATS) {
                if (dev->phydev)
-                       return phy_get_sset_count(dev->phydev);
+                       return phy_ethtool_get_sset_count(dev->phydev);
                else
                        return -EOPNOTSUPP;
        }
@@ -272,15 +255,10 @@ static void __ethtool_get_strings(struct net_device *dev,
        else if (stringset == ETH_SS_PHY_TUNABLES)
                memcpy(data, phy_tunable_strings, sizeof(phy_tunable_strings));
        else if (stringset == ETH_SS_PHY_STATS) {
-               struct phy_device *phydev = dev->phydev;
-
-               if (phydev) {
-                       mutex_lock(&phydev->lock);
-                       phydev->drv->get_strings(phydev, data);
-                       mutex_unlock(&phydev->lock);
-               } else {
+               if (dev->phydev)
+                       phy_ethtool_get_strings(dev->phydev, data);
+               else
                        return;
-               }
        } else
                /* ops->get_strings is valid because checked earlier */
                ops->get_strings(dev, stringset, data);
@@ -2001,7 +1979,7 @@ static int ethtool_get_phy_stats(struct net_device *dev, 
void __user *useraddr)
        if (!phydev)
                return -EOPNOTSUPP;
 
-       n_stats = phy_get_sset_count(phydev);
+       n_stats = phy_ethtool_get_sset_count(dev->phydev);
        if (n_stats < 0)
                return n_stats;
        if (n_stats > S32_MAX / sizeof(u64))
@@ -2016,9 +1994,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, 
void __user *useraddr)
        if (n_stats && !data)
                return -ENOMEM;
 
-       mutex_lock(&phydev->lock);
-       phydev->drv->get_stats(phydev, &stats, data);
-       mutex_unlock(&phydev->lock);
+       ret = phy_ethtool_get_stats(dev->phydev, &stats, data);
+       if (ret < 0)
+               return ret;
 
        ret = -EFAULT;
        if (copy_to_user(useraddr, &stats, sizeof(stats)))
-- 
2.7.4

Reply via email to