Commit c889e91d authored by Laxman Dewangan's avatar Laxman Dewangan Committed by Wolfram Sang

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: default avatarLaxman Dewangan <ldewangan@nvidia.com>
Acked-by: default avatarStephen Warren <swarren@wwwdotorg.org>
Signed-off-by: default avatarWolfram Sang <w.sang@pengutronix.de>
Cc: stable@kernel.org
parent 3ac0b337
...@@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
disable_irq_nosync(i2c_dev->irq); disable_irq_nosync(i2c_dev->irq);
i2c_dev->irq_disabled = 1; i2c_dev->irq_disabled = 1;
} }
complete(&i2c_dev->msg_complete);
goto err; goto err;
} }
...@@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
i2c_dev->msg_err |= I2C_ERR_NO_ACK; i2c_dev->msg_err |= I2C_ERR_NO_ACK;
if (status & I2C_INT_ARBITRATION_LOST) if (status & I2C_INT_ARBITRATION_LOST)
i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST;
complete(&i2c_dev->msg_complete);
goto err; goto err;
} }
...@@ -429,14 +426,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -429,14 +426,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); 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) { if (status & I2C_INT_PACKET_XFER_COMPLETE) {
BUG_ON(i2c_dev->msg_buf_remaining); BUG_ON(i2c_dev->msg_buf_remaining);
complete(&i2c_dev->msg_complete); complete(&i2c_dev->msg_complete);
} }
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
return IRQ_HANDLED; return IRQ_HANDLED;
err: err:
/* An error occurred, mask all interrupts */ /* An error occurred, mask all interrupts */
...@@ -446,6 +443,8 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -446,6 +443,8 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
i2c_writel(i2c_dev, status, I2C_INT_STATUS); i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc) if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
complete(&i2c_dev->msg_complete);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment