aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@linaro.org>2013-03-25 00:09:49 +0800
committerHaojian Zhuang <haojian.zhuang@linaro.org>2013-03-25 09:07:38 +0800
commitd5deb78db6db4a4a84e946ba955ca9b08949adaa (patch)
tree07f2c02b75d649fdee27377bc6665d3ebb30699e
parentb1afbfc711079c6b1606156c1372a063e28e3c04 (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.c8
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;
}