aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-05-07 02:46:19 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-05-12 10:10:12 -0400
commitc889e91d2cc22123f20f40dde0c0a91856a20eea (patch)
tree82119964f7b663140b10ede80bf1759471d79972 /drivers
parent3ac0b3379307f9c9bd00beacbf02623ab127e334 (diff)
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@nvidia.com> Acked-by: Stephen Warren <swarren@wwwdotorg.org> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Cc: stable@kernel.org
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-tegra.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 18067b3ee8c9..8b2e555a9563 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
401 disable_irq_nosync(i2c_dev->irq); 401 disable_irq_nosync(i2c_dev->irq);
402 i2c_dev->irq_disabled = 1; 402 i2c_dev->irq_disabled = 1;
403 } 403 }
404
405 complete(&i2c_dev->msg_complete);
406 goto err; 404 goto err;
407 } 405 }
408 406
@@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
411 i2c_dev->msg_err |= I2C_ERR_NO_ACK; 409 i2c_dev->msg_err |= I2C_ERR_NO_ACK;
412 if (status & I2C_INT_ARBITRATION_LOST) 410 if (status & I2C_INT_ARBITRATION_LOST)
413 i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; 411 i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST;
414 complete(&i2c_dev->msg_complete);
415 goto err; 412 goto err;
416 } 413 }
417 414
@@ -429,14 +426,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
429 tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); 426 tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ);
430 } 427 }
431 428
429 i2c_writel(i2c_dev, status, I2C_INT_STATUS);
430 if (i2c_dev->is_dvc)
431 dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
432
432 if (status & I2C_INT_PACKET_XFER_COMPLETE) { 433 if (status & I2C_INT_PACKET_XFER_COMPLETE) {
433 BUG_ON(i2c_dev->msg_buf_remaining); 434 BUG_ON(i2c_dev->msg_buf_remaining);
434 complete(&i2c_dev->msg_complete); 435 complete(&i2c_dev->msg_complete);
435 } 436 }
436
437 i2c_writel(i2c_dev, status, I2C_INT_STATUS);
438 if (i2c_dev->is_dvc)
439 dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
440 return IRQ_HANDLED; 437 return IRQ_HANDLED;
441err: 438err:
442 /* An error occurred, mask all interrupts */ 439 /* An error occurred, mask all interrupts */
@@ -446,6 +443,8 @@ err:
446 i2c_writel(i2c_dev, status, I2C_INT_STATUS); 443 i2c_writel(i2c_dev, status, I2C_INT_STATUS);
447 if (i2c_dev->is_dvc) 444 if (i2c_dev->is_dvc)
448 dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); 445 dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
446
447 complete(&i2c_dev->msg_complete);
449 return IRQ_HANDLED; 448 return IRQ_HANDLED;
450} 449}
451 450