summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorWilliam A. Kennington III <william@wkennington.com>2023-09-23 18:02:14 -0700
committerWolfram Sang <wsa@kernel.org>2023-09-27 21:32:06 +0200
commit92e73d807b68b2214fcafca4e130b5300a9d4b3c (patch)
tree48f67cd004bb6b1f94a6570ce5f09b90a71499dd /drivers
parentb13e59e74ff71a1004e0508107e91e9a84fd7388 (diff)
downloadlinux-stable-92e73d807b68b2214fcafca4e130b5300a9d4b3c.tar.gz
linux-stable-92e73d807b68b2214fcafca4e130b5300a9d4b3c.tar.bz2
linux-stable-92e73d807b68b2214fcafca4e130b5300a9d4b3c.zip
i2c: npcm7xx: Fix callback completion ordering
Sometimes, our completions race with new master transfers and override the bus->operation and bus->master_or_slave variables. This causes transactions to timeout and kernel crashes less frequently. To remedy this, we re-order all completions to the very end of the function. Fixes: 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver") Signed-off-by: William A. Kennington III <william@wkennington.com> Reviewed-by: Tali Perry <tali.perry1@gmail.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-npcm7xx.c17
1 files changed, 7 insertions, 10 deletions
diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
index 495a8b5f6a2b..ae4bae63ad4f 100644
--- a/drivers/i2c/busses/i2c-npcm7xx.c
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
@@ -694,6 +694,7 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
{
struct i2c_msg *msgs;
int msgs_num;
+ bool do_complete = false;
msgs = bus->msgs;
msgs_num = bus->msgs_num;
@@ -722,23 +723,17 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
msgs[1].flags & I2C_M_RD)
msgs[1].len = info;
}
- if (completion_done(&bus->cmd_complete) == false)
- complete(&bus->cmd_complete);
- break;
-
+ do_complete = true;
+ break;
case I2C_NACK_IND:
/* MASTER transmit got a NACK before tx all bytes */
bus->cmd_err = -ENXIO;
- if (bus->master_or_slave == I2C_MASTER)
- complete(&bus->cmd_complete);
-
+ do_complete = true;
break;
case I2C_BUS_ERR_IND:
/* Bus error */
bus->cmd_err = -EAGAIN;
- if (bus->master_or_slave == I2C_MASTER)
- complete(&bus->cmd_complete);
-
+ do_complete = true;
break;
case I2C_WAKE_UP_IND:
/* I2C wake up */
@@ -752,6 +747,8 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
if (bus->slave)
bus->master_or_slave = I2C_SLAVE;
#endif
+ if (do_complete)
+ complete(&bus->cmd_complete);
}
static u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus)