Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <khali@linux-fr.org>
Cc: Michael Lawnick <ml.lawnick@gmx.de>

+8 -6
+7 -6
drivers/i2c/i2c-core.c
··· 662 662 return -EINVAL; 663 663 664 664 /* Keep track of the added device */ 665 - i2c_lock_adapter(adap); 665 + mutex_lock(&adap->userspace_clients_lock); 666 666 list_add_tail(&client->detected, &adap->userspace_clients); 667 - i2c_unlock_adapter(adap); 667 + mutex_unlock(&adap->userspace_clients_lock); 668 668 dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", 669 669 info.type, info.addr); 670 670 ··· 703 703 704 704 /* Make sure the device was added through sysfs */ 705 705 res = -ENOENT; 706 - i2c_lock_adapter(adap); 706 + mutex_lock(&adap->userspace_clients_lock); 707 707 list_for_each_entry_safe(client, next, &adap->userspace_clients, 708 708 detected) { 709 709 if (client->addr == addr) { ··· 716 716 break; 717 717 } 718 718 } 719 - i2c_unlock_adapter(adap); 719 + mutex_unlock(&adap->userspace_clients_lock); 720 720 721 721 if (res < 0) 722 722 dev_err(dev, "%s: Can't find device in list\n", ··· 798 798 } 799 799 800 800 rt_mutex_init(&adap->bus_lock); 801 + mutex_init(&adap->userspace_clients_lock); 801 802 INIT_LIST_HEAD(&adap->userspace_clients); 802 803 803 804 /* Set default timeout to 1 second if not already set */ ··· 1004 1003 return res; 1005 1004 1006 1005 /* Remove devices instantiated from sysfs */ 1007 - i2c_lock_adapter(adap); 1006 + mutex_lock(&adap->userspace_clients_lock); 1008 1007 list_for_each_entry_safe(client, next, &adap->userspace_clients, 1009 1008 detected) { 1010 1009 dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, ··· 1012 1011 list_del(&client->detected); 1013 1012 i2c_unregister_device(client); 1014 1013 } 1015 - i2c_unlock_adapter(adap); 1014 + mutex_unlock(&adap->userspace_clients_lock); 1016 1015 1017 1016 /* Detach any active clients. This can't fail, thus we do not 1018 1017 checking the returned value. */
+1
include/linux/i2c.h
··· 368 368 char name[48]; 369 369 struct completion dev_released; 370 370 371 + struct mutex userspace_clients_lock; 371 372 struct list_head userspace_clients; 372 373 }; 373 374 #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)