Skip to content
  • Maciej W. Rozycki's avatar
    PHYLIB: IRQ event workqueue handling fixes · 0ac49527
    Maciej W. Rozycki authored
    
    
    Keep track of disable_irq_nosync() invocations and call enable_irq() the
    right number of times if work has been cancelled that would include them.
    
    Now that the call to flush_work_keventd() (problematic because of
    rtnl_mutex being held) has been replaced by cancel_work_sync() another
    issue has arisen and been left unresolved.  As the MDIO bus cannot be
    accessed from the interrupt context the PHY interrupt handler uses
    disable_irq_nosync() to prevent from looping and schedules some work to be
    done as a softirq, which, apart from handling the state change of the
    originating PHY, is responsible for reenabling the interrupt.  Now if the
    interrupt line is shared by another device and a call to the softirq
    handler has been cancelled, that call to enable_irq() never happens and the
    other device cannot use its interrupt anymore as its stuck disabled.
    
    I decided to use a counter rather than a flag because there may be more
    than one call to phy_change() cancelled in the queue -- a real one and a
    fake one triggered by free_irq() if DEBUG_SHIRQ is used, if nothing else.
    Therefore because of its nesting property enable_irq() has to be called the
    right number of times to match the number disable_irq_nosync() was called
    and restore the original state.  This DEBUG_SHIRQ feature is also the
    reason why free_irq() has to be called before cancel_work_sync().
    
    While at it I updated the comment about phy_stop_interrupts() being called
    from `keventd' -- this is no longer relevant as the use of
    cancel_work_sync() makes such an approach unnecessary.  OTOH a similar
    comment referring to flush_scheduled_work() in phy_stop() still applies as
    using cancel_work_sync() there would be dangerous.
    
    Checked with checkpatch.pl and at the run time (with and without
    DEBUG_SHIRQ).
    
    Signed-off-by: default avatarMaciej W. Rozycki <macro@linux-mips.org>
    Cc: Andy Fleming <afleming@freescale.com>
    Cc: Jeff Garzik <jgarzik@pobox.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
    0ac49527