All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wolfram Sang <wsa+renesas@sang-engineering.com>
To: Guenter Roeck <linux@roeck-us.net>
Cc: Wolfram Sang <wsa@kernel.org>, Jean Delvare <khali@linux-fr.org>,
	linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/2] i2c: smbus: Improve handling of stuck alerts
Date: Sun, 28 Jul 2024 22:01:22 +0200	[thread overview]
Message-ID: <ZqajkhSiuJ23DCUP@shikoro> (raw)
In-Reply-To: <20220110172857.2980523-2-linux@roeck-us.net>

[-- Attachment #1: Type: text/plain, Size: 4166 bytes --]

On Mon, Jan 10, 2022 at 09:28:56AM -0800, Guenter Roeck wrote:
> The following messages were observed while testing alert functionality
> on systems with multiple I2C devices on a single bus if alert was active
> on more than one chip.
> 
> smbus_alert 3-000c: SMBALERT# from dev 0x0c, flag 0
> smbus_alert 3-000c: no driver alert()!
> 
> and:
> 
> smbus_alert 3-000c: SMBALERT# from dev 0x28, flag 0
> 
> Once it starts, this message repeats forever at high rate. There is no
> device at any of the reported addresses.
> 
> Analysis shows that this is seen if multiple devices have the alert pin
> active. Apparently some devices do not support SMBus arbitration correctly.
> They keep sending address bits after detecting an address collision and
> handle the collision not at all or too late.
> Specifically, address 0x0c is seen with ADT7461A at address 0x4c and
> ADM1021 at address 0x18 if alert is active on both chips. Address 0x28 is
> seen with ADT7483 at address 0x2a and ADT7461 at address 0x4c if alert is
> active on both chips.
> 
> Once the system is in bad state (alert is set by more than one chip),
> it often only recovers by power cycling.
> 
> To reduce the impact of this problem, abort the endless loop in
> smbus_alert() if the same address is read more than once and not
> handled by a driver.
> 
> Fixes: b5527a7766f0 ("i2c: Add SMBus alert support")
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>

It fixed the interrupt storm for me and I like the approach. I'd apply
it to for-current once rc1 is released. Two minor changes, though.

> ---
>  drivers/i2c/i2c-smbus.c | 30 ++++++++++++++++++++++++------
>  1 file changed, 24 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
> index d3d06e3b4f3b..533c885b99ac 100644
> --- a/drivers/i2c/i2c-smbus.c
> +++ b/drivers/i2c/i2c-smbus.c
> @@ -34,6 +34,7 @@ static int smbus_do_alert(struct device *dev, void *addrp)
>  	struct i2c_client *client = i2c_verify_client(dev);
>  	struct alert_data *data = addrp;
>  	struct i2c_driver *driver;
> +	int ret;
>  
>  	if (!client || client->addr != data->addr)
>  		return 0;
> @@ -47,16 +48,21 @@ static int smbus_do_alert(struct device *dev, void *addrp)
>  	device_lock(dev);
>  	if (client->dev.driver) {
>  		driver = to_i2c_driver(client->dev.driver);
> -		if (driver->alert)
> +		if (driver->alert) {
>  			driver->alert(client, data->type, data->data);
> -		else
> +			ret = -EBUSY;
> +		} else {
>  			dev_warn(&client->dev, "no driver alert()!\n");
> -	} else
> +			ret = -EOPNOTSUPP;
> +		}
> +	} else {
>  		dev_dbg(&client->dev, "alert with no driver\n");
> +		ret = -ENODEV;
> +	}
>  	device_unlock(dev);
>  
>  	/* Stop iterating after we find the device */

I moved this comment up where -EBUSY is assigned to 'ret'.

> -	return -EBUSY;
> +	return ret;
>  }
>  
>  /*
> @@ -67,6 +73,7 @@ static irqreturn_t smbus_alert(int irq, void *d)
>  {
>  	struct i2c_smbus_alert *alert = d;
>  	struct i2c_client *ara;
> +	unsigned short prev_addr = 0;	/* Not a valid address */

I used I2C_CLIENT_END as an invalid address. We use it for the same
purpose in other parts of the core as well.

>  
>  	ara = alert->ara;
>  
> @@ -94,8 +101,19 @@ static irqreturn_t smbus_alert(int irq, void *d)
>  			data.addr, data.data);
>  
>  		/* Notify driver for the device which issued the alert */
> -		device_for_each_child(&ara->adapter->dev, &data,
> -				      smbus_do_alert);
> +		status = device_for_each_child(&ara->adapter->dev, &data,
> +					       smbus_do_alert);
> +		/*
> +		 * If we read the same address more than once, and the alert
> +		 * was not handled by a driver, it won't do any good to repeat
> +		 * the loop because it will never terminate.
> +		 * Bail out in this case.
> +		 * Note: This assumes that a driver with alert handler handles
> +		 * the alert properly and clears it if necessary.
> +		 */
> +		if (data.addr == prev_addr && status != -EBUSY)
> +			break;
> +		prev_addr = data.addr;
>  	}
>  
>  	return IRQ_HANDLED;
> -- 
> 2.33.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2024-07-28 20:01 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-10 17:28 [PATCH 0/2] i2c: smbus: Handle stuck alerts Guenter Roeck
2022-01-10 17:28 ` [PATCH 1/2] i2c: smbus: Improve handling of " Guenter Roeck
2024-07-28 20:01   ` Wolfram Sang [this message]
2024-07-29  7:49   ` Wolfram Sang
2022-01-10 17:28 ` [PATCH 2/2] i2c: smbus: Send alert notifications to all devices if source not found Guenter Roeck
2024-07-28 20:04   ` Wolfram Sang
2024-07-29  0:31     ` Guenter Roeck
2024-07-29  7:57       ` Wolfram Sang
2024-07-29 14:23         ` Guenter Roeck
2024-07-29 18:36           ` Wolfram Sang
2024-07-29 18:44             ` Guenter Roeck
2024-07-29 20:52               ` Wolfram Sang
2024-07-29 21:39                 ` Guenter Roeck
2024-06-12 17:49 ` [PATCH 0/2] i2c: smbus: Handle stuck alerts Guenter Roeck
2024-06-12 20:21   ` Wolfram Sang
2024-06-12 20:29     ` Guenter Roeck
2024-07-28 19:59 ` Wolfram Sang
2024-07-29  0:31   ` Guenter Roeck
2024-07-29  8:04     ` Wolfram Sang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZqajkhSiuJ23DCUP@shikoro \
    --to=wsa+renesas@sang-engineering.com \
    --cc=khali@linux-fr.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=wsa@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.