• Ben Hutchings's avatar
    sfc: Rework IRQ enable/disable · d8291187
    Ben Hutchings authored
    There are many problems with the current efx_stop_interrupts() and
    efx_start_interrupts():
    
    1. On Siena, it is unsafe to disable the master IRQ enable bit
    (DRV_INT_EN_KER) while any IRQ sources are enabled.
    
    2. On EF10 there is no master IRQ enable bit, so we cannot expect to
    defer IRQs without tearing down event queues.  (Though I don't think
    we will need to keep any event queues around while the device is down,
    as we do for VFDI on Siena.)
    
    3. synchronize_irq() only waits for a running IRQ handler to finish,
    not for any propagation through IRQ controllers.  Therefore an IRQ may
    still be received and handled after efx_stop_interrupts() returns.
    IRQ handlers can then race with channel reallocation.
    
    To fix this:
    
    a. Introduce a software IRQ enable flag.  So long as this is clear,
    IRQ handlers will only acknowledge IRQs and not touch the channel
    structures.
    
    b. Define a new struct efx_msi_context as the context for MSIs.  This
    is never reallocated and is sufficient to find the software enable
    flag and the channel structure.  It also includes the channel/IRQ
    name, which was previously separated out as it must also not be
    reallocated.
    
    c. Split efx_{start,stop}_interrupts() into
    efx_{,soft_}_{enable,disable}_interrupts().  The 'soft' functions
    don't touch the hardware master enable flag (if it exists) and don't
    reinitialise or tear down channels with the keep_eventq flag set.
    Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
    d8291187
efx.c 78.9 KB