[PATCH] spi: Fix memory leak on splited transfers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Gustav Wiklander <gustavwi@xxxxxxxx>

In the prepare_message callback the bus driver has the
opportunity to split a transfer into smaller chunks.
spi_map_msg is done after prepare_message.

Function spi_res_release releases the splited transfers
in the message. Therefore spi_res_release should be called
after spi_map_msg.

The previous try at this was commit c9ba7a16d0f1
which released the splited transfers after
spi_finalize_current_message had been called.
This introduced a race since the message struct could be
out of scope because the spi_sync call got completed.

Fixes this leak on spi bus driver spi-bcm2835.c when transfer
size is greater than 65532:

[   76.611642][  T170] kmemleak: unreferenced object 0xfffffff06ef81480
(size 128):
[   76.618965][  T170] kmemleak:   comm "insmod", pid 493, jiffies
4294941102 (age 38.540s)
[   76.627031][  T170] kmemleak:   backtrace:
[   76.631206][  T170] kmemleak:     [<ffffffa542c5f8f8>]
create_object+0x100/0x288
[   76.638596][  T170] kmemleak:     [<ffffffa5432a9ee4>]
kmemleak_alloc+0x8c/0xe0
[   76.645723][  T170] kmemleak:     [<ffffffa542c4cbe8>]
__kmalloc+0x1c8/0x370
[   76.652754][  T170] kmemleak:     [<ffffffa542e14c94>]
sg_kmalloc+0x1c/0x68
[   76.659782][  T170] kmemleak:     [<ffffffa542e1543c>]
__sg_alloc_table+0xf4/0x128
[   76.667420][  T170] kmemleak:     [<ffffffa542e15820>]
sg_alloc_table+0x28/0xc8
[   76.674636][  T170] kmemleak:     [<ffffffa542f938a4>]
spi_map_buf+0xa4/0x300
[   76.681838][  T170] kmemleak:     [<ffffffa542f94648>]
__spi_pump_messages+0x370/0x748
[   76.689573][  T170] kmemleak:     [<ffffffa542f94c24>]
__spi_sync+0x1d4/0x270
[   76.696863][  T170] kmemleak:     [<ffffffa542f94cf4>]
spi_sync+0x34/0x58
[   76.703562][  T170] kmemleak:     [<ffffffa4cd94a638>]
spi_test_execute_msg+0x60/0x340 [spi_loopback_test]
[   76.713193][  T170] kmemleak:     [<ffffffa4cd94ae60>]
spi_test_run_iter+0x548/0x578 [spi_loopback_test]
[   76.722740][  T170] kmemleak:     [<ffffffa4cd94af24>]
spi_test_run_test+0x94/0x140 [spi_loopback_test]
[   76.732037][  T170] kmemleak:     [<ffffffa4cd94b120>]
spi_test_run_tests+0x150/0x180 [spi_loopback_test]
[   76.741498][  T170] kmemleak:     [<ffffffa4cd94b1a0>]
spi_loopback_test_probe+0x50/0xd0 [spi_loopback_test]
[   76.751392][  T170] kmemleak:     [<ffffffa542f911f4>]
spi_drv_probe+0x84/0xe0
---
 drivers/spi/spi.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index dc12af018350..0cab239d8e7f 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1327,8 +1327,6 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
 	if (msg->status && ctlr->handle_err)
 		ctlr->handle_err(ctlr, msg);
 
-	spi_res_release(ctlr, msg);
-
 	spi_finalize_current_message(ctlr);
 
 	return ret;
@@ -1725,6 +1723,13 @@ void spi_finalize_current_message(struct spi_controller *ctlr)
 
 	spi_unmap_msg(ctlr, mesg);
 
+	/* In the prepare_messages callback the spi bus has the opportunity to
+	 * split a transfer to smaller chunks.
+	 * Release splited transfers here since spi_map_msg is done on the
+	 * splited transfers.
+	 */
+	spi_res_release(ctlr, mesg);
+
 	if (ctlr->cur_msg_prepared && ctlr->unprepare_message) {
 		ret = ctlr->unprepare_message(ctlr, mesg);
 		if (ret) {
-- 
2.11.0




[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux