i2c: Use a separate mutex for userspace client lists
Subsystems (2)
PATCH 1/1 i2c: Use a separate mutex for userspace client lists
Moving userspace-instantiated clients to separate lists wasn't nearly enough to avoid deadlocks in multiplexed bus cases. We also want to have a dedicated mutex to protect each list.
Signed-off-by Jean Delvare <[email protected]>
Cc Michael Lawnick <[email protected]>
---
Michael, this should solve any deadlock issue related to userspace devices we've been discussing lately. I should probably have done this from the beginning. This also has the benefit of making your own patch slightly smaller - I'll update it myself.
drivers/i2c/i2c-core.c | 13 +++++++------ include/linux/i2c.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-)
drivers/i2c/i2c-core.c +7 -6
@@ -656,9 +656,9 @@ i2c_sysfs_new_device(struct device *dev,return -EINVAL ;/* Keep track of the added device */ -i2c_lock_adapter (adap); +mutex_lock (&adap->userspace_clients_lock);list_add_tail (&client->detected, &adap->userspace_clients); -i2c_unlock_adapter (adap); +mutex_unlock (&adap->userspace_clients_lock);dev_info (dev,"%s: Instantiated device %s at 0x%02hx\n" ,"new_device" , info.type, info.addr);
@@ -697,7 +697,7 @@ i2c_sysfs_delete_device(struct device *d/* Make sure the device was added through sysfs */ res = -ENOENT ; -i2c_lock_adapter (adap); +mutex_lock (&adap->userspace_clients_lock);list_for_each_entry_safe (client, next, &adap->userspace_clients, detected) {if (client->addr == addr) {
@@ -710,7 +710,7 @@ i2c_sysfs_delete_device(struct device *dbreak ; } } -i2c_unlock_adapter (adap); +mutex_unlock (&adap->userspace_clients_lock);if (res <0 ) dev_err(dev, "%s: Can't find device in list\n",
@@ -792,6 +792,7 @@ static int i2c_register_adapter(struct i }rt_mutex_init (&adap->bus_lock); +mutex_init (&adap->userspace_clients_lock);INIT_LIST_HEAD (&adap->userspace_clients);/* Set default timeout to 1 second if not already set */
@@ -994,7 +995,7 @@ int i2c_del_adapter(struct i2c_adapter *return res;/* Remove devices instantiated from sysfs */ -i2c_lock_adapter (adap); +mutex_lock (&adap->userspace_clients_lock);list_for_each_entry_safe (client, next, &adap->userspace_clients, detected) { dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,
@@ -1002,7 +1003,7 @@ int i2c_del_adapter(struct i2c_adapter *list_del (&client->detected);i2c_unregister_device (client); } -i2c_unlock_adapter (adap); +mutex_unlock (&adap->userspace_clients_lock);/* Detach any active clients. This can't fail, thus we do not checking the returned value. */
include/linux/i2c.h +1 -0
@@ -366,6 +366,7 @@ struct i2c_adapter {char name[48 ];struct completion dev_released; +struct mutex userspace_clients_lock;struct list_head userspace_clients; };#define to_i2c_adapter (d) container_of(d, struct i2c_adapter, dev)
Signature · 1 line
Jean Delvare