summaryrefslogtreecommitdiff
path: root/drivers/net/phy/phy.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2020-05-10 21:12:36 +0200
committerJakub Kicinski <kuba@kernel.org>2020-05-10 12:28:41 -0700
commit1dd3f212af30b42c90ba252c165f2f6d2ddf5230 (patch)
treede9a4697a11d2968403b1de30b5f00a8974941d8 /drivers/net/phy/phy.c
parent0df960f14e17e55e68dfd1342f063d17dbcc6107 (diff)
net: ethtool: Add infrastructure for reporting cable test results
Provide infrastructure for PHY drivers to report the cable test results. A netlink skb is associated to the phydev. Helpers will be added which can add results to this skb. Once the test has finished the results are sent to user space. When netlink ethtool is not part of the kernel configuration stubs are provided. It is also impossible to trigger a cable test, so the error code returned by the alloc function is of no consequence. v2: Include the status complete in the netlink notification message v4: Replace -EINVAL with -EMSGSIZE Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Michal Kubecek <mkubecek@suse.cz> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 9fa61019533f..afdc1c2146ee 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
+#include <linux/ethtool_netlink.h>
#include <linux/phy.h>
#include <linux/phy_led_triggers.h>
#include <linux/sfp.h>
@@ -30,6 +31,9 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+#include <net/sock.h>
#define PHY_STATE_TIME HZ
@@ -478,6 +482,8 @@ static void phy_abort_cable_test(struct phy_device *phydev)
{
int err;
+ ethnl_cable_test_finished(phydev);
+
err = phy_init_hw(phydev);
if (err)
phydev_err(phydev, "Error while aborting cable test");
@@ -486,7 +492,7 @@ static void phy_abort_cable_test(struct phy_device *phydev)
int phy_start_cable_test(struct phy_device *phydev,
struct netlink_ext_ack *extack)
{
- int err;
+ int err = -ENOMEM;
if (!(phydev->drv &&
phydev->drv->cable_test_start &&
@@ -512,19 +518,30 @@ int phy_start_cable_test(struct phy_device *phydev,
goto out;
}
+ err = ethnl_cable_test_alloc(phydev);
+ if (err)
+ goto out;
+
/* Mark the carrier down until the test is complete */
phy_link_down(phydev, true);
err = phydev->drv->cable_test_start(phydev);
if (err) {
phy_link_up(phydev);
- goto out;
+ goto out_free;
}
phydev->state = PHY_CABLETEST;
if (phy_polling_mode(phydev))
phy_trigger_machine(phydev);
+
+ mutex_unlock(&phydev->lock);
+
+ return 0;
+
+out_free:
+ ethnl_cable_test_free(phydev);
out:
mutex_unlock(&phydev->lock);
@@ -964,6 +981,7 @@ void phy_state_machine(struct work_struct *work)
}
if (finished) {
+ ethnl_cable_test_finished(phydev);
needs_aneg = true;
phydev->state = PHY_UP;
}