]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
i2c: npcm7xx: Fix callback completion ordering
authorWilliam A. Kennington III <william@wkennington.com>
Sun, 24 Sep 2023 01:02:14 +0000 (18:02 -0700)
committerWolfram Sang <wsa@kernel.org>
Wed, 27 Sep 2023 19:32:06 +0000 (21:32 +0200)
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>
drivers/i2c/busses/i2c-npcm7xx.c

index 495a8b5f6a2ba31c430a89d37c252a780d6ceb50..ae4bae63ad4f3c3086635928acdd9b46deb10c28 100644 (file)
@@ -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)