Commit 390946b1 authored by Jean Delvare's avatar Jean Delvare Committed by Jean Delvare

i2c-core: Fix for lockdep validator

If kernel is compiled with CONFIG_PROVE_LOCKING the
validator raises an error when a multiplexer is removed
via sysfs and sub-clients are connected to it. This is a
false positive.
Documentation/lockdep-design.txt recommends to handle this
via calls to mutex_lock_nested().

Based on an earlier fix from Michael Lawnick.

Note that the extra code resolves to nothing unless
CONFIG_DEBUG_LOCK_ALLOC=y.
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
Cc: Michael Lawnick <ml.lawnick@gmx.de>
parent e68bb91b
...@@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev) ...@@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev)
complete(&adap->dev_released); complete(&adap->dev_released);
} }
/*
* This function is only needed for mutex_lock_nested, so it is never
* called unless locking correctness checking is enabled. Thus we
* make it inline to avoid a compiler warning. That's what gcc ends up
* doing anyway.
*/
static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
{
unsigned int depth = 0;
while ((adapter = i2c_parent_is_i2c_adapter(adapter)))
depth++;
return depth;
}
/* /*
* Let users instantiate I2C devices through sysfs. This can be used when * Let users instantiate I2C devices through sysfs. This can be used when
* platform initialization code doesn't contain the proper data for * platform initialization code doesn't contain the proper data for
...@@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, ...@@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
/* Make sure the device was added through sysfs */ /* Make sure the device was added through sysfs */
res = -ENOENT; res = -ENOENT;
mutex_lock(&adap->userspace_clients_lock); mutex_lock_nested(&adap->userspace_clients_lock,
i2c_adapter_depth(adap));
list_for_each_entry_safe(client, next, &adap->userspace_clients, list_for_each_entry_safe(client, next, &adap->userspace_clients,
detected) { detected) {
if (client->addr == addr) { if (client->addr == addr) {
...@@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap) ...@@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
return res; return res;
/* Remove devices instantiated from sysfs */ /* Remove devices instantiated from sysfs */
mutex_lock(&adap->userspace_clients_lock); mutex_lock_nested(&adap->userspace_clients_lock,
i2c_adapter_depth(adap));
list_for_each_entry_safe(client, next, &adap->userspace_clients, list_for_each_entry_safe(client, next, &adap->userspace_clients,
detected) { detected) {
dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment