After rethinking, it looks like this last cancel should be useless.So, if phy_interrupt() schedules only if !PHY_HALTED and phy_change()does enable_irq() with no exeptions, it seems phy_interrupt() evenwithout lock must see PHY_HALTED state before this free_irq() withpossible DEBUG_SHIRQ call, then maybe only this safety:

WARN_ON(work_pending(&phydev->phy_queue));

Btw, I've read this was considered and not liked, but IMHO, if thisreally has to be like this, creating phy's own workqueue seems to beresonable, at the very least to reduce latencies to other users ofthis irq.