Skip to content

Commit 81c9cdb

Browse files
committed
spi: fix controller deregistration (part 2/2)
Johan Hovold <johan@kernel.org> says: Device managed registration generally only works if all involved resources are managed as otherwise resources may be disabled or freed while they are still in use. This series fixes the SPI controller drivers that get this wrong by disabling resources such as clocks, DMA and interrupts while the controller (and its devices) are still registered, which can lead to issues like system errors due to unclocked accesses, NULL-pointer dereferences, hangs or just prevent SPI device drivers from doing I/O during during deregistration (e.g. to power down devices). I decided to split these fixes in two parts consisting of 20 and 26 patches respectively in order not to spam the lists too much. I've also prepared a follow-on series to convert the drivers here that do not yet use device managed controller allocation (which avoids taking extra references during deregistration). After that it should be possible to change the SPI API so that it no longer drops a reference during deregistration without too much effort (cf. [1]). Note that this series is based on spi/for-next which specifically has commit 1f8fd94 ("spi: zynq-qspi: Simplify clock handling with devm_clk_get_enabled()") (which is not in the for-7.1 branch). Johan [1] https://lore.kernel.org/lkml/20260325145319.1132072-1-johan@kernel.org/
2 parents 5b94c94 + c9c0127 commit 81c9cdb

26 files changed

Lines changed: 176 additions & 42 deletions

drivers/spi/spi-mt65xx.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
13251325

13261326
pm_runtime_enable(dev);
13271327

1328-
ret = devm_spi_register_controller(dev, host);
1328+
ret = spi_register_controller(host);
13291329
if (ret) {
13301330
pm_runtime_disable(dev);
13311331
return dev_err_probe(dev, ret, "failed to register host\n");
@@ -1340,6 +1340,8 @@ static void mtk_spi_remove(struct platform_device *pdev)
13401340
struct mtk_spi *mdata = spi_controller_get_devdata(host);
13411341
int ret;
13421342

1343+
spi_unregister_controller(host);
1344+
13431345
cpu_latency_qos_remove_request(&mdata->qos_request);
13441346
if (mdata->use_spimem && !completion_done(&mdata->spimem_done))
13451347
complete(&mdata->spimem_done);

drivers/spi/spi-mtk-nor.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ static int mtk_nor_probe(struct platform_device *pdev)
913913
pm_runtime_enable(&pdev->dev);
914914
pm_runtime_get_noresume(&pdev->dev);
915915

916-
ret = devm_spi_register_controller(&pdev->dev, ctlr);
916+
ret = spi_register_controller(ctlr);
917917
if (ret < 0)
918918
goto err_probe;
919919

@@ -938,6 +938,8 @@ static void mtk_nor_remove(struct platform_device *pdev)
938938
struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev);
939939
struct mtk_nor *sp = spi_controller_get_devdata(ctlr);
940940

941+
spi_unregister_controller(ctlr);
942+
941943
pm_runtime_disable(&pdev->dev);
942944
pm_runtime_set_suspended(&pdev->dev);
943945
pm_runtime_dont_use_autosuspend(&pdev->dev);

drivers/spi/spi-mxs.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
619619
if (ret)
620620
goto out_pm_runtime_put;
621621

622-
ret = devm_spi_register_controller(&pdev->dev, host);
622+
ret = spi_register_controller(host);
623623
if (ret) {
624624
dev_err(&pdev->dev, "Cannot register SPI host, %d\n", ret);
625625
goto out_pm_runtime_put;
@@ -650,11 +650,17 @@ static void mxs_spi_remove(struct platform_device *pdev)
650650
spi = spi_controller_get_devdata(host);
651651
ssp = &spi->ssp;
652652

653+
spi_controller_get(host);
654+
655+
spi_unregister_controller(host);
656+
653657
pm_runtime_disable(&pdev->dev);
654658
if (!pm_runtime_status_suspended(&pdev->dev))
655659
mxs_spi_runtime_suspend(&pdev->dev);
656660

657661
dma_release_channel(ssp->dmach);
662+
663+
spi_controller_put(host);
658664
}
659665

660666
static struct platform_driver mxs_spi_driver = {

drivers/spi/spi-npcm-pspi.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ static int npcm_pspi_probe(struct platform_device *pdev)
413413
/* set to default clock rate */
414414
npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK);
415415

416-
ret = devm_spi_register_controller(&pdev->dev, host);
416+
ret = spi_register_controller(host);
417417
if (ret)
418418
goto out_disable_clk;
419419

@@ -434,8 +434,14 @@ static void npcm_pspi_remove(struct platform_device *pdev)
434434
struct spi_controller *host = platform_get_drvdata(pdev);
435435
struct npcm_pspi *priv = spi_controller_get_devdata(host);
436436

437+
spi_controller_get(host);
438+
439+
spi_unregister_controller(host);
440+
437441
npcm_pspi_reset_hw(priv);
438442
clk_disable_unprepare(priv->clk);
443+
444+
spi_controller_put(host);
439445
}
440446

441447
static const struct of_device_id npcm_pspi_match[] = {

drivers/spi/spi-omap2-mcspi.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1592,7 +1592,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
15921592
if (status < 0)
15931593
goto disable_pm;
15941594

1595-
status = devm_spi_register_controller(&pdev->dev, ctlr);
1595+
status = spi_register_controller(ctlr);
15961596
if (status < 0)
15971597
goto disable_pm;
15981598

@@ -1613,11 +1613,17 @@ static void omap2_mcspi_remove(struct platform_device *pdev)
16131613
struct spi_controller *ctlr = platform_get_drvdata(pdev);
16141614
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
16151615

1616+
spi_controller_get(ctlr);
1617+
1618+
spi_unregister_controller(ctlr);
1619+
16161620
omap2_mcspi_release_dma(ctlr);
16171621

16181622
pm_runtime_dont_use_autosuspend(mcspi->dev);
16191623
pm_runtime_put_sync(mcspi->dev);
16201624
pm_runtime_disable(&pdev->dev);
1625+
1626+
spi_controller_put(ctlr);
16211627
}
16221628

16231629
/* work with hotplug and coldplug */

drivers/spi/spi-pic32-sqi.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ static int pic32_sqi_probe(struct platform_device *pdev)
642642
host->prepare_transfer_hardware = pic32_sqi_prepare_hardware;
643643
host->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware;
644644

645-
ret = devm_spi_register_controller(&pdev->dev, host);
645+
ret = spi_register_controller(host);
646646
if (ret) {
647647
dev_err(&host->dev, "failed registering spi host\n");
648648
free_irq(sqi->irq, sqi);
@@ -665,9 +665,15 @@ static void pic32_sqi_remove(struct platform_device *pdev)
665665
{
666666
struct pic32_sqi *sqi = platform_get_drvdata(pdev);
667667

668+
spi_controller_get(sqi->host);
669+
670+
spi_unregister_controller(sqi->host);
671+
668672
/* release resources */
669673
free_irq(sqi->irq, sqi);
670674
ring_desc_ring_free(sqi);
675+
676+
spi_controller_put(sqi->host);
671677
}
672678

673679
static const struct of_device_id pic32_sqi_of_ids[] = {

drivers/spi/spi-pic32.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ static int pic32_spi_probe(struct platform_device *pdev)
821821
}
822822

823823
/* register host */
824-
ret = devm_spi_register_controller(&pdev->dev, host);
824+
ret = spi_register_controller(host);
825825
if (ret) {
826826
dev_err(&host->dev, "failed registering spi host\n");
827827
goto err_bailout;
@@ -840,11 +840,16 @@ static int pic32_spi_probe(struct platform_device *pdev)
840840

841841
static void pic32_spi_remove(struct platform_device *pdev)
842842
{
843-
struct pic32_spi *pic32s;
843+
struct pic32_spi *pic32s = platform_get_drvdata(pdev);
844+
845+
spi_controller_get(pic32s->host);
846+
847+
spi_unregister_controller(pic32s->host);
844848

845-
pic32s = platform_get_drvdata(pdev);
846849
pic32_spi_disable(pic32s);
847850
pic32_spi_dma_unprep(pic32s);
851+
852+
spi_controller_put(pic32s->host);
848853
}
849854

850855
static const struct of_device_id pic32_spi_of_match[] = {

drivers/spi/spi-pl022.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1956,7 +1956,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
19561956

19571957
/* Register with the SPI framework */
19581958
amba_set_drvdata(adev, pl022);
1959-
status = devm_spi_register_controller(&adev->dev, host);
1959+
status = spi_register_controller(host);
19601960
if (status != 0) {
19611961
dev_err_probe(&adev->dev, status,
19621962
"problem registering spi host\n");
@@ -1997,6 +1997,10 @@ pl022_remove(struct amba_device *adev)
19971997
if (!pl022)
19981998
return;
19991999

2000+
spi_controller_get(pl022->host);
2001+
2002+
spi_unregister_controller(pl022->host);
2003+
20002004
/*
20012005
* undo pm_runtime_put() in probe. I assume that we're not
20022006
* accessing the primecell here.
@@ -2008,6 +2012,8 @@ pl022_remove(struct amba_device *adev)
20082012
pl022_dma_remove(pl022);
20092013

20102014
amba_release_regions(adev);
2015+
2016+
spi_controller_put(pl022->host);
20112017
}
20122018

20132019
#ifdef CONFIG_PM_SLEEP

drivers/spi/spi-qup.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ static int spi_qup_probe(struct platform_device *pdev)
11931193
pm_runtime_set_active(dev);
11941194
pm_runtime_enable(dev);
11951195

1196-
ret = devm_spi_register_controller(dev, host);
1196+
ret = spi_register_controller(host);
11971197
if (ret)
11981198
goto disable_pm;
11991199

@@ -1320,6 +1320,10 @@ static void spi_qup_remove(struct platform_device *pdev)
13201320
struct spi_qup *controller = spi_controller_get_devdata(host);
13211321
int ret;
13221322

1323+
spi_controller_get(host);
1324+
1325+
spi_unregister_controller(host);
1326+
13231327
ret = pm_runtime_get_sync(&pdev->dev);
13241328

13251329
if (ret >= 0) {
@@ -1339,6 +1343,8 @@ static void spi_qup_remove(struct platform_device *pdev)
13391343

13401344
pm_runtime_put_noidle(&pdev->dev);
13411345
pm_runtime_disable(&pdev->dev);
1346+
1347+
spi_controller_put(host);
13421348
}
13431349

13441350
static const struct of_device_id spi_qup_dt_match[] = {

drivers/spi/spi-rspi.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev)
11711171
{
11721172
struct rspi_data *rspi = platform_get_drvdata(pdev);
11731173

1174+
spi_controller_get(rspi->ctlr);
1175+
1176+
spi_unregister_controller(rspi->ctlr);
1177+
11741178
rspi_release_dma(rspi->ctlr);
11751179
pm_runtime_disable(&pdev->dev);
1180+
1181+
spi_controller_put(rspi->ctlr);
11761182
}
11771183

11781184
static const struct spi_ops rspi_ops = {
@@ -1376,9 +1382,9 @@ static int rspi_probe(struct platform_device *pdev)
13761382
if (ret < 0)
13771383
dev_warn(&pdev->dev, "DMA not available, using PIO\n");
13781384

1379-
ret = devm_spi_register_controller(&pdev->dev, ctlr);
1385+
ret = spi_register_controller(ctlr);
13801386
if (ret < 0) {
1381-
dev_err(&pdev->dev, "devm_spi_register_controller error.\n");
1387+
dev_err(&pdev->dev, "failed to register controller\n");
13821388
goto error3;
13831389
}
13841390

0 commit comments

Comments
 (0)