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
next prev 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