diff options
author | Axel Lin <axel.lin@ingics.com> | 2013-09-10 15:43:41 +0800 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-09-17 12:56:14 +0100 |
commit | 94c69f765f1b4a658d96905ec59928e3e3e07e6a (patch) | |
tree | cfa1fffd3906bff17eed2e9771f2c33fd55877af /drivers/spi/spi-davinci.c | |
parent | 272b98c6455f00884f0350f775c5342358ebb73f (diff) |
spi: bitbang: Let spi_bitbang_start() take a reference to master
Many drivers that use bitbang library have a leak on probe error paths.
This is because once a spi_master_get() call succeeds, we need an additional
spi_master_put() call to free the memory.
Fix this issue by moving the code taking a reference to master to
spi_bitbang_start(), so spi_bitbang_start() will take a reference to master on
success. With this change, the caller is responsible for calling
spi_bitbang_stop() to decrement the reference and spi_master_put() as
counterpart of spi_alloc_master() to prevent a memory leak.
So now we have below patten for drivers using bitbang library:
probe:
spi_alloc_master -> Init reference count to 1
spi_bitbang_start -> Increment reference count
remove:
spi_bitbang_stop -> Decrement reference count
spi_master_put -> Decrement reference count (reference count reaches 0)
Fixup all users accordingly.
Signed-off-by: Axel Lin <axel.lin@ingics.com>
Suggested-by: Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
Acked-by: Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi-davinci.c')
-rw-r--r-- | drivers/spi/spi-davinci.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 8fbfe2483ffd..af2bb73d0168 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -916,7 +916,7 @@ static int davinci_spi_probe(struct platform_device *pdev) if (ret) goto unmap_io; - dspi->bitbang.master = spi_master_get(master); + dspi->bitbang.master = master; if (dspi->bitbang.master == NULL) { ret = -ENODEV; goto irq_free; @@ -925,7 +925,7 @@ static int davinci_spi_probe(struct platform_device *pdev) dspi->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dspi->clk)) { ret = -ENODEV; - goto put_master; + goto irq_free; } clk_prepare_enable(dspi->clk); @@ -1015,8 +1015,6 @@ free_dma: free_clk: clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); -put_master: - spi_master_put(master); irq_free: free_irq(dspi->irq, dspi); unmap_io: @@ -1024,7 +1022,7 @@ unmap_io: release_region: release_mem_region(dspi->pbase, resource_size(r)); free_master: - kfree(master); + spi_master_put(master); err: return ret; } @@ -1051,11 +1049,11 @@ static int davinci_spi_remove(struct platform_device *pdev) clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); - spi_master_put(master); free_irq(dspi->irq, dspi); iounmap(dspi->base); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(dspi->pbase, resource_size(r)); + spi_master_put(master); return 0; } |