[3.13.y.z extended stable] Patch "i2c: at91: Fix a race condition during signal handling in at91_do_twi_xfer." has been added to staging queue

Kamal Mostafa kamal at canonical.com
Tue Sep 30 21:29:48 UTC 2014

This is a note to let you know that I have just added a patch titled

    i2c: at91: Fix a race condition during signal handling in at91_do_twi_xfer.

to the linux-3.13.y-queue branch of the 3.13.y.z extended stable tree 
which can be found at:


This patch is scheduled to be released in version

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.13.y.z tree, see



>From 7ecde1db23fc0567eade80472c52766964161c4d Mon Sep 17 00:00:00 2001
From: Simon Lindgren <simon at aqwary.com>
Date: Tue, 26 Aug 2014 21:13:24 +0200
Subject: i2c: at91: Fix a race condition during signal handling in

commit 6721f28a26efd6368497abbdef5dcfc59608d899 upstream.

There is a race condition in at91_do_twi_xfer when signals arrive.
If a signal is recieved while waiting for a transfer to complete
wait_for_completion_interruptible_timeout() will return -ERESTARTSYS.
This is not handled correctly resulting in interrupts still being
enabled and a transfer being in flight when we return.

Symptoms include a range of oopses and bus lockups. Oopses can happen
when the transfer completes because the interrupt handler will corrupt
the stack. If a new transfer is started before the interrupt fires
the controller will start a new transfer in the middle of the old one,
resulting in confused slaves and a locked bus.

To avoid this, use wait_for_completion_io_timeout instead so that we
don't have to deal with gracefully shutting down the transfer and
disabling the interrupts.

Signed-off-by: Simon Lindgren <simon at aqwary.com>
Acked-by: Ludovic Desroches <ludovic.desroches at atmel.com>
Signed-off-by: Wolfram Sang <wsa at the-dreams.de>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
 drivers/i2c/busses/i2c-at91.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index d13d3bb..ae4cdc0 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -421,8 +421,8 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)

-	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
-							dev->adapter.timeout);
+	ret = wait_for_completion_io_timeout(&dev->cmd_complete,
+					     dev->adapter.timeout);
 	if (ret == 0) {
 		dev_err(dev->dev, "controller timed out\n");

More information about the kernel-team mailing list