[linux-yocto] [PATCH 3/8] misc: lsi-smmon: Bug when probing with IRQ pending
Charlie Paul
cpaul.windriver at gmail.com
Tue Jun 3 18:14:25 PDT 2014
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 21d59b0..774430f 100644
--- a/drivers/misc/lsi-smmon.c
+++ b/drivers/misc/lsi-smmon.c
@@ -201,8 +201,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);
@@ -219,26 +219,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