summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorYicong Yang <yangyicong@hisilicon.com>2023-03-13 15:45:52 +0800
committerWolfram Sang <wsa@kernel.org>2023-03-16 21:02:15 +0100
commitd98263512684a47e81bcb72a5408958ecd1e60b0 (patch)
tree994045fad33e2630909891469ae8900231b1be6a /drivers/i2c
parentcc9812a3096d1986caca9a23bee99effc45c08df (diff)
downloadlinux-stable-d98263512684a47e81bcb72a5408958ecd1e60b0.tar.gz
linux-stable-d98263512684a47e81bcb72a5408958ecd1e60b0.tar.bz2
linux-stable-d98263512684a47e81bcb72a5408958ecd1e60b0.zip
i2c: hisi: Only use the completion interrupt to finish the transfer
The controller will always generate a completion interrupt when the transfer is finished normally or not. Currently we use either error or completion interrupt to finish, this may result the completion interrupt unhandled and corrupt the next transfer, especially at low speed mode. Since on error case, the error interrupt will come first then is the completion interrupt. So only use the completion interrupt to finish the whole transfer process. Fixes: d62fbdb99a85 ("i2c: add support for HiSilicon I2C controller") Reported-by: Sheng Feng <fengsheng5@huawei.com> Signed-off-by: Sheng Feng <fengsheng5@huawei.com> Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-hisi.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-hisi.c b/drivers/i2c/busses/i2c-hisi.c
index 1b7609a34f4a..e067671b3ce2 100644
--- a/drivers/i2c/busses/i2c-hisi.c
+++ b/drivers/i2c/busses/i2c-hisi.c
@@ -348,7 +348,11 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context)
hisi_i2c_read_rx_fifo(ctlr);
out:
- if (int_stat & HISI_I2C_INT_TRANS_CPLT || ctlr->xfer_err) {
+ /*
+ * Only use TRANS_CPLT to indicate the completion. On error cases we'll
+ * get two interrupts, INT_ERR first then TRANS_CPLT.
+ */
+ if (int_stat & HISI_I2C_INT_TRANS_CPLT) {
hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
complete(ctlr->completion);