diff options
author | Haojian Zhuang <haojian.zhuang@linaro.org> | 2013-03-25 00:09:49 +0800 |
---|---|---|
committer | Haojian Zhuang <haojian.zhuang@linaro.org> | 2013-03-25 09:07:38 +0800 |
commit | d5deb78db6db4a4a84e946ba955ca9b08949adaa (patch) | |
tree | 07f2c02b75d649fdee27377bc6665d3ebb30699e | |
parent | b1afbfc711079c6b1606156c1372a063e28e3c04 (diff) |
mfd: hi6421: avoid to call irq handler with lock
While hi6421 SoC interrupt occurs, it always locks spinlock even calling
child irq handler. If child irq handler accesses pmic registers, it will
be dead lock since accessing function also uses spinlock.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
-rw-r--r-- | drivers/mfd/hi6421-pmic-core.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c index 043956076be..cce368b856d 100644 --- a/drivers/mfd/hi6421-pmic-core.c +++ b/drivers/mfd/hi6421-pmic-core.c @@ -115,21 +115,25 @@ static irqreturn_t hi6421_irq_handler(int irq, void *data) unsigned long pending; int i, offset; - spin_lock(&pmic->lock); for (i = HI6421_REG_IRQ1; i <= HI6421_REG_IRQ3; i++) { + spin_lock(&pmic->lock); pending = readl_relaxed(pmic->regs + (i << 2)); pending &= HI6421_MASK_FIELD; writel_relaxed(pending, pmic->regs + ((i + 3) << 2)); + spin_unlock(&pmic->lock); + if (pending) { for_each_set_bit(offset, &pending, HI6421_BITS) generic_handle_irq(hi6421_to_irq(pmic, offset)); } + + spin_lock(&pmic->lock); writel_relaxed(0, pmic->regs + ((i + 3) << 2)); writel_relaxed(pending, pmic->regs + (i << 2)); + spin_unlock(&pmic->lock); } - spin_unlock(&pmic->lock); return IRQ_HANDLED; } |