Commit 705ee1e2 authored by Simon Lindgren's avatar Simon Lindgren Committed by Greg Kroah-Hartman

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

commit 6721f28a 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: default avatarSimon Lindgren <simon@aqwary.com>
Acked-by: default avatarLudovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b998a12e
...@@ -434,7 +434,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) ...@@ -434,7 +434,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
} }
} }
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, ret = wait_for_completion_io_timeout(&dev->cmd_complete,
dev->adapter.timeout); dev->adapter.timeout);
if (ret == 0) { if (ret == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment