[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