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

Commit 77ed74da authored by Jean Delvare's avatar Jean Delvare Committed by Linus Torvalds
Browse files

[PATCH] i2c: Prevent deadlock on i2c client registration



Delay the call to adapter->client_register() until after we are
certain that the client registration is a success. At this point the
client is fully initialized and we no longer hold the adapter->clist
mutex, so this should prevent the deadlocks if the client_register()
callback needs to take that mutex too, as is the case for the bttv
driver.

This fixes bug #7234.

Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5ffd1a6a
Loading
Loading
Loading
Loading
+13 −12
Original line number Original line Diff line number Diff line
@@ -420,14 +420,6 @@ int i2c_attach_client(struct i2c_client *client)
	}
	}
	list_add_tail(&client->list,&adapter->clients);
	list_add_tail(&client->list,&adapter->clients);
	
	
	if (adapter->client_register)  {
		if (adapter->client_register(client))  {
			dev_dbg(&adapter->dev, "client_register "
				"failed for client [%s] at 0x%02x\n",
				client->name, client->addr);
		}
	}

	client->usage_count = 0;
	client->usage_count = 0;


	client->dev.parent = &client->adapter->dev;
	client->dev.parent = &client->adapter->dev;
@@ -445,10 +437,17 @@ int i2c_attach_client(struct i2c_client *client)
	res = device_create_file(&client->dev, &dev_attr_client_name);
	res = device_create_file(&client->dev, &dev_attr_client_name);
	if (res)
	if (res)
		goto out_unregister;
		goto out_unregister;

out_unlock:
	mutex_unlock(&adapter->clist_lock);
	mutex_unlock(&adapter->clist_lock);
	return res;

	if (adapter->client_register)  {
		if (adapter->client_register(client)) {
			dev_dbg(&adapter->dev, "client_register "
				"failed for client [%s] at 0x%02x\n",
				client->name, client->addr);
		}
	}

	return 0;


out_unregister:
out_unregister:
	init_completion(&client->released); /* Needed? */
	init_completion(&client->released); /* Needed? */
@@ -458,7 +457,9 @@ int i2c_attach_client(struct i2c_client *client)
	list_del(&client->list);
	list_del(&client->list);
	dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
	dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
		"(%d)\n", client->name, client->addr, res);
		"(%d)\n", client->name, client->addr, res);
	goto out_unlock;
out_unlock:
	mutex_unlock(&adapter->clist_lock);
	return res;
}
}