[PATCH] i2c: npcm7xx: Fix callback completion ordering

William A. Kennington III posted 1 patch 2 years, 4 months ago
drivers/i2c/busses/i2c-npcm7xx.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
[PATCH] i2c: npcm7xx: Fix callback completion ordering
Posted by William A. Kennington III 2 years, 4 months ago
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>
---
 drivers/i2c/busses/i2c-npcm7xx.c | 17 +++++++----------
 1 file 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)
-- 
2.42.0.515.g380fc7ccd1-goog
Re: [PATCH] i2c: npcm7xx: Fix callback completion ordering
Posted by Wolfram Sang 2 years, 4 months ago
On Sat, Sep 23, 2023 at 06:02:14PM -0700, William A. Kennington III wrote:
> 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>

Applied to for-current, thanks!

Re: [PATCH] i2c: npcm7xx: Fix callback completion ordering
Posted by Tali Perry 2 years, 4 months ago
On Sun, Sep 24, 2023 at 4:02 AM William A. Kennington III
<william@wkennington.com> wrote:
>
> 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>
> ---
>  drivers/i2c/busses/i2c-npcm7xx.c | 17 +++++++----------
>  1 file 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)
> --
> 2.42.0.515.g380fc7ccd1-goog
>

Thanks William for the fix!

Reviewed-by: Tali Perry <tali.perry1@gmail.com>