Merge branch 'net-ethtool-Untangle-PHYLIB-dependency'
Florian Fainelli says: ==================== net: ethtool: Untangle PHYLIB dependency This patch series untangles the ethtool netlink dependency with PHYLIB which exists because the cable test feature calls directly into PHY library functions. The approach taken here is to introduce ethtool_phy_ops function pointers which can be dynamically registered when PHYLIB loads. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
417e19d12b
@ -3027,6 +3027,11 @@ static struct phy_driver genphy_driver = {
|
||||
.set_loopback = genphy_loopback,
|
||||
};
|
||||
|
||||
static const struct ethtool_phy_ops phy_ethtool_phy_ops = {
|
||||
.start_cable_test = phy_start_cable_test,
|
||||
.start_cable_test_tdr = phy_start_cable_test_tdr,
|
||||
};
|
||||
|
||||
static int __init phy_init(void)
|
||||
{
|
||||
int rc;
|
||||
@ -3035,6 +3040,7 @@ static int __init phy_init(void)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
|
||||
features_init();
|
||||
|
||||
rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
|
||||
@ -3056,6 +3062,7 @@ static void __exit phy_exit(void)
|
||||
phy_driver_unregister(&genphy_c45_driver);
|
||||
phy_driver_unregister(&genphy_driver);
|
||||
mdio_bus_exit();
|
||||
ethtool_set_ethtool_phy_ops(NULL);
|
||||
}
|
||||
|
||||
subsys_initcall(phy_init);
|
||||
|
@ -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 */
|
||||
|
@ -455,7 +455,6 @@ config FAILOVER
|
||||
config ETHTOOL_NETLINK
|
||||
bool "Netlink interface for ethtool"
|
||||
default y
|
||||
depends on PHYLIB=y || PHYLIB=n
|
||||
help
|
||||
An alternative userspace interface for ethtool based on generic
|
||||
netlink. It provides better extensibility and some new features,
|
||||
|
@ -58,6 +58,7 @@ int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *tb[ETHTOOL_A_CABLE_TEST_MAX + 1];
|
||||
struct ethnl_req_info req_info = {};
|
||||
const struct ethtool_phy_ops *ops;
|
||||
struct net_device *dev;
|
||||
int ret;
|
||||
|
||||
@ -81,11 +82,17 @@ int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
ops = ethtool_phy_ops;
|
||||
if (!ops || !ops->start_cable_test) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out_rtnl;
|
||||
}
|
||||
|
||||
ret = ethnl_ops_begin(dev);
|
||||
if (ret < 0)
|
||||
goto out_rtnl;
|
||||
|
||||
ret = phy_start_cable_test(dev->phydev, info->extack);
|
||||
ret = ops->start_cable_test(dev->phydev, info->extack);
|
||||
|
||||
ethnl_ops_complete(dev);
|
||||
|
||||
@ -308,6 +315,7 @@ int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1];
|
||||
struct ethnl_req_info req_info = {};
|
||||
const struct ethtool_phy_ops *ops;
|
||||
struct phy_tdr_config cfg;
|
||||
struct net_device *dev;
|
||||
int ret;
|
||||
@ -337,11 +345,17 @@ int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info)
|
||||
goto out_dev_put;
|
||||
|
||||
rtnl_lock();
|
||||
ops = ethtool_phy_ops;
|
||||
if (!ops || !ops->start_cable_test_tdr) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out_rtnl;
|
||||
}
|
||||
|
||||
ret = ethnl_ops_begin(dev);
|
||||
if (ret < 0)
|
||||
goto out_rtnl;
|
||||
|
||||
ret = phy_start_cable_test_tdr(dev->phydev, info->extack, &cfg);
|
||||
ret = ops->start_cable_test_tdr(dev->phydev, info->extack, &cfg);
|
||||
|
||||
ethnl_ops_complete(dev);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user