提交 c889e91d 编写于 作者: L Laxman Dewangan 提交者: 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: NLaxman Dewangan <ldewangan@nvidia.com>
Acked-by: NStephen Warren <swarren@wwwdotorg.org>
Signed-off-by: NWolfram Sang <w.sang@pengutronix.de>
Cc: stable@kernel.org
上级 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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册