[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241203124323.155866-5-maxime.chevallier@bootlin.com>
Date: Tue, 3 Dec 2024 13:43:15 +0100
From: Maxime Chevallier <maxime.chevallier@...tlin.com>
To: davem@...emloft.net,
Andrew Lunn <andrew@...n.ch>,
Jakub Kicinski <kuba@...nel.org>,
Eric Dumazet <edumazet@...gle.com>,
Paolo Abeni <pabeni@...hat.com>,
Russell King <linux@...linux.org.uk>,
Christophe Leroy <christophe.leroy@...roup.eu>,
Heiner Kallweit <hkallweit1@...il.com>
Cc: Maxime Chevallier <maxime.chevallier@...tlin.com>,
netdev@...r.kernel.org,
linux-kernel@...r.kernel.org,
thomas.petazzoni@...tlin.com,
Simon Horman <horms@...nel.org>,
Herve Codina <herve.codina@...tlin.com>,
Uwe Kleine-König <u.kleine-koenig@...libre.com>,
linuxppc-dev@...ts.ozlabs.org
Subject: [PATCH net-next v3 04/10] net: freescale: ucc_geth: Fix WOL configuration
The get/set_wol ethtool ops rely on querying the PHY for its WoL
capabilities, checking for the presence of a PHY and a PHY interrupts
isn't enough. Address that by cleaning up the WoL configuration
sequence.
Signed-off-by: Maxime Chevallier <maxime.chevallier@...tlin.com>
---
V3: No changes
drivers/net/ethernet/freescale/ucc_geth.c | 4 +--
drivers/net/ethernet/freescale/ucc_geth.h | 1 +
.../net/ethernet/freescale/ucc_geth_ethtool.c | 36 +++++++++++++++----
3 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index cc5f9ca42a78..587bcbc079da 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -3413,11 +3413,11 @@ static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
*/
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
- if (ugeth->wol_en & WAKE_MAGIC) {
+ if (ugeth->wol_en & WAKE_MAGIC && !ugeth->phy_wol_en) {
setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX);
- } else if (!(ugeth->wol_en & WAKE_PHY)) {
+ } else if (!ugeth->phy_wol_en) {
phy_stop(ndev->phydev);
}
diff --git a/drivers/net/ethernet/freescale/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h
index c08a56b7c9fe..e08cfc8d8904 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.h
+++ b/drivers/net/ethernet/freescale/ucc_geth.h
@@ -1217,6 +1217,7 @@ struct ucc_geth_private {
int oldduplex;
int oldlink;
int wol_en;
+ u32 phy_wol_en;
struct device_node *node;
};
diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index fb5254d7d1ba..89b323ef8145 100644
--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
@@ -346,26 +346,48 @@ static void uec_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct ucc_geth_private *ugeth = netdev_priv(netdev);
struct phy_device *phydev = netdev->phydev;
- if (phydev && phydev->irq)
- wol->supported |= WAKE_PHY;
+ wol->supported = 0;
+ wol->wolopts = 0;
+
+ if (phydev)
+ phy_ethtool_get_wol(phydev, wol);
+
if (qe_alive_during_sleep())
wol->supported |= WAKE_MAGIC;
- wol->wolopts = ugeth->wol_en;
+ wol->wolopts |= ugeth->wol_en;
}
static int uec_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
struct phy_device *phydev = netdev->phydev;
+ int ret = 0;
- if (wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
- return -EINVAL;
- else if (wol->wolopts & WAKE_PHY && (!phydev || !phydev->irq))
+ if (phydev) {
+ ret = phy_ethtool_set_wol(phydev, wol);
+ if (ret == -EOPNOTSUPP) {
+ ugeth->phy_wol_en = 0;
+ } else if (ret) {
+ return ret;
+ } else {
+ ugeth->phy_wol_en = wol->wolopts;
+ goto out;
+ }
+ }
+
+ /* If the PHY isn't handling the WoL and the MAC is asked to more than
+ * WAKE_MAGIC, error-out
+ */
+ if (!ugeth->phy_wol_en &&
+ wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;
- else if (wol->wolopts & WAKE_MAGIC && !qe_alive_during_sleep())
+
+ if (wol->wolopts & WAKE_MAGIC &&
+ !qe_alive_during_sleep())
return -EINVAL;
+out:
ugeth->wol_en = wol->wolopts;
device_set_wakeup_enable(&netdev->dev, ugeth->wol_en);
--
2.47.0
Powered by blists - more mailing lists