This is a note to let you know that I've just added the patch titled i2c: hisi: Only use the completion interrupt to finish the transfer to the 5.15-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: i2c-hisi-only-use-the-completion-interrupt-to-finish.patch and it can be found in the queue-5.15 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 761f47aafd9b65d8daf8328c50acde69ad1a414a Author: Yicong Yang <yangyicong@xxxxxxxxxxxxx> Date: Mon Mar 13 15:45:52 2023 +0800 i2c: hisi: Only use the completion interrupt to finish the transfer [ Upstream commit d98263512684a47e81bcb72a5408958ecd1e60b0 ] 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@xxxxxxxxxx> Signed-off-by: Sheng Feng <fengsheng5@xxxxxxxxxx> Signed-off-by: Yicong Yang <yangyicong@xxxxxxxxxxxxx> Signed-off-by: Wolfram Sang <wsa@xxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/i2c/busses/i2c-hisi.c b/drivers/i2c/busses/i2c-hisi.c index acf3948120613..72e43ecaff133 100644 --- a/drivers/i2c/busses/i2c-hisi.c +++ b/drivers/i2c/busses/i2c-hisi.c @@ -340,7 +340,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);