2024-05-30 07:12:17

by Tommy Huang

[permalink] [raw]
Subject: [PATCH] i2c: aspeed: Update the stop sw state when the bus recovry occurs

When the i2c bus recovey occurs, driver will send i2c stop command
in the scl low condition. In this case the sw state will still keep
original situation. Under multi-master usage, i2c bus recovery will
be called when i2c transfer timeout occurs. Update the stop command
calling with aspeed_i2c_do_stop function to update master_state.

Fixes: f327c686d3ba ("i2c: aspeed: added driver for Aspeed I2C")

Signed-off-by: Tommy Huang <[email protected]>
---
drivers/i2c/busses/i2c-aspeed.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index ce8c4846b7fa..32f8b0c1c174 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -169,6 +169,7 @@ struct aspeed_i2c_bus {
};

static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
+static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus);

static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
{
@@ -187,7 +188,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
command);

reinit_completion(&bus->cmd_complete);
- writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
+ aspeed_i2c_do_stop(bus);
spin_unlock_irqrestore(&bus->lock, flags);

time_left = wait_for_completion_timeout(
--
2.25.1



2024-05-30 07:49:31

by Paul Menzel

[permalink] [raw]
Subject: Re: [PATCH] i2c: aspeed: Update the stop sw state when the bus recovry occurs

Dear Tommy,


Thank you for your patch.

Am 30.05.24 um 09:06 schrieb Tommy Huang:
> When the i2c bus recovey occurs, driver will send i2c stop command

recove*r*y

> in the scl low condition. In this case the sw state will still keep
> original situation. Under multi-master usage, i2c bus recovery will

What is the user visible problem?

> be called when i2c transfer timeout occurs. Update the stop command
> calling with aspeed_i2c_do_stop function to update master_state.

How can this be tested?

> Fixes: f327c686d3ba ("i2c: aspeed: added driver for Aspeed I2C")
>

The blank line can be removed.

> Signed-off-by: Tommy Huang <[email protected]>
> ---
> drivers/i2c/busses/i2c-aspeed.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index ce8c4846b7fa..32f8b0c1c174 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -169,6 +169,7 @@ struct aspeed_i2c_bus {
> };
>
> static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
> +static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus);
>
> static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> {
> @@ -187,7 +188,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> command);
>
> reinit_completion(&bus->cmd_complete);
> - writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
> + aspeed_i2c_do_stop(bus);
> spin_unlock_irqrestore(&bus->lock, flags);
>
> time_left = wait_for_completion_timeout(


Kind regards,

Paul

2024-05-30 08:03:46

by Tommy Huang

[permalink] [raw]
Subject: RE: [PATCH] i2c: aspeed: Update the stop sw state when the bus recovry occurs

Hi Paul,

Thanks for your comments.

> -----Original Message-----
> From: Paul Menzel <[email protected]>
> Sent: Thursday, May 30, 2024 3:48 PM
> To: Tommy Huang <[email protected]>
> Cc: [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> BMC-SW <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]
> Subject: Re: [PATCH] i2c: aspeed: Update the stop sw state when the bus
> recovry occurs
>
> Dear Tommy,
>
>
> Thank you for your patch.
>
> Am 30.05.24 um 09:06 schrieb Tommy Huang:
> > When the i2c bus recovey occurs, driver will send i2c stop command
>
> recove*r*y

I will fix this spelling typo on next patch. Thanks.

>
> > in the scl low condition. In this case the sw state will still keep
> > original situation. Under multi-master usage, i2c bus recovery will
>
> What is the user visible problem?
>

In the multi-master case, the i2c transfer timeout will execute the aspeed_i2c_recover_bus.
What we noticed when timeout appears, and kernel panic is observed:
- xfer goes through aspeed_i2c_recovery_bus
- inside recovery we can see “SCL hung (state ec0b0000), attempting recovery”.
- STOP_CMD is performed but time_left = 0 what causes that aspeed_i2c_reset is called (and returns 0)
- Going out of timeout handling, release memory, irq handler is invoked and rise interrupt causing that released memory is used.

> > be called when i2c transfer timeout occurs. Update the stop command
> > calling with aspeed_i2c_do_stop function to update master_state.
>
> How can this be tested?

It just updates master_state for usage safety. The original stop command still be triggered.
>
> > Fixes: f327c686d3ba ("i2c: aspeed: added driver for Aspeed I2C")
> >
>
> The blank line can be removed.
>
> > Signed-off-by: Tommy Huang <[email protected]>
> > ---
> > drivers/i2c/busses/i2c-aspeed.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-aspeed.c
> > b/drivers/i2c/busses/i2c-aspeed.c index ce8c4846b7fa..32f8b0c1c174
> > 100644
> > --- a/drivers/i2c/busses/i2c-aspeed.c
> > +++ b/drivers/i2c/busses/i2c-aspeed.c
> > @@ -169,6 +169,7 @@ struct aspeed_i2c_bus {
> > };
> >
> > static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
> > +static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus);
> >
> > static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> > {
> > @@ -187,7 +188,7 @@ static int aspeed_i2c_recover_bus(struct
> aspeed_i2c_bus *bus)
> > command);
> >
> > reinit_completion(&bus->cmd_complete);
> > - writel(ASPEED_I2CD_M_STOP_CMD, bus->base +
> ASPEED_I2C_CMD_REG);
> > + aspeed_i2c_do_stop(bus);
> > spin_unlock_irqrestore(&bus->lock, flags);
> >
> > time_left = wait_for_completion_timeout(
>
>
> Kind regards,
>
> Paul

BR,

Tommy

2024-06-06 01:27:30

by Andi Shyti

[permalink] [raw]
Subject: Re: [PATCH] i2c: aspeed: Update the stop sw state when the bus recovry occurs

Hi Tommy,

On Thu, May 30, 2024 at 03:06:56PM +0800, Tommy Huang wrote:
> When the i2c bus recovey occurs, driver will send i2c stop command
> in the scl low condition. In this case the sw state will still keep
> original situation. Under multi-master usage, i2c bus recovery will
> be called when i2c transfer timeout occurs. Update the stop command
> calling with aspeed_i2c_do_stop function to update master_state.
>
> Fixes: f327c686d3ba ("i2c: aspeed: added driver for Aspeed I2C")
>
> Signed-off-by: Tommy Huang <[email protected]>

Can you please add:

Cc: <[email protected]> # v4.13+

> ---
> drivers/i2c/busses/i2c-aspeed.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index ce8c4846b7fa..32f8b0c1c174 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -169,6 +169,7 @@ struct aspeed_i2c_bus {
> };
>
> static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
> +static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus);

Can you please move aspeed_i2c_do_stop() on top? Doesn't make
much sense to add the prototype here as there is no dependencies.

It's different the case of aspeed_i2c_reset() because it needs
aspeed_i2c_init().

> static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> {
> @@ -187,7 +188,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> command);
>
> reinit_completion(&bus->cmd_complete);
> - writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
> + aspeed_i2c_do_stop(bus);

The patch is good, though!

Thanks,
Andi

2024-06-08 04:38:35

by Tommy Huang

[permalink] [raw]
Subject: RE: [PATCH] i2c: aspeed: Update the stop sw state when the bus recovry occurs

Hi Andi,

> -----Original Message-----
> From: Andi Shyti <[email protected]>
> Sent: Thursday, June 6, 2024 9:27 AM
> To: Tommy Huang <[email protected]>
> Cc: [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; BMC-SW
> <[email protected]>
> Subject: Re: [PATCH] i2c: aspeed: Update the stop sw state when the bus
> recovry occurs
>
> Hi Tommy,
>
> On Thu, May 30, 2024 at 03:06:56PM +0800, Tommy Huang wrote:
> > When the i2c bus recovey occurs, driver will send i2c stop command in
> > the scl low condition. In this case the sw state will still keep
> > original situation. Under multi-master usage, i2c bus recovery will be
> > called when i2c transfer timeout occurs. Update the stop command
> > calling with aspeed_i2c_do_stop function to update master_state.
> >
> > Fixes: f327c686d3ba ("i2c: aspeed: added driver for Aspeed I2C")
> >
> > Signed-off-by: Tommy Huang <[email protected]>
>
> Can you please add:
>
> Cc: <[email protected]> # v4.13+

Got it. I will add it.

>
> > ---
> > drivers/i2c/busses/i2c-aspeed.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-aspeed.c
> > b/drivers/i2c/busses/i2c-aspeed.c index ce8c4846b7fa..32f8b0c1c174
> > 100644
> > --- a/drivers/i2c/busses/i2c-aspeed.c
> > +++ b/drivers/i2c/busses/i2c-aspeed.c
> > @@ -169,6 +169,7 @@ struct aspeed_i2c_bus { };
> >
> > static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
> > +static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus);
>
> Can you please move aspeed_i2c_do_stop() on top? Doesn't make much sense
> to add the prototype here as there is no dependencies.

Sure. I will update it.

>
> It's different the case of aspeed_i2c_reset() because it needs aspeed_i2c_init().
>
> > static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) { @@
> > -187,7 +188,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus
> *bus)
> > command);
> >
> > reinit_completion(&bus->cmd_complete);
> > - writel(ASPEED_I2CD_M_STOP_CMD, bus->base +
> ASPEED_I2C_CMD_REG);
> > + aspeed_i2c_do_stop(bus);
>
> The patch is good, though!
>

Thanks for your commects.

> Thanks,
> Andi

2024-06-11 00:34:13

by Tommy Huang

[permalink] [raw]
Subject: RE: [PATCH] i2c: aspeed: Update the stop sw state when the bus recovry occurs

Hi Andi,

There is a problem to move aspeed_i2c_do_stop() on top.
This function is like with aspeed_i2c_reset function needs the aspeed_i2c_bus structure definition.

BR,

By Tommy

> -----Original Message-----
> From: Tommy Huang <[email protected]>
> Sent: Saturday, June 8, 2024 12:38 PM
> To: Andi Shyti <[email protected]>
> Cc: [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; BMC-SW
> <[email protected]>
> Subject: RE: [PATCH] i2c: aspeed: Update the stop sw state when the bus
> recovry occurs
>
> Hi Andi,
>
> > -----Original Message-----
> > From: Andi Shyti <[email protected]>
> > Sent: Thursday, June 6, 2024 9:27 AM
> > To: Tommy Huang <[email protected]>
> > Cc: [email protected]; [email protected];
> > [email protected]; [email protected]; [email protected];
> > [email protected]; [email protected];
> > [email protected];
> > [email protected]; [email protected]; BMC-SW
> > <[email protected]>
> > Subject: Re: [PATCH] i2c: aspeed: Update the stop sw state when the
> > bus recovry occurs
> >
> > Hi Tommy,
> >
> > On Thu, May 30, 2024 at 03:06:56PM +0800, Tommy Huang wrote:
> > > When the i2c bus recovey occurs, driver will send i2c stop command
> > > in the scl low condition. In this case the sw state will still keep
> > > original situation. Under multi-master usage, i2c bus recovery will
> > > be called when i2c transfer timeout occurs. Update the stop command
> > > calling with aspeed_i2c_do_stop function to update master_state.
> > >
> > > Fixes: f327c686d3ba ("i2c: aspeed: added driver for Aspeed I2C")
> > >
> > > Signed-off-by: Tommy Huang <[email protected]>
> >
> > Can you please add:
> >
> > Cc: <[email protected]> # v4.13+
>
> Got it. I will add it.
>
> >
> > > ---
> > > drivers/i2c/busses/i2c-aspeed.c | 3 ++-
> > > 1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/i2c/busses/i2c-aspeed.c
> > > b/drivers/i2c/busses/i2c-aspeed.c index ce8c4846b7fa..32f8b0c1c174
> > > 100644
> > > --- a/drivers/i2c/busses/i2c-aspeed.c
> > > +++ b/drivers/i2c/busses/i2c-aspeed.c
> > > @@ -169,6 +169,7 @@ struct aspeed_i2c_bus { };
> > >
> > > static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
> > > +static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus);
> >
> > Can you please move aspeed_i2c_do_stop() on top? Doesn't make much
> > sense to add the prototype here as there is no dependencies.
>
> Sure. I will update it.
>
> >
> > It's different the case of aspeed_i2c_reset() because it needs
> aspeed_i2c_init().
> >
> > > static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) { @@
> > > -187,7 +188,7 @@ static int aspeed_i2c_recover_bus(struct
> > > aspeed_i2c_bus
> > *bus)
> > > command);
> > >
> > > reinit_completion(&bus->cmd_complete);
> > > - writel(ASPEED_I2CD_M_STOP_CMD, bus->base +
> > ASPEED_I2C_CMD_REG);
> > > + aspeed_i2c_do_stop(bus);
> >
> > The patch is good, though!
> >
>
> Thanks for your commects.
>
> > Thanks,
> > Andi