• Lennert Buytenhek's avatar
    ksz884x: fix receive polling race condition · 4945106d
    Lennert Buytenhek authored
    The ksz884x driver does receive processing in a custom tasklet, and
    seems to be assuming that since it takes its private interface spinlock
    with spin_lock_irq(), it won't be running concurrently with its own
    interrupt handler, as it cannot be preempted by it, but since its
    interrupt handler doesn't do any locking whatsoever, the receive
    processing tasklet and interrupt handler can end up running concurrently
    on different CPUs.
    
    As a result of this, the ksz884x receive path ends up locking up fairly
    easily, when the receive processing tasklet's reenabling of receive
    interrupts (due to it being done with polling the receive ring) races
    with the interrupt handler's disabling of receive interrupts (due to a
    new receive interrupt coming in) resulting in the receive interrupt
    being masked but the receive processing tasklet not being scheduled.
    
    Fix this by making the ksz884x interrupt handler take its private
    interface spinlock.  This requires upgrading the spin_lock() in the
    transmit cleanup tasklet to a spin_lock_irq(), as otherwise the IRQ
    handler can preempt transmit cleanup and deadlock the system, but
    with those two changes, no more receive lockups have been observed.
    Reported-by: default avatarChris Healy <cphealy@gmail.com>
    Signed-off-by: default avatarLennert Buytenhek <buytenh@wantstofly.org>
    
    ----
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    4945106d
ksz884x.c 179 KB