diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-03-07 12:11:41 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-05-30 10:09:19 -0700 |
commit | ecfc4f641d3bc4491170d6a5dd212ff587683bfa (patch) | |
tree | 433dae3936a3fcf79cd475a4ead8d035ad857c2f /drivers/i2c | |
parent | 58f7137049f6e7ad1d41fda34f68753de89bee39 (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/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 18 |
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. */ |