• Ben Hutchings's avatar
    sh_eth: Fix serialisation of interrupt disable with interrupt & NAPI handlers · 283e38db
    Ben Hutchings authored
    In order to stop the RX path accessing the RX ring while it's being
    stopped or resized, we clear the interrupt mask (EESIPR) and then call
    free_irq() or synchronise_irq().  This is insufficient because the
    interrupt handler or NAPI poller may set EESIPR again after we clear
    it.  Also, in sh_eth_set_ringparam() we currently don't disable NAPI
    polling at all.
    
    I could easily trigger a crash by running the loop:
    
       while ethtool -G eth0 rx 128 && ethtool -G eth0 rx 64; do echo -n .; done
    
    and 'ping -f' toward the sh_eth port from another machine.
    
    To fix this:
    - Add a software flag (irq_enabled) to signal whether interrupts
      should be enabled
    - In the interrupt handler, if the flag is clear then clear EESIPR
      and return
    - In the NAPI poller, if the flag is clear then don't set EESIPR
    - Set the flag before enabling interrupts in sh_eth_dev_init() and
      sh_eth_set_ringparam()
    - Clear the flag and serialise with the interrupt and NAPI
      handlers before clearing EESIPR in sh_eth_close() and
      sh_eth_set_ringparam()
    
    After this, I could run the loop for 100,000 iterations successfully.
    Signed-off-by: default avatarBen Hutchings <ben.hutchings@codethink.co.uk>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    283e38db
sh_eth.c 72 KB