Skip to content

Commit 14a71d5

Browse files
committed
regulator: Fix lockdep warning resolving supplies
With commit eaa7995 (regulator: core: avoid regulator_resolve_supply() race condition) we started holding the rdev lock while resolving supplies, an operation that requires holding the regulator_list_mutex. This results in lockdep warnings since in other places we take the list mutex then the mutex on an individual rdev. Since the goal is to make sure that we don't call set_supply() twice rather than a concern about the cost of resolution pull the rdev lock and check for duplicate resolution down to immediately before we do the set_supply() and drop it again once the allocation is done. Fixes: eaa7995 (regulator: core: avoid regulator_resolve_supply() race condition) Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20210122132042.10306-1-broonie@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 51dfb6c commit 14a71d5

1 file changed

Lines changed: 17 additions & 12 deletions

File tree

drivers/regulator/core.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,17 +1823,6 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
18231823
if (rdev->supply)
18241824
return 0;
18251825

1826-
/*
1827-
* Recheck rdev->supply with rdev->mutex lock held to avoid a race
1828-
* between rdev->supply null check and setting rdev->supply in
1829-
* set_supply() from concurrent tasks.
1830-
*/
1831-
regulator_lock(rdev);
1832-
1833-
/* Supply just resolved by a concurrent task? */
1834-
if (rdev->supply)
1835-
goto out;
1836-
18371826
r = regulator_dev_lookup(dev, rdev->supply_name);
18381827
if (IS_ERR(r)) {
18391828
ret = PTR_ERR(r);
@@ -1885,12 +1874,29 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
18851874
goto out;
18861875
}
18871876

1877+
/*
1878+
* Recheck rdev->supply with rdev->mutex lock held to avoid a race
1879+
* between rdev->supply null check and setting rdev->supply in
1880+
* set_supply() from concurrent tasks.
1881+
*/
1882+
regulator_lock(rdev);
1883+
1884+
/* Supply just resolved by a concurrent task? */
1885+
if (rdev->supply) {
1886+
regulator_unlock(rdev);
1887+
put_device(&r->dev);
1888+
goto out;
1889+
}
1890+
18881891
ret = set_supply(rdev, r);
18891892
if (ret < 0) {
1893+
regulator_unlock(rdev);
18901894
put_device(&r->dev);
18911895
goto out;
18921896
}
18931897

1898+
regulator_unlock(rdev);
1899+
18941900
/*
18951901
* In set_machine_constraints() we may have turned this regulator on
18961902
* but we couldn't propagate to the supply if it hadn't been resolved
@@ -1906,7 +1912,6 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
19061912
}
19071913

19081914
out:
1909-
regulator_unlock(rdev);
19101915
return ret;
19111916
}
19121917

0 commit comments

Comments
 (0)