[linux-yocto] [PATCH 144/161] misc: lsi-smmon: Bug when probing with IRQ pending
Cristian Bercaru
cristian.bercaru at windriver.com
Thu May 21 12:22:06 PDT 2015
From: Anders Berg <anders.berg at avagotech.com>
We must not call the ncr_write function to unmask interrupts with
the memory controller interrupt enabled, as this could cause the ISR to
be invoked before ncr_write has released the lock used to serialize
register accesses.
To avoid this, temporarily disable the IRQ line while unmasking the
interrupt sources in the controller.
Signed-off-by: Anders Berg <anders.berg at avagotech.com>
---
drivers/misc/lsi-smmon.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/drivers/misc/lsi-smmon.c b/drivers/misc/lsi-smmon.c
index fe0d9e0..d263df9 100644
--- a/drivers/misc/lsi-smmon.c
+++ b/drivers/misc/lsi-smmon.c
@@ -200,8 +200,8 @@ smmon_probe(struct platform_device *pdev)
{
struct sm_dev *sm;
struct resource *io;
- struct resource *irq;
- u32 mask = SM_INT_MASK;
+ int irq;
+ u32 mask;
int rc = 0;
sm = devm_kzalloc(&pdev->dev, sizeof *sm, GFP_KERNEL);
@@ -218,26 +218,37 @@ smmon_probe(struct platform_device *pdev)
}
sm->region = io->start;
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq) {
- rc = -EINVAL;
+ /* Disable all memory controller interrupts */
+ mask = 0xffffffff;
+ ncr_write(sm->region, 0x414, 4, &mask);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ rc = irq;
goto out;
}
- rc = devm_request_irq(&pdev->dev, irq->start, smmon_isr,
- IRQF_ONESHOT, dev_name(&pdev->dev), pdev);
+ rc = devm_request_irq(&pdev->dev, irq, smmon_isr,
+ IRQF_ONESHOT, dev_name(&pdev->dev), sm);
if (rc)
goto out;
- /* Enable memory controller interrupts */
- ncr_write(sm->region, 0x414, 4, &mask);
-
rc = sysfs_create_group(&pdev->dev.kobj, &smmon_attr_group);
if (rc)
goto out;
dev_set_drvdata(&pdev->dev, sm);
pr_info("%s: Memory controller monitor\n", dev_name(&pdev->dev));
+
+ /* Enable memory controller interrupts. We need to disable the
+ * interrupt while unmasking it, since otherwise there will be a
+ * locking conflict in ncr_write/ncr_read when the ISR tries to read
+ * interrupt status.
+ */
+ disable_irq(irq);
+ mask = SM_INT_MASK;
+ ncr_write(sm->region, 0x414, 4, &mask);
+ enable_irq(irq);
out:
return rc;
}
--
1.7.9.5
More information about the linux-yocto
mailing list