Skip to contentSkip to conversation

i2c bus multiplexing (Version 2).

PATCH In review Rodolfo Giometti 5 participants 23 messages Feb 5, 2009 – Apr 16, 2010 18 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

This patch set adds to the I2C core the ability to handle multiplexed I2C bus topologies by presenting each multiplexed segment as a I2C adapter.

As you can see from the changelog I had to update i2c-core since when a real adapter (not multiplexer) driver is inserted into the kernel _after_ an i2c multiplxer one, function i2c_add_adapter() is called recursively (and the same for i2c_del_adapter() during module removal) causing a kernel hang due the i2c's "core_lock" mutex.

Changelog
=========

Version 1 -> 2:
---------------

* Fixes a bug related to recursive calls of i2c_(add|del)_adapter() functions when main adapter is inserted or removed _after_ slave adapetrs (i2c multiplexers).

This goal has been achieved by:

a) using rwsem instead of mutex for accessing board info data struct,

b) ignoring any active client detaching faults (see relative patch for further info),

c) removing "core_lock" mutex into adapters (de)registration code.

Rodolfo

--

 b/drivers/i2c/Kconfig         |   10 +
 b/drivers/i2c/Makefile        |    3 
 b/drivers/i2c/i2c-boardinfo.c |    6 
 b/drivers/i2c/i2c-core.c      |    4 
 b/drivers/i2c/i2c-core.h      |    2 
 b/drivers/i2c/i2c-mux.c       |  180 +++++++++++++++++++++++
 b/drivers/i2c/muxes/Kconfig   |    8 +
 b/drivers/i2c/muxes/Makefile  |    6
 b/drivers/i2c/muxes/pca954x.c |  325 ++++++++++++++++++++++++++++++++++++++++++
 b/include/linux/i2c-id.h      |    3
 b/include/linux/i2c.h         |   14 +
 b/include/linux/i2c/pca954x.h |   13 +
 drivers/i2c/i2c-core.c        |   78 ++++------
 drivers/i2c/muxes/Kconfig     |    9 +
 drivers/i2c/muxes/Makefile    |    2
 15 files changed, 615 insertions(+), 48 deletions(-)

A message that is not in the archive (sent off-list or not yet received): 1233840973-13268-1-git-send-email-giometti-k2GhghHVRtY@public.gmane.org

#2 lore raw

PATCH 1/6 i2c: put driver_unregister() out of core_lock protection.

As for i2c_register_driver() during driver registration only class_for_each_device() call is protected by the i2c "core_lock" so we can (hopefully) do the same during driver deletion.

---
 drivers/i2c/i2c-core.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/i2c/i2c-core.c +2 -2
index b1c9abe..3454878 100644
@@ -799,10 +799,10 @@ void i2c_del_driver(struct i2c_driver *driver)
 	class_for_each_device(&i2c_adapter_class, NULL, driver,
 			      __detach_adapter);
 
+	mutex_unlock(&core_lock);
+
 	driver_unregister(&driver->driver);
 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
-
-	mutex_unlock(&core_lock);
 }
 EXPORT_SYMBOL(i2c_del_driver);
 
Signature · 1 line
1.5.6.3

A message that is not in the archive (sent off-list or not yet received): 1233840973-13268-2-git-send-email-giometti-k2GhghHVRtY@public.gmane.org

#4 lore raw

PATCH 2/6 i2c: use rwsem instead of mutex.

By using rwsem we can easily manage recursive calls of i2c_scan_static_board_info() function without breaking the locking.

---
 drivers/i2c/i2c-boardinfo.c |    6 +++---
 drivers/i2c/i2c-core.c      |    4 ++--
 drivers/i2c/i2c-core.h      |    2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)
drivers/i2c/i2c-boardinfo.c +3 -3
index ffb35f0..981cdd8 100644
@@ -25,7 +25,7 @@
 /* These symbols are exported ONLY FOR the i2c core.
  * No other users will be supported.
  */
-DEFINE_MUTEX(__i2c_board_lock);
+DECLARE_RWSEM(__i2c_board_lock);
 EXPORT_SYMBOL_GPL(__i2c_board_lock);
 
 LIST_HEAD(__i2c_board_list);
@@ -63,7 +63,7 @@ i2c_register_board_info(int busnum,
 {
 	int status;
 
-	mutex_lock(&__i2c_board_lock);
+	down_write(&__i2c_board_lock);
 
 	/* dynamic bus numbers will be assigned after the last static one */
 	if (busnum >= __i2c_first_dynamic_bus_num)
@@ -84,7 +84,7 @@ i2c_register_board_info(int busnum,
 		list_add_tail(&devinfo->list, &__i2c_board_list);
 	}
 
-	mutex_unlock(&__i2c_board_lock);
+	up_write(&__i2c_board_lock);
 
 	return status;
 }
drivers/i2c/i2c-core.c +2 -2
index 3454878..74b89a9 100644
@@ -408,7 +408,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
 {
 	struct i2c_devinfo	*devinfo;
 
-	mutex_lock(&__i2c_board_lock);
+	down_read(&__i2c_board_lock);
 	list_for_each_entry(devinfo, &__i2c_board_list, list) {
 		if (devinfo->busnum == adapter->nr
 				&& !i2c_new_device(adapter,
@@ -417,7 +417,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
 				i2c_adapter_id(adapter),
 				devinfo->board_info.addr);
 	}
-	mutex_unlock(&__i2c_board_lock);
+	up_read(&__i2c_board_lock);
 }
 
 static int i2c_do_add_adapter(struct device_driver *d, void *data)
drivers/i2c/i2c-core.h +1 -1
index cd5bff8..e6af064 100644
@@ -25,7 +25,7 @@ struct i2c_devinfo {
 /* board_lock protects board_list and first_dynamic_bus_num.
  * only i2c core components are allowed to use these symbols.
  */
-extern struct mutex	__i2c_board_lock;
+extern struct rw_semaphore	__i2c_board_lock;
 extern struct list_head	__i2c_board_list;
 extern int		__i2c_first_dynamic_bus_num;
 
Signature · 1 line
1.5.6.3

A message that is not in the archive (sent off-list or not yet received): 1233840973-13268-3-git-send-email-giometti-k2GhghHVRtY@public.gmane.org

#6 lore raw

PATCH 3/6 i2c: ignore active clients detaching during adapter removal.

When we are removing an adapter we decide to ignore any active client detaching faults for two reasons:

1) one (or more) active client may be switched off, so it cannot replay to the "adapter removed" event.

2) it shouldn't happen, and even if it happens it may be due a bus fault which can be resolved by resetting the adapter (most of them can be resetted simply by rmmod and then insmod the module again).

---
 drivers/i2c/i2c-core.c |   17 +++++++----------
 1 files changed, 7 insertions(+), 10 deletions(-)
drivers/i2c/i2c-core.c +7 -10
index 74b89a9..5d3646f 100644
@@ -593,11 +593,13 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
 
 	if (!driver->detach_adapter)
 		return 0;
+
+	/* We ignore the return code; if it fails, too bad */
 	res = driver->detach_adapter(adapter);
 	if (res)
 		dev_err(&adapter->dev, "detach_adapter failed (%d) "
 			"for driver [%s]\n", res, driver->driver.name);
-	return res;
+	return 0;
 }
 
 /**
@@ -611,7 +613,7 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
 	struct i2c_client *client, *_n;
-	int res = 0;
+	int res = 0, dummy;
 
 	mutex_lock(&core_lock);
 
@@ -624,13 +626,10 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 	}
 
 	/* Tell drivers about this removal */
-	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
+	dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
 			       i2c_do_del_adapter);
-	if (res)
-		goto out_unlock;
 
-	/* detach any active clients. This must be done first, because
-	 * it can fail; in which case we give up. */
+	/* Detach any active clients */
 	list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) {
 		struct i2c_driver	*driver;
 
@@ -643,12 +642,10 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 		}
 
 		/* legacy drivers create and remove clients themselves */
-		if ((res = driver->detach_client(client))) {
+		if (driver->detach_client(client))
 			dev_err(&adap->dev, "detach_client failed for client "
 				"[%s] at address 0x%02x\n", client->name,
 				client->addr);
-			goto out_unlock;
-		}
 	}
 
 	/* clean up the sysfs representation */
Signature · 1 line
1.5.6.3

A message that is not in the archive (sent off-list or not yet received): 1233840973-13268-4-git-send-email-giometti-k2GhghHVRtY@public.gmane.org

#8 lore raw

PATCH 4/6 i2c: free adapters (de)registration from i2c "core_lock" mutex.

The adapters (de)registration are now protectd by using a dedicated mutex instead of using global "core_lock" one. This allow multiple (and recursive) (de)registration of several adapters (or i2c multiplexers acting as i2c virtual adapters).

---
 drivers/i2c/i2c-core.c |   57 +++++++++++++++++++++++------------------------
 1 files changed, 28 insertions(+), 29 deletions(-)
drivers/i2c/i2c-core.c +28 -29
index 5d3646f..4b088ef 100644
@@ -40,6 +40,7 @@
 
 
 static DEFINE_MUTEX(core_lock);
+static DEFINE_MUTEX(idr_adapter_lock);
 static DEFINE_IDR(i2c_adapter_idr);
 
 #define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect)
@@ -438,7 +439,7 @@ static int i2c_do_add_adapter(struct device_driver *d, void *data)
 
 static int i2c_register_adapter(struct i2c_adapter *adap)
 {
-	int res = 0, dummy;
+	int res, dummy;
 
 	/* Can't register until after driver model init */
 	if (unlikely(WARN_ON(!i2c_bus_type.p)))
@@ -448,8 +449,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 	mutex_init(&adap->clist_lock);
 	INIT_LIST_HEAD(&adap->clients);
 
-	mutex_lock(&core_lock);
-
 	/* Add the adapter to the driver core.
 	 * If the parent pointer is not set up,
 	 * we add this adapter to the host bus.
@@ -463,8 +462,13 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 	adap->dev.release = &i2c_adapter_dev_release;
 	adap->dev.class = &i2c_adapter_class;
 	res = device_register(&adap->dev);
-	if (res)
-		goto out_list;
+	if (res) {
+		mutex_lock(&idr_adapter_lock);
+		idr_remove(&i2c_adapter_idr, adap->nr);
+		mutex_unlock(&idr_adapter_lock);
+
+		return res;
+	}
 
 	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
@@ -476,13 +480,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 	dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
 				 i2c_do_add_adapter);
 
-out_unlock:
-	mutex_unlock(&core_lock);
-	return res;
-
-out_list:
-	idr_remove(&i2c_adapter_idr, adap->nr);
-	goto out_unlock;
+	return 0;
 }
 
 /**
@@ -506,11 +504,11 @@ retry:
 	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
 		return -ENOMEM;
 
-	mutex_lock(&core_lock);
+	mutex_lock(&idr_adapter_lock);
 	/* "above" here means "above or equal to", sigh */
 	res = idr_get_new_above(&i2c_adapter_idr, adapter,
 				__i2c_first_dynamic_bus_num, &id);
-	mutex_unlock(&core_lock);
+	mutex_unlock(&idr_adapter_lock);
 
 	if (res < 0) {
 		if (res == -EAGAIN)
@@ -555,7 +553,7 @@ retry:
 	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
 		return -ENOMEM;
 
-	mutex_lock(&core_lock);
+	mutex_lock(&idr_adapter_lock);
 	/* "above" here means "above or equal to", sigh;
 	 * we need the "equal to" result to force the result
 	 */
@@ -564,7 +562,7 @@ retry:
 		status = -EBUSY;
 		idr_remove(&i2c_adapter_idr, id);
 	}
-	mutex_unlock(&core_lock);
+	mutex_unlock(&idr_adapter_lock);
 	if (status == -EAGAIN)
 		goto retry;
 
@@ -612,19 +610,25 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
  */
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
+	struct i2c_adapter *ptr;
 	struct i2c_client *client, *_n;
-	int res = 0, dummy;
+	int dummy;
 
-	mutex_lock(&core_lock);
+	mutex_lock(&idr_adapter_lock);
 
 	/* First make sure that this adapter was ever added */
-	if (idr_find(&i2c_adapter_idr, adap->nr) != adap) {
+	ptr = idr_find(&i2c_adapter_idr, adap->nr);
+	if (ptr != adap) {
 		pr_debug("i2c-core: attempting to delete unregistered "
 			 "adapter [%s]\n", adap->name);
-		res = -EINVAL;
-		goto out_unlock;
+		mutex_unlock(&idr_adapter_lock);
+		return -EINVAL;
 	}
 
+	/* ... then remove adapter ID */
+	idr_remove(&i2c_adapter_idr, adap->nr);
+	mutex_unlock(&idr_adapter_lock);
+
 	/* Tell drivers about this removal */
 	dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
 			       i2c_do_del_adapter);
@@ -655,18 +659,13 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 	/* wait for sysfs to drop all references */
 	wait_for_completion(&adap->dev_released);
 
-	/* free bus id */
-	idr_remove(&i2c_adapter_idr, adap->nr);
-
 	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
 
 	/* Clear the device structure in case this adapter is ever going to be
 	   added again */
 	memset(&adap->dev, 0, sizeof(adap->dev));
 
- out_unlock:
-	mutex_unlock(&core_lock);
-	return res;
+	return 0;
 }
 EXPORT_SYMBOL(i2c_del_adapter);
 
@@ -1497,12 +1496,12 @@ struct i2c_adapter* i2c_get_adapter(int id)
 {
 	struct i2c_adapter *adapter;
 
-	mutex_lock(&core_lock);
+	mutex_lock(&idr_adapter_lock);
 	adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
 	if (adapter && !try_module_get(adapter->owner))
 		adapter = NULL;
 
-	mutex_unlock(&core_lock);
+	mutex_unlock(&idr_adapter_lock);
 	return adapter;
 }
 EXPORT_SYMBOL(i2c_get_adapter);
Signature · 1 line
1.5.6.3

A message that is not in the archive (sent off-list or not yet received): 1233840973-13268-5-git-send-email-giometti-k2GhghHVRtY@public.gmane.org

#10 lore raw

PATCH 5/6 i2c: Multiplexed I2C bus core support.

Add to the I2C core the ability to handle multiplexed I2C bus topologies by presenting each multiplexed segment as a I2C adapter.

---
 drivers/i2c/Kconfig        |   10 +++
 drivers/i2c/Makefile       |    3 +-
 drivers/i2c/i2c-mux.c      |  180 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/muxes/Kconfig  |    8 ++
 drivers/i2c/muxes/Makefile |    6 ++
 include/linux/i2c-id.h     |    3 +
 include/linux/i2c.h        |   14 ++++
 7 files changed, 223 insertions(+), 1 deletions(-)
 create mode 100644 drivers/i2c/i2c-mux.c
 create mode 100644 drivers/i2c/muxes/Kconfig
 create mode 100644 drivers/i2c/muxes/Makefile
drivers/i2c/Kconfig +10 -0
index 711ca08..78dc245 100644
@@ -27,6 +27,16 @@ config I2C_BOARDINFO
 	boolean
 	default y
 
+config I2C_MUX
+	tristate "I2C bus multiplexing support"
+	depends on I2C
+	help
+	  Say Y here if you want the I2C core to support the ability to
+	  handle multiplexed I2C bus topologies, by presenting each
+	  multiplexed segment as a I2C adapter.
+
+source drivers/i2c/muxes/Kconfig
+
 config I2C_CHARDEV
 	tristate "I2C device interface"
 	help
drivers/i2c/Makefile +2 -1
index ba26e6c..281e2a7 100644
@@ -4,8 +4,9 @@
 
 obj-$(CONFIG_I2C_BOARDINFO)	+= i2c-boardinfo.o
 obj-$(CONFIG_I2C)		+= i2c-core.o
+obj-$(CONFIG_I2C_MUX)		+= i2c-mux.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
-obj-y				+= busses/ chips/ algos/
+obj-y				+= busses/ chips/ muxes/ algos/
 
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
 EXTRA_CFLAGS += -DDEBUG
drivers/i2c/i2c-mux.c new file +180 -0

180 lines not on this page · raw message

drivers/i2c/muxes/Kconfig new file +8 -0
new file mode 100644
index 0000000..95b9bde
@@ -0,0 +1,8 @@
+#
+# Multiplexer I2C chip drivers configuration
+#
+
+menu "Multiplexer I2C Chip support"
+	depends on I2C && I2C_MUX && EXPERIMENTAL
+
+endmenu
drivers/i2c/muxes/Makefile new file +6 -0
new file mode 100644
index 0000000..5e70bde
@@ -0,0 +1,6 @@
+#
+# Makefile for multiplexer I2C chip drivers.
+
+ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
include/linux/i2c-id.h +3 -0
index 01d67ba..d4f97b6 100644
@@ -162,4 +162,7 @@
 #define I2C_HW_SAA7146		0x060000 /* SAA7146 video decoder bus */
 #define I2C_HW_SAA7134		0x090000 /* SAA7134 video decoder bus */
 
+/* --- Virtual adapter mark */
+#define I2C_HW_VIRT            0x80000000
+
 #endif /* LINUX_I2C_ID_H */
include/linux/i2c.h +14 -0
index 20873d4..748fc22 100644
@@ -588,6 +588,20 @@ union i2c_smbus_data {
 #define I2C_SMBUS_BLOCK_PROC_CALL   7		/* SMBus 2.0 */
 #define I2C_SMBUS_I2C_BLOCK_DATA    8
 
+/*
+ * Called to create a 'virtual' i2c bus which represents a multiplexed bus
+ * segment.  The client and mux_val are passed to the select and deselect
+ * callback functions to perform hardware-specific mux control.
+ */
+struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
+				void *client, u32 force_nr, u32 mux_val,
+				int (*select_cb) (struct i2c_adapter *,
+						void *, u32),
+				int (*deselect_cb) (struct i2c_adapter *,
+						void *, u32));
+
+int i2c_del_mux_adapter(struct i2c_adapter *adap);
+
 
 #ifdef __KERNEL__
 
Signature · 1 line
1.5.6.3

A message that is not in the archive (sent off-list or not yet received): 1233840973-13268-6-git-send-email-giometti-k2GhghHVRtY@public.gmane.org

#12 lore raw

PATCH 6/6 i2c: driver for PCA954x I2C multiplexer series.

---
 drivers/i2c/muxes/Kconfig   |    9 ++
 drivers/i2c/muxes/Makefile  |    2 +
 drivers/i2c/muxes/pca954x.c |  325 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c/pca954x.h |   13 ++
 4 files changed, 349 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/muxes/pca954x.c
 create mode 100644 include/linux/i2c/pca954x.h
drivers/i2c/muxes/Kconfig +9 -0
index 95b9bde..72c7055 100644
@@ -5,4 +5,13 @@
 menu "Multiplexer I2C Chip support"
 	depends on I2C && I2C_MUX && EXPERIMENTAL
 
+config I2CMUX_PCA954x
+	tristate "Philips PCA953x I2C Mux/switches"
+	help
+	  If you say yes here you get support for the Philips PCA954x
+	  I2C mux/switch devices.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called pca954x.
+
 endmenu
drivers/i2c/muxes/Makefile +2 -0
index 5e70bde..f752576 100644
@@ -1,6 +1,8 @@
 #
 # Makefile for multiplexer I2C chip drivers.
 
+obj-$(CONFIG_I2CMUX_PCA954x)	+= pca954x.o
+
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
drivers/i2c/muxes/pca954x.c new file +325 -0

325 lines not on this page · raw message

include/linux/i2c/pca954x.h new file +13 -0
new file mode 100644
index 0000000..18d5e79
@@ -0,0 +1,13 @@
+/* Platform data for the PCA954x I2C multiplexers */
+
+struct pca954x_platform_mode {
+	int		adap_id;
+	unsigned int	deselect_on_exit:1;
+	int		(*is_chan_connected)(struct i2c_adapter *adap,
+					struct i2c_client *client, u32 chan);
+};
+
+struct pca954x_platform_data {
+	struct pca954x_platform_mode *modes;
+	int num_modes;
+};
Signature · 1 line
1.5.6.3
#13 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

In reply to a message not in the archive
Quoted 10 lines · Rodolfo Giometti

When we are removing an adapter we decide to ignore any active client detaching faults for two reasons:

1) one (or more) active client may be switched off, so it cannot replay to the "adapter removed" event.

2) it shouldn't happen, and even if it happens it may be due a bus fault which can be resolved by resetting the adapter (most of them can be resetted simply by rmmod and then insmod the module again).

This bothers me. If the client can't detach, it can't; there may be all kinds of chaos introduced by trying to fake success in such cases. Like resources that suddenly just vanish, leaving breakage in their wake.

If this is a shutdown() path, where it's basically just a polite driver notification, that's one thing.

But I2C gets used as a system control bus, so this sort of "ignore the errors" stuff worries me a lot.

- Dave

A message that is not in the archive (sent off-list or not yet received): 200902051602.44036.david-b-yBeKhBN/[email protected]

#15 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 17 lines · David Brownell
Quoted 10 lines · Rodolfo Giometti

When we are removing an adapter we decide to ignore any active client detaching faults for two reasons:

1) one (or more) active client may be switched off, so it cannot replay to the "adapter removed" event.

2) it shouldn't happen, and even if it happens it may be due a bus fault which can be resolved by resetting the adapter (most of them can be resetted simply by rmmod and then insmod the module again).

This bothers me. If the client can't detach, it can't; there may be all kinds of chaos introduced by trying to fake success in such cases. Like resources that suddenly just vanish, leaving breakage in their wake.

Quoted 5 lines

If this is a shutdown() path, where it's basically just a polite driver notification, that's one thing.

But I2C gets used as a system control bus, so this sort of "ignore the errors" stuff worries me a lot.

If so I suppose we should take in account the adapter->client_unregister() return value also, which is currently ignored in i2c_unregister_device() function...

However, since I2c is a bus it could be possible that a slave device stops functioning (or the user decides to turn it off), so aborting the adapter removal in these cases can be not right... moreover if the adapter should be logically separated from the i2c clients I suppose is better allowing the user to remove (and eventually replace) it and then resolving i2c client's stale states into the relative driver.

I suppose this is the same behaviour of USB bus: we can remove an USB host adapter independently from USB devices.

Ciao,

Rodolfo

Signature · 4 lines
gnu/Linux Solutions                  e-mail: giometti-AVVDYK/kqiJWk0Htik3J/[email protected]
Linux Device Driver                          [email protected]
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti

A message that is not in the archive (sent off-list or not yet received): 20090206102220.GF28554-AVVDYK/kqiJWk0Htik3J/[email protected]

#17 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 21 lines · Rodolfo Giometti
Quoted 20 lines · David Brownell
Quoted 10 lines · Rodolfo Giometti

When we are removing an adapter we decide to ignore any active client detaching faults for two reasons:

1) one (or more) active client may be switched off, so it cannot replay to the "adapter removed" event.

2) it shouldn't happen, and even if it happens it may be due a bus fault which can be resolved by resetting the adapter (most of them can be resetted simply by rmmod and then insmod the module again).

This bothers me. If the client can't detach, it can't; there may be all kinds of chaos introduced by trying to fake success in such cases. Like resources that suddenly just vanish, leaving breakage in their wake.

If this is a shutdown() path, where it's basically just a polite driver notification, that's one thing.

Quoted 6 lines
Quoted 2 lines

But I2C gets used as a system control bus, so this sort of "ignore the errors" stuff worries me a lot.

If so I suppose we should take in account the adapter->client_unregister() return value also, which is currently ignored in i2c_unregister_device() function...

Taking the old, deprecated, notoriously broken i2c model as an example doesn't necessarily serve your cause ;)

Quoted 9 lines

However, since I2c is a bus it could be possible that a slave device stops functioning (or the user decides to turn it off), so aborting the adapter removal in these cases can be not right... moreover if the adapter should be logically separated from the i2c clients I suppose is better allowing the user to remove (and eventually replace) it and then resolving i2c client's stale states into the relative driver.

I suppose this is the same behaviour of USB bus: we can remove an USB host adapter independently from USB devices.

The big difference, I presume, is that USB is never a system bus. But even for USB, devices can't exist without the host. If you kill the host and resurrect it later, you also kill the devices and resurrect them later.

The debate about drivers failing device removal is an old one, not specific to i2c. My opinion is that .remove() should succeed as much as possible. It should really only fail if the problem is so serious that the system's state would otherwise become a problem (e.g. freeing memory which is still referenced.) This should be a rare case.

Signature · 1 line
Jean Delvare

A message that is not in the archive (sent off-list or not yet received): [email protected]

#19 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 3 lines · Jean Delvare

Taking the old, deprecated, notoriously broken i2c model as an example doesn't necessarily serve your cause ;)

I see, but till this part is in we should consider it, shouldn't we? Eheheh :D

Quoted 4 lines

The big difference, I presume, is that USB is never a system bus. But even for USB, devices can't exist without the host. If you kill the host and resurrect it later, you also kill the devices and resurrect them later.

But this can be done with i2c devices too! Let's think about leds drivers with uses an i2c GPIOs expander, they can exist without any adapter, even if they are not functional of course. :)

Quoted 5 lines

The debate about drivers failing device removal is an old one, not specific to i2c. My opinion is that .remove() should succeed as much as possible. It should really only fail if the problem is so serious that the system's state would otherwise become a problem (e.g. freeing memory which is still referenced.) This should be a rare case.

I think that i2c clients devices should be really separated by adapter ones, that is we should be free to add and remove any adapter without considering the clients state. Then each clients device drivers should free each allocated resource they use and the adapters shouldn't know about it.

Doing like this will semply the code a lot and it allows i2c core to be more flexible.

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail: giometti-AVVDYK/kqiJWk0Htik3J/[email protected]
Linux Device Driver                          [email protected]
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti

A message that is not in the archive (sent off-list or not yet received): 20090206125907.GA8581-AVVDYK/kqiJWk0Htik3J/[email protected]

#21 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 7 lines · Rodolfo Giometti
Quoted 3 lines · Jean Delvare

Taking the old, deprecated, notoriously broken i2c model as an example doesn't necessarily serve your cause ;)

I see, but till this part is in we should consider it, shouldn't we? Eheheh :D

No. As I've said before, ideally I wanted legacy binding style to die _before_ we add support for multiplexing. But if we don't want to wait, I still want legacy binding and multiplexing to be mutually exclusive.

Quoted 8 lines
Quoted 4 lines

The big difference, I presume, is that USB is never a system bus. But even for USB, devices can't exist without the host. If you kill the host and resurrect it later, you also kill the devices and resurrect them later.

But this can be done with i2c devices too! Let's think about leds drivers with uses an i2c GPIOs expander, they can exist without any adapter, even if they are not functional of course. :)

That not the question. We all agree that some i2c chip drivers don't need to be able to prevent the removal of the underlying bus driver. The open point is whether some i2c chip drivers do. Honestly, I don't know, as such cases would happen on embedded systems, which are out of my realm. But maybe David has examples in mind.

Quoted 11 lines
Quoted 5 lines

The debate about drivers failing device removal is an old one, not specific to i2c. My opinion is that .remove() should succeed as much as possible. It should really only fail if the problem is so serious that the system's state would otherwise become a problem (e.g. freeing memory which is still referenced.) This should be a rare case.

I think that i2c clients devices should be really separated by adapter ones, that is we should be free to add and remove any adapter without considering the clients state. Then each clients device drivers should free each allocated resource they use and the adapters shouldn't know about it.

How does your description differ from the current implementation? I don't follow you.

Quoted 2 lines

Doing like this will semply the code a lot and it allows i2c core to be more flexible.

Patches welcome... but I have no clue what you want to do at this point.

Signature · 1 line
Jean Delvare

A message that is not in the archive (sent off-list or not yet received): [email protected]

#23 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 4 lines · Jean Delvare

No. As I've said before, ideally I wanted legacy binding style to die _before_ we add support for multiplexing. But if we don't want to wait, I still want legacy binding and multiplexing to be mutually exclusive.

Ok.

Quoted 9 lines
Quoted 8 lines
Quoted 4 lines

The big difference, I presume, is that USB is never a system bus. But even for USB, devices can't exist without the host. If you kill the host and resurrect it later, you also kill the devices and resurrect them later.

But this can be done with i2c devices too! Let's think about leds drivers with uses an i2c GPIOs expander, they can exist without any adapter, even if they are not functional of course. :)

Quoted 5 lines

That not the question. We all agree that some i2c chip drivers don't need to be able to prevent the removal of the underlying bus driver. The open point is whether some i2c chip drivers do. Honestly, I don't know, as such cases would happen on embedded systems, which are out of my realm. But maybe David has examples in mind.

I see. But in this case we should dig into the code and verify what each i2c drivers wish to do during driver removal and eventually fix it, is that right?

Quoted 6 lines
Quoted 6 lines
Quoted 5 lines

The debate about drivers failing device removal is an old one, not specific to i2c. My opinion is that .remove() should succeed as much as possible. It should really only fail if the problem is so serious that the system's state would otherwise become a problem (e.g. freeing memory which is still referenced.) This should be a rare case.

Quoted 8 lines
Quoted 5 lines

I think that i2c clients devices should be really separated by adapter ones, that is we should be free to add and remove any adapter without considering the clients state. Then each clients device drivers should free each allocated resource they use and the adapters shouldn't know about it.

How does your description differ from the current implementation? I don't follow you.

Currently an i2c driver may block adpater removal procedure, my implementation, instead, considers i2c adapter completely separated from i2c clients so that no one can't interfere with adapter insertion/removal code.

Quoted 4 lines
Quoted 2 lines

Doing like this will semply the code a lot and it allows i2c core to be more flexible.

Patches welcome... but I have no clue what you want to do at this point.

If you agree I can provide a branch tree from current vanilla and describe my solution into linux-i2c wiki, so users may test it and propose enhancements without touching current stable code.

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail: giometti-AVVDYK/kqiJWk0Htik3J/[email protected]
Linux Device Driver                          [email protected]
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti

A message that is not in the archive (sent off-list or not yet received): 20090209130642.GV7975-AVVDYK/kqiJWk0Htik3J/[email protected]

#25 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 10 lines · Rodolfo Giometti
Quoted 5 lines · Jean Delvare

That not the question. We all agree that some i2c chip drivers don't need to be able to prevent the removal of the underlying bus driver. The open point is whether some i2c chip drivers do. Honestly, I don't know, as such cases would happen on embedded systems, which are out of my realm. But maybe David has examples in mind.

I see. But in this case we should dig into the code and verify what each i2c drivers wish to do during driver removal and eventually fix it, is that right?

I simply don't know. As I have written above, I do not have any example of an I2C device which should be allowed to prevent bus removal. But I am a PC person and the i2c subsystem is used in a very different way on embedded systems. So better discuss this with people who know these systems.

Quoted 8 lines
Quoted 3 lines

(...)
How does your description differ from the current implementation? I don't follow you.

Currently an i2c driver may block adpater removal procedure, my implementation, instead, considers i2c adapter completely separated from i2c clients so that no one can't interfere with adapter insertion/removal code.

As far as I can see this only happens for legacy i2c chip drivers, which implement driver->detach_client() or driver->detach_adapter(). The plan is to get rid of the last few users of this model as soon as possible, so that's not really relevant.

Do you see any other place in i2c-core where we check for error on device removal and do something based on that, in particular for new-style i2c chip drivers?

Quoted 5 lines
Quoted 1 line

Patches welcome... but I have no clue what you want to do at this point.

If you agree I can provide a branch tree from current vanilla and describe my solution into linux-i2c wiki, so users may test it and propose enhancements without touching current stable code.

Well, you can always do that if you want, but please first clearly define the practical problem you are trying to solve. We are not going to change the i2c core without a good reason.

Oh, and if you have time to spend on i2c, then helping getting rid of the remaining legacy drivers would be greatly appreciated. As long as we have to support both models, there are many core cleanups and improvements that are simply not possible (or so risky that nobody wants to try.)

Signature · 1 line
Jean Delvare

A message that is not in the archive (sent off-list or not yet received): [email protected]

#27 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 9 lines · Jean Delvare
Quoted 4 lines · Rodolfo Giometti

If you agree I can provide a branch tree from current vanilla and describe my solution into linux-i2c wiki, so users may test it and propose enhancements without touching current stable code.

Well, you can always do that if you want, but please first clearly define the practical problem you are trying to solve. We are not going to change the i2c core without a good reason.

I created a new page here:

http://i2c.wiki.kernel.org/index.php/I2C_bus_multiplexing

Please, take a look and report everything should be fixed. :)

Hope I did exactly what you requested...

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail: giometti-AVVDYK/kqiJWk0Htik3J/[email protected]
Linux Device Driver                          [email protected]
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti

A message that is not in the archive (sent off-list or not yet received): 20090218164812.GA11217-AVVDYK/kqiJWk0Htik3J/[email protected]

#29 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Hi Rodolfo,

Sorry for the late answer, I missed this post in the middle of the thread.

Quoted 8 lines · Rodolfo Giometti
Quoted 3 lines · Jean Delvare

Well, you can always do that if you want, but please first clearly define the practical problem you are trying to solve. We are not going to change the i2c core without a good reason.

I created a new page here:

http://i2c.wiki.kernel.org/index.php/I2C_bus_multiplexing

Thanks for doing this!

Quoted 1 line

Please, take a look and report everything should be fixed. :)

Random comments:

* I really would like to get rid of the "virtual" term that has been repeatedly abused. Bus segments behind multiplexers are very real.

* I am surprised that you use the term "trunk" for all segments, be they in front of or behind multiplexers. When I think of a multiplexer, I designate the segment between the controller and the multiplexer as the trunk, and the segments behind the multiplexer as branches.

Other than that I am rather happy with your page, which explains the problem and the proposed solution clearly.

Signature · 1 line
Jean Delvare

A message that is not in the archive (sent off-list or not yet received): [email protected]

#31 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 4 lines · Jean Delvare

Hi Rodolfo,

Sorry for the late answer, I missed this post in the middle of the thread.

Don't worry about it! :)

Quoted 10 lines · Rodolfo Giometti
Quoted 8 lines · Jean Delvare
Quoted 3 lines

Well, you can always do that if you want, but please first clearly define the practical problem you are trying to solve. We are not going to change the i2c core without a good reason.

I created a new page here:

http://i2c.wiki.kernel.org/index.php/I2C_bus_multiplexing

Quoted 8 lines

Thanks for doing this!

Quoted 1 line

Please, take a look and report everything should be fixed. :)

Random comments:

* I really would like to get rid of the "virtual" term that has been repeatedly abused. Bus segments behind multiplexers are very real.

Actually I use the term "virtual" regarding to the adapters not to the bus segments. In fact the new devices created are not "real" adapters but "virtual" ones.

Quoted 5 lines

* I am surprised that you use the term "trunk" for all segments, be they in front of or behind multiplexers. When I think of a multiplexer, I designate the segment between the controller and the multiplexer as the trunk, and the segments behind the multiplexer as branches.

Ok, this can be corrected easily. :)

Quoted 2 lines

Other than that I am rather happy with your page, which explains the problem and the proposed solution clearly.

Thanks a lot!

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail: giometti-AVVDYK/kqiJWk0Htik3J/[email protected]
Linux Device Driver                          [email protected]
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti

A message that is not in the archive (sent off-list or not yet received): 20090528075835.GH20243-AVVDYK/kqiJWk0Htik3J/[email protected]

#33 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 7 lines · Rodolfo Giometti
Quoted 2 lines · Jean Delvare

* I really would like to get rid of the "virtual" term that has been repeatedly abused. Bus segments behind multiplexers are very real.

Actually I use the term "virtual" regarding to the adapters not to the bus segments. In fact the new devices created are not "real" adapters but "virtual" ones.

The confusion comes from the fact that struct i2c_adapter should have been named struct i2c_segment, as this is what it really represents. But back when it was decided, multiplexing wasn't considered so the developers thought "controller", "adapter" and "segment" were the same thing.

Ideally we should rename i2c_adapter to i2c_segment, but this seems a little intrusive for a rather thin benefit.

Signature · 1 line
Jean Delvare
#34 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

In reply to a message not in the archive
Quoted 21 lines · Jean Delvare

Hi Rodolfo,

Sorry for the late answer, I missed this post in the middle of the thread.

Quoted 8 lines · Rodolfo Giometti
Quoted 3 lines · Jean Delvare

Well, you can always do that if you want, but please first clearly define the practical problem you are trying to solve. We are not going to change the i2c core without a good reason.

I created a new page here:

http://i2c.wiki.kernel.org/index.php/I2C_bus_multiplexing

Thanks for doing this!

Quoted 1 line

Please, take a look and report everything should be fixed. :)

Random comments:

Quoted 8 lines

* I really would like to get rid of the "virtual" term that has been repeatedly abused. Bus segments behind multiplexers are very real.

* I am surprised that you use the term "trunk" for all segments, be they in front of or behind multiplexers. When I think of a multiplexer, I designate the segment between the controller and the multiplexer as the trunk, and the segments behind the multiplexer as branches.

Both fixed. Please review the page again. :)

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail: giometti-AVVDYK/kqiJWk0Htik3J/[email protected]
Linux Device Driver                          [email protected]
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti

A message that is not in the archive (sent off-list or not yet received): 20090529072835.GA4575-AVVDYK/kqiJWk0Htik3J/[email protected]

#36 lore raw

Re: [PATCH 3/6] i2c: ignore active clients detaching during adapter removal.

Quoted 6 lines · Rodolfo Giometti
Quoted 5 lines · Jean Delvare

Random comments:

* I really would like to get rid of the "virtual" term that has been repeatedly abused. Bus segments behind multiplexers are very real.

Quoted 7 lines
Quoted 5 lines

* I am surprised that you use the term "trunk" for all segments, be they in front of or behind multiplexers. When I think of a multiplexer, I designate the segment between the controller and the multiplexer as the trunk, and the segments behind the multiplexer as branches.

Both fixed. Please review the page again. :)

Looks good, thanks!

Signature · 1 line
Jean Delvare
#37 lore raw

Re: [PATCH 2/6] i2c: use rwsem instead of mutex.

In reply to a message not in the archive

Hi Rodolfo,

Quoted 68 lines · Rodolfo Giometti

By using rwsem we can easily manage recursive calls of i2c_scan_static_board_info() function without breaking the locking.

---
 drivers/i2c/i2c-boardinfo.c |    6 +++---
 drivers/i2c/i2c-core.c      |    4 ++--
 drivers/i2c/i2c-core.h      |    2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)
drivers/i2c/i2c-boardinfo.c +3 -3
index ffb35f0..981cdd8 100644
@@ -25,7 +25,7 @@
 /* These symbols are exported ONLY FOR the i2c core.
  * No other users will be supported.
  */
-DEFINE_MUTEX(__i2c_board_lock);
+DECLARE_RWSEM(__i2c_board_lock);
 EXPORT_SYMBOL_GPL(__i2c_board_lock);
 
 LIST_HEAD(__i2c_board_list);
@@ -63,7 +63,7 @@ i2c_register_board_info(int busnum,
 {
 	int status;
 
-	mutex_lock(&__i2c_board_lock);
+	down_write(&__i2c_board_lock);
 
 	/* dynamic bus numbers will be assigned after the last static one */
 	if (busnum >= __i2c_first_dynamic_bus_num)
@@ -84,7 +84,7 @@ i2c_register_board_info(int busnum,
 		list_add_tail(&devinfo->list, &__i2c_board_list);
 	}
 
-	mutex_unlock(&__i2c_board_lock);
+	up_write(&__i2c_board_lock);
 
 	return status;
 }
drivers/i2c/i2c-core.c +2 -2
index 3454878..74b89a9 100644
@@ -408,7 +408,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
 {
 	struct i2c_devinfo	*devinfo;
 
-	mutex_lock(&__i2c_board_lock);
+	down_read(&__i2c_board_lock);
 	list_for_each_entry(devinfo, &__i2c_board_list, list) {
 		if (devinfo->busnum == adapter->nr
 				&& !i2c_new_device(adapter,
@@ -417,7 +417,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
 				i2c_adapter_id(adapter),
 				devinfo->board_info.addr);
 	}
-	mutex_unlock(&__i2c_board_lock);
+	up_read(&__i2c_board_lock);
 }
 
 static int i2c_do_add_adapter(struct device_driver *d, void *data)
drivers/i2c/i2c-core.h +0 -0
index cd5bff8..e6af064 100644

drivers/i2c/i2c-core.h struct i2c_devinfo { · line 31

Quoted 8 lines
drivers/i2c/i2c-core.h +1 -1
@@ -25,7 +25,7 @@ struct i2c_devinfo {
 /* board_lock protects board_list and first_dynamic_bus_num.
  * only i2c core components are allowed to use these symbols.
  */
-extern struct mutex	__i2c_board_lock;
+extern struct rw_semaphore	__i2c_board_lock;
 extern struct list_head	__i2c_board_list;
 extern int		__i2c_first_dynamic_bus_num;
 

Patch applied, thank you. I've add missing includes of <linux/rwsem.h> in all 3 files.

Signature · 1 line
Jean Delvare
#38 lore raw
In reply to Rodolfo Giometti
Quoted 4 lines

This patch set adds to the I2C core the ability to handle multiplexed I2C bus topologies by presenting each multiplexed segment as a I2C adapter.

Hi Rodolfo,

Thanks for this patch. I learned about this patch through linux-media mailing list.

1)I have a sensor board header that uses pca9543a i2c switch which is addressed by this patch. In my board, I have another i2c chip that share the same i2c address with the sensor. Currently I cannot have both these drivers co-exists due to this. Please let me know if this can work once I use this patch.

2)Which kernel version you use for this patch?

3) Where can I download your patch so that I can give it a shot. Is there any platform data I need to setup in my arch/ folder to use this patch?

4) When do you think this will be merged to mainline kernel?

Thanks

Murali

A message that is not in the archive (sent off-list or not yet received): [email protected]

#40 lore raw

Hi Murali,

Quoted 7 lines · Muralidharan Karicheri
Quoted 4 lines

This patch set adds to the I2C core the ability to handle multiplexed I2C bus topologies by presenting each multiplexed segment as a I2C adapter.

Hi Rodolfo,

Quoted 8 lines

Thanks for this patch. I learned about this patch through linux-media mailing list.

1)I have a sensor board header that uses pca9543a i2c switch which is addressed by this patch. In my board, I have another i2c chip that share the same i2c address with the sensor. Currently I cannot have both these drivers co-exists due to this. Please let me know if this can work once I use this patch.

Yes, this is the idea. With bus multiplexing support, we can finally handle bus topologies with multiple chips using the same I2C address.

Quoted 7 lines

2)Which kernel version you use for this patch?

3) Where can I download your patch so that I can give it a shot. Is there any platform data I need to setup in my arch/ folder to use this patch?

4) When do you think this will be merged to mainline kernel?

I am reviewing the patches at the moment, after Michael sends an updated version addressing my comments, we should be ready to go. So we currently aim at merging i2c multiplexing support into kernel 2.6.35. At least a first version... more features can be added later.

Signature · 1 line
Jean Delvare