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

Commit db93facf authored by Jim Lin's avatar Jim Lin Committed by Linus Walleij
Browse files

pinctrl: Fix two deadlocks



This patch is to fix two deadlock cases.
Deadlock 1:
CPU #1
 pinctrl_register-> pinctrl_get ->
 create_pinctrl
 (Holding lock pinctrl_maps_mutex)
 -> get_pinctrl_dev_from_devname
 (Trying to acquire lock pinctrldev_list_mutex)
CPU #0
 pinctrl_unregister
 (Holding lock pinctrldev_list_mutex)
 -> pinctrl_put ->> pinctrl_free ->
 pinctrl_dt_free_maps -> pinctrl_unregister_map
 (Trying to acquire lock pinctrl_maps_mutex)

Simply to say
CPU#1 is holding lock A and trying to acquire lock B,
CPU#0 is holding lock B and trying to acquire lock A.

Deadlock 2:
CPU #3
 pinctrl_register-> pinctrl_get ->
 create_pinctrl
 (Holding lock pinctrl_maps_mutex)
 -> get_pinctrl_dev_from_devname
 (Trying to acquire lock pinctrldev_list_mutex)
CPU #2
 pinctrl_unregister
 (Holding lock pctldev->mutex)
 -> pinctrl_put ->> pinctrl_free ->
 pinctrl_dt_free_maps -> pinctrl_unregister_map
 (Trying to acquire lock pinctrl_maps_mutex)
CPU #0
 tegra_gpio_request
 (Holding lock pinctrldev_list_mutex)
 -> pinctrl_get_device_gpio_range
 (Trying to acquire lock pctldev->mutex)

Simply to say
CPU#3 is holding lock A and trying to acquire lock D,
CPU#2 is holding lock B and trying to acquire lock A,
CPU#0 is holding lock D and trying to acquire lock B.

Cc: Stable <stable@vger.kernel.org>
Signed-off-by: default avatarJim Lin <jilin@nvidia.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 53b1bfc7
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -1801,14 +1801,15 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
	if (pctldev == NULL)
	if (pctldev == NULL)
		return;
		return;


	mutex_lock(&pinctrldev_list_mutex);
	mutex_lock(&pctldev->mutex);
	mutex_lock(&pctldev->mutex);

	pinctrl_remove_device_debugfs(pctldev);
	pinctrl_remove_device_debugfs(pctldev);
	mutex_unlock(&pctldev->mutex);


	if (!IS_ERR(pctldev->p))
	if (!IS_ERR(pctldev->p))
		pinctrl_put(pctldev->p);
		pinctrl_put(pctldev->p);


	mutex_lock(&pinctrldev_list_mutex);
	mutex_lock(&pctldev->mutex);
	/* TODO: check that no pinmuxes are still active? */
	/* TODO: check that no pinmuxes are still active? */
	list_del(&pctldev->node);
	list_del(&pctldev->node);
	/* Destroy descriptor tree */
	/* Destroy descriptor tree */