summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-03-07 12:11:41 +0530
committerSimone Willett <swillett@nvidia.com>2012-05-30 10:09:19 -0700
commitecfc4f641d3bc4491170d6a5dd212ff587683bfa (patch)
tree433dae3936a3fcf79cd475a4ead8d035ad857c2f /drivers
parent58f7137049f6e7ad1d41fda34f68753de89bee39 (diff)
i2c: tegra: Fix possible race condition.
on tegra3, the i2c communication start immediately after writing the tx fifo. And hence there is possibility to complete the transfer and generates done interrupt before actually sw updates their local pointers/count. This patch will make sure that pointers/count can get updated before data written into the fifo. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/89510 (cherry picked from commit 999c09f0ed32f271e767a319dd094947e63fdb8c) Change-Id: I8e974b83b5306ec3363d4ca31ce1b539a498ca08 Signed-off-by: Johnny Qiu <joqiu@nvidia.com> Reviewed-on: http://git-master/r/99997 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-tegra.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 96916bed997f..1358dc70b0e4 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -331,12 +331,19 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
int tx_fifo_avail;
- u8 *buf = i2c_dev->msg_buf;
- size_t buf_remaining = i2c_dev->msg_buf_remaining;
+ u8 *buf;
+ size_t buf_remaining;
int words_to_transfer;
unsigned long flags;
spin_lock_irqsave(&i2c_dev->fifo_lock, flags);
+ if (!i2c_dev->msg_buf_remaining) {
+ spin_unlock_irqrestore(&i2c_dev->fifo_lock, flags);
+ return 0;
+ }
+
+ buf = i2c_dev->msg_buf;
+ buf_remaining = i2c_dev->msg_buf_remaining;
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
@@ -375,7 +382,12 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
* boundary and fault.
*/
if (tx_fifo_avail > 0 && buf_remaining > 0) {
- BUG_ON(buf_remaining > 3);
+ if (buf_remaining > 3) {
+ dev_err(i2c_dev->dev,
+ "Remaining buffer more than 3 %d\n",
+ buf_remaining);
+ BUG();
+ }
memcpy(&val, buf, buf_remaining);
/* Again update before writing to FIFO to make sure isr sees. */