spi: uniphier: fix reference count leak in uniphier_spi_probe()
commit37c2c83ca4
upstream. The issue happens in several error paths in uniphier_spi_probe(). When either dma_get_slave_caps() or devm_spi_register_master() returns an error code, the function forgets to decrease the refcount of both `dma_rx` and `dma_tx` objects, which may lead to refcount leaks. Fix it by decrementing the reference count of specific objects in those error paths. Signed-off-by: Xin Xiong <xiongx18@fudan.edu.cn> Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn> Signed-off-by: Xin Tan <tanxin.ctf@gmail.com> Reviewed-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> Fixes:28d1dddc59
("spi: uniphier: Add DMA transfer mode support") Link: https://lore.kernel.org/r/20220125101214.35677-1-xiongx18@fudan.edu.cn Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
66606d329d
Коммит
dd00b4f8f7
|
@ -726,7 +726,7 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get TX DMA capacities: %d\n",
|
||||
ret);
|
||||
goto out_disable_clk;
|
||||
goto out_release_dma;
|
||||
}
|
||||
dma_tx_burst = caps.max_burst;
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
if (IS_ERR_OR_NULL(master->dma_rx)) {
|
||||
if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto out_disable_clk;
|
||||
goto out_release_dma;
|
||||
}
|
||||
master->dma_rx = NULL;
|
||||
dma_rx_burst = INT_MAX;
|
||||
|
@ -744,7 +744,7 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get RX DMA capacities: %d\n",
|
||||
ret);
|
||||
goto out_disable_clk;
|
||||
goto out_release_dma;
|
||||
}
|
||||
dma_rx_burst = caps.max_burst;
|
||||
}
|
||||
|
@ -753,10 +753,20 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
if (ret)
|
||||
goto out_disable_clk;
|
||||
goto out_release_dma;
|
||||
|
||||
return 0;
|
||||
|
||||
out_release_dma:
|
||||
if (!IS_ERR_OR_NULL(master->dma_rx)) {
|
||||
dma_release_channel(master->dma_rx);
|
||||
master->dma_rx = NULL;
|
||||
}
|
||||
if (!IS_ERR_OR_NULL(master->dma_tx)) {
|
||||
dma_release_channel(master->dma_tx);
|
||||
master->dma_tx = NULL;
|
||||
}
|
||||
|
||||
out_disable_clk:
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче