net: ethtool: Add helpers for cable test TDR data
authorAndrew Lunn <andrew@lunn.ch>
Tue, 26 May 2020 22:21:39 +0000 (00:21 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 27 May 2020 06:22:20 +0000 (23:22 -0700)
Add helpers for returning raw TDR helpers in netlink messages.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/ethtool_netlink.h
net/ethtool/cabletest.c

index 24817ba..8fbe4f9 100644 (file)
@@ -22,6 +22,10 @@ void ethnl_cable_test_free(struct phy_device *phydev);
 void ethnl_cable_test_finished(struct phy_device *phydev);
 int ethnl_cable_test_result(struct phy_device *phydev, u8 pair, u8 result);
 int ethnl_cable_test_fault_length(struct phy_device *phydev, u8 pair, u32 cm);
+int ethnl_cable_test_amplitude(struct phy_device *phydev, u8 pair, s16 mV);
+int ethnl_cable_test_pulse(struct phy_device *phydev, u16 mV);
+int ethnl_cable_test_step(struct phy_device *phydev, u32 first, u32 last,
+                         u32 step);
 #else
 static inline int ethnl_cable_test_alloc(struct phy_device *phydev, u8 cmd)
 {
@@ -46,5 +50,22 @@ static inline int ethnl_cable_test_fault_length(struct phy_device *phydev,
 {
        return -EOPNOTSUPP;
 }
+
+static inline int ethnl_cable_test_amplitude(struct phy_device *phydev,
+                                            u8 pair, s16 mV)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int ethnl_cable_test_pulse(struct phy_device *phydev, u16 mV)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int ethnl_cable_test_step(struct phy_device *phydev, u32 first,
+                                       u32 last, u32 step)
+{
+       return -EOPNOTSUPP;
+}
 #endif /* IS_ENABLED(ETHTOOL_NETLINK) */
 #endif /* _LINUX_ETHTOOL_NETLINK_H_ */
index 94e9d5f..390d067 100644 (file)
@@ -100,7 +100,10 @@ int ethnl_cable_test_alloc(struct phy_device *phydev, u8 cmd)
 {
        int err = -ENOMEM;
 
-       phydev->skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+       /* One TDR sample occupies 20 bytes. For a 150 meter cable,
+        * with four pairs, around 12K is needed.
+        */
+       phydev->skb = genlmsg_new(SZ_16K, GFP_KERNEL);
        if (!phydev->skb)
                goto out;
 
@@ -251,3 +254,78 @@ out_dev_put:
        dev_put(dev);
        return ret;
 }
+int ethnl_cable_test_amplitude(struct phy_device *phydev,
+                              u8 pair, s16 mV)
+{
+       struct nlattr *nest;
+       int ret = -EMSGSIZE;
+
+       nest = nla_nest_start(phydev->skb,
+                             ETHTOOL_A_CABLE_TDR_NEST_AMPLITUDE);
+       if (!nest)
+               return -EMSGSIZE;
+
+       if (nla_put_u8(phydev->skb, ETHTOOL_A_CABLE_AMPLITUDE_PAIR, pair))
+               goto err;
+       if (nla_put_u16(phydev->skb, ETHTOOL_A_CABLE_AMPLITUDE_mV, mV))
+               goto err;
+
+       nla_nest_end(phydev->skb, nest);
+       return 0;
+
+err:
+       nla_nest_cancel(phydev->skb, nest);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ethnl_cable_test_amplitude);
+
+int ethnl_cable_test_pulse(struct phy_device *phydev, u16 mV)
+{
+       struct nlattr *nest;
+       int ret = -EMSGSIZE;
+
+       nest = nla_nest_start(phydev->skb, ETHTOOL_A_CABLE_TDR_NEST_PULSE);
+       if (!nest)
+               return -EMSGSIZE;
+
+       if (nla_put_u16(phydev->skb, ETHTOOL_A_CABLE_PULSE_mV, mV))
+               goto err;
+
+       nla_nest_end(phydev->skb, nest);
+       return 0;
+
+err:
+       nla_nest_cancel(phydev->skb, nest);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ethnl_cable_test_pulse);
+
+int ethnl_cable_test_step(struct phy_device *phydev, u32 first, u32 last,
+                         u32 step)
+{
+       struct nlattr *nest;
+       int ret = -EMSGSIZE;
+
+       nest = nla_nest_start(phydev->skb, ETHTOOL_A_CABLE_TDR_NEST_STEP);
+       if (!nest)
+               return -EMSGSIZE;
+
+       if (nla_put_u32(phydev->skb, ETHTOOL_A_CABLE_STEP_FIRST_DISTANCE,
+                       first))
+               goto err;
+
+       if (nla_put_u32(phydev->skb, ETHTOOL_A_CABLE_STEP_LAST_DISTANCE, last))
+               goto err;
+
+       if (nla_put_u32(phydev->skb, ETHTOOL_A_CABLE_STEP_STEP_DISTANCE, step))
+               goto err;
+
+       nla_nest_end(phydev->skb, nest);
+       return 0;
+
+err:
+       nla_nest_cancel(phydev->skb, nest);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ethnl_cable_test_step);