spi/mxs: Fix device remove function

The call sequence spi_alloc_master/spi_register_master/spi_unregister_master
is complete; it reduces the device reference count to zero, which results in
device memory being freed. The remove function accesses the freed memory after
the call to spi_unregister_master(), _and_ it calls spi_master_put on the freed
memory.

Acquire a reference to the SPI master device and release it after cleanup is
complete (with the existing spi_master_put) to solve the problem.

Also, the device subsystem ensures that the remove function is only called once,
and resets device driver data to NULL. Remove the unnecessaary calls to
platform_set_drvdata().

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
Guenter Roeck 2012-08-24 11:03:02 -07:00 committed by Mark Brown
parent 41682e03d4
commit 7d520d28dd

View file

@ -586,7 +586,6 @@ static int __devinit mxs_spi_probe(struct platform_device *pdev)
return 0; return 0;
out_free_dma: out_free_dma:
platform_set_drvdata(pdev, NULL);
dma_release_channel(ssp->dmach); dma_release_channel(ssp->dmach);
clk_disable_unprepare(ssp->clk); clk_disable_unprepare(ssp->clk);
out_master_free: out_master_free:
@ -600,14 +599,12 @@ static int __devexit mxs_spi_remove(struct platform_device *pdev)
struct mxs_spi *spi; struct mxs_spi *spi;
struct mxs_ssp *ssp; struct mxs_ssp *ssp;
master = platform_get_drvdata(pdev); master = spi_master_get(platform_get_drvdata(pdev));
spi = spi_master_get_devdata(master); spi = spi_master_get_devdata(master);
ssp = &spi->ssp; ssp = &spi->ssp;
spi_unregister_master(master); spi_unregister_master(master);
platform_set_drvdata(pdev, NULL);
dma_release_channel(ssp->dmach); dma_release_channel(ssp->dmach);
clk_disable_unprepare(ssp->clk); clk_disable_unprepare(ssp->clk);