Skip to content

Commit cc941e5

Browse files
Russell King (Oracle)davem330
authored andcommitted
net: phy: fix IRQ-based wake-on-lan over hibernate / power off
Uwe reports: "Most PHYs signal WoL using an interrupt. So disabling interrupts [at shutdown] breaks WoL at least on PHYs covered by the marvell driver." Discussing with Ioana, the problem which was trying to be solved was: "The board in question is a LS1021ATSN which has two AR8031 PHYs that share an interrupt line. In case only one of the PHYs is probed and there are pending interrupts on the PHY#2 an IRQ storm will happen since there is no entity to clear the interrupt from PHY#2's registers. PHY#1's driver will get stuck in .handle_interrupt() indefinitely." Further confirmation that "the two AR8031 PHYs are on the same MDIO bus." With WoL using interrupts to wake the system, in such a case, the system will begin booting with an asserted interrupt. Thus, we need to cope with an interrupt asserted during boot. Solve this instead by disabling interrupts during PHY probe. This will ensure in Ioana's situation that both PHYs of the same type sharing an interrupt line on a common MDIO bus will have their interrupt outputs disabled when the driver probes the device, but before we hook in any interrupt handlers - thus avoiding the interrupt storm. A better fix would be for platform firmware to disable the interrupting devices at source during boot, before control is handed to the kernel. Fixes: e2f016c ("net: phy: add a shutdown procedure") Link: 20230804071757.383971-1-u.kleine-koenig@pengutronix.de Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 829c652 commit cc941e5

1 file changed

Lines changed: 2 additions & 11 deletions

File tree

drivers/net/phy/phy_device.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3216,6 +3216,8 @@ static int phy_probe(struct device *dev)
32163216
goto out;
32173217
}
32183218

3219+
phy_disable_interrupts(phydev);
3220+
32193221
/* Start out supporting everything. Eventually,
32203222
* a controller will attach, and may modify one
32213223
* or both of these values
@@ -3333,16 +3335,6 @@ static int phy_remove(struct device *dev)
33333335
return 0;
33343336
}
33353337

3336-
static void phy_shutdown(struct device *dev)
3337-
{
3338-
struct phy_device *phydev = to_phy_device(dev);
3339-
3340-
if (phydev->state == PHY_READY || !phydev->attached_dev)
3341-
return;
3342-
3343-
phy_disable_interrupts(phydev);
3344-
}
3345-
33463338
/**
33473339
* phy_driver_register - register a phy_driver with the PHY layer
33483340
* @new_driver: new phy_driver to register
@@ -3376,7 +3368,6 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
33763368
new_driver->mdiodrv.driver.bus = &mdio_bus_type;
33773369
new_driver->mdiodrv.driver.probe = phy_probe;
33783370
new_driver->mdiodrv.driver.remove = phy_remove;
3379-
new_driver->mdiodrv.driver.shutdown = phy_shutdown;
33803371
new_driver->mdiodrv.driver.owner = owner;
33813372
new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
33823373

0 commit comments

Comments
 (0)