diff mbox series

[RFC,10/13] net: phy: Allow options to be passed to the cable test

Message ID 20190612160534.23533-11-andrew@lunn.ch
State RFC
Delegated to: David Miller
Headers show
Series Ethernet PHY cable test support | expand

Commit Message

Andrew Lunn June 12, 2019, 4:05 p.m. UTC
Some PHYs can do more than just measure the distance to a fault.  But
these additional actions are expensive. So allow options to be passed
to enable these additional actions.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/phy/marvell.c            |  6 +++++-
 drivers/net/phy/phy.c                |  5 +++--
 include/linux/phy.h                  |  7 ++++---
 include/uapi/linux/ethtool_netlink.h |  1 +
 net/ethtool/actions.c                | 10 ++++++++--
 5 files changed, 21 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 96354513daba..11a19c354533 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -1667,10 +1667,14 @@  static void marvell_get_stats(struct phy_device *phydev,
 		data[i] = marvell_get_stat(phydev, i);
 }
 
-static int marvell_vct7_cable_test_start(struct phy_device *phydev)
+static int marvell_vct7_cable_test_start(struct phy_device *phydev,
+					 int options)
 {
 	int bmcr, bmsr, ret;
 
+	if (options)
+		return -EOPNOTSUPP;
+
 	/* If auto-negotiation is enabled, but not complete, the
 	   cable test never completes. So disable auto-neg.
 	*/
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 6540523d773a..38a766fc0923 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -533,7 +533,8 @@  int phy_cable_test_fault_length(struct phy_device *phydev, u8 pair, u16 cm)
 EXPORT_SYMBOL_GPL(phy_cable_test_fault_length);
 
 int phy_start_cable_test(struct phy_device *phydev,
-			 struct netlink_ext_ack *extack, u32 seq)
+			 struct netlink_ext_ack *extack, u32 seq,
+			 int options)
 {
 	int err = -ENOMEM;
 	int ret;
@@ -577,7 +578,7 @@  int phy_start_cable_test(struct phy_device *phydev,
 	/* Mark the carrier down until the test is complete */
 	phy_link_down(phydev, true);
 
-	err = phydev->drv->cable_test_start(phydev);
+	err = phydev->drv->cable_test_start(phydev, options);
 	if (err) {
 		phy_link_up(phydev);
 		goto out_free;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 23c18583ea07..2ef7dc37ea44 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -641,7 +641,7 @@  struct phy_driver {
 			     struct ethtool_eeprom *ee, u8 *data);
 
 	/* Start a cable test */
-	int (*cable_test_start)(struct phy_device *dev);
+	int (*cable_test_start)(struct phy_device *dev, int options);
 	/* Once per second, or on interrupt, request the status of the
 	 * test.
 	 */
@@ -1078,12 +1078,12 @@  int phy_reset_after_clk_enable(struct phy_device *phydev);
 #if IS_ENABLED(CONFIG_PHYLIB)
 int phy_start_cable_test(struct phy_device *phydev,
 			 struct netlink_ext_ack *extack,
-			 u32 seq);
+			 u32 seq, int options);
 #else
 static inline
 int phy_start_cable_test(struct phy_device *phydev,
 			 struct netlink_ext_ack *extack,
-			 u32 seq)
+			 u32 seq, int options)
 {
 	NL_SET_ERR_MSG(extack, "Kernel not compiled with PHYLIB support");
 	return -EOPNOTSUPP;
@@ -1093,6 +1093,7 @@  int phy_start_cable_test(struct phy_device *phydev,
 int phy_cable_test_result(struct phy_device *phydev, u8 pair, u16 result);
 int phy_cable_test_fault_length(struct phy_device *phydev, u8 pair,
 				u16 cm);
+#define PHY_CABLE_TEST_AMPLITUDE_GRAPH BIT(0)
 
 static inline void phy_device_reset(struct phy_device *phydev, int value)
 {
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index aac76a26f97b..841f23ca2306 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -565,6 +565,7 @@  enum {
 enum {
 	ETHTOOL_A_CABLE_TEST_UNSPEC,
 	ETHTOOL_A_CABLE_TEST_DEV,		/* nest - ETHTOOL_A_DEV_* */
+	ETHTOOL_A_CABLE_TEST_AMPLITUDE_GRAPH,
 
 	__ETHTOOL_A_CABLE_TEST_CNT,
 	ETHTOOL_A_CABLE_TEST_MAX = (__ETHTOOL_A_CABLE_TEST_CNT - 1)
diff --git a/net/ethtool/actions.c b/net/ethtool/actions.c
index 8595cc27d532..12ff93c526f0 100644
--- a/net/ethtool/actions.c
+++ b/net/ethtool/actions.c
@@ -382,7 +382,8 @@  int ethnl_act_reset(struct sk_buff *skb, struct genl_info *info)
 static const struct
 nla_policy cable_test_policy[ETHTOOL_A_CABLE_TEST_MAX + 1] = {
 	[ETHTOOL_A_CABLE_TEST_UNSPEC]	= { .type = NLA_REJECT },
-	[ETHTOOL_A_CABLE_TEST_DEV]		= { .type = NLA_NESTED },
+	[ETHTOOL_A_CABLE_TEST_DEV]	= { .type = NLA_NESTED },
+	[ETHTOOL_A_CABLE_TEST_AMPLITUDE_GRAPH] = { .type = NLA_FLAG },
 };
 
 void ethnl_cable_test_notify(struct net_device *dev,
@@ -418,6 +419,7 @@  void ethnl_cable_test_notify(struct net_device *dev,
 int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)
 {
 	struct nlattr *tb[ETHTOOL_A_CABLE_TEST_MAX + 1];
+	int options = 0;
 	struct net_device *dev;
 	int ret;
 
@@ -435,12 +437,16 @@  int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)
 	if (!dev->phydev)
 		goto out_dev;
 
+	if (tb[ETHTOOL_A_CABLE_TEST_AMPLITUDE_GRAPH])
+		options = PHY_CABLE_TEST_AMPLITUDE_GRAPH;
+
 	rtnl_lock();
 	ret = ethnl_before_ops(dev);
 	if (ret < 0)
 		goto out_rtnl;
 
-	ret = phy_start_cable_test(dev->phydev, info->extack, info->snd_seq);
+	ret = phy_start_cable_test(dev->phydev, info->extack, info->snd_seq,
+				   options);
 
 	ethnl_after_ops(dev);