ARM: 7377/1: vic: re-read status register before dispatching each IRQ handler
handle_IRQ may briefly cause interrupts to be re-enabled during soft IRQ processing on the exit path, leading to nested handling of VIC interrupts. Since the current code does not re-read the VIC_IRQ_STATUS register, this can lead to multiple invocations of the same interrupt handler and spurious interrupts to be reported. This patch changes the VIC interrupt dispatching code to re-read the status register each time, avoiding duplicate invocations of the same handler. Acked-and-Tested-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Jamie Iles <jamie@jamieiles.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
Родитель
dff2aa7af8
Коммит
34af657916
|
@ -427,19 +427,18 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
|
|||
|
||||
/*
|
||||
* Handle each interrupt in a single VIC. Returns non-zero if we've
|
||||
* handled at least one interrupt. This does a single read of the
|
||||
* status register and handles all interrupts in order from LSB first.
|
||||
* handled at least one interrupt. This reads the status register
|
||||
* before handling each interrupt, which is necessary given that
|
||||
* handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
|
||||
*/
|
||||
static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
|
||||
{
|
||||
u32 stat, irq;
|
||||
int handled = 0;
|
||||
|
||||
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
|
||||
while (stat) {
|
||||
while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
|
||||
irq = ffs(stat) - 1;
|
||||
handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
|
||||
stat &= ~(1 << irq);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче