diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-03-07 12:11:41 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 00:49:19 -0700 |
commit | 7517a6cc8d91f17a4a7da2b63791b6410d13b592 (patch) | |
tree | 3027fb65927555e6d7c57b5f5eb2649bce0c2137 /drivers/i2c | |
parent | a407b08cc8d976c747cb8d078ee5c6c4a40f84ab (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>
Rebase-Id: Rab617c55de93014bc6a34f4540d8e6278b2cd2eb
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 0385bae5083c..4bea5ee76e15 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -326,12 +326,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) >> @@ -370,7 +377,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. */ |