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: Jean Delvare <khali@linux-fr.org> Cc: Michael Lawnick <ml.lawnick@gmx.de>
This commit is contained in:
parent
e68bb91baa
commit
390946b172
1 changed files with 20 additions and 2 deletions
|
@ -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,
|
||||||
|
|
||||||
/* 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)
|
||||||
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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue