From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E9D41C531FA for ; Fri, 24 Jul 2026 08:52:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=RXEn6DnJlp+z/3iwtjtL7o5DVxbThA9UIOkFBH/Ojxs=; b=qA8hXylUawosC9odTjEVwhmnKc Vubkget23leZLoA140VibQdYKIa0/s3WJ+4vWh/Et9udsPR7O2iDwBuJOkKP5DF4Uy7aF7IageJvw 3kkTKw3Aho0nkzK8rw5cIY7ckR2uTlRC54ofOVa3t4DAUfrYOfZMw0K3wvig7IAZPXh/2AifNpIJE F+muZixYeFNg9BQzGtEEzL8iSyTXXnOH4efC5IqT1gei7be4nktJj6Cz9xqX2rYAEPMxg75HhRzpF kyE106Sm2JErcx5MsP9V/z4acQahMFwbrB+sFOB8/xZ3NgTIyqYqExzjtGPYEmQkut5OZQd8Ky5rK K6DlxmpQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wnBe5-0000000Ft33-3D8N; Fri, 24 Jul 2026 08:52:41 +0000 Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wnBe3-0000000Ft2j-2yBc for linux-arm-kernel@lists.infradead.org; Fri, 24 Jul 2026 08:52:40 +0000 Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-845b6d9bf39so188908b3a.1 for ; Fri, 24 Jul 2026 01:52:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784883158; x=1785487958; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=RXEn6DnJlp+z/3iwtjtL7o5DVxbThA9UIOkFBH/Ojxs=; b=Gh4oaLZy+0ult8M7INKFp3r13Px7f+3k0LsvdOflZaQNHXivR0FXdp25lVi4rScf5B GtrW+EENQ+9M1gfLufQ8DmATalMhiuxKppiGEX6kehmU707SVkDC7fw/AcJEUJi8AsT1 5nOjDVJ/vMJFp8CHHx25I1gQkGnN0ZjWQ1FEm0hxCmBjs86u9NcF95DLQllXDS/+uHWc QC2kNIqo1hUdjdXgXddWYcL5ii3ixO3MOkaVMzZQut4o5iVJrmr/DRCLdVj+nLs8aml5 Y1KQAJ13hsyvhoSuXzryhstIhckYubCxQi6iB0Mk1AOoKKtXCUvX/5tckQ/HCw7MbXFV m2mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784883158; x=1785487958; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=RXEn6DnJlp+z/3iwtjtL7o5DVxbThA9UIOkFBH/Ojxs=; b=iLEXGNMszVFrrLKy6YPMcGv1pMKN6jwyRbA2Y1qv04r5sRFsA21qPKtOHIbdAYYVBy XTLRZb+/V3lev4npnYs9OibR+PoV4DXJZK1+/z7lS+lP3Ftl5bgG7+QoxTDHRW2T8xGH DCsLWepm0lj37e4T+eJBwhZ2Y4v68itk1+TouzDNnNGfzYLSEXO3ozlu9QjDlMP9QmyB +TZiyFsDOtHHgr9jonegqoZE/aM1z2gJDxrydTRaTAsTnAcKLfiaSfWl0gB//2p2UhL/ T63auYgZa/yeMNjK4IQvZlGB3ohnNzC6YlZOueH987cb4fXSf7U/zkvLzYJglbBiX7+d uI/w== X-Forwarded-Encrypted: i=1; AHgh+Rr9vlccQT3Zb2xVR9lW/yISJODQSWCbAxaTKfUC2n3sxl1rZrsCCTO2mnpuwDu0yeqNWLJy9vrqcU5zA4UedpZP@lists.infradead.org X-Gm-Message-State: AOJu0Yyz8YJiEmgoxVKnRFufv6mOCdVtoMLJWPxNgyz2NqZCR0Q/noNe htwrAOW1zYJTlRl/I7T/AL1jCbWBu7lDgNghTsKuR4Q8lCQ+bKbMPT9k X-Gm-Gg: AR+sD12SYejqbbUJLY57pN4CyHnF0IPmg73DDJfPy48yexMBm3TA+GNzL4QTRP3R88X QGkjkXMta8yaUyFIjwoETtgHauNo5QPURSk8y4f4QIarzREwbpguwUgQ0EKe6cb4yTDleRUaJDN 4Hgkvch4QdhNr3B59J2+S+oZLb9iPzno9VgUWNQxxz2ZlESvRFeTa2difZqDQe/Bq9GhcydUDhq Mad+YYKGQLcHgFtEwL75aLl/d7l61XbEWeYdPy0pPzIzVaNGnphDCjVkrx4QTlbAITjVx0kkQE8 Hctjv7Y0lE+6zAB/mvwCYKKVAiy98738Ft1JRjZneJM/c0J1GPugd2xdONc5BfEyOXAJvLsY1ZO G3wpTJ+WQJHRbc8U+J7m6zLu38F4UfvQmitkI2xJSgM0mlixFLX8ao5y+ntGWT9NW8GqA37aufL Ge X-Received: by 2002:a05:6a00:e89:b0:848:420a:9ce0 with SMTP id d2e1a72fcca58-84e2e8094aemr6572103b3a.6.1784883158018; Fri, 24 Jul 2026 01:52:38 -0700 (PDT) Received: from server227.. ([39.170.101.209]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84e17262e33sm4416793b3a.14.2026.07.24.01.52.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 01:52:37 -0700 (PDT) From: Zxyan Zhu To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Heiner Kallweit , Maxime Coquelin , Alexandre Torgue , Zxyan Zhu Subject: [PATCH net-next] net: phylink: add phylink_pcs_loopback() method for PCS loopback support Date: Fri, 24 Jul 2026 16:52:24 +0800 Message-Id: <20260724085224.3321663-1-zxyan0222@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260724_015239_787601_7D710827 X-CRM114-Status: GOOD ( 17.90 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add a pcs_loopback callback to struct phylink_pcs_ops to allow PCS devices to expose loopback capability. This is useful for MAC drivers running selftests on interfaces that use in-band signalling and have no external PHY device. The phylink_pcs_loopback() helper calls the PCS ops callback if available, and returns -EOPNOTSUPP for PCS devices that do not support loopback. In stmmac, use phylink_pcs_loopback() in stmmac_test_phy_loopback() and stmmac_selftest_run() when no phydev is present but a PCS with loopback support exists. This enables PHY loopback selftests on interfaces without an external PHY. Signed-off-by: Zxyan Zhu --- .../stmicro/stmmac/stmmac_selftests.c | 36 ++++++++++++++----- drivers/net/phy/phylink.c | 19 ++++++++++ include/linux/phylink.h | 16 +++++++++ 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index 29e824bd90ca..e6ac51018a65 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -377,20 +377,36 @@ static int stmmac_test_mac_loopback(struct stmmac_priv *priv) static int stmmac_test_phy_loopback(struct stmmac_priv *priv) { struct stmmac_packet_attrs attr = { }; + struct phylink_pcs *pcs; int ret; - if (!priv->dev->phydev) - return -EOPNOTSUPP; + if (priv->dev->phydev) { + ret = phy_loopback(priv->dev->phydev, true, 0); + if (ret) + return ret; - ret = phy_loopback(priv->dev->phydev, true, 0); - if (ret) + attr.dst = priv->dev->dev_addr; + ret = __stmmac_test_loopback(priv, &attr); + + phy_loopback(priv->dev->phydev, false, 0); return ret; + } - attr.dst = priv->dev->dev_addr; - ret = __stmmac_test_loopback(priv, &attr); + /* Use PCS loopback for interfaces without an external PHY. */ + pcs = priv->hw->phylink_pcs; + if (pcs) { + ret = phylink_pcs_loopback(pcs, true); + if (ret) + return ret; - phy_loopback(priv->dev->phydev, false, 0); - return ret; + attr.dst = priv->dev->dev_addr; + ret = __stmmac_test_loopback(priv, &attr); + + phylink_pcs_loopback(pcs, false); + return ret; + } + + return -EOPNOTSUPP; } static int stmmac_test_mmc(struct stmmac_priv *priv) @@ -1986,6 +2002,8 @@ void stmmac_selftest_run(struct net_device *dev, ret = -EOPNOTSUPP; if (dev->phydev) ret = phy_loopback(dev->phydev, true, 0); + else if (priv->hw->phylink_pcs) + ret = phylink_pcs_loopback(priv->hw->phylink_pcs, true); if (!ret) break; fallthrough; @@ -2019,6 +2037,8 @@ void stmmac_selftest_run(struct net_device *dev, ret = -EOPNOTSUPP; if (dev->phydev) ret = phy_loopback(dev->phydev, false, 0); + else if (priv->hw->phylink_pcs) + ret = phylink_pcs_loopback(priv->hw->phylink_pcs, false); if (!ret) break; fallthrough; diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 59dfe35afa54..a7f78c82913a 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -997,6 +997,25 @@ int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs) } EXPORT_SYMBOL_GPL(phylink_pcs_pre_init); +/** + * phylink_pcs_loopback() - Enable or disable loopback at the PCS + * @pcs: a pointer to a &struct phylink_pcs. + * @enable: true to enable loopback, false to disable + * + * Enable or disable loopback mode at the PCS level. This is used by MAC + * drivers for selftest purposes when no external PHY is present. + * + * Returns 0 on success, negative error code on failure. + */ +int phylink_pcs_loopback(struct phylink_pcs *pcs, bool enable) +{ + if (pcs->ops->pcs_loopback) + return pcs->ops->pcs_loopback(pcs, enable); + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL_GPL(phylink_pcs_loopback); + static void phylink_mac_config(struct phylink *pl, const struct phylink_link_state *state) { diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 2bc0db3d52ac..66c7016d4acd 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -518,6 +518,7 @@ struct phylink_pcs { * the MAC. * @pcs_pre_init: configure PCS components necessary for MAC hardware * initialization e.g. RX clock for stmmac. + * @pcs_loopback: enable/disable loopback mode at the PCS. */ struct phylink_pcs_ops { int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, @@ -542,6 +543,7 @@ struct phylink_pcs_ops { void (*pcs_disable_eee)(struct phylink_pcs *pcs); void (*pcs_enable_eee)(struct phylink_pcs *pcs); int (*pcs_pre_init)(struct phylink_pcs *pcs); + int (*pcs_loopback)(struct phylink_pcs *pcs, bool enable); }; #if 0 /* For kernel-doc purposes only. */ @@ -717,8 +719,22 @@ void pcs_enable_eee(struct phylink_pcs *pcs); */ int pcs_pre_init(struct phylink_pcs *pcs); +/** + * pcs_loopback() - Enable or disable loopback at the PCS + * @pcs: a pointer to a &struct phylink_pcs. + * @enable: true to enable loopback, false to disable + * + * Enable or disable loopback mode at the PCS level. This is used by MAC + * drivers for selftest purposes when no external PHY is present. + * + * Returns 0 on success, or a negative error code on failure. + */ +int pcs_loopback(struct phylink_pcs *pcs, bool enable); + #endif +int phylink_pcs_loopback(struct phylink_pcs *pcs, bool enable); + struct phylink *phylink_create(struct phylink_config *, const struct fwnode_handle *, phy_interface_t, base-commit: 1df10cef2d1e7f9f2fb7eddb67fc70d3abf101f9 -- 2.34.1