diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-08-23 20:08:47 -0700 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-08-27 09:37:52 -0700 |
commit | 154390dcf826dc97b9d338305db14582c32cb58a (patch) | |
tree | bb26c340dfaaa81a88bc2bd0a0cc71521f1c06ac | |
parent | 58ed90de3ef58a19c035355a4a0cd6dfef6d6b0c (diff) | |
download | linux-3.10-154390dcf826dc97b9d338305db14582c32cb58a.tar.gz linux-3.10-154390dcf826dc97b9d338305db14582c32cb58a.tar.bz2 linux-3.10-154390dcf826dc97b9d338305db14582c32cb58a.zip |
spi/stmp: 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 respective check and drop the
unnecessaary call to platform_set_drvdata().
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | drivers/spi/spi-stmp.c | 6 |
1 files changed, 1 insertions, 5 deletions
diff --git a/drivers/spi/spi-stmp.c b/drivers/spi/spi-stmp.c index 58e38528532..911e904b3c8 100644 --- a/drivers/spi/spi-stmp.c +++ b/drivers/spi/spi-stmp.c @@ -594,9 +594,7 @@ static int __devexit stmp_spi_remove(struct platform_device *dev) struct stmp_spi *ss; struct spi_master *master; - master = platform_get_drvdata(dev); - if (master == NULL) - goto out0; + master = spi_master_get(platform_get_drvdata(dev)); ss = spi_master_get_devdata(master); spi_unregister_master(master); @@ -609,8 +607,6 @@ static int __devexit stmp_spi_remove(struct platform_device *dev) destroy_workqueue(ss->workqueue); iounmap(ss->regs); spi_master_put(master); - platform_set_drvdata(dev, NULL); -out0: return 0; } |