Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev)
	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
 * 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 */
	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,
				 detected) {
		if (client->addr == addr) {
@@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
		return res;

	/* 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,
				 detected) {
		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,