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: 56a1485b10
("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>
This commit is contained in:
Родитель
b13e59e74f
Коммит
92e73d807b
|
@ -694,6 +694,7 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
|
||||||
{
|
{
|
||||||
struct i2c_msg *msgs;
|
struct i2c_msg *msgs;
|
||||||
int msgs_num;
|
int msgs_num;
|
||||||
|
bool do_complete = false;
|
||||||
|
|
||||||
msgs = bus->msgs;
|
msgs = bus->msgs;
|
||||||
msgs_num = bus->msgs_num;
|
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].flags & I2C_M_RD)
|
||||||
msgs[1].len = info;
|
msgs[1].len = info;
|
||||||
}
|
}
|
||||||
if (completion_done(&bus->cmd_complete) == false)
|
do_complete = true;
|
||||||
complete(&bus->cmd_complete);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case I2C_NACK_IND:
|
case I2C_NACK_IND:
|
||||||
/* MASTER transmit got a NACK before tx all bytes */
|
/* MASTER transmit got a NACK before tx all bytes */
|
||||||
bus->cmd_err = -ENXIO;
|
bus->cmd_err = -ENXIO;
|
||||||
if (bus->master_or_slave == I2C_MASTER)
|
do_complete = true;
|
||||||
complete(&bus->cmd_complete);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case I2C_BUS_ERR_IND:
|
case I2C_BUS_ERR_IND:
|
||||||
/* Bus error */
|
/* Bus error */
|
||||||
bus->cmd_err = -EAGAIN;
|
bus->cmd_err = -EAGAIN;
|
||||||
if (bus->master_or_slave == I2C_MASTER)
|
do_complete = true;
|
||||||
complete(&bus->cmd_complete);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case I2C_WAKE_UP_IND:
|
case I2C_WAKE_UP_IND:
|
||||||
/* I2C wake up */
|
/* I2C wake up */
|
||||||
|
@ -752,6 +747,8 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
|
||||||
if (bus->slave)
|
if (bus->slave)
|
||||||
bus->master_or_slave = I2C_SLAVE;
|
bus->master_or_slave = I2C_SLAVE;
|
||||||
#endif
|
#endif
|
||||||
|
if (do_complete)
|
||||||
|
complete(&bus->cmd_complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus)
|
static u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче