clear the status bit if the mask register doesn't prevent the chip level irq from being asserted
OR in the following sequence, there will be irq storm happens: 1) interrupt is triggered; 2) another thread disables it(the mask bit is set); 3) _Then_ the interrupt thread is not ACKed(the status bit is not cleared), and it's ignored; 4) if the irq is still asserted because of the uncleared status bit, the irq storm happens; Change-Id: I371201f365c5a8470073a393068cfeb4e3d14a03 Signed-off-by: Yi Zhang <yizh...@marvell.com> --- drivers/base/regmap/regmap-irq.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index d10456f..cd655b8 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -105,6 +105,27 @@ static void regmap_irq_sync_unlock(struct irq_data *data) "Failed to sync wakes in %x: %d\n", reg, ret); } + + if (!d->chip->init_ack_masked) + continue; + + /* Ack masked but set interrupts */ + reg = d->chip->status_base + + (i * map->reg_stride * d->irq_reg_stride); + ret = regmap_read(d->map, reg, &d->status_buf[i]); + if (ret != 0) + dev_err(d->map->dev, "Failed to read IRQ status: %d\n", + ret); + + if (d->status_buf[i] && d->chip->ack_base) { + reg = d->chip->ack_base + + (i * map->reg_stride * d->irq_reg_stride); + ret = regmap_write(d->map, reg, + d->status_buf[i] & d->mask_buf[i]); + if (ret != 0) + dev_err(d->map->dev, "Failed to ack 0x%x: %d\n", + reg, ret); + } } if (d->chip->runtime_pm) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/