* [PATCH RFC net-next 1/3] net: phylink: add config of PHY receive clock-stop in phylink_resume()
2025-03-04 10:53 [PATCH RFC net-next 0/3] net: stmmac: approach 2 to solve EEE LPI reset issues Russell King (Oracle)
@ 2025-03-04 10:53 ` Russell King (Oracle)
2025-03-04 10:53 ` [PATCH RFC net-next 2/3] net: phylink: add functions to block/unblock rx clock stop Russell King (Oracle)
2025-03-04 10:53 ` [PATCH RFC net-next 3/3] net: stmmac: block PHY rx clock-stop over reset Russell King (Oracle)
2 siblings, 0 replies; 4+ messages in thread
From: Russell King (Oracle) @ 2025-03-04 10:53 UTC (permalink / raw)
To: Jon Hunter, Thierry Reding, Lad, Prabhakar
Cc: Alexandre Torgue, Andrew Lunn, Andrew Lunn, David S. Miller,
Eric Dumazet, Heiner Kallweit, Jakub Kicinski, linux-arm-kernel,
linux-stm32, Maxime Coquelin, netdev, Paolo Abeni
Add configuration of the receive clock-stop in phylink_resume() to
ensure that the clock-stop is correctly configured.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phylink.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a3b186ab3854..0aae0bb2a254 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -2264,7 +2264,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
pl->mac_tx_clk_stop = phy_eee_tx_clock_stop_capable(phy) > 0;
if (pl->mac_supports_eee_ops) {
- /* Explicitly configure whether the PHY is allowed to stop it's
+ /* Explicitly configure whether the PHY is allowed to stop its
* receive clock.
*/
ret = phy_eee_rx_clock_stop(phy,
@@ -2645,8 +2645,22 @@ EXPORT_SYMBOL_GPL(phylink_suspend);
*/
void phylink_resume(struct phylink *pl)
{
+ int ret;
+
ASSERT_RTNL();
+ if (pl->mac_supports_eee_ops && pl->phydev) {
+ /* Explicitly configure whether the PHY is allowed to stop its
+ * receive clock on resume to ensure that it is correctly
+ * configured.
+ */
+ ret = phy_eee_rx_clock_stop(pl->phydev,
+ pl->config->eee_rx_clk_stop_enable);
+ if (ret == -EOPNOTSUPP)
+ phylink_warn(pl, "failed to set rx clock stop: %pe\n",
+ ERR_PTR(ret));
+ }
+
if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
/* Wake-on-Lan enabled, MAC handling */
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH RFC net-next 2/3] net: phylink: add functions to block/unblock rx clock stop
2025-03-04 10:53 [PATCH RFC net-next 0/3] net: stmmac: approach 2 to solve EEE LPI reset issues Russell King (Oracle)
2025-03-04 10:53 ` [PATCH RFC net-next 1/3] net: phylink: add config of PHY receive clock-stop in phylink_resume() Russell King (Oracle)
@ 2025-03-04 10:53 ` Russell King (Oracle)
2025-03-04 10:53 ` [PATCH RFC net-next 3/3] net: stmmac: block PHY rx clock-stop over reset Russell King (Oracle)
2 siblings, 0 replies; 4+ messages in thread
From: Russell King (Oracle) @ 2025-03-04 10:53 UTC (permalink / raw)
To: Jon Hunter, Thierry Reding, Lad, Prabhakar
Cc: Alexandre Torgue, Andrew Lunn, Andrew Lunn, David S. Miller,
Eric Dumazet, Heiner Kallweit, Jakub Kicinski, linux-arm-kernel,
linux-stm32, Maxime Coquelin, netdev, Paolo Abeni
Some MACs require the PHY receive clock to be running to complete setup
actions. This may fail if the PHY has negotiated EEE, the MAC supports
receive clock stop, and the link has entered LPI state. Provide a pair
of APIs that MAC drivers can use to temporarily block the PHY disabling
the receive clock.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phylink.c | 62 +++++++++++++++++++++++++++++++--------
include/linux/phylink.h | 3 ++
2 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 0aae0bb2a254..9a62808cf935 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -88,6 +88,7 @@ struct phylink {
bool mac_enable_tx_lpi;
bool mac_tx_clk_stop;
u32 mac_tx_lpi_timer;
+ u8 mac_rx_clk_stop_blocked;
struct sfp_bus *sfp_bus;
bool sfp_may_have_phy;
@@ -2592,6 +2593,55 @@ void phylink_stop(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_stop);
+
+void phylink_rx_clk_stop_block(struct phylink *pl)
+{
+ ASSERT_RTNL();
+
+ if (pl->mac_rx_clk_stop_blocked == U8_MAX) {
+ phylink_warn(pl, "%s called too many times - ignoring\n",
+ __func__);
+ dump_stack();
+ return;
+ }
+
+ /* Disable PHY receive clock stop if this is the first time this
+ * function has been called and clock-stop was previously enabled.
+ */
+ if (pl->mac_rx_clk_stop_blocked++ == 0 &&
+ pl->mac_supports_eee_ops && pl->phydev)
+ pl->config->eee_rx_clk_stop_enable)
+ phy_eee_rx_clock_stop(pl->phydev, false);
+}
+
+/**
+ * phylink_rx_clk_stop_unblock() - unblock PHY ability to stop receive clock
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * All calls to phylink_rx_clk_stop_block() must be balanced with a
+ * corresponding call to phylink_rx_clk_stop_unblock() to restore the PHYs
+ * clock stop ability.
+ */
+void phylink_rx_clk_stop_unblock(struct phylink *pl)
+{
+ ASSERT_RTNL();
+
+ if (pl->mac_rx_clk_stop_blocked == 0) {
+ phylink_warn(pl, "%s called too many times - ignoring\n",
+ __func__);
+ dump_stack();
+ return;
+ }
+
+ /* Re-enable PHY receive clock stop if the number of unblocks matches
+ * the number of calls to the block function above.
+ */
+ if (--pl->mac_rx_clk_stop_blocked == 0 &&
+ pl->mac_supports_eee_ops && pl->phydev &&
+ pl->config->eee_rx_clk_stop_enable)
+ phy_eee_rx_clock_stop(pl->phydev, true);
+}
+
/**
* phylink_suspend() - handle a network device suspend event
* @pl: a pointer to a &struct phylink returned from phylink_create()
@@ -2649,18 +2699,6 @@ void phylink_resume(struct phylink *pl)
ASSERT_RTNL();
- if (pl->mac_supports_eee_ops && pl->phydev) {
- /* Explicitly configure whether the PHY is allowed to stop its
- * receive clock on resume to ensure that it is correctly
- * configured.
- */
- ret = phy_eee_rx_clock_stop(pl->phydev,
- pl->config->eee_rx_clk_stop_enable);
- if (ret == -EOPNOTSUPP)
- phylink_warn(pl, "failed to set rx clock stop: %pe\n",
- ERR_PTR(ret));
- }
-
if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
/* Wake-on-Lan enabled, MAC handling */
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 08df65f6867a..249c437d6b7b 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -698,6 +698,9 @@ int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs);
void phylink_start(struct phylink *);
void phylink_stop(struct phylink *);
+void phylink_rx_clk_stop_block(struct phylink *);
+void phylink_rx_clk_stop_unblock(struct phylink *);
+
void phylink_suspend(struct phylink *pl, bool mac_wol);
void phylink_resume(struct phylink *pl);
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH RFC net-next 3/3] net: stmmac: block PHY rx clock-stop over reset
2025-03-04 10:53 [PATCH RFC net-next 0/3] net: stmmac: approach 2 to solve EEE LPI reset issues Russell King (Oracle)
2025-03-04 10:53 ` [PATCH RFC net-next 1/3] net: phylink: add config of PHY receive clock-stop in phylink_resume() Russell King (Oracle)
2025-03-04 10:53 ` [PATCH RFC net-next 2/3] net: phylink: add functions to block/unblock rx clock stop Russell King (Oracle)
@ 2025-03-04 10:53 ` Russell King (Oracle)
2 siblings, 0 replies; 4+ messages in thread
From: Russell King (Oracle) @ 2025-03-04 10:53 UTC (permalink / raw)
To: Jon Hunter, Thierry Reding, Lad, Prabhakar
Cc: Alexandre Torgue, Andrew Lunn, Andrew Lunn, David S. Miller,
Eric Dumazet, Heiner Kallweit, Jakub Kicinski, linux-arm-kernel,
linux-stm32, Maxime Coquelin, netdev, Paolo Abeni
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index aec230353ac4..21026ea7541c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3097,7 +3097,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
priv->plat->dma_cfg->atds = 1;
+ /* Note that the PHY clock must be running for reset to complete. */
+ phylink_rx_clk_stop_block(priv->phylink);
ret = stmmac_reset(priv, priv->ioaddr);
+ phylink_rx_clk_stop_unblock(priv->phylink);
if (ret) {
netdev_err(priv->dev, "Failed to reset the dma\n");
return ret;
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread