All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] i2c: Add SMBus alert support
@ 2010-02-13 22:04 Jean Delvare
       [not found] ` <20100213230438.31fd0fd7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: Jean Delvare @ 2010-02-13 22:04 UTC (permalink / raw)
  To: Linux I2C; +Cc: David Brownell, Trent Piepho

Hi all,

This patchset adds SMBus alert support.

[PATCH 1/5] i2c: Add SMBus alert support
[PATCH 2/5] i2c: Separate Kconfig option for i2c-smbus
[PATCH 3/5] i2c-parport: Add SMBus alert support
[PATCH 4/5] i2c-parport-light: Add SMBus alert support
[PATCH 5/5] hwmon: (lm90) Add SMBus alert support

Reviews and testing welcome.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/5] i2c: Add SMBus alert support
       [not found] ` <20100213230438.31fd0fd7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2010-02-13 22:06   ` Jean Delvare
       [not found]     ` <20100213230656.341ec091-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  2010-02-13 22:07   ` [PATCH 2/5] i2c: Separate Kconfig option for i2c-smbus Jean Delvare
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Jean Delvare @ 2010-02-13 22:06 UTC (permalink / raw)
  To: Linux I2C; +Cc: David Brownell, Trent Piepho

SMBus alert support. The SMBus alert protocol allows several SMBus
slave devices to share a single interrupt pin on the SMBus master,
while still allowing the master to know which slave triggered the
interrupt.

This is based on preliminary work by David Brownell. The key
difference between David's implementation and mine is that his was
part of i2c-core, while mine is split into a separate, standalone
module named i2c-smbus. The i2c-smbus module is meant to include
support for all SMBus extensions to the I2C protocol in the future.

The benefit of this approach is a zero cost for I2C bus segments which
do not need SMBus alert support. Where David's implementation
increased the size of struct i2c_adapter by 7% (40 bytes on i386),
mine doesn't touch it. Where David's implementation added over 150
lines of code to i2c-core (+10%), mine doesn't touch it. The only
change that touches all the users of the i2c subsystem is a new
callback in struct i2c_driver (common to both implementations.) I seem
to remember Trent was worried about the footprint of David'd
implementation, hopefully mine addresses the issue.

Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: Trent Piepho <tpiepho-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 Documentation/i2c/smbus-protocol |   16 ++
 drivers/i2c/Makefile             |    2 
 drivers/i2c/i2c-smbus.c          |  264 ++++++++++++++++++++++++++++++++++++++
 include/linux/i2c-smbus.h        |   50 +++++++
 include/linux/i2c.h              |    7 +
 5 files changed, 338 insertions(+), 1 deletion(-)

--- linux-2.6.33-rc7.orig/Documentation/i2c/smbus-protocol	2010-02-12 14:19:47.000000000 +0100
+++ linux-2.6.33-rc7/Documentation/i2c/smbus-protocol	2010-02-12 14:19:51.000000000 +0100
@@ -185,6 +185,22 @@ the protocol. All ARP communications use
 require PEC checksums.
 
 
+SMBus Alert
+===========
+
+SMBus Alert was introduced in Revision 1.0 of the specification.
+
+The SMBus alert protocol allows several SMBus slave devices to share a
+single interrupt pin on the SMBus master, while still allowing the master
+to know which slave triggered the interrupt.
+
+This is implemented the following way in the Linux kernel:
+* I2C bus drivers which support SMBus alert should call
+  i2c_setup_smbus_alert() to setup SMBus alert support.
+* I2C drivers for devices which can trigger SMBus alerts should implement
+  the optional alert() callback.
+
+
 I2C Block Transactions
 ======================
 
--- linux-2.6.33-rc7.orig/drivers/i2c/Makefile	2010-02-12 14:19:47.000000000 +0100
+++ linux-2.6.33-rc7/drivers/i2c/Makefile	2010-02-12 16:08:34.000000000 +0100
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_I2C_BOARDINFO)	+= i2c-boardinfo.o
-obj-$(CONFIG_I2C)		+= i2c-core.o
+obj-$(CONFIG_I2C)		+= i2c-core.o i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-y				+= busses/ chips/ algos/
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.33-rc7/drivers/i2c/i2c-smbus.c	2010-02-12 16:11:34.000000000 +0100
@@ -0,0 +1,264 @@
+/*
+ * i2c-smbus.c - SMBus extensions to the I2C protocol
+ *
+ * Copyright (C) 2010 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
+ *
+ * SMBus alert support based on earlier work by David Brownell (2008).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/semaphore.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
+
+struct i2c_smbus_alert {
+	unsigned int		alert_edge_triggered:1;
+	int			irq;
+	struct work_struct	alert;
+	struct i2c_client	*ara;
+};
+
+struct alert_data {
+	unsigned short		addr;
+	u8			flag:1;
+};
+
+/* If this is the alerting device, notify its driver */
+static int smbus_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_smbus_alert *data;
+	struct i2c_client *ara;
+	unsigned short prev_addr = 0;	/* Not a valid address */
+
+	data = container_of(work, struct i2c_smbus_alert, alert);
+	ara = data->ara;
+
+	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(ara);
+		if (status < 0)
+			break;
+
+		data.flag = status & 1;
+		data.addr = status >> 1;
+
+		if (data.addr == prev_addr) {
+			dev_warn(&ara->dev, "Duplicate SMBALERT# from dev "
+				"0x%02x, skipping\n", data.addr);
+			break;
+		}
+		dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n",
+			data.addr, data.flag);
+
+		/* Notify driver for the device which issued the alert */
+		device_for_each_child(&ara->adapter->dev, &data,
+				      smbus_do_alert);
+		prev_addr = data.addr;
+	}
+
+	/* We handled all alerts; re-enable level-triggered IRQs */
+	if (!data->alert_edge_triggered)
+		enable_irq(data->irq);
+}
+
+static irqreturn_t smbalert_irq(int irq, void *d)
+{
+	struct i2c_smbus_alert *data = d;
+
+	/* Disable level-triggered IRQs until we handle them */
+	if (!data->alert_edge_triggered)
+		disable_irq_nosync(irq);
+
+	schedule_work(&data->alert);
+	return IRQ_HANDLED;
+}
+
+/* Setup SMBALERT# infrastructure */
+static int smbalert_probe(struct i2c_client *ara,
+			  const struct i2c_device_id *id)
+{
+	struct i2c_smbus_alert_setup *setup = ara->dev.platform_data;
+	struct i2c_smbus_alert *data;
+	struct i2c_adapter *adapter = ara->adapter;
+	int res;
+
+	data = kzalloc(sizeof(struct i2c_smbus_alert), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->alert_edge_triggered = setup->alert_edge_triggered;
+	data->irq = setup->irq;
+	INIT_WORK(&data->alert, smbus_alert);
+	data->ara = ara;
+
+	if (setup->irq > 0) {
+		res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq,
+				       0, "smbus_alert", data);
+		if (res) {
+			kfree(data);
+			return res;
+		}
+	}
+
+	i2c_set_clientdata(ara, data);
+	dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n",
+		 setup->alert_edge_triggered ? "edge" : "level");
+
+	return 0;
+}
+
+/* IRQ resource is managed so it is freed automatically */
+static int smbalert_remove(struct i2c_client *ara)
+{
+	struct i2c_smbus_alert *data = i2c_get_clientdata(ara);
+
+	cancel_work_sync(&data->alert);
+
+	i2c_set_clientdata(ara, NULL);
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id smbalert_ids[] = {
+	{ "smbus_alert", 0 },
+	{ /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, smbalert_ids);
+
+static struct i2c_driver smbalert_driver = {
+	.driver = {
+		.name	= "smbus_alert",
+	},
+	.probe		= smbalert_probe,
+	.remove		= smbalert_remove,
+	.id_table	= smbalert_ids,
+};
+
+/**
+ * i2c_setup_smbus_alert - Setup SMBus alert support
+ * @adapter: the target adapter
+ * @setup: setup data for the SMBus alert handler
+ * Context: can sleep
+ *
+ * Setup handling of the SMBus alert protocol on a given I2C bus segment.
+ *
+ * Handling can be done either through our IRQ handler, or by the
+ * adapter (from its handler, periodic polling, or whatever).
+ *
+ * NOTE that if we manage the IRQ, we *MUST* know if it's level or
+ * edge triggered in order to hand it to the workqueue correctly.
+ * If triggering the alert seems to wedge the system, you probably
+ * should have said it's level triggered.
+ *
+ * This returns the ara client, which should be saved for later use with
+ * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
+ * to indicate an error.
+ */
+struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
+					 struct i2c_smbus_alert_setup *setup)
+{
+	struct i2c_board_info ara_board_info = {
+		I2C_BOARD_INFO("smbus_alert", 0x0c),
+		.platform_data = setup,
+	};
+
+	return i2c_new_device(adapter, &ara_board_info);
+}
+EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
+
+/**
+ * i2c_handle_smbus_alert - Handle an SMBus alert
+ * @ara: the ARA client on the relevant adapter
+ * Context: can't sleep
+ *
+ * Helper function to be called from an I2C bus driver's interrupt
+ * handler. It will schedule the alert work, in turn calling the
+ * corresponding I2C device driver's alert function.
+ *
+ * It is assumed that ara is a valid i2c client previously returned by
+ * i2c_setup_smbus_alert().
+ */
+int i2c_handle_smbus_alert(struct i2c_client *ara)
+{
+	struct i2c_smbus_alert *data = i2c_get_clientdata(ara);
+
+	return schedule_work(&data->alert);
+}
+EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);
+
+static int __init i2c_smbus_init(void)
+{
+	return i2c_add_driver(&smbalert_driver);
+}
+
+static void __exit i2c_smbus_exit(void)
+{
+	i2c_del_driver(&smbalert_driver);
+}
+
+module_init(i2c_smbus_init);
+module_exit(i2c_smbus_exit);
+
+MODULE_AUTHOR("Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>");
+MODULE_DESCRIPTION("SMBus protocol extensions support");
+MODULE_LICENSE("GPL");
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.33-rc7/include/linux/i2c-smbus.h	2010-02-12 16:08:43.000000000 +0100
@@ -0,0 +1,50 @@
+/*
+ * i2c-smbus.h - SMBus extensions to the I2C protocol
+ *
+ * Copyright (C) 2010 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LINUX_I2C_SMBUS_H
+#define _LINUX_I2C_SMBUS_H
+
+#include <linux/i2c.h>
+
+
+/**
+ * i2c_smbus_alert_setup - platform data for the smbus_alert i2c client
+ * @alert_edge_triggered: whether the alert interrupt is edge (1) or level (0)
+ *		triggered
+ * @irq: IRQ number, if the smbus_alert driver should take care of interrupt
+ *		handling
+ *
+ * If irq is not specified, the smbus_alert driver doesn't take care of
+ * interrupt handling. In that case it is up to the I2C bus driver to either
+ * handle the interrupts or to poll for alerts.
+ *
+ * If irq is specified then it it crucial that alert_edge_triggered is
+ * properly set.
+ */
+struct i2c_smbus_alert_setup {
+	unsigned int		alert_edge_triggered:1;
+	int			irq;
+};
+
+struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
+					 struct i2c_smbus_alert_setup *setup);
+int i2c_handle_smbus_alert(struct i2c_client *ara);
+
+#endif /* _LINUX_I2C_SMBUS_H */
--- linux-2.6.33-rc7.orig/include/linux/i2c.h	2010-02-12 14:19:47.000000000 +0100
+++ linux-2.6.33-rc7/include/linux/i2c.h	2010-02-12 14:19:51.000000000 +0100
@@ -152,6 +152,13 @@ struct i2c_driver {
 	int (*suspend)(struct i2c_client *, pm_message_t mesg);
 	int (*resume)(struct i2c_client *);
 
+	/* Alert callback, for example for the SMBus alert protocol.
+	 * The format and meaning of the data value depends on the protocol.
+	 * For the SMBus alert protocol, there is a single bit of data passed
+	 * as the alert response's low bit ("event flag").
+	 */
+	void (*alert)(struct i2c_client *, unsigned int data);
+
 	/* a ioctl like command that can be used to perform specific functions
 	 * with the device.
 	 */

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/5] i2c: Separate Kconfig option for i2c-smbus
       [not found] ` <20100213230438.31fd0fd7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  2010-02-13 22:06   ` [PATCH 1/5] " Jean Delvare
@ 2010-02-13 22:07   ` Jean Delvare
  2010-02-13 22:08   ` [PATCH 3/5] i2c-parport: Add SMBus alert support Jean Delvare
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Jean Delvare @ 2010-02-13 22:07 UTC (permalink / raw)
  To: Linux I2C; +Cc: David Brownell, Trent Piepho

Having a separate Kconfig option for i2c-smbus makes it possible to
build that support as a module even when i2c-core itself is built-in.
Bus drivers which implement SMBus alert should select this option, so
in most cases this option is hidden and the user doesn't have to care
about it.

Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: Trent Piepho <tpiepho-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 drivers/i2c/Kconfig  |   10 ++++++++++
 drivers/i2c/Makefile |    3 ++-
 2 files changed, 12 insertions(+), 1 deletion(-)

--- linux-2.6.33-rc7.orig/drivers/i2c/Kconfig	2010-02-12 14:20:30.000000000 +0100
+++ linux-2.6.33-rc7/drivers/i2c/Kconfig	2010-02-12 14:20:35.000000000 +0100
@@ -61,6 +61,16 @@ config I2C_HELPER_AUTO
 
 	  In doubt, say Y.
 
+config I2C_SMBUS
+	tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO
+	help
+	  Say Y here if you want support for SMBus extensions to the I2C
+	  specification. At the moment, the only supported extension is
+	  the SMBus alert protocol.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-smbus.
+
 source drivers/i2c/algos/Kconfig
 source drivers/i2c/busses/Kconfig
 source drivers/i2c/chips/Kconfig
--- linux-2.6.33-rc7.orig/drivers/i2c/Makefile	2010-02-12 14:20:30.000000000 +0100
+++ linux-2.6.33-rc7/drivers/i2c/Makefile	2010-02-12 14:20:35.000000000 +0100
@@ -3,7 +3,8 @@
 #
 
 obj-$(CONFIG_I2C_BOARDINFO)	+= i2c-boardinfo.o
-obj-$(CONFIG_I2C)		+= i2c-core.o i2c-smbus.o
+obj-$(CONFIG_I2C)		+= i2c-core.o
+obj-$(CONFIG_I2C_SMBUS)		+= i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-y				+= busses/ chips/ algos/
 

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 3/5] i2c-parport: Add SMBus alert support
       [not found] ` <20100213230438.31fd0fd7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  2010-02-13 22:06   ` [PATCH 1/5] " Jean Delvare
  2010-02-13 22:07   ` [PATCH 2/5] i2c: Separate Kconfig option for i2c-smbus Jean Delvare
@ 2010-02-13 22:08   ` Jean Delvare
  2010-02-13 22:09   ` [PATCH 4/5] i2c-parport-light: " Jean Delvare
  2010-02-13 22:11   ` [PATCH 5/5] hwmon: (lm90) " Jean Delvare
  4 siblings, 0 replies; 16+ messages in thread
From: Jean Delvare @ 2010-02-13 22:08 UTC (permalink / raw)
  To: Linux I2C; +Cc: David Brownell, Trent Piepho

Add support for the SMBus alert mechanism to the i2c-parport driver.
The ADM1032 evaluation board at least is properly wired for this.

Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: Trent Piepho <tpiepho-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 Documentation/i2c/busses/i2c-parport |    3 ++
 drivers/i2c/busses/Kconfig           |    1 
 drivers/i2c/busses/i2c-parport.c     |   37 ++++++++++++++++++++++++++++++++--
 drivers/i2c/busses/i2c-parport.h     |    4 ++-
 4 files changed, 42 insertions(+), 3 deletions(-)

--- linux-2.6.33-rc7.orig/Documentation/i2c/busses/i2c-parport	2010-02-12 14:20:30.000000000 +0100
+++ linux-2.6.33-rc7/Documentation/i2c/busses/i2c-parport	2010-02-12 14:20:39.000000000 +0100
@@ -29,6 +29,9 @@ can be easily added when needed.
 Earlier kernels defaulted to type=0 (Philips).  But now, if the type
 parameter is missing, the driver will simply fail to initialize.
 
+SMBus alert support is available on adapters which have this line properly
+connected to the parallel port's interrupt pin.
+
 
 Building your own adapter
 -------------------------
--- linux-2.6.33-rc7.orig/drivers/i2c/busses/Kconfig	2010-02-12 14:20:30.000000000 +0100
+++ linux-2.6.33-rc7/drivers/i2c/busses/Kconfig	2010-02-12 14:20:39.000000000 +0100
@@ -571,6 +571,7 @@ config I2C_PARPORT
 	tristate "Parallel port adapter"
 	depends on PARPORT
 	select I2C_ALGOBIT
+	select I2C_SMBUS
 	help
 	  This supports parallel port I2C adapters such as the ones made by
 	  Philips or Velleman, Analog Devices evaluation boards, and more.
--- linux-2.6.33-rc7.orig/drivers/i2c/busses/i2c-parport.c	2010-02-12 14:20:30.000000000 +0100
+++ linux-2.6.33-rc7/drivers/i2c/busses/i2c-parport.c	2010-02-12 14:20:39.000000000 +0100
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2007 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
+   Copyright (C) 2003-2010 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -31,6 +31,7 @@
 #include <linux/parport.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/i2c-smbus.h>
 #include "i2c-parport.h"
 
 /* ----- Device list ------------------------------------------------------ */
@@ -39,6 +40,8 @@ struct i2c_par {
 	struct pardevice *pdev;
 	struct i2c_adapter adapter;
 	struct i2c_algo_bit_data algo_data;
+	struct i2c_smbus_alert_setup alert_data;
+	struct i2c_client *ara;
 	struct i2c_par *next;
 };
 
@@ -144,6 +147,19 @@ static struct i2c_algo_bit_data parport_
 
 /* ----- I2c and parallel port call-back functions and structures --------- */
 
+void i2c_parport_irq(void *data)
+{
+	struct i2c_par *adapter = data;
+	struct i2c_client *ara = adapter->ara;
+
+	if (ara) {
+		dev_dbg(&ara->dev, "SMBus alert received\n");
+		i2c_handle_smbus_alert(ara);
+	} else
+		dev_dbg(&adapter->adapter.dev,
+			"SMBus alert received but no ARA client!\n");
+}
+
 static void i2c_parport_attach (struct parport *port)
 {
 	struct i2c_par *adapter;
@@ -155,8 +171,9 @@ static void i2c_parport_attach (struct p
 	}
 
 	pr_debug("i2c-parport: attaching to %s\n", port->name);
+	parport_disable_irq(port);
 	adapter->pdev = parport_register_device(port, "i2c-parport",
-		NULL, NULL, NULL, PARPORT_FLAG_EXCL, NULL);
+		NULL, NULL, i2c_parport_irq, PARPORT_FLAG_EXCL, adapter);
 	if (!adapter->pdev) {
 		printk(KERN_ERR "i2c-parport: Unable to register with parport\n");
 		goto ERROR0;
@@ -197,6 +214,18 @@ static void i2c_parport_attach (struct p
 		goto ERROR1;
 	}
 
+	/* Setup SMBus alert if supported */
+	if (adapter_parm[type].smbus_alert) {
+		adapter->alert_data.alert_edge_triggered = 1;
+		adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,
+						     &adapter->alert_data);
+		if (adapter->ara)
+			parport_enable_irq(port);
+		else
+			printk(KERN_WARNING "i2c-parport: Failed to register "
+			       "ARA client\n");
+	}
+
 	/* Add the new adapter to the list */
 	adapter->next = adapter_list;
 	adapter_list = adapter;
@@ -217,6 +246,10 @@ static void i2c_parport_detach (struct p
 	for (prev = NULL, adapter = adapter_list; adapter;
 	     prev = adapter, adapter = adapter->next) {
 		if (adapter->pdev->port == port) {
+			if (adapter->ara) {
+				parport_disable_irq(port);
+				i2c_unregister_device(adapter->ara);
+			}
 			i2c_del_adapter(&adapter->adapter);
 
 			/* Un-init if needed (power off...) */
--- linux-2.6.33-rc7.orig/drivers/i2c/busses/i2c-parport.h	2010-02-12 14:20:30.000000000 +0100
+++ linux-2.6.33-rc7/drivers/i2c/busses/i2c-parport.h	2010-02-12 14:20:39.000000000 +0100
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.h I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2004 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
+   Copyright (C) 2003-2010 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@ struct adapter_parm {
 	struct lineop getsda;
 	struct lineop getscl;
 	struct lineop init;
+	unsigned int smbus_alert:1;
 };
 
 static struct adapter_parm adapter_parm[] = {
@@ -73,6 +74,7 @@ static struct adapter_parm adapter_parm[
 		.setscl	= { 0x01, DATA, 1 },
 		.getsda	= { 0x10, STAT, 1 },
 		.init	= { 0xf0, DATA, 0 },
+		.smbus_alert = 1,
 	},
 	/* type 5: ADM1025, ADM1030 and ADM1031 evaluation boards */
 	{

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 4/5] i2c-parport-light: Add SMBus alert support
       [not found] ` <20100213230438.31fd0fd7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
                     ` (2 preceding siblings ...)
  2010-02-13 22:08   ` [PATCH 3/5] i2c-parport: Add SMBus alert support Jean Delvare
@ 2010-02-13 22:09   ` Jean Delvare
  2010-02-13 22:11   ` [PATCH 5/5] hwmon: (lm90) " Jean Delvare
  4 siblings, 0 replies; 16+ messages in thread
From: Jean Delvare @ 2010-02-13 22:09 UTC (permalink / raw)
  To: Linux I2C; +Cc: David Brownell, Trent Piepho

Add support for the SMBus alert mechanism to the i2c-parport-light
driver. The ADM1032 evaluation board at least is properly wired for
this.

Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: Trent Piepho <tpiepho-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 Documentation/i2c/busses/i2c-parport-light |   11 +++++++
 drivers/i2c/busses/Kconfig                 |    1 
 drivers/i2c/busses/i2c-parport-light.c     |   42 ++++++++++++++++++++++++++--
 3 files changed, 51 insertions(+), 3 deletions(-)

--- linux-2.6.33-rc8.orig/Documentation/i2c/busses/i2c-parport-light	2010-02-13 22:31:35.000000000 +0100
+++ linux-2.6.33-rc8/Documentation/i2c/busses/i2c-parport-light	2010-02-13 22:34:52.000000000 +0100
@@ -9,3 +9,14 @@ parport handling is not an option. The d
 and the impossibility to daisy-chain other parallel port devices.                 
   
 Please see i2c-parport for documentation.
+
+Module parameters:
+
+* type: type of adapter (see i2c-parport or modinfo)
+
+* base: base I/O address
+  Default is 0x378 which is fairly common for parallel ports, at least on PC.
+
+* irq: optional IRQ
+  This must be passed if you want SMBus alert support, assuming your adapter
+  actually supports this.
--- linux-2.6.33-rc8.orig/drivers/i2c/busses/Kconfig	2010-02-13 22:34:09.000000000 +0100
+++ linux-2.6.33-rc8/drivers/i2c/busses/Kconfig	2010-02-13 22:34:52.000000000 +0100
@@ -595,6 +595,7 @@ config I2C_PARPORT
 config I2C_PARPORT_LIGHT
 	tristate "Parallel port adapter (light)"
 	select I2C_ALGOBIT
+	select I2C_SMBUS
 	help
 	  This supports parallel port I2C adapters such as the ones made by
 	  Philips or Velleman, Analog Devices evaluation boards, and more.
--- linux-2.6.33-rc8.orig/drivers/i2c/busses/i2c-parport-light.c	2010-02-13 22:31:36.000000000 +0100
+++ linux-2.6.33-rc8/drivers/i2c/busses/i2c-parport-light.c	2010-02-13 22:34:52.000000000 +0100
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport-light.c I2C bus over parallel port                           *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2007 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
+   Copyright (C) 2003-2010 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
    
    Based on older i2c-velleman.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -32,6 +32,7 @@
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/i2c-smbus.h>
 #include <asm/io.h>
 #include "i2c-parport.h"
 
@@ -44,6 +45,10 @@ static u16 base;
 module_param(base, ushort, 0);
 MODULE_PARM_DESC(base, "Base I/O address");
 
+static int irq;
+module_param(irq, int, 0);
+MODULE_PARM_DESC(irq, "IRQ (optional)");
+
 /* ----- Low-level parallel port access ----------------------------------- */
 
 static inline void port_write(unsigned char p, unsigned char d)
@@ -120,6 +125,16 @@ static struct i2c_adapter parport_adapte
 	.name		= "Parallel port adapter (light)",
 };
 
+/* SMBus alert support */
+static struct i2c_smbus_alert_setup alert_data = {
+	.alert_edge_triggered	= 1,
+};
+static struct i2c_client *ara;
+static struct lineop parport_ctrl_irq = {
+	.val		= (1 << 4),
+	.port		= CTRL,
+};
+
 static int __devinit i2c_parport_probe(struct platform_device *pdev)
 {
 	int err;
@@ -136,13 +151,31 @@ static int __devinit i2c_parport_probe(s
 
 	parport_adapter.dev.parent = &pdev->dev;
 	err = i2c_bit_add_bus(&parport_adapter);
-	if (err)
+	if (err) {
 		dev_err(&pdev->dev, "Unable to register with I2C\n");
-	return err;
+		return err;
+	}
+
+	/* Setup SMBus alert if supported */
+	if (adapter_parm[type].smbus_alert && irq) {
+		alert_data.irq = irq;
+		ara = i2c_setup_smbus_alert(&parport_adapter, &alert_data);
+		if (ara)
+			line_set(1, &parport_ctrl_irq);
+		else
+			dev_warn(&pdev->dev, "Failed to register ARA client\n");
+	}
+
+	return 0;
 }
 
 static int __devexit i2c_parport_remove(struct platform_device *pdev)
 {
+	if (ara) {
+		line_set(0, &parport_ctrl_irq);
+		i2c_unregister_device(ara);
+		ara = NULL;
+	}
 	i2c_del_adapter(&parport_adapter);
 
 	/* Un-init if needed (power off...) */
@@ -209,6 +242,9 @@ static int __init i2c_parport_init(void)
 	if (!request_region(base, 3, DRVNAME))
 		return -EBUSY;
 
+	if (irq != 0)
+		pr_info(DRVNAME ": using irq %d\n", irq);
+
         if (!adapter_parm[type].getscl.val)
 		parport_algo_data.getscl = NULL;
 

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 5/5] hwmon: (lm90) Add SMBus alert support
       [not found] ` <20100213230438.31fd0fd7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
                     ` (3 preceding siblings ...)
  2010-02-13 22:09   ` [PATCH 4/5] i2c-parport-light: " Jean Delvare
@ 2010-02-13 22:11   ` Jean Delvare
       [not found]     ` <20100213231116.1d3ad806-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  4 siblings, 1 reply; 16+ messages in thread
From: Jean Delvare @ 2010-02-13 22:11 UTC (permalink / raw)
  To: Linux I2C; +Cc: David Brownell, Trent Piepho

Tested successfully with an ADM1032 chip on its evaluation board. It
should work fine with all other chips as well.

At this point this is more of a proof-of-concept, we don't do anything
terribly useful on SMBus alert: we simply log the event. But this could
later evolve into libsensors signaling so that user-space applications
can take an appropriate action.

Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: Trent Piepho <tpiepho-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 Documentation/hwmon/lm90 |   12 ++++++++
 drivers/hwmon/lm90.c     |   63 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)

--- linux-2.6.33-rc8.orig/Documentation/hwmon/lm90	2010-02-13 16:24:06.000000000 +0100
+++ linux-2.6.33-rc8/Documentation/hwmon/lm90	2010-02-13 16:24:41.000000000 +0100
@@ -173,6 +173,18 @@ The lm90 driver will not update its valu
 other second; reading them more often will do no harm, but will return
 'old' values.
 
+SMBus Alert Support
+-------------------
+
+This driver has basic support for SMBus alert. When an alert is received,
+the status register is read and the faulty temperature channel is logged.
+
+The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
+alert protocol properly so additional care is needed: the ALERT output is
+disabled when an alert is received, and is re-enabled only when the alarm
+is gone. Otherwise the chip would block alerts from other chips in the bus
+as long as the alarm is active.
+
 PEC Support
 -----------
 
--- linux-2.6.33-rc8.orig/drivers/hwmon/lm90.c	2010-02-13 16:24:17.000000000 +0100
+++ linux-2.6.33-rc8/drivers/hwmon/lm90.c	2010-02-13 15:50:53.000000000 +0100
@@ -152,6 +152,7 @@ static int lm90_detect(struct i2c_client
 static int lm90_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id);
 static void lm90_init_client(struct i2c_client *client);
+static void lm90_alert(struct i2c_client *client, unsigned int flag);
 static int lm90_remove(struct i2c_client *client);
 static struct lm90_data *lm90_update_device(struct device *dev);
 
@@ -186,6 +187,7 @@ static struct i2c_driver lm90_driver = {
 	},
 	.probe		= lm90_probe,
 	.remove		= lm90_remove,
+	.alert		= lm90_alert,
 	.id_table	= lm90_id,
 	.detect		= lm90_detect,
 	.address_list	= normal_i2c,
@@ -204,6 +206,7 @@ struct lm90_data {
 	int flags;
 
 	u8 config_orig;		/* Original configuration register value */
+	u8 alert_alarms;	/* Which alarm bits trigger ALERT# */
 
 	/* registers values */
 	s8 temp8[4];	/* 0: local low limit
@@ -806,6 +809,19 @@ static int lm90_probe(struct i2c_client
 			new_client->flags &= ~I2C_CLIENT_PEC;
 	}
 
+	/* Different devices have different alarm bits triggering the
+	 * ALERT# output */
+	switch (data->kind) {
+	case lm90:
+	case lm99:
+	case lm86:
+		data->alert_alarms = 0x7b;
+		break;
+	default:
+		data->alert_alarms = 0x7c;
+		break;
+	}
+
 	/* Initialize the LM90 chip */
 	lm90_init_client(new_client);
 
@@ -895,6 +911,38 @@ static int lm90_remove(struct i2c_client
 	return 0;
 }
 
+static void lm90_alert(struct i2c_client *client, unsigned int flag)
+{
+	struct lm90_data *data = i2c_get_clientdata(client);
+	u8 config, alarms;
+
+	lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
+	if ((alarms & 0x7f) == 0) {
+		dev_info(&client->dev, "Everything OK\n");
+	} else {
+		if (alarms & 0x61)
+			dev_warn(&client->dev,
+				 "temp%d out of range, please check!\n", 1);
+		if (alarms & 0x1a)
+			dev_warn(&client->dev,
+				 "temp%d out of range, please check!\n", 2);
+		if (alarms & 0x04)
+			dev_warn(&client->dev,
+				 "temp%d diode open, please check!\n", 2);
+
+		/* Disable ALERT# output, because these chips don't implement
+		  SMBus alert correctly; they should only hold the alert line
+		  low briefly. */
+		if ((data->kind == adm1032 || data->kind == adt7461)
+		 && (alarms & data->alert_alarms)) {
+			dev_dbg(&client->dev, "Disabling ALERT#\n");
+			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
+			i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
+						  config | 0x80);
+		}
+	}
+}
+
 static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
 {
 	int err;
@@ -982,6 +1030,21 @@ static struct lm90_data *lm90_update_dev
 		}
 		lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
 
+		/* Re-enable ALERT# output if it was originally enabled and
+		 * relevant alarms are all clear */
+		if ((data->config_orig & 0x80) == 0
+		 && (data->alarms & data->alert_alarms) == 0) {
+			u8 config;
+
+			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
+			if (config & 0x80) {
+				dev_dbg(&client->dev, "Re-enabling ALERT#\n");
+				i2c_smbus_write_byte_data(client,
+							  LM90_REG_W_CONFIG1,
+							  config & ~0x80);
+			}
+		}
+
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] i2c: Add SMBus alert support
       [not found]     ` <20100213230656.341ec091-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2010-02-14  2:06       ` David Brownell
       [not found]         ` <201002131806.07359.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  2010-02-15 18:26       ` Jonathan Cameron
  1 sibling, 1 reply; 16+ messages in thread
From: David Brownell @ 2010-02-14  2:06 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C, Trent Piepho

On Saturday 13 February 2010, Jean Delvare wrote:

> The benefit of this approach is a zero cost for I2C bus segments which
> do not need SMBus alert support. Where David's implementation
> increased the size of struct i2c_adapter by 7% (40 bytes on i386),
> mine doesn't touch it. Where David's implementation added over 150
> lines of code to i2c-core (+10%), mine doesn't touch it. The only
> change that touches all the users of the i2c subsystem is a new
> callback in struct i2c_driver (common to both implementations.) I seem
> to remember Trent was worried about the footprint of David'd
> implementation, hopefully mine addresses the issue.

I'm not sure I could justify making I2C and SMBus differ in *ONLY* this
particular way, since otherwise they're treated identically.  I certainly
wouldn't worry about 40 bytes in a Linux kernel ... that's noise.  (If
this were inside a microcontroller that only had a few KB of SRAM, then
I'd certainly worry!)

But that doesn't much matter.  If SMBALERT# support is now going to exist,
that's enough for me.


> + *
> + * Copyright (C) 2010 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> + *
> + * SMBus alert support based on earlier work by David Brownell (2008).
> + *

That should be "Copyright (C) 2008 David Brownell" ... not
just "based on", since significant chunks are the same code.


> +       struct i2c_client       *ara;

Worth spelling out what "ARA" means; it shouldn't be
just another mysterious TLA.


> +struct alert_data {
> +       unsigned short          addr;
> +       u8                      flag:1;
> +};
> +

Better to make "flag" be "bool" ... there's no space saving
in the struct to have it be a one bit field, and in terms of
code generation it *costs more* than using a "bool".


> +/* If this is the alerting device, notify its driver */
> +static int smbus_do_alert(struct device *dev, void *addrp)
> +{
> +       struct i2c_client *client = i2c_verify_client(dev);
> +       struct alert_data *data = addrp;

Surely the callback should take a "struct alert_data *" then??


> +static irqreturn_t smbalert_irq(int irq, void *d)
> +{
> +       struct i2c_smbus_alert *data = d;
> +
> +       /* Disable level-triggered IRQs until we handle them */
> +       if (!data->alert_edge_triggered)
> +               disable_irq_nosync(irq);
> +
> +       schedule_work(&data->alert);
> +       return IRQ_HANDLED;
> +}
> +

Now that genirq handles threaded IRQs, should this code be updated
to use that infrastructure instead of a work struct?  There are
several mechanisms to kick in here.  It'd be fair to have a way for
IRQ threads to issue i2c_handle_smbus_alert() -- or maybe some
sibling method -- especially if i2c_setup_smbus_alert() causes
this code to provide the hardirq handler.

By the way ... you probably know that the I2C/SMBus controller
in most of Intel's Southbridge chips (like ICH8) supports
the SMBALERT# mechanism.  Testing may be awkward, but it'd be
good to verify this incarnation of SMBALERT# support can work
with those controllers.  (Where "alert" is just another cause
for an IRQ from i2c-i801.c or whatever, not a dedicated IRQ
from a GPIO or from the parport.)

- Dave

p.s. for the record ... I'd try testing this, but the board I
     have which needs that support doesn't have current-enough
     Linux to do so.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/5] hwmon: (lm90) Add SMBus alert support
       [not found]     ` <20100213231116.1d3ad806-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2010-02-14  2:11       ` David Brownell
  2010-02-14  8:33       ` Trent Piepho
  1 sibling, 0 replies; 16+ messages in thread
From: David Brownell @ 2010-02-14  2:11 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C, Trent Piepho

On Saturday 13 February 2010, Jean Delvare wrote:
> At this point this is more of a proof-of-concept, we don't do anything
> terribly useful on SMBus alert: we simply log the event. But this could
> later evolve into libsensors signaling so that user-space applications
> can take an appropriate action.

Yeah, this is a case where it's a *GOOD THING* to let that
particular camel stick its nose into the tent ... ;)

Polling for alerts is kind of sub-optimal, and that's the
best that's been possible until now.

- Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/5] hwmon: (lm90) Add SMBus alert support
       [not found]     ` <20100213231116.1d3ad806-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  2010-02-14  2:11       ` David Brownell
@ 2010-02-14  8:33       ` Trent Piepho
       [not found]         ` <Pine.LNX.4.64.1002140000220.2366-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
  1 sibling, 1 reply; 16+ messages in thread
From: Trent Piepho @ 2010-02-14  8:33 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C, David Brownell

On Sat, 13 Feb 2010, Jean Delvare wrote:
> Tested successfully with an ADM1032 chip on its evaluation board. It
> should work fine with all other chips as well.
>
> At this point this is more of a proof-of-concept, we don't do anything
> terribly useful on SMBus alert: we simply log the event. But this could
> later evolve into libsensors signaling so that user-space applications
> can take an appropriate action.

When I added alert support to the lm63 driver, I had it wake up any process
that's select()ing on the the alarm* files.  I also wrote a hw monitor
daemon that supports this system.  It worked pretty well.  Much more
efficient than polling once per second, and also much faster to resond to
an alert event.

I didn't bother to use ARA, since I know what device is generating the
interrupt.  Does your system support devices with an alert line that don't
use SMBus ARA?

> +static void lm90_alert(struct i2c_client *client, unsigned int flag)
> +{
> +	struct lm90_data *data = i2c_get_clientdata(client);
> +	u8 config, alarms;
> +
> +	lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);

Does lm90_read_reg() update the driver's cached copy of the alarm status
register?  Because if it doesn't, then won't anything reading the alarm
status via sysfs not see the alarms?

What happens if a process reads one of the sysfs attributes after the
interrupt is generated but before the driver runs this code?

In the lm63, the alarm register is clear on read.  So you get the alert,
check alarm status, and think there are no alarms.

What I did for the lm63 driver was assume that if there was an alert
generated, there must have been an alarm bit set.  If there isn't one set
now, then the only way it may have been cleared is if the driver read the
alarm status.  In which case the driver's cache copy of the alarm status
should be used to see what generated the alert.

Another thing I found is that after getting notified of the alert, the most
natural thing for userspace to do is check the temperature/fan/etc
attribute that just alarmed.  "Fan Alert, fan1 speed of 2000 RPM is below
minimum of 300 RPM" Huh?  2000 < 300?  What's going on?  The 2000 RPM is
one second old cached data!  The current speed should cause an alarm, but
the 1 HZ max update rate the driver makes userspace wait for it, somewhat
defeating the purpose of the alert irq.  I have the lm63 driver invalidate
the cached data on alert, so that if userspace reads an attribute it gets
fresh data.

> +		/* Re-enable ALERT# output if it was originally enabled and
> +		 * relevant alarms are all clear */
> +		if ((data->config_orig & 0x80) == 0
> +		 && (data->alarms & data->alert_alarms) == 0) {
> +			u8 config;
> +
> +			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
> +			if (config & 0x80) {
> +				dev_dbg(&client->dev, "Re-enabling ALERT#\n");
> +				i2c_smbus_write_byte_data(client,
> +							  LM90_REG_W_CONFIG1,
> +							  config & ~0x80);
> +			}
> +		}

I didn't like the idea of having to have userspace poll attributes to get
alarms re-enabled.  I have the driver start a kernel timer going that
checks the alarm status.  It also notified processes sleeping in the alarm
attributes when the check back to 0.  The time period the kernel polling
can be based on the driver's knowledge of the chip's update rate.  It can
be set to poll faster when there is an alarm.  Of course you rejected my
patch to let the lm63 driver set and know the update rate because that
information could never be useful to anyone...

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/5] hwmon: (lm90) Add SMBus alert support
       [not found]         ` <Pine.LNX.4.64.1002140000220.2366-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
@ 2010-02-14 13:28           ` Jean Delvare
  0 siblings, 0 replies; 16+ messages in thread
From: Jean Delvare @ 2010-02-14 13:28 UTC (permalink / raw)
  To: Trent Piepho; +Cc: Linux I2C, David Brownell

Hi Trent,

On Sun, 14 Feb 2010 00:33:53 -0800 (PST), Trent Piepho wrote:
> On Sat, 13 Feb 2010, Jean Delvare wrote:
> > Tested successfully with an ADM1032 chip on its evaluation board. It
> > should work fine with all other chips as well.
> >
> > At this point this is more of a proof-of-concept, we don't do anything
> > terribly useful on SMBus alert: we simply log the event. But this could
> > later evolve into libsensors signaling so that user-space applications
> > can take an appropriate action.
> 
> When I added alert support to the lm63 driver, I had it wake up any process
> that's select()ing on the the alarm* files.  I also wrote a hw monitor
> daemon that supports this system.  It worked pretty well.  Much more
> efficient than polling once per second, and also much faster to resond to
> an alert event.

Why didn't you add support to libsensors instead? This would seem the
right way if we want popular monitoring applications to take benefit of
this new feature.

> I didn't bother to use ARA, since I know what device is generating the
> interrupt.  Does your system support devices with an alert line that don't
> use SMBus ARA?

Not sure what you mean by "my system". My hardware setup is an
evaluation board connecting to the parallel port, it has an ADM1032
chip and that's all. Also, if you don't want to use the SMBus alert
mechanism, there's nothing preventing you from using raw interrupts
right now, you don't need my patches. Every driver can request an IRQ
and make use of it.

> > +static void lm90_alert(struct i2c_client *client, unsigned int flag)
> > +{
> > +	struct lm90_data *data = i2c_get_clientdata(client);
> > +	u8 config, alarms;
> > +
> > +	lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
> 
> Does lm90_read_reg() update the driver's cached copy of the alarm status
> register?

No, it doesn't.

> Because if it doesn't, then won't anything reading the alarm
> status via sysfs not see the alarms?

If the alarms have worn off meanwhile, yes indeed. But updating the
cache wouldn't really help, because it only lives for one second, so
any application polling less frequently than this would miss the
transient alarm anyway. And systems with more than one polling
application (for example sensord + a desktop applet) can easily miss
transient alarms even without my patch.

I tend to see transient alarms as an optional bonus without any
guarantee. Guaranteeing that transient alarms are always caught would
require a major redesign of all our drivers. And in practice, the
latching of alarm flags tend to confuse users more than it helps them.

> What happens if a process reads one of the sysfs attributes after the
> interrupt is generated but before the driver runs this code?

Good question. I admit that I have not necessarily thought of all the
possible race conditions. If the alarm is still present, it shouldn't
make a difference because the next conversion cycle will set the alarm
flag again. It would only make a difference if the alarm has gone away
meanwhile, and the extra read cleared the alarm bit. In that case, the
interrupt handler has no way to know what cause the problem. It will
log that everything is OK (to the user's surprise I guess) and do
nothing else. I don't see any problem here.

> In the lm63, the alarm register is clear on read.  So you get the alert,
> check alarm status, and think there are no alarms.

Yes, that's the same here. Almost all hwmon chips have alarm registers
which clear on read.

> What I did for the lm63 driver was assume that if there was an alert
> generated, there must have been an alarm bit set.  If there isn't one set
> now, then the only way it may have been cleared is if the driver read the
> alarm status.  In which case the driver's cache copy of the alarm status
> should be used to see what generated the alert.

Hmm, that's an interesting strategy, I admit. Now the problem I have at
least with the ADM1032 is that I also get an interrupt when I re-enable
the ALERT output. When this happens, the lack of alarm bit being set is
totally expected, so I certainly don't want to read the cached value to
display an alert message to the user.

I don't think this is a problem anyway. Either the alarm condition is
gone, meaning it was transient, and the user probably doesn't care. Or
the alarm condition is still there and the next cycle will trigger an
interrupt again, so the user will finally know what's up.

> 
> Another thing I found is that after getting notified of the alert, the most
> natural thing for userspace to do is check the temperature/fan/etc
> attribute that just alarmed.  "Fan Alert, fan1 speed of 2000 RPM is below
> minimum of 300 RPM" Huh?  2000 < 300?  What's going on?  The 2000 RPM is
> one second old cached data!  The current speed should cause an alarm, but
> the 1 HZ max update rate the driver makes userspace wait for it, somewhat
> defeating the purpose of the alert irq.  I have the lm63 driver invalidate
> the cached data on alert, so that if userspace reads an attribute it gets
> fresh data.

This is a good idea, I will probably do the same (even though I am a
little worried about locking... invalidating the cache requires holding
the lock, which may take long if user-space is reading the values at
that time). That being said, it is in no way bullet-proof: by the time
the user-space application reads the attributes, the faulty condition
may have gone away. So it is better to rely on the alarm flags to print
the warning, and only provide the sensor and limit values as hints.

> 
> > +		/* Re-enable ALERT# output if it was originally enabled and
> > +		 * relevant alarms are all clear */
> > +		if ((data->config_orig & 0x80) == 0
> > +		 && (data->alarms & data->alert_alarms) == 0) {
> > +			u8 config;
> > +
> > +			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
> > +			if (config & 0x80) {
> > +				dev_dbg(&client->dev, "Re-enabling ALERT#\n");
> > +				i2c_smbus_write_byte_data(client,
> > +							  LM90_REG_W_CONFIG1,
> > +							  config & ~0x80);
> > +			}
> > +		}
> 
> I didn't like the idea of having to have userspace poll attributes to get
> alarms re-enabled.  I have the driver start a kernel timer going that
> checks the alarm status.  It also notified processes sleeping in the alarm
> attributes when the check back to 0.  The time period the kernel polling
> can be based on the driver's knowledge of the chip's update rate.  It can
> be set to poll faster when there is an alarm.

I tried to make my changes integrate into the current usage scheme of
the hwmon drivers (user-space repeatedly polling for values.) And it
was really only a way to test the rest of the SMBus alert code. As long
as it doesn't do anything useful, I do not think it is a problem to
rely on user-space. It can certainly evolve in the future, especially
if we make it possible for the kernel to take thermal management
measures by itself (e.g. processor throttling). But for this, we would
have to somehow unify the thermal zones subsystem with the hwmon one.
This is way beyond the scope of my patch.

> Of course you rejected my
> patch to let the lm63 driver set and know the update rate because that
> information could never be useful to anyone...

Trent, you rejected your patch yourself. We (I wasn't alone) asked you
to split your patch into a part which everybody agreed on and a part
where more discussion was needed. You never followed up, so your
changes never went anywhere. You did it to yourself, really.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] i2c: Add SMBus alert support
       [not found]         ` <201002131806.07359.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2010-02-14 14:40           ` Jean Delvare
       [not found]             ` <20100214154034.2c92a8b7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: Jean Delvare @ 2010-02-14 14:40 UTC (permalink / raw)
  To: David Brownell; +Cc: Linux I2C, Trent Piepho

Hi David,

On Sat, 13 Feb 2010 18:06:07 -0800, David Brownell wrote:
> On Saturday 13 February 2010, Jean Delvare wrote:
> 
> > The benefit of this approach is a zero cost for I2C bus segments which
> > do not need SMBus alert support. Where David's implementation
> > increased the size of struct i2c_adapter by 7% (40 bytes on i386),
> > mine doesn't touch it. Where David's implementation added over 150
> > lines of code to i2c-core (+10%), mine doesn't touch it. The only
> > change that touches all the users of the i2c subsystem is a new
> > callback in struct i2c_driver (common to both implementations.) I seem
> > to remember Trent was worried about the footprint of David'd
> > implementation, hopefully mine addresses the issue.
> 
> I'm not sure I could justify making I2C and SMBus differ in *ONLY* this
> particular way, since otherwise they're treated identically.

I'm not sure what you call "making I2C and SMBus differ". My
implementation simply makes it possible to exclude the extra code if
you don't need it. It doesn't prevent I2C controller drivers from
relying on that code if they want to. I named it "i2c-smbus" because I
don't think we want one separate module for every extension provided by
SMBus, and based on the assumption that people who don't want one,
won't want any of them. But if the future makes me wrong, I will be
happy to rename the module to i2c-smbus-alert.

> I certainly
> wouldn't worry about 40 bytes in a Linux kernel ... that's noise.  (If
> this were inside a microcontroller that only had a few KB of SRAM, then
> I'd certainly worry!)

That's 40 bytes * number of I2C segments on the system. There tends to
be more and more I2C segments on systems, and when we add support for
multiplexing (the next big thing on my list) it will only get worse.
BTW, my impression is that multiplexing and SMBus alert are almost
mutually exclusive, so not having all the data in every segment makes a
lot of sense to me.

> 
> But that doesn't much matter.  If SMBALERT# support is now going to exist,
> that's enough for me.

Honestly, I don't worry much either way myself. But I can imagine some
people would, and I didn't want to give them a reason to reject SMBus
alert support.

> > + *
> > + * Copyright (C) 2010 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> > + *
> > + * SMBus alert support based on earlier work by David Brownell (2008).
> > + *
> 
> That should be "Copyright (C) 2008 David Brownell" ... not
> just "based on", since significant chunks are the same code.

I'm sorry about this. For some reason, I decided that, just because
your code never made it upstream, you did not get to hold a copyright
on it. Silly me. It's fixed now, please accept my humble excuses.

> > +       struct i2c_client       *ara;
> 
> Worth spelling out what "ARA" means; it shouldn't be
> just another mysterious TLA.

Good idea, added.

> > +struct alert_data {
> > +       unsigned short          addr;
> > +       u8                      flag:1;
> > +};
> > +
> 
> Better to make "flag" be "bool" ... there's no space saving
> in the struct to have it be a one bit field, and in terms of
> code generation it *costs more* than using a "bool".

No, thanks. Your code used a bool and I voluntarily changed it to a
regular number. My reason for doing this is that bool has semantics
which are absent from the SMBus specifications. This bit of data is
really 0 or 1, it doesn't carry the meaning of "false" or "true".

> > +/* If this is the alerting device, notify its driver */
> > +static int smbus_do_alert(struct device *dev, void *addrp)
> > +{
> > +       struct i2c_client *client = i2c_verify_client(dev);
> > +       struct alert_data *data = addrp;
> 
> Surely the callback should take a "struct alert_data *" then??

smbus_do_alert() is called by device_for_each_child(), we don't get to
change its prototype.

> > +static irqreturn_t smbalert_irq(int irq, void *d)
> > +{
> > +       struct i2c_smbus_alert *data = d;
> > +
> > +       /* Disable level-triggered IRQs until we handle them */
> > +       if (!data->alert_edge_triggered)
> > +               disable_irq_nosync(irq);
> > +
> > +       schedule_work(&data->alert);
> > +       return IRQ_HANDLED;
> > +}
> > +
> 
> Now that genirq handles threaded IRQs, should this code be updated
> to use that infrastructure instead of a work struct?  There are
> several mechanisms to kick in here.  It'd be fair to have a way for
> IRQ threads to issue i2c_handle_smbus_alert() -- or maybe some
> sibling method -- especially if i2c_setup_smbus_alert() causes
> this code to provide the hardirq handler.

Honestly, this is all beyond me. I suggest that anyone needing this
work on it on his/her own and submits an incremental patch when done. I
have already spent more time than I wanted on this, I can't afford
spending more, especially for a feature I don't need myself.

> By the way ... you probably know that the I2C/SMBus controller
> in most of Intel's Southbridge chips (like ICH8) supports
> the SMBALERT# mechanism.  Testing may be awkward, but it'd be
> good to verify this incarnation of SMBALERT# support can work
> with those controllers.  (Where "alert" is just another cause
> for an IRQ from i2c-i801.c or whatever, not a dedicated IRQ
> from a GPIO or from the parport.)

I have only one system with an ICH and an SMBus device with support for
alerts. It is not currently available for testing... when it becomes
available, I may take a look. That being said, the main obstacle I see
is that the i2c-i801 driver doesn't make use of interrupts at all at
the moment. I don't know if it is possible to enable them to get the
alerts but to not make use of them during regular transactions. The
various attempts to make the i2c-i801 driver use interrupts never made
it to mainline, there was always an least one issue remaining
preventing it. I would love if we finally managed to switch to full
interrupt support.

That being said, my code is based on yours, and I see to remember you
said yours was compatible with the ICH expectations, so I'd expect mine
to work too.

> p.s. for the record ... I'd try testing this, but the board I
>      have which needs that support doesn't have current-enough
>      Linux to do so.

Thank you! And thanks for the review as well, very much appreciated.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] i2c: Add SMBus alert support
       [not found]             ` <20100214154034.2c92a8b7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2010-02-14 18:05               ` David Brownell
       [not found]                 ` <201002141005.53934.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2010-02-14 18:05 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C, Trent Piepho

On Sunday 14 February 2010, Jean Delvare wrote:
> > to use that infrastructure instead of a work struct?  There are
> > several mechanisms to kick in here.  It'd be fair to have a way for
> > IRQ threads to issue i2c_handle_smbus_alert() -- or maybe some
> > sibling method -- especially if i2c_setup_smbus_alert() causes
> > this code to provide the hardirq handler.
> 
> Honestly, this is all beyond me. I suggest that anyone needing this
> work on it on his/her own and submits an incremental patch when done. I
> have already spent more time than I wanted on this, I can't afford
> spending more, especially for a feature I don't need myself.

Then I'd suggest sticking in a REVISIT comment to that effect,
to help armor this patch against repeats of that feedback which
don't accompany such an incremental patch.  :)


> > By the way ... you probably know that the I2C/SMBus controller
> > in most of Intel's Southbridge chips (like ICH8) supports
> > the SMBALERT# mechanism.  Testing may be awkward, but it'd be
> > good to verify this incarnation of SMBALERT# support can work
> > with those controllers.  (Where "alert" is just another cause
> > for an IRQ from i2c-i801.c or whatever, not a dedicated IRQ
> > from a GPIO or from the parport.)
> 
> I have only one system with an ICH and an SMBus device with support for
> alerts. It is not currently available for testing... when it becomes
> available, I may take a look. That being said, the main obstacle I see
> is that the i2c-i801 driver doesn't make use of interrupts at all at
> the moment. I don't know if it is possible to enable them to get the
> alerts but to not make use of them during regular transactions. The
> various attempts to make the i2c-i801 driver use interrupts never made
> it to mainline, there was always an least one issue remaining
> preventing it. I would love if we finally managed to switch to full
> interrupt support.

Ah, I recall some of that mess, now that you mention it.  Ouch!

(By the way ... glad to see you did the nice thing with parport I2C
and SMALERT#.  I've not seen much Linux code using the parport IRQ,
and if nothing else it's nice to have some verification that it has
not bit-rotted to death!)


> That being said, my code is based on yours, and I see to remember you
> said yours was compatible with the ICH expectations, so I'd expect mine
> to work too.

The compatibility was because the driver could say "I got an SMBALERT IRQ"
to the infrastructure from its hardirq handler.  I think the comments in
your version touched on that point.

- Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] i2c: Add SMBus alert support
       [not found]                 ` <201002141005.53934.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2010-02-14 19:18                   ` Jean Delvare
  0 siblings, 0 replies; 16+ messages in thread
From: Jean Delvare @ 2010-02-14 19:18 UTC (permalink / raw)
  To: David Brownell; +Cc: Linux I2C, Trent Piepho

On Sun, 14 Feb 2010 10:05:53 -0800, David Brownell wrote:
> On Sunday 14 February 2010, Jean Delvare wrote:
> > > to use that infrastructure instead of a work struct?  There are
> > > several mechanisms to kick in here.  It'd be fair to have a way for
> > > IRQ threads to issue i2c_handle_smbus_alert() -- or maybe some
> > > sibling method -- especially if i2c_setup_smbus_alert() causes
> > > this code to provide the hardirq handler.
> > 
> > Honestly, this is all beyond me. I suggest that anyone needing this
> > work on it on his/her own and submits an incremental patch when done. I
> > have already spent more time than I wanted on this, I can't afford
> > spending more, especially for a feature I don't need myself.
> 
> Then I'd suggest sticking in a REVISIT comment to that effect,
> to help armor this patch against repeats of that feedback which
> don't accompany such an incremental patch.  :)

I would wholeheartedly accept a patch adding such a comment ;)
Seriously, I wouldn't know what to write.

> > > By the way ... you probably know that the I2C/SMBus controller
> > > in most of Intel's Southbridge chips (like ICH8) supports
> > > the SMBALERT# mechanism.  Testing may be awkward, but it'd be
> > > good to verify this incarnation of SMBALERT# support can work
> > > with those controllers.  (Where "alert" is just another cause
> > > for an IRQ from i2c-i801.c or whatever, not a dedicated IRQ
> > > from a GPIO or from the parport.)
> > 
> > I have only one system with an ICH and an SMBus device with support for
> > alerts. It is not currently available for testing... when it becomes
> > available, I may take a look. That being said, the main obstacle I see
> > is that the i2c-i801 driver doesn't make use of interrupts at all at
> > the moment. I don't know if it is possible to enable them to get the
> > alerts but to not make use of them during regular transactions. The
> > various attempts to make the i2c-i801 driver use interrupts never made
> > it to mainline, there was always an least one issue remaining
> > preventing it. I would love if we finally managed to switch to full
> > interrupt support.
> 
> Ah, I recall some of that mess, now that you mention it.  Ouch!
> 
> (By the way ... glad to see you did the nice thing with parport I2C
> and SMALERT#.  I've not seen much Linux code using the parport IRQ,
> and if nothing else it's nice to have some verification that it has
> not bit-rotted to death!)

I'm not so sure. You'll notice I had to call parport_disable_irq()
before registering my device. Without it, my IRQ handler would be
called before being ready. This is odd given that the comments in the
parport subsystem code say that you have to call parport_enable_irq()
if you want to receive interrupts (which seems logical). So there's
certainly something slightly broken down there. I don't really have the
time to investigate though :(

> > That being said, my code is based on yours, and I see to remember you
> > said yours was compatible with the ICH expectations, so I'd expect mine
> > to work too.
> 
> The compatibility was because the driver could say "I got an SMBALERT IRQ"
> to the infrastructure from its hardirq handler.  I think the comments in
> your version touched on that point.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] i2c: Add SMBus alert support
       [not found]     ` <20100213230656.341ec091-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  2010-02-14  2:06       ` David Brownell
@ 2010-02-15 18:26       ` Jonathan Cameron
       [not found]         ` <4B7991CC.3020904-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
  1 sibling, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2010-02-15 18:26 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C, David Brownell, Trent Piepho

Hi Jean,

I have a couple of parts I can test this on (connected to a pxa271)
but it may be a little while before I get to it (so don't let me
hold the patch up!)

On tiny point below.  Worth changing if you are doing another roll of the patch
as at least in my dozy Monday evening state it confused me for a few moments!

Thanks,

Jonathan

Acked-by: Jonathan Cameron <jic23-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
> SMBus alert support. The SMBus alert protocol allows several SMBus
> slave devices to share a single interrupt pin on the SMBus master,
> while still allowing the master to know which slave triggered the
> interrupt.
> 
> This is based on preliminary work by David Brownell. The key
> difference between David's implementation and mine is that his was
> part of i2c-core, while mine is split into a separate, standalone
> module named i2c-smbus. The i2c-smbus module is meant to include
> support for all SMBus extensions to the I2C protocol in the future.
> 
> The benefit of this approach is a zero cost for I2C bus segments which
> do not need SMBus alert support. Where David's implementation
> increased the size of struct i2c_adapter by 7% (40 bytes on i386),
> mine doesn't touch it. Where David's implementation added over 150
> lines of code to i2c-core (+10%), mine doesn't touch it. The only
> change that touches all the users of the i2c subsystem is a new
> callback in struct i2c_driver (common to both implementations.) I seem
> to remember Trent was worried about the footprint of David'd
> implementation, hopefully mine addresses the issue.
> 
> Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
> Cc: Trent Piepho <tpiepho-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> ---
>  Documentation/i2c/smbus-protocol |   16 ++
>  drivers/i2c/Makefile             |    2 
>  drivers/i2c/i2c-smbus.c          |  264 ++++++++++++++++++++++++++++++++++++++
>  include/linux/i2c-smbus.h        |   50 +++++++
>  include/linux/i2c.h              |    7 +
>  5 files changed, 338 insertions(+), 1 deletion(-)
> 
> --- linux-2.6.33-rc7.orig/Documentation/i2c/smbus-protocol	2010-02-12 14:19:47.000000000 +0100
> +++ linux-2.6.33-rc7/Documentation/i2c/smbus-protocol	2010-02-12 14:19:51.000000000 +0100
> @@ -185,6 +185,22 @@ the protocol. All ARP communications use
>  require PEC checksums.
>  
>  
> +SMBus Alert
> +===========
> +
> +SMBus Alert was introduced in Revision 1.0 of the specification.
> +
> +The SMBus alert protocol allows several SMBus slave devices to share a
> +single interrupt pin on the SMBus master, while still allowing the master
> +to know which slave triggered the interrupt.
> +
> +This is implemented the following way in the Linux kernel:
> +* I2C bus drivers which support SMBus alert should call
> +  i2c_setup_smbus_alert() to setup SMBus alert support.
> +* I2C drivers for devices which can trigger SMBus alerts should implement
> +  the optional alert() callback.
> +
> +
>  I2C Block Transactions
>  ======================
>  
> --- linux-2.6.33-rc7.orig/drivers/i2c/Makefile	2010-02-12 14:19:47.000000000 +0100
> +++ linux-2.6.33-rc7/drivers/i2c/Makefile	2010-02-12 16:08:34.000000000 +0100
> @@ -3,7 +3,7 @@
>  #
>  
>  obj-$(CONFIG_I2C_BOARDINFO)	+= i2c-boardinfo.o
> -obj-$(CONFIG_I2C)		+= i2c-core.o
> +obj-$(CONFIG_I2C)		+= i2c-core.o i2c-smbus.o
>  obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
>  obj-y				+= busses/ chips/ algos/
>  
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6.33-rc7/drivers/i2c/i2c-smbus.c	2010-02-12 16:11:34.000000000 +0100
...
> +/*
> + * 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_smbus_alert *data;
> +	struct i2c_client *ara;
> +	unsigned short prev_addr = 0;	/* Not a valid address */
> +
> +	data = container_of(work, struct i2c_smbus_alert, alert);
> +	ara = data->ara;
> +
> +	for (;;) {
> +		s32 status;
> +		struct alert_data data;
Can we change the name of data here.  From readability point of view it
would be better not to have this reliance on scope (as data used for 
struct i2c_smbus_alert *data above. (obviously changing it above would 
work as well!) 
> +
> +		/*
> +		 * 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(ara);
> +		if (status < 0)
> +			break;
> +
> +		data.flag = status & 1;
> +		data.addr = status >> 1;
> +
> +		if (data.addr == prev_addr) {
> +			dev_warn(&ara->dev, "Duplicate SMBALERT# from dev "
> +				"0x%02x, skipping\n", data.addr);
> +			break;
> +		}
> +		dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n",
> +			data.addr, data.flag);
> +
> +		/* Notify driver for the device which issued the alert */
> +		device_for_each_child(&ara->adapter->dev, &data,
> +				      smbus_do_alert);
> +		prev_addr = data.addr;
> +	}
> +
> +	/* We handled all alerts; re-enable level-triggered IRQs */
> +	if (!data->alert_edge_triggered)
> +		enable_irq(data->irq);
> +}
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] i2c: Add SMBus alert support
       [not found]         ` <4B7991CC.3020904-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
@ 2010-02-16  9:56           ` Jean Delvare
       [not found]             ` <20100216105606.003b01dd-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: Jean Delvare @ 2010-02-16  9:56 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: Linux I2C, David Brownell, Trent Piepho

Hi Jonathan,

On Mon, 15 Feb 2010 18:26:20 +0000, Jonathan Cameron wrote:
> I have a couple of parts I can test this on (connected to a pxa271)
> but it may be a little while before I get to it (so don't let me
> hold the patch up!)

That would be great. You can always get the latest version of the patch
either in my i2c tree or in linux-next.

> On tiny point below.  Worth changing if you are doing another roll of the patch
> as at least in my dozy Monday evening state it confused me for a few moments!
> ...
> > --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> > +++ linux-2.6.33-rc7/drivers/i2c/i2c-smbus.c	2010-02-12 16:11:34.000000000 +0100
> ...
> > +/*
> > + * 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_smbus_alert *data;
> > +	struct i2c_client *ara;
> > +	unsigned short prev_addr = 0;	/* Not a valid address */
> > +
> > +	data = container_of(work, struct i2c_smbus_alert, alert);
> > +	ara = data->ara;
> > +
> > +	for (;;) {
> > +		s32 status;
> > +		struct alert_data data;
> Can we change the name of data here.  From readability point of view it
> would be better not to have this reliance on scope (as data used for 
> struct i2c_smbus_alert *data above. (obviously changing it above would 
> work as well!) 

Oh, yeah, of course. Thanks for pointing this out. I wish we built the
kernel with -Wshadow so that gcc could tell us automatically...

I have changed all instances of struct i2c_smbus_alert * to name
"alert", this solves the problem and should make the code more
consistent and readable.

Thanks!
-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] i2c: Add SMBus alert support
       [not found]             ` <20100216105606.003b01dd-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2010-02-16 13:39               ` Mark Brown
  0 siblings, 0 replies; 16+ messages in thread
From: Mark Brown @ 2010-02-16 13:39 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Jonathan Cameron, Linux I2C, David Brownell, Trent Piepho

On Tue, Feb 16, 2010 at 10:56:06AM +0100, Jean Delvare wrote:
> On Mon, 15 Feb 2010 18:26:20 +0000, Jonathan Cameron wrote:

> > Can we change the name of data here.  From readability point of view it
> > would be better not to have this reliance on scope (as data used for 
> > struct i2c_smbus_alert *data above. (obviously changing it above would 
> > work as well!) 

> Oh, yeah, of course. Thanks for pointing this out. I wish we built the
> kernel with -Wshadow so that gcc could tell us automatically...

If you build with sparse (install it then add C=1 to the command line)
it'll pick up shadowing along with all the other stuff.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-02-16 13:39 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-13 22:04 [PATCH 0/5] i2c: Add SMBus alert support Jean Delvare
     [not found] ` <20100213230438.31fd0fd7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2010-02-13 22:06   ` [PATCH 1/5] " Jean Delvare
     [not found]     ` <20100213230656.341ec091-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2010-02-14  2:06       ` David Brownell
     [not found]         ` <201002131806.07359.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2010-02-14 14:40           ` Jean Delvare
     [not found]             ` <20100214154034.2c92a8b7-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2010-02-14 18:05               ` David Brownell
     [not found]                 ` <201002141005.53934.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2010-02-14 19:18                   ` Jean Delvare
2010-02-15 18:26       ` Jonathan Cameron
     [not found]         ` <4B7991CC.3020904-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-02-16  9:56           ` Jean Delvare
     [not found]             ` <20100216105606.003b01dd-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2010-02-16 13:39               ` Mark Brown
2010-02-13 22:07   ` [PATCH 2/5] i2c: Separate Kconfig option for i2c-smbus Jean Delvare
2010-02-13 22:08   ` [PATCH 3/5] i2c-parport: Add SMBus alert support Jean Delvare
2010-02-13 22:09   ` [PATCH 4/5] i2c-parport-light: " Jean Delvare
2010-02-13 22:11   ` [PATCH 5/5] hwmon: (lm90) " Jean Delvare
     [not found]     ` <20100213231116.1d3ad806-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2010-02-14  2:11       ` David Brownell
2010-02-14  8:33       ` Trent Piepho
     [not found]         ` <Pine.LNX.4.64.1002140000220.2366-3bmvVOk6DZ+DGx/iekXGtrjh7zpefjiS@public.gmane.org>
2010-02-14 13:28           ` Jean Delvare

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.