Skip to content

Commit 3d87b61

Browse files
krzkbroonie
authored andcommitted
spi: spi-fsl-dspi: Fix external abort on interrupt in resume or exit paths
If shared interrupt comes late, during probe error path or device remove (could be triggered with CONFIG_DEBUG_SHIRQ), the interrupt handler dspi_interrupt() will access registers with the clock being disabled. This leads to external abort on non-linefetch on Toradex Colibri VF50 module (with Vybrid VF5xx): $ echo 4002d000.spi > /sys/devices/platform/soc/40000000.bus/4002d000.spi/driver/unbind Unhandled fault: external abort on non-linefetch (0x1008) at 0x8887f02c Internal error: : 1008 [#1] ARM Hardware name: Freescale Vybrid VF5xx/VF6xx (Device Tree) Backtrace: (regmap_mmio_read32le) (regmap_mmio_read) (_regmap_bus_reg_read) (_regmap_read) (regmap_read) (dspi_interrupt) (free_irq) (devm_irq_release) (release_nodes) (devres_release_all) (device_release_driver_internal) The resource-managed framework should not be used for shared interrupt handling, because the interrupt handler might be called after releasing other resources and disabling clocks. Similar bug could happen during suspend - the shared interrupt handler could be invoked after suspending the device. Each device sharing this interrupt line should disable the IRQ during suspend so handler will be invoked only in following cases: 1. None suspended, 2. All devices resumed. Fixes: 349ad66 ("spi:Add Freescale DSPI driver for Vybrid VF610 platform") Signed-off-by: Krzysztof Kozlowski <[email protected]> Tested-by: Vladimir Oltean <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Cc: <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 3c525b6 commit 3d87b61

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

drivers/spi/spi-fsl-dspi.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,8 @@ static int dspi_suspend(struct device *dev)
11091109
struct spi_controller *ctlr = dev_get_drvdata(dev);
11101110
struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
11111111

1112+
if (dspi->irq)
1113+
disable_irq(dspi->irq);
11121114
spi_controller_suspend(ctlr);
11131115
clk_disable_unprepare(dspi->clk);
11141116

@@ -1129,6 +1131,8 @@ static int dspi_resume(struct device *dev)
11291131
if (ret)
11301132
return ret;
11311133
spi_controller_resume(ctlr);
1134+
if (dspi->irq)
1135+
enable_irq(dspi->irq);
11321136

11331137
return 0;
11341138
}
@@ -1385,8 +1389,8 @@ static int dspi_probe(struct platform_device *pdev)
13851389
goto poll_mode;
13861390
}
13871391

1388-
ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt,
1389-
IRQF_SHARED, pdev->name, dspi);
1392+
ret = request_threaded_irq(dspi->irq, dspi_interrupt, NULL,
1393+
IRQF_SHARED, pdev->name, dspi);
13901394
if (ret < 0) {
13911395
dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n");
13921396
goto out_clk_put;
@@ -1400,7 +1404,7 @@ static int dspi_probe(struct platform_device *pdev)
14001404
ret = dspi_request_dma(dspi, res->start);
14011405
if (ret < 0) {
14021406
dev_err(&pdev->dev, "can't get dma channels\n");
1403-
goto out_clk_put;
1407+
goto out_free_irq;
14041408
}
14051409
}
14061410

@@ -1415,11 +1419,14 @@ static int dspi_probe(struct platform_device *pdev)
14151419
ret = spi_register_controller(ctlr);
14161420
if (ret != 0) {
14171421
dev_err(&pdev->dev, "Problem registering DSPI ctlr\n");
1418-
goto out_clk_put;
1422+
goto out_free_irq;
14191423
}
14201424

14211425
return ret;
14221426

1427+
out_free_irq:
1428+
if (dspi->irq)
1429+
free_irq(dspi->irq, dspi);
14231430
out_clk_put:
14241431
clk_disable_unprepare(dspi->clk);
14251432
out_ctlr_put:
@@ -1445,6 +1452,8 @@ static int dspi_remove(struct platform_device *pdev)
14451452
regmap_update_bits(dspi->regmap, SPI_MCR, SPI_MCR_HALT, SPI_MCR_HALT);
14461453

14471454
dspi_release_dma(dspi);
1455+
if (dspi->irq)
1456+
free_irq(dspi->irq, dspi);
14481457
clk_disable_unprepare(dspi->clk);
14491458

14501459
return 0;

0 commit comments

Comments
 (0)