public inbox for linux-i2c@vger.kernel.org
 help / color / mirror / Atom feed
From: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
To: David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
Cc: Linux I2C <linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [patch 2.6.27-rc7] i2c: smbalert# support
Date: Fri, 21 Nov 2008 15:18:08 +0100	[thread overview]
Message-ID: <20081121151808.324ca78c@hyperion.delvare> (raw)
In-Reply-To: <200811181401.34809.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>

Hi David,

On Tue, 18 Nov 2008 14:01:34 -0800, David Brownell wrote:
> +struct alert_data {
> +	unsigned short	addr;
> +	bool		flag;
> +};
> +
> +/* If this is the alerting device, notify its driver. */
> +static int i2c_do_alert(struct device *dev, void *addrp)
> +{
> +	struct i2c_client	*client = i2c_verify_client(dev);
> +	struct alert_data	*data = addrp;
> +
> +	if (!client || client->addr != data->addr)
> +		return 0;
> +	if (client->flags & I2C_CLIENT_TEN)
> +		return 0;
> +
> +	/* Drivers should either disable alerts, or provide at least
> +	 * a minimal handler.  Lock so client->driver won't change.
> +	 */
> +	down(&dev->sem);
> +	if (client->driver) {
> +		if (client->driver->alert)
> +			client->driver->alert(client, data->flag);
> +		else
> +			dev_warn(&client->dev, "no driver alert()!\n");
> +	} else
> +		dev_dbg(&client->dev, "alert with no driver\n");
> +	up(&dev->sem);
> +
> +	/* Stop iterating after we find the device. */
> +	return -EBUSY;
> +}
> +
> +/*
> + * The alert IRQ handler needs to hand work off to a task which can issue
> + * SMBus calls, because those sleeping calls can't be made in IRQ context.
> + */
> +static void smbus_alert(struct work_struct *work)
> +{
> +	struct i2c_adapter	*bus;
> +
> +	bus = container_of(work, struct i2c_adapter, alert);
> +	for (;;) {
> +		s32			status;
> +		struct alert_data	data;
> +
> +		/* Devices with pending alerts reply in address order, low
> +		 * to high, because of slave transmit arbitration.  After
> +		 * responding, an SMBus device stops asserting SMBALERT#.
> +		 *
> +		 * NOTE that SMBus 2.0 reserves 10-bit addresess for future
> +		 * use.  We neither handle them, nor try to use PEC here.
> +		 */
> +		status = i2c_smbus_read_byte(bus->ara);
> +		if (status < 0)
> +			break;
> +
> +		data.flag = (status & 1) != 0;
> +		data.addr = status >> 1;
> +		dev_dbg(&bus->dev, "SMBALERT# %s from dev 0x%02x\n",
> +				data.flag ? "true" : "false", data.addr);
> +
> +		/* Notify driver for the device which issued the alert. */
> +		device_for_each_child(&bus->dev, &data, i2c_do_alert);
> +	}
> +
> +	/* We handled all alerts; reenable level-triggered IRQs. */
> +	if (!bus->alert_edge_triggered)
> +		enable_irq(bus->irq);
> +}

I got this function stuck in an endless loop while I was experimenting
with my parallel port evaluation board. You might argue that this is
because my code was bogus or incomplete and that would be correct, but
nevertheless, I don't think we should give driver authors the
possibility to bring their system down that way. Not to mention the
possibility of broken hardware answering to the ARA when it shouldn't.
So, I propose the following addition to make sure that we can't get
stuck in such an endless loop:

From: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Subject: i2c: Dismiss unhandled SMBus alerts

If a given I2C driver doesn't handle SMBus alerts properly, then there
is a risk that smbus_alert() will loop forever. We really do not want
this to happen, so add a detection mechanism which will interrupt the
loop in such a case.

Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/i2c/i2c-core.c |    8 ++++++++
 1 file changed, 8 insertions(+)

--- linux-2.6.28-rc6.orig/drivers/i2c/i2c-core.c	2008-11-21 11:01:53.000000000 +0100
+++ linux-2.6.28-rc6/drivers/i2c/i2c-core.c	2008-11-21 14:55:29.000000000 +0100
@@ -446,6 +446,7 @@ static int i2c_do_alert(struct device *d
 static void smbus_alert(struct work_struct *work)
 {
 	struct i2c_adapter	*bus;
+	unsigned short		prev_addr = 0;
 
 	bus = container_of(work, struct i2c_adapter, alert);
 	for (;;) {
@@ -465,11 +466,18 @@ static void smbus_alert(struct work_stru
 
 		data.flag = (status & 1) != 0;
 		data.addr = status >> 1;
+
+		if (data.addr == prev_addr) {
+			dev_warn(&bus->dev, "Duplicate SMBALERT# from dev "
+				"0x%02x, skipping\n", data.addr);
+			break;
+		}
 		dev_dbg(&bus->dev, "SMBALERT# %s from dev 0x%02x\n",
 				data.flag ? "true" : "false", data.addr);
 
 		/* Notify driver for the device which issued the alert. */
 		device_for_each_child(&bus->dev, &data, i2c_do_alert);
+		prev_addr = data.addr;
 	}
 
 	/* We handled all alerts; reenable level-triggered IRQs. */

What do you think?

Thanks,
-- 
Jean Delvare

  parent reply	other threads:[~2008-11-21 14:18 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <200804161434.54335.laurentp@cse-semaphore.com>
     [not found] ` <20080416153043.02f89554@hyperion.delvare>
     [not found]   ` <200804161027.49943.david-b@pacbell.net>
     [not found]     ` <200804161027.49943.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-02 11:10       ` [patch 2.6.25-git] i2c: smbalert# support David Brownell
     [not found]         ` <200805020410.44723.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-05  5:56           ` [patch 2.6.265-rc1] " David Brownell
     [not found]             ` <200805042256.49252.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-09-23 22:32               ` [patch 2.6.27-rc7] " David Brownell
     [not found]                 ` <200809231532.40083.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-09-26  1:07                   ` [lm-sensors] " Trent Piepho
     [not found]                     ` <Pine.LNX.4.64.0809251728130.7680-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2008-09-26  2:01                       ` David Brownell
     [not found]                         ` <200809251902.00201.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-09-27  0:29                           ` Trent Piepho
     [not found]                             ` <Pine.LNX.4.64.0809261652040.7680-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2008-10-17 19:04                               ` David Brownell
     [not found]                                 ` <200810171204.54448.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-10-17 20:43                                   ` Trent Piepho
2008-11-18  8:15                   ` Jean Delvare
     [not found]                     ` <20081118091546.421d6b78-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-18 22:01                       ` David Brownell
     [not found]                         ` <200811181401.34809.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-19  9:51                           ` [lm-sensors] " Trent Piepho
     [not found]                             ` <Pine.LNX.4.64.0811190140510.11673-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2008-11-19 15:16                               ` Jean Delvare
     [not found]                                 ` <20081119161632.2d0bde9e-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-20 22:00                                   ` Trent Piepho
     [not found]                                     ` <Pine.LNX.4.64.0811201354310.11673-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2008-11-20 22:56                                       ` David Brownell
     [not found]                                         ` <200811201456.36551.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-22  0:55                                           ` Trent Piepho
     [not found]                                             ` <Pine.LNX.4.64.0811211621340.18022-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2008-11-22  2:58                                               ` David Brownell
2008-11-21  8:42                                       ` Jean Delvare
     [not found]                                         ` <20081121094218.34ecd82a-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-22  6:04                                           ` Trent Piepho
     [not found]                                             ` <Pine.LNX.4.64.0811212122370.18022-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2008-11-22 10:13                                               ` Jean Delvare
     [not found]                                                 ` <20081122111340.0bfc2c05-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-22 20:28                                                   ` Trent Piepho
     [not found]                                                     ` <Pine.LNX.4.64.0811221055470.18022-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2008-11-23 21:45                                                       ` Jean Delvare
2008-11-19 13:57                           ` Jean Delvare
     [not found]                             ` <20081119145712.1abaa63f-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-19 18:08                               ` David Brownell
2008-11-21 14:18                           ` Jean Delvare [this message]
     [not found]                             ` <20081121151808.324ca78c-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-21 16:24                               ` David Brownell
     [not found]                                 ` <200811210824.55601.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-21 19:22                                   ` Jean Delvare
     [not found]                                     ` <20081121202223.0261fb9c-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-21 21:54                                       ` David Brownell
     [not found]                                         ` <200811211354.51501.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-22  9:03                                           ` Jean Delvare
     [not found]                                             ` <20081122100344.61cf42b7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-11-22  9:48                                               ` David Brownell

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=20081121151808.324ca78c@hyperion.delvare \
    --to=khali-puyad+kwke1g9huczpvpmw@public.gmane.org \
    --cc=david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox