Linux Kernel Mailing List | 26 May 2012 22:46

i2c: tegra: notify transfer-complete after clearing status.

Gitweb:     http://git.kernel.org/linus/;a=commit;h=c889e91d2cc22123f20f40dde0c0a91856a20eea
Commit:     c889e91d2cc22123f20f40dde0c0a91856a20eea
Parent:     3ac0b3379307f9c9bd00beacbf02623ab127e334
Author:     Laxman Dewangan <ldewangan <at> nvidia.com>
AuthorDate: Mon May 7 12:16:19 2012 +0530
Committer:  Wolfram Sang <w.sang <at> pengutronix.de>
CommitDate: Sat May 12 16:10:12 2012 +0200

    i2c: tegra: notify transfer-complete after clearing status.

    The notification of the transfer complete by calling complete()
    should be done after clearing all interrupt status.
    This avoids the race condition of misconfigure the i2c controller
    in multi-core environment.

    Signed-off-by: Laxman Dewangan <ldewangan <at> nvidia.com>
    Acked-by: Stephen Warren <swarren <at> wwwdotorg.org>
    Signed-off-by: Wolfram Sang <w.sang <at> pengutronix.de>
    Cc: stable <at> kernel.org
---
 drivers/i2c/busses/i2c-tegra.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 18067b3..8b2e555 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
 <at>  <at>  -401,8 +401,6  <at>  <at>  static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 			disable_irq_nosync(i2c_dev->irq);
 			i2c_dev->irq_disabled = 1;
 		}
-
-		complete(&i2c_dev->msg_complete);
 		goto err;
 	}

 <at>  <at>  -411,7 +409,6  <at>  <at>  static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 			i2c_dev->msg_err |= I2C_ERR_NO_ACK;
 		if (status & I2C_INT_ARBITRATION_LOST)
 			i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST;
-		complete(&i2c_dev->msg_complete);
 		goto err;
 	}

 <at>  <at>  -429,14 +426,14  <at>  <at>  static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 			tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ);
 	}

+	i2c_writel(i2c_dev, status, I2C_INT_STATUS);
+	if (i2c_dev->is_dvc)
+		dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
+
 	if (status & I2C_INT_PACKET_XFER_COMPLETE) {
 		BUG_ON(i2c_dev->msg_buf_remaining);
 		complete(&i2c_dev->msg_complete);
 	}

Gmane