In order to decouple ethtool from its PHY library dependency, define an
ethtool_phy_ops singleton which can be overriden by the PHY library when
it loads with an appropriate set of function pointers.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 include/linux/ethtool.h | 25 +++++++++++++++++++++++++
 net/ethtool/common.c    | 11 +++++++++++
 net/ethtool/common.h    |  2 ++
 3 files changed, 38 insertions(+)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 48ad3b6a0150..0c139a93b67a 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -502,5 +502,30 @@ int ethtool_virtdev_set_link_ksettings(struct net_device 
*dev,
                                       const struct ethtool_link_ksettings *cmd,
                                       u32 *dev_speed, u8 *dev_duplex);
 
+struct netlink_ext_ack;
+struct phy_device;
+struct phy_tdr_config;
+
+/**
+ * struct ethtool_phy_ops - Optional PHY device options
+ * @start_cable_test - Start a cable test
+ * @start_cable_test_tdr - Start a Time Domain Reflectometry cable test
+ *
+ * All operations are optional (i.e. the function pointer may be set to %NULL)
+ * and callers must take this into account. Callers must hold the RTNL lock.
+ */
+struct ethtool_phy_ops {
+       int (*start_cable_test)(struct phy_device *phydev,
+                               struct netlink_ext_ack *extack);
+       int (*start_cable_test_tdr)(struct phy_device *phydev,
+                                   struct netlink_ext_ack *extack,
+                                   const struct phy_tdr_config *config);
+};
+
+/**
+ * ethtool_set_ethtool_phy_ops - Set the ethtool_phy_ops singleton
+ * @ops: Ethtool PHY operations to set
+ */
+void ethtool_set_ethtool_phy_ops(const struct ethtool_phy_ops *ops);
 
 #endif /* _LINUX_ETHTOOL_H */
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index aaecfc916a4d..ce4dbae5a943 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -2,6 +2,7 @@
 
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
+#include <linux/rtnetlink.h>
 
 #include "common.h"
 
@@ -373,3 +374,13 @@ int __ethtool_get_ts_info(struct net_device *dev, struct 
ethtool_ts_info *info)
 
        return 0;
 }
+
+const struct ethtool_phy_ops *ethtool_phy_ops;
+
+void ethtool_set_ethtool_phy_ops(const struct ethtool_phy_ops *ops)
+{
+       rtnl_lock();
+       ethtool_phy_ops = ops;
+       rtnl_unlock();
+}
+EXPORT_SYMBOL_GPL(ethtool_set_ethtool_phy_ops);
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
index a62f68ccc43a..b83bef38368c 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -37,4 +37,6 @@ bool convert_legacy_settings_to_link_ksettings(
 int ethtool_get_max_rxfh_channel(struct net_device *dev, u32 *max);
 int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info 
*info);
 
+extern const struct ethtool_phy_ops *ethtool_phy_ops;
+
 #endif /* _ETHTOOL_COMMON_H */
-- 
2.25.1

Reply via email to