On Mon, May 23, 2022 at 03:47:09PM +0200, Lukas Wunner wrote: > On Mon, May 23, 2022 at 02:34:49PM +0200, Andrew Lunn wrote: > > > --- a/drivers/net/phy/phy_device.c > > > +++ b/drivers/net/phy/phy_device.c > > > @@ -283,8 +283,11 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev) > > > * may call phy routines that try to grab the same lock, and that may > > > * lead to a deadlock. > > > */ > > > - if (phydev->attached_dev && phydev->adjust_link) > > > + if (phydev->attached_dev && phydev->adjust_link) { > > > + if (phy_interrupt_is_valid(phydev)) > > > + synchronize_irq(phydev->irq); > > > phy_stop_machine(phydev); > > > + } > > > > What is this hunk trying to achieve? As far as i know, interrupts have > > not been disabled. So as soon as the call to synchronize_irq() > > finishes, could well be another interrupt happens. > > That other interrupt would bail out of phy_interrupt() because > the is_prepared flag is set on the PHY's struct device, see > first hunk of the patch. > > The problem is that an interrupt may occur before the system > sleep transition commences. phy_interrupt() will notice that > is_prepared is not (yet) set, hence invokes drv->handle_interrupt(). > Let's say the IRQ thread is preempted at that point, the system > sleep transition is started and mdio_bus_phy_suspend() is run. > It calls phy_stop_machine(), so the state machine is now stopped. > Now phy_interrupt() continues, and the PHY driver's ->handle_interrupt() > callback starts the state machine. Boom, that's not what we want. > > So the synchronize_irq() ensures that any already running > phy_interrupt() runs to completion before phy_stop_machine() > is called. It doesn't matter if another interrupt occurs > because then is_prepared will have been set and therefore > phy_interrupt() won't call drv->handle_interrupt(). > > Let me know if I haven't explained it in sufficient clarity, > I'll be happy to try again. :) I think some comments are needed. If i don't understand what is going on, i'm sure others don't as well. Andrew