aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemi Pommarel <repk@triplefau.lt>2019-01-10 18:01:35 -0500
committerUlf Hansson <ulf.hansson@linaro.org>2019-01-14 06:03:04 -0500
commitbb364890323cca6e43f13e86d190ebf34a7d8cea (patch)
tree73b48a1dd6299be611cd61f3bf2ff8667a6dcc1b
parent287b1da6a458a30da2e5be745498d31092ebb001 (diff)
mmc: meson-gx: Free irq in release() callback
Because the irq was requested through device managed resources API (devm_request_threaded_irq()) it was freed after meson_mmc_remove() completion, thus after mmc_free_host() has reclaimed meson_host memory. As this irq is IRQF_SHARED, while using CONFIG_DEBUG_SHIRQ, its handler get called by free_irq(). So meson_mmc_irq() was called after the meson_host memory reclamation and was using invalid memory. We ended up with the following scenario: device_release_driver() meson_mmc_remove() mmc_free_host() /* Freeing host memory */ ... devres_release_all() devm_irq_release() __free_irq() meson_mmc_irq() /* Uses freed memory */ To avoid this, the irq is released in meson_mmc_remove() and in mseon_mmc_probe() error path before mmc_free_host() gets called. Reported-by: Elie Roudninski <xademax@gmail.com> Signed-off-by: Remi Pommarel <repk@triplefau.lt> Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index c2690c1a50ff..f115d7c63ffe 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -179,6 +179,8 @@ struct meson_host {
179 struct sd_emmc_desc *descs; 179 struct sd_emmc_desc *descs;
180 dma_addr_t descs_dma_addr; 180 dma_addr_t descs_dma_addr;
181 181
182 int irq;
183
182 bool vqmmc_enabled; 184 bool vqmmc_enabled;
183}; 185};
184 186
@@ -1231,7 +1233,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
1231 struct resource *res; 1233 struct resource *res;
1232 struct meson_host *host; 1234 struct meson_host *host;
1233 struct mmc_host *mmc; 1235 struct mmc_host *mmc;
1234 int ret, irq; 1236 int ret;
1235 1237
1236 mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev); 1238 mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
1237 if (!mmc) 1239 if (!mmc)
@@ -1276,8 +1278,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
1276 goto free_host; 1278 goto free_host;
1277 } 1279 }
1278 1280
1279 irq = platform_get_irq(pdev, 0); 1281 host->irq = platform_get_irq(pdev, 0);
1280 if (irq <= 0) { 1282 if (host->irq <= 0) {
1281 dev_err(&pdev->dev, "failed to get interrupt resource.\n"); 1283 dev_err(&pdev->dev, "failed to get interrupt resource.\n");
1282 ret = -EINVAL; 1284 ret = -EINVAL;
1283 goto free_host; 1285 goto free_host;
@@ -1331,9 +1333,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
1331 writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, 1333 writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
1332 host->regs + SD_EMMC_IRQ_EN); 1334 host->regs + SD_EMMC_IRQ_EN);
1333 1335
1334 ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq, 1336 ret = request_threaded_irq(host->irq, meson_mmc_irq,
1335 meson_mmc_irq_thread, IRQF_SHARED, 1337 meson_mmc_irq_thread, IRQF_SHARED, NULL, host);
1336 NULL, host);
1337 if (ret) 1338 if (ret)
1338 goto err_init_clk; 1339 goto err_init_clk;
1339 1340
@@ -1351,7 +1352,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
1351 if (host->bounce_buf == NULL) { 1352 if (host->bounce_buf == NULL) {
1352 dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); 1353 dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
1353 ret = -ENOMEM; 1354 ret = -ENOMEM;
1354 goto err_init_clk; 1355 goto err_free_irq;
1355 } 1356 }
1356 1357
1357 host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, 1358 host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
@@ -1370,6 +1371,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
1370err_bounce_buf: 1371err_bounce_buf:
1371 dma_free_coherent(host->dev, host->bounce_buf_size, 1372 dma_free_coherent(host->dev, host->bounce_buf_size,
1372 host->bounce_buf, host->bounce_dma_addr); 1373 host->bounce_buf, host->bounce_dma_addr);
1374err_free_irq:
1375 free_irq(host->irq, host);
1373err_init_clk: 1376err_init_clk:
1374 clk_disable_unprepare(host->mmc_clk); 1377 clk_disable_unprepare(host->mmc_clk);
1375err_core_clk: 1378err_core_clk:
@@ -1387,6 +1390,7 @@ static int meson_mmc_remove(struct platform_device *pdev)
1387 1390
1388 /* disable interrupts */ 1391 /* disable interrupts */
1389 writel(0, host->regs + SD_EMMC_IRQ_EN); 1392 writel(0, host->regs + SD_EMMC_IRQ_EN);
1393 free_irq(host->irq, host);
1390 1394
1391 dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, 1395 dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
1392 host->descs, host->descs_dma_addr); 1396 host->descs, host->descs_dma_addr);