• J
    dsa: mv88e6xxx: Ensure all pending interrupts are handled prior to exit · 7c0db24c
    John David Anglin 提交于
    The GPIO interrupt controller on the espressobin board only supports edge interrupts.
    If one enables the use of hardware interrupts in the device tree for the 88E6341, it is
    possible to miss an edge.  When this happens, the INTn pin on the Marvell switch is
    stuck low and no further interrupts occur.
    
    I found after adding debug statements to mv88e6xxx_g1_irq_thread_work() that there is
    a race in handling device interrupts (e.g. PHY link interrupts).  Some interrupts are
    directly cleared by reading the Global 1 status register.  However, the device interrupt
    flag, for example, is not cleared until all the unmasked SERDES and PHY ports are serviced.
    This is done by reading the relevant SERDES and PHY status register.
    
    The code only services interrupts whose status bit is set at the time of reading its status
    register.  If an interrupt event occurs after its status is read and before all interrupts
    are serviced, then this event will not be serviced and the INTn output pin will remain low.
    
    This is not a problem with polling or level interrupts since the handler will be called
    again to process the event.  However, it's a big problem when using level interrupts.
    
    The fix presented here is to add a loop around the code servicing switch interrupts.  If
    any pending interrupts remain after the current set has been handled, we loop and process
    the new set.  If there are no pending interrupts after servicing, we are sure that INTn has
    gone high and we will get an edge when a new event occurs.
    
    Tested on espressobin board.
    
    Fixes: dc30c35b ("net: dsa: mv88e6xxx: Implement interrupt support.")
    Signed-off-by: NJohn David Anglin <dave.anglin@bell.net>
    Tested-by: NAndrew Lunn <andrew@lunn.ch>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    7c0db24c
chip.c 139.7 KB