From patchwork Sat May 9 16:28:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 219554 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4ED7BC28CBC for ; Sat, 9 May 2020 16:29:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 23C1D2063A for ; Sat, 9 May 2020 16:29:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=lunn.ch header.i=@lunn.ch header.b="aTWTw8oH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728340AbgEIQ30 (ORCPT ); Sat, 9 May 2020 12:29:26 -0400 Received: from vps0.lunn.ch ([185.16.172.187]:50980 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726214AbgEIQ3Y (ORCPT ); Sat, 9 May 2020 12:29:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=MXAkb6n8ox0CNUdGt+lWSjswMEnZ+Ow9tJWz5wEE7nU=; b=aTWTw8oHHVEOc2O9mmqgTMnK6U ZX2hKbqwHjF+BBvq79Felk2ZOlwgtFQO3ESNj0JksSxKWUZzM2OScj6FMztBnIGXyo1bIwymTotB2 J7SoRl7896jTT2H7zDQTDQQve0/TZO/xyYBRnLzKNhXANcQ71pcbLu6L4ziK1OvjnXIw=; Received: from andrew by vps0.lunn.ch with local (Exim 4.93) (envelope-from ) id 1jXSLc-001WH6-0F; Sat, 09 May 2020 18:29:08 +0200 From: Andrew Lunn To: David Miller Cc: netdev , Florian Fainelli , Heiner Kallweit , Chris Healy , Michal Kubecek , michael@walle.cc, Andrew Lunn Subject: [PATCH net-next v3 01/10] net: phy: Add cable test support to state machine Date: Sat, 9 May 2020 18:28:42 +0200 Message-Id: <20200509162851.362346-2-andrew@lunn.ch> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200509162851.362346-1-andrew@lunn.ch> References: <20200509162851.362346-1-andrew@lunn.ch> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Running a cable test is desruptive to normal operation of the PHY and can take a 5 to 10 seconds to complete. The RTNL lock cannot be held for this amount of time, and add a new state to the state machine for running a cable test. The driver is expected to implement two functions. The first is used to start a cable test. Once the test has started, it should return. The second function is called once per second, or on interrupt to check if the cable test is complete, and to allow the PHY to report the status. v2: Rename phy_cable_test_abort to phy_abort_cable_test Return different extack when already running test Use phy_init_hw() to reset the PHY Reviewed-by: Florian Fainelli Signed-off-by: Andrew Lunn --- drivers/net/phy/phy.c | 76 +++++++++++++++++++++++++++++++++++++++++++ include/linux/phy.h | 28 ++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 8c22d02b4218..0f4b27215429 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ static const char *phy_state_to_str(enum phy_state st) PHY_STATE_STR(UP) PHY_STATE_STR(RUNNING) PHY_STATE_STR(NOLINK) + PHY_STATE_STR(CABLETEST) PHY_STATE_STR(HALTED) } @@ -472,6 +474,62 @@ static void phy_trigger_machine(struct phy_device *phydev) phy_queue_state_machine(phydev, 0); } +static void phy_abort_cable_test(struct phy_device *phydev) +{ + int err; + + err = phy_init_hw(phydev); + if (err) + phydev_err(phydev, "Error while aborting cable test"); +} + +int phy_start_cable_test(struct phy_device *phydev, + struct netlink_ext_ack *extack) +{ + int err; + + if (!(phydev->drv && + phydev->drv->cable_test_start && + phydev->drv->cable_test_get_status)) { + NL_SET_ERR_MSG(extack, + "PHY driver does not support cable testing"); + return -EOPNOTSUPP; + } + + mutex_lock(&phydev->lock); + if (phydev->state == PHY_CABLETEST) { + NL_SET_ERR_MSG(extack, + "PHY already performing a test"); + err = -EBUSY; + goto out; + } + + if (phydev->state < PHY_UP || + phydev->state > PHY_CABLETEST) { + NL_SET_ERR_MSG(extack, + "PHY not configured. Try setting interface up"); + err = -EBUSY; + 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; + } + + phydev->state = PHY_CABLETEST; + +out: + mutex_unlock(&phydev->lock); + + return err; +} +EXPORT_SYMBOL(phy_start_cable_test); + static int phy_config_aneg(struct phy_device *phydev) { if (phydev->drv->config_aneg) @@ -810,6 +868,9 @@ void phy_stop(struct phy_device *phydev) mutex_lock(&phydev->lock); + if (phydev->state == PHY_CABLETEST) + phy_abort_cable_test(phydev); + if (phydev->sfp_bus) sfp_upstream_stop(phydev->sfp_bus); @@ -872,6 +933,7 @@ void phy_state_machine(struct work_struct *work) container_of(dwork, struct phy_device, state_queue); bool needs_aneg = false, do_suspend = false; enum phy_state old_state; + bool finished = false; int err = 0; mutex_lock(&phydev->lock); @@ -890,6 +952,20 @@ void phy_state_machine(struct work_struct *work) case PHY_RUNNING: err = phy_check_link_status(phydev); break; + case PHY_CABLETEST: + err = phydev->drv->cable_test_get_status(phydev, &finished); + if (err) { + phy_abort_cable_test(phydev); + needs_aneg = true; + phydev->state = PHY_UP; + break; + } + + if (finished) { + needs_aneg = true; + phydev->state = PHY_UP; + } + break; case PHY_HALTED: if (phydev->link) { phydev->link = 0; diff --git a/include/linux/phy.h b/include/linux/phy.h index a2b91b5f9d0a..632403fc34f4 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -372,6 +373,12 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); * - irq or timer will set NOLINK if link goes down * - phy_stop moves to HALTED * + * CABLETEST: PHY is performing a cable test. Packet reception/sending + * is not expected to work, carrier will be indicated as down. PHY will be + * poll once per second, or on interrupt for it current state. + * Once complete, move to UP to restart the PHY. + * - phy_stop aborts the running test and moves to HALTED + * * HALTED: PHY is up, but no polling or interrupts are done. Or * PHY is in an error state. * - phy_start moves to UP @@ -383,6 +390,7 @@ enum phy_state { PHY_UP, PHY_RUNNING, PHY_NOLINK, + PHY_CABLETEST, }; /** @@ -689,6 +697,13 @@ struct phy_driver { int (*module_eeprom)(struct phy_device *dev, struct ethtool_eeprom *ee, u8 *data); + /* Start a cable test */ + int (*cable_test_start)(struct phy_device *dev); + /* Once per second, or on interrupt, request the status of the + * test. + */ + int (*cable_test_get_status)(struct phy_device *dev, bool *finished); + /* Get statistics from the phy using ethtool */ int (*get_sset_count)(struct phy_device *dev); void (*get_strings)(struct phy_device *dev, u8 *data); @@ -1227,6 +1242,19 @@ int phy_speed_up(struct phy_device *phydev); int phy_restart_aneg(struct phy_device *phydev); 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); +#else +static inline +int phy_start_cable_test(struct phy_device *phydev, + struct netlink_ext_ack *extack) +{ + NL_SET_ERR_MSG(extack, "Kernel not compiled with PHYLIB support"); + return -EOPNOTSUPP; +} +#endif + static inline void phy_device_reset(struct phy_device *phydev, int value) { mdio_device_reset(&phydev->mdio, value); From patchwork Sat May 9 16:28:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 219555 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FA73C47247 for ; Sat, 9 May 2020 16:29:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 40D0D2063A for ; Sat, 9 May 2020 16:29:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=lunn.ch header.i=@lunn.ch header.b="ROOxDAQx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728285AbgEIQ3U (ORCPT ); Sat, 9 May 2020 12:29:20 -0400 Received: from vps0.lunn.ch ([185.16.172.187]:50950 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726214AbgEIQ3S (ORCPT ); Sat, 9 May 2020 12:29:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=yr1VwdDWOEpQrztcbRgaaPX0B8nGblzxM6jvpyonPGM=; b=ROOxDAQxBDoPU+38S/5gF6BhhH UjIKRUrScvOW0Z/F46VLr+hhnkWNSf/AfE3DQ71q6i3fyrT/tuIBPUraRwu5oA/ZKBdBMeZg6CY4g GFjwkpQoEY+u4YorBcDNqQiHwSu9DIGLkkYAAoz3R3tK3LcfzlsuMFTywd+KmMO6KSMg=; Received: from andrew by vps0.lunn.ch with local (Exim 4.93) (envelope-from ) id 1jXSLc-001WHB-1O; Sat, 09 May 2020 18:29:08 +0200 From: Andrew Lunn To: David Miller Cc: netdev , Florian Fainelli , Heiner Kallweit , Chris Healy , Michal Kubecek , michael@walle.cc, Andrew Lunn Subject: [PATCH net-next v3 02/10] net: phy: Add support for polling cable test Date: Sat, 9 May 2020 18:28:43 +0200 Message-Id: <20200509162851.362346-3-andrew@lunn.ch> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200509162851.362346-1-andrew@lunn.ch> References: <20200509162851.362346-1-andrew@lunn.ch> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Some PHYs are not capable of generating interrupts when a cable test finished. They do however support interrupts for normal operations, like link up/down. As such, the PHY state machine would normally not poll the PHY. Add support for indicating the PHY state machine must poll the PHY when performing a cable test. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli --- drivers/net/phy/phy.c | 2 ++ include/linux/phy.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 0f4b27215429..9fa61019533f 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -523,6 +523,8 @@ int phy_start_cable_test(struct phy_device *phydev, phydev->state = PHY_CABLETEST; + if (phy_polling_mode(phydev)) + phy_trigger_machine(phydev); out: mutex_unlock(&phydev->lock); diff --git a/include/linux/phy.h b/include/linux/phy.h index 632403fc34f4..f58eee735a45 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -79,6 +79,7 @@ extern const int phy_10gbit_features_array[1]; #define PHY_IS_INTERNAL 0x00000001 #define PHY_RST_AFTER_CLK_EN 0x00000002 +#define PHY_POLL_CABLE_TEST 0x00000004 #define MDIO_DEVICE_IS_PHY 0x80000000 /* Interface Mode definitions */ @@ -1061,6 +1062,10 @@ static inline bool phy_interrupt_is_valid(struct phy_device *phydev) */ static inline bool phy_polling_mode(struct phy_device *phydev) { + if (phydev->state == PHY_CABLETEST) + if (phydev->drv->flags & PHY_POLL_CABLE_TEST) + return true; + return phydev->irq == PHY_POLL; } From patchwork Sat May 9 16:28:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 219552 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8B6DC47247 for ; Sat, 9 May 2020 16:29:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C3B932063A for ; Sat, 9 May 2020 16:29:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=lunn.ch header.i=@lunn.ch header.b="lEqVTcno" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728388AbgEIQ3d (ORCPT ); Sat, 9 May 2020 12:29:33 -0400 Received: from vps0.lunn.ch ([185.16.172.187]:51020 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728309AbgEIQ3c (ORCPT ); Sat, 9 May 2020 12:29:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=fUJEBqKB3ZfzFlSbk8yHCH/KGszuTMxp7o/M3pYM6R0=; b=lEqVTcnogcB8suW7t4oF1D4PcE U3RfGU7is7+5z881hCBu9Hrb0tsADYMPdSQAyrSCkFvOl6NPXrdxEwOOUNyHoJw9RuWXAFRzJct2s GmlBcajCrEJqILE9SwZq1ah0pZr/ohpMHq9kgV48DbyTNha3Z0AHBSTEovYAzPH83g2w=; Received: from andrew by vps0.lunn.ch with local (Exim 4.93) (envelope-from ) id 1jXSLc-001WHL-3N; Sat, 09 May 2020 18:29:08 +0200 From: Andrew Lunn To: David Miller Cc: netdev , Florian Fainelli , Heiner Kallweit , Chris Healy , Michal Kubecek , michael@walle.cc, Andrew Lunn Subject: [PATCH net-next v3 04/10] net: ethtool: Add attributes for cable test reports Date: Sat, 9 May 2020 18:28:45 +0200 Message-Id: <20200509162851.362346-5-andrew@lunn.ch> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200509162851.362346-1-andrew@lunn.ch> References: <20200509162851.362346-1-andrew@lunn.ch> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add the attributes needed to report cable test results to userspace. The reports are expected to be per twisted pair. A nested property per pair can report the result of the cable test. A nested property can also report the length of the cable to any fault. v2: Grammar fixes Change length from u16 to u32 s/DEV/HEADER/g Add status attributes Rename pairs from numbers to letters. v3: Fixed example in document Add ETHTOOL_A_CABLE_NEST_* enum Add ETHTOOL_MSG_CABLE_TEST_NTF to documentation Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli --- Documentation/networking/ethtool-netlink.rst | 41 +++++++++++++ include/uapi/linux/ethtool_netlink.h | 60 +++++++++++++++++++- 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index a8731d33d0c9..eed46b6aa07d 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -236,6 +236,7 @@ Kernel to userspace: ``ETHTOOL_MSG_EEE_GET_REPLY`` EEE settings ``ETHTOOL_MSG_EEE_NTF`` EEE settings ``ETHTOOL_MSG_TSINFO_GET_REPLY`` timestamping info + ``ETHTOOL_MSG_CABLE_TEST_NTF`` Cable test results ===================================== ================================= ``GET`` requests are sent by userspace applications to retrieve device @@ -970,6 +971,46 @@ Request contents: ``ETHTOOL_A_CABLE_TEST_HEADER`` nested request header ==================================== ====== ========================== +Notification contents: + +An Ethernet cable typically contains 1, 2 or 4 pairs. The length of +the pair can only be measured when there is a fault in the pair and +hence a reflection. Information about the fault may not be available, +depending on the specific hardware. Hence the contents of the notify +message are mostly optional. The attributes can be repeated an +arbitrary number of times, in an arbitrary order, for an arbitrary +number of pairs. + +The example shows the notification sent when the test is completed for +a T2 cable, i.e. two pairs. One pair is OK and hence has no length +information. The second pair has a fault and does have length +information. + + +---------------------------------------------+--------+---------------------+ + | ``ETHTOOL_A_CABLE_TEST_HEADER`` | nested | reply header | + +---------------------------------------------+--------+---------------------+ + | ``ETHTOOL_A_CABLE_TEST_STATUS`` | u8 | completed | + +---------------------------------------------+--------+---------------------+ + | ``ETHTOOL_A_CABLE_TEST_NTF_NEST`` | nested | all the results | + +-+-------------------------------------------+--------+---------------------+ + | | ``ETHTOOL_A_CABLE_NEST_RESULT`` | nested | cable test result | + +-+-+-----------------------------------------+--------+---------------------+ + | | | ``ETHTOOL_A_CABLE_RESULTS_PAIR`` | u8 | pair number | + +-+-+-----------------------------------------+--------+---------------------+ + | | | ``ETHTOOL_A_CABLE_RESULTS_CODE`` | u8 | result code | + +-+-+-----------------------------------------+--------+---------------------+ + | | ``ETHTOOL_A_CABLE_NEST_RESULT`` | nested | cable test results | + +-+-+-----------------------------------------+--------+---------------------+ + | | | ``ETHTOOL_A_CABLE_RESULTS_PAIR`` | u8 | pair number | + +-+-+-----------------------------------------+--------+---------------------+ + | | | ``ETHTOOL_A_CABLE_RESULTS_CODE`` | u8 | result code | + +-+-+-----------------------------------------+--------+---------------------+ + | | ``ETHTOOL_A_CABLE_NEST_FAULT_LENGTH`` | nested | cable length | + +-+-+-----------------------------------------+--------+---------------------+ + | | | ``ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR`` | u8 | pair number | + +-+-+-----------------------------------------+--------+---------------------+ + | | | ``ETHTOOL_A_CABLE_FAULT_LENGTH_CM`` | u32 | length in cm | + +-+-+-----------------------------------------+--------+---------------------+ Request translation =================== diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 48bb3a23b3fa..2881af411f76 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -75,6 +75,7 @@ enum { ETHTOOL_MSG_EEE_GET_REPLY, ETHTOOL_MSG_EEE_NTF, ETHTOOL_MSG_TSINFO_GET_REPLY, + ETHTOOL_MSG_CABLE_TEST_NTF, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -404,7 +405,6 @@ enum { /* add new constants above here */ __ETHTOOL_A_TSINFO_CNT, ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1) - }; /* CABLE TEST */ @@ -418,6 +418,64 @@ enum { ETHTOOL_A_CABLE_TEST_MAX = __ETHTOOL_A_CABLE_TEST_CNT - 1 }; +/* CABLE TEST NOTIFY */ +enum { + ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC, + ETHTOOL_A_CABLE_RESULT_CODE_OK, + ETHTOOL_A_CABLE_RESULT_CODE_OPEN, + ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT, + ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT, +}; + +enum { + ETHTOOL_A_CABLE_PAIR_A, + ETHTOOL_A_CABLE_PAIR_B, + ETHTOOL_A_CABLE_PAIR_C, + ETHTOOL_A_CABLE_PAIR_D, +}; + +enum { + ETHTOOL_A_CABLE_RESULT_UNSPEC, + ETHTOOL_A_CABLE_RESULT_PAIR, /* u8 ETHTOOL_A_CABLE_PAIR_ */ + ETHTOOL_A_CABLE_RESULT_CODE, /* u8 ETHTOOL_A_CABLE_RESULT_CODE_ */ + + __ETHTOOL_A_CABLE_RESULT_CNT, + ETHTOOL_A_CABLE_RESULT_MAX = (__ETHTOOL_A_CABLE_RESULT_CNT - 1) +}; + +enum { + ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC, + ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR, /* u8 ETHTOOL_A_CABLE_PAIR_ */ + ETHTOOL_A_CABLE_FAULT_LENGTH_CM, /* u32 */ + + __ETHTOOL_A_CABLE_FAULT_LENGTH_CNT, + ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = (__ETHTOOL_A_CABLE_FAULT_LENGTH_CNT - 1) +}; + +enum { + ETHTOOL_A_CABLE_TEST_NTF_STATUS_UNSPEC, + ETHTOOL_A_CABLE_TEST_NTF_STATUS_STARTED, + ETHTOOL_A_CABLE_TEST_NTF_STATUS_COMPLETED +}; + +enum { + ETHTOOL_A_CABLE_NEST_UNSPEC, + ETHTOOL_A_CABLE_NEST_RESULT, /* nest - ETHTOOL_A_CABLE_RESULT_ */ + ETHTOOL_A_CABLE_NEST_FAULT_LENGTH, /* nest - ETHTOOL_A_CABLE_FAULT_LENGTH_ */ + __ETHTOOL_A_CABLE_NEST_CNT, + ETHTOOL_A_CABLE_NEST_MAX = (__ETHTOOL_A_CABLE_NEST_CNT - 1) +}; + +enum { + ETHTOOL_A_CABLE_TEST_NTF_UNSPEC, + ETHTOOL_A_CABLE_TEST_NTF_HEADER, /* nest - ETHTOOL_A_HEADER_* */ + ETHTOOL_A_CABLE_TEST_NTF_STATUS, /* u8 - _STARTED/_COMPLETE */ + ETHTOOL_A_CABLE_TEST_NTF_NEST, /* nest - of results: */ + + __ETHTOOL_A_CABLE_TEST_NTF_CNT, + ETHTOOL_A_CABLE_TEST_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_NTF_CNT - 1) +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 From patchwork Sat May 9 16:28:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 219553 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94F6AC54E49 for ; Sat, 9 May 2020 16:29:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7016A2063A for ; Sat, 9 May 2020 16:29:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=lunn.ch header.i=@lunn.ch header.b="2qGF4sjI" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728370AbgEIQ32 (ORCPT ); Sat, 9 May 2020 12:29:28 -0400 Received: from vps0.lunn.ch ([185.16.172.187]:50992 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728309AbgEIQ30 (ORCPT ); Sat, 9 May 2020 12:29:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=mC8/SK80C58CKYagFaziO4BM3EWmFL3KdX/575m3eyw=; b=2qGF4sjItdARAO11sDp4J2FzYK lPpwhdogxQW1apixf+oRXKi4GZiFysC064Tk+P30wmtDzK6uo5z+9MpGPDjHoeGET7Iso6xULAMWa rASt/VTvDFGYRvffAnnJJLrri7zKKir3JCzi1kGGPRXgKOD1MvlLtVXz6VZ+6e+JD/y4=; Received: from andrew by vps0.lunn.ch with local (Exim 4.93) (envelope-from ) id 1jXSLc-001WHf-79; Sat, 09 May 2020 18:29:08 +0200 From: Andrew Lunn To: David Miller Cc: netdev , Florian Fainelli , Heiner Kallweit , Chris Healy , Michal Kubecek , michael@walle.cc, Andrew Lunn Subject: [PATCH net-next v3 08/10] net: phy: marvell: Add cable test support Date: Sat, 9 May 2020 18:28:49 +0200 Message-Id: <20200509162851.362346-9-andrew@lunn.ch> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200509162851.362346-1-andrew@lunn.ch> References: <20200509162851.362346-1-andrew@lunn.ch> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The Marvell PHYs have a couple of different register sets for performing cable tests. Page 7 provides the simplest to use. v3: s/mavell/marvell/g Remove include of Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli --- drivers/net/phy/marvell.c | 201 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 7fc8e10c5f33..4bc7febf9248 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #define MII_MARVELL_MSCR_PAGE 0x02 #define MII_MARVELL_LED_PAGE 0x03 #define MII_MARVELL_MISC_TEST_PAGE 0x06 +#define MII_MARVELL_VCT7_PAGE 0x07 #define MII_MARVELL_WOL_PAGE 0x11 #define MII_M1011_IEVENT 0x13 @@ -162,6 +164,36 @@ #define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1 /* SGMII to copper */ #define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */ +#define MII_VCT7_PAIR_0_DISTANCE 0x10 +#define MII_VCT7_PAIR_1_DISTANCE 0x11 +#define MII_VCT7_PAIR_2_DISTANCE 0x12 +#define MII_VCT7_PAIR_3_DISTANCE 0x13 + +#define MII_VCT7_RESULTS 0x14 +#define MII_VCT7_RESULTS_PAIR3_MASK 0xf000 +#define MII_VCT7_RESULTS_PAIR2_MASK 0x0f00 +#define MII_VCT7_RESULTS_PAIR1_MASK 0x00f0 +#define MII_VCT7_RESULTS_PAIR0_MASK 0x000f +#define MII_VCT7_RESULTS_PAIR3_SHIFT 12 +#define MII_VCT7_RESULTS_PAIR2_SHIFT 8 +#define MII_VCT7_RESULTS_PAIR1_SHIFT 4 +#define MII_VCT7_RESULTS_PAIR0_SHIFT 0 +#define MII_VCT7_RESULTS_INVALID 0 +#define MII_VCT7_RESULTS_OK 1 +#define MII_VCT7_RESULTS_OPEN 2 +#define MII_VCT7_RESULTS_SAME_SHORT 3 +#define MII_VCT7_RESULTS_CROSS_SHORT 4 +#define MII_VCT7_RESULTS_BUSY 9 + +#define MII_VCT7_CTRL 0x15 +#define MII_VCT7_CTRL_RUN_NOW BIT(15) +#define MII_VCT7_CTRL_RUN_ANEG BIT(14) +#define MII_VCT7_CTRL_DISABLE_CROSS BIT(13) +#define MII_VCT7_CTRL_RUN_AFTER_BREAK_LINK BIT(12) +#define MII_VCT7_CTRL_IN_PROGRESS BIT(11) +#define MII_VCT7_CTRL_METERS BIT(10) +#define MII_VCT7_CTRL_CENTIMETERS 0 + #define LPA_PAUSE_FIBER 0x180 #define LPA_PAUSE_ASYM_FIBER 0x100 @@ -1658,6 +1690,163 @@ 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) +{ + int bmcr, bmsr, ret; + + /* If auto-negotiation is enabled, but not complete, the cable + * test never completes. So disable auto-neg. + */ + bmcr = phy_read(phydev, MII_BMCR); + if (bmcr < 0) + return bmcr; + + bmsr = phy_read(phydev, MII_BMSR); + + if (bmsr < 0) + return bmsr; + + if (bmcr & BMCR_ANENABLE) { + ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); + if (ret < 0) + return ret; + ret = genphy_soft_reset(phydev); + if (ret < 0) + return ret; + } + + /* If the link is up, allow it some time to go down */ + if (bmsr & BMSR_LSTATUS) + msleep(1500); + + return phy_write_paged(phydev, MII_MARVELL_VCT7_PAGE, + MII_VCT7_CTRL, + MII_VCT7_CTRL_RUN_NOW | + MII_VCT7_CTRL_CENTIMETERS); +} + +static int marvell_vct7_distance_to_length(int distance, bool meter) +{ + if (meter) + distance *= 100; + + return distance; +} + +static bool marvell_vct7_distance_valid(int result) +{ + switch (result) { + case MII_VCT7_RESULTS_OPEN: + case MII_VCT7_RESULTS_SAME_SHORT: + case MII_VCT7_RESULTS_CROSS_SHORT: + return true; + } + return false; +} + +static int marvell_vct7_report_length(struct phy_device *phydev, + int pair, bool meter) +{ + int length; + int ret; + + ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE, + MII_VCT7_PAIR_0_DISTANCE + pair); + if (ret < 0) + return ret; + + length = marvell_vct7_distance_to_length(ret, meter); + + ethnl_cable_test_fault_length(phydev, pair, length); + + return 0; +} + +static int marvell_vct7_cable_test_report_trans(int result) +{ + switch (result) { + case MII_VCT7_RESULTS_OK: + return ETHTOOL_A_CABLE_RESULT_CODE_OK; + case MII_VCT7_RESULTS_OPEN: + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; + case MII_VCT7_RESULTS_SAME_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; + case MII_VCT7_RESULTS_CROSS_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; + default: + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; + } +} + +static int marvell_vct7_cable_test_report(struct phy_device *phydev) +{ + int pair0, pair1, pair2, pair3; + bool meter; + int ret; + + ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE, + MII_VCT7_RESULTS); + if (ret < 0) + return ret; + + pair3 = (ret & MII_VCT7_RESULTS_PAIR3_MASK) >> + MII_VCT7_RESULTS_PAIR3_SHIFT; + pair2 = (ret & MII_VCT7_RESULTS_PAIR2_MASK) >> + MII_VCT7_RESULTS_PAIR2_SHIFT; + pair1 = (ret & MII_VCT7_RESULTS_PAIR1_MASK) >> + MII_VCT7_RESULTS_PAIR1_SHIFT; + pair0 = (ret & MII_VCT7_RESULTS_PAIR0_MASK) >> + MII_VCT7_RESULTS_PAIR0_SHIFT; + + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, + marvell_vct7_cable_test_report_trans(pair0)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, + marvell_vct7_cable_test_report_trans(pair1)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, + marvell_vct7_cable_test_report_trans(pair2)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, + marvell_vct7_cable_test_report_trans(pair3)); + + ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE, MII_VCT7_CTRL); + if (ret < 0) + return ret; + + meter = ret & MII_VCT7_CTRL_METERS; + + if (marvell_vct7_distance_valid(pair0)) + marvell_vct7_report_length(phydev, 0, meter); + if (marvell_vct7_distance_valid(pair1)) + marvell_vct7_report_length(phydev, 1, meter); + if (marvell_vct7_distance_valid(pair2)) + marvell_vct7_report_length(phydev, 2, meter); + if (marvell_vct7_distance_valid(pair3)) + marvell_vct7_report_length(phydev, 3, meter); + + return 0; +} + +static int marvell_vct7_cable_test_get_status(struct phy_device *phydev, + bool *finished) +{ + int ret; + + *finished = false; + + ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE, + MII_VCT7_CTRL); + + if (ret < 0) + return ret; + + if (!(ret & MII_VCT7_CTRL_IN_PROGRESS)) { + *finished = true; + + return marvell_vct7_cable_test_report(phydev); + } + + return 0; +} + #ifdef CONFIG_HWMON static int m88e1121_get_temp(struct phy_device *phydev, long *temp) { @@ -2353,6 +2542,7 @@ static struct phy_driver marvell_drivers[] = { .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "Marvell 88E1510", .features = PHY_GBIT_FIBRE_FEATURES, + .flags = PHY_POLL_CABLE_TEST, .probe = &m88e1510_probe, .config_init = &m88e1510_config_init, .config_aneg = &m88e1510_config_aneg, @@ -2372,12 +2562,15 @@ static struct phy_driver marvell_drivers[] = { .set_loopback = genphy_loopback, .get_tunable = m88e1011_get_tunable, .set_tunable = m88e1011_set_tunable, + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, }, { .phy_id = MARVELL_PHY_ID_88E1540, .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "Marvell 88E1540", /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, .probe = m88e1510_probe, .config_init = &marvell_config_init, .config_aneg = &m88e1510_config_aneg, @@ -2394,6 +2587,8 @@ static struct phy_driver marvell_drivers[] = { .get_stats = marvell_get_stats, .get_tunable = m88e1540_get_tunable, .set_tunable = m88e1540_set_tunable, + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, }, { .phy_id = MARVELL_PHY_ID_88E1545, @@ -2401,6 +2596,7 @@ static struct phy_driver marvell_drivers[] = { .name = "Marvell 88E1545", .probe = m88e1510_probe, /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, .config_init = &marvell_config_init, .config_aneg = &m88e1510_config_aneg, .read_status = &marvell_read_status, @@ -2416,6 +2612,8 @@ static struct phy_driver marvell_drivers[] = { .get_stats = marvell_get_stats, .get_tunable = m88e1540_get_tunable, .set_tunable = m88e1540_set_tunable, + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, }, { .phy_id = MARVELL_PHY_ID_88E3016, @@ -2442,6 +2640,7 @@ static struct phy_driver marvell_drivers[] = { .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "Marvell 88E6390", /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, .probe = m88e6390_probe, .config_init = &marvell_config_init, .config_aneg = &m88e6390_config_aneg, @@ -2458,6 +2657,8 @@ static struct phy_driver marvell_drivers[] = { .get_stats = marvell_get_stats, .get_tunable = m88e1540_get_tunable, .set_tunable = m88e1540_set_tunable, + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, }, }; From patchwork Sat May 9 16:28:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 219556 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6C6DEC47257 for ; Sat, 9 May 2020 16:29:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 46E002063A for ; Sat, 9 May 2020 16:29:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=lunn.ch header.i=@lunn.ch header.b="wano6lKa" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728238AbgEIQ3R (ORCPT ); Sat, 9 May 2020 12:29:17 -0400 Received: from vps0.lunn.ch ([185.16.172.187]:50918 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726214AbgEIQ3P (ORCPT ); Sat, 9 May 2020 12:29:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=y8WrBDCDpC/HTli4Cc2EZDrTMMb2e3/CK/gr9C1ti7E=; b=wano6lKaCoiNrKbudsjOOk0pBP pM+LSTfVX3xKSQ67D5wmL+0YztxDCbEWWsVUlThy8VUtMOA7dp4UMGY5XDkhJQAo4L7GlRaUM9RDH r8FEzdiXC1D0Q2nKtWI5w5+4Bak+atpEhTEZq1LWJbiAIo2kmafmhkh3MbUtEaNAajF8=; Received: from andrew by vps0.lunn.ch with local (Exim 4.93) (envelope-from ) id 1jXSLc-001WHk-88; Sat, 09 May 2020 18:29:08 +0200 From: Andrew Lunn To: David Miller Cc: netdev , Florian Fainelli , Heiner Kallweit , Chris Healy , Michal Kubecek , michael@walle.cc, Andrew Lunn Subject: [PATCH net-next v3 09/10] net: phy: Put interface into oper testing during cable test Date: Sat, 9 May 2020 18:28:50 +0200 Message-Id: <20200509162851.362346-10-andrew@lunn.ch> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200509162851.362346-1-andrew@lunn.ch> References: <20200509162851.362346-1-andrew@lunn.ch> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Since running a cable test is disruptive, put the interface into operative state testing while the test is running. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Reviewed-by: Michal Kubecek --- drivers/net/phy/phy.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index afdc1c2146ee..9bdc924eea83 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -492,6 +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) { + struct net_device *dev = phydev->attached_dev; int err = -ENOMEM; if (!(phydev->drv && @@ -525,8 +526,10 @@ int phy_start_cable_test(struct phy_device *phydev, /* Mark the carrier down until the test is complete */ phy_link_down(phydev, true); + netif_testing_on(dev); err = phydev->drv->cable_test_start(phydev); if (err) { + netif_testing_off(dev); phy_link_up(phydev); goto out_free; } @@ -879,6 +882,8 @@ EXPORT_SYMBOL(phy_free_interrupt); */ void phy_stop(struct phy_device *phydev) { + struct net_device *dev = phydev->attached_dev; + if (!phy_is_started(phydev)) { WARN(1, "called from state %s\n", phy_state_to_str(phydev->state)); @@ -887,8 +892,10 @@ void phy_stop(struct phy_device *phydev) mutex_lock(&phydev->lock); - if (phydev->state == PHY_CABLETEST) + if (phydev->state == PHY_CABLETEST) { phy_abort_cable_test(phydev); + netif_testing_off(dev); + } if (phydev->sfp_bus) sfp_upstream_stop(phydev->sfp_bus); @@ -950,6 +957,7 @@ void phy_state_machine(struct work_struct *work) struct delayed_work *dwork = to_delayed_work(work); struct phy_device *phydev = container_of(dwork, struct phy_device, state_queue); + struct net_device *dev = phydev->attached_dev; bool needs_aneg = false, do_suspend = false; enum phy_state old_state; bool finished = false; @@ -975,6 +983,7 @@ void phy_state_machine(struct work_struct *work) err = phydev->drv->cable_test_get_status(phydev, &finished); if (err) { phy_abort_cable_test(phydev); + netif_testing_off(dev); needs_aneg = true; phydev->state = PHY_UP; break; @@ -982,6 +991,7 @@ void phy_state_machine(struct work_struct *work) if (finished) { ethnl_cable_test_finished(phydev); + netif_testing_off(dev); needs_aneg = true; phydev->state = PHY_UP; }