[PATCH net] net: phy: marvell: keep WOL_EIE across interrupt reconfiguration
From: Rosen Penev <hidden>
Date: 2026-09-17 22:01:40
Also in:
lkml
Subsystem:
ethernet phy library, networking drivers, the rest · Maintainers:
Andrew Lunn, Heiner Kallweit, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
On the 88E1318S/88E1510, copper page register 0x12 is both the
MII_M1011_IMASK interrupt mask used by marvell_config_intr() and the
CSIER register in which m88e1318_set_wol() arms the WoL interrupt
(MII_88E1318S_PHY_CSIER_WOL_EIE). marvell_config_intr() rewrote the
whole register, so any interrupt reconfiguration (for example the
phy_disable_interrupts() on link down behind mvneta) silently cleared
WOL_EIE: m88e1318_get_wol() still reported WAKE_MAGIC, but a matched
magic packet was no longer routed to INTn and the board did not wake.
Give these two PHYs a dedicated config_intr that preserves WOL_EIE with
a read-modify-write, and a handle_interrupt that also claims the WoL
event mirrored in the interrupt status register. Other Marvell PHYs keep
the plain marvell_config_intr()/marvell_handle_interrupt().
Fixes: 3871c3876f80 ("mv643xx_eth with 88E1318S: support Wake on LAN")
Assisted-by: LLM
Signed-off-by: Rosen Penev <redacted>
---
drivers/net/phy/marvell.c | 70 ++++++++++++++++++++++++++++++++++++---
1 file changed, 66 insertions(+), 4 deletions(-)
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index f71cffa88406..0897cfcd6ab7 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c@@ -425,6 +425,68 @@ static irqreturn_t marvell_handle_interrupt(struct phy_device *phydev) return IRQ_HANDLED; } +/* + * On the 88E1318S/88E1510, copper page register 0x12 serves two + * masters: it is the MII_M1011_IMASK interrupt mask for the generic + * Marvell interrupt handling, and m88e1318_set_wol() sets the WoL + * interrupt enable bit (MII_88E1318S_PHY_CSIER_WOL_EIE) in it. The + * interrupt routines below therefore preserve that bit, so reconfiguring + * the PHY interrupts cannot disarm Wake-on-LAN behind the user's back. + */ +static int m88e1318_config_intr(struct phy_device *phydev) +{ + int val, err; + + val = phy_read(phydev, MII_88E1318S_PHY_CSIER); + if (val < 0) + return val; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + err = marvell_ack_interrupt(phydev); + if (err < 0) + return err; + + err = phy_write(phydev, MII_88E1318S_PHY_CSIER, + MII_M1011_IMASK_INIT | + (val & MII_88E1318S_PHY_CSIER_WOL_EIE)); + } else { + /* Disable the PHY interrupts, but keep WOL_EIE set so an + * armed magic packet still asserts INTn while the + * interface is down or the machine is suspended. + */ + err = phy_write(phydev, MII_88E1318S_PHY_CSIER, + val & MII_88E1318S_PHY_CSIER_WOL_EIE); + if (err < 0) + return err; + + err = marvell_ack_interrupt(phydev); + } + + return err; +} + +static irqreturn_t m88e1318_handle_interrupt(struct phy_device *phydev) +{ + int irq_status; + + irq_status = phy_read(phydev, MII_M1011_IEVENT); + if (irq_status < 0) { + phy_error(phydev); + return IRQ_NONE; + } + + /* Claim events from the IMASK_INIT set as well as the WoL event + * mirrored from WOL_EIE in the enable register. + */ + if (!(irq_status & (MII_M1011_IMASK_INIT | + MII_88E1318S_PHY_CSIER_WOL_EIE))) + return IRQ_NONE; + + phy_trigger_machine(phydev); + + return IRQ_HANDLED; +} + static int marvell_set_polarity(struct phy_device *phydev, int polarity) { u16 val;
@@ -3817,8 +3879,8 @@ static struct phy_driver marvell_drivers[] = { .config_init = m88e1318_config_init, .config_aneg = m88e1318_config_aneg, .read_status = marvell_read_status, - .config_intr = marvell_config_intr, - .handle_interrupt = marvell_handle_interrupt, + .config_intr = m88e1318_config_intr, + .handle_interrupt = m88e1318_handle_interrupt, .get_wol = m88e1318_get_wol, .set_wol = m88e1318_set_wol, .resume = genphy_resume,
@@ -3925,8 +3987,8 @@ static struct phy_driver marvell_drivers[] = { .config_init = m88e1510_config_init, .config_aneg = m88e1510_config_aneg, .read_status = marvell_read_status, - .config_intr = marvell_config_intr, - .handle_interrupt = marvell_handle_interrupt, + .config_intr = m88e1318_config_intr, + .handle_interrupt = m88e1318_handle_interrupt, .get_wol = m88e1318_get_wol, .set_wol = m88e1318_set_wol, .resume = m88e1510_resume,
--
2.55.0