Commit 5bec2487 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'regulator-fix-v5.11-rc5' of...

Merge tag 'regulator-fix-v5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator fixes from Mark Brown:
 "The main thing here is a change to make sure that we don't try to
  double resolve the supply of a regulator if we have two probes going
  on simultaneously, plus an incremental fix on top of that to resolve a
  lockdep issue it introduced.

  There's also a patch from Dmitry Osipenko adding stubs for some
  functions to avoid build issues in consumers in some configurations"

* tag 'regulator-fix-v5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator:
  regulator: Fix lockdep warning resolving supplies
  regulator: consumer: Add missing stubs to regulator/consumer.h
  regulator: core: avoid regulator_resolve_supply() race condition
parents 377bf660 14a71d50
...@@ -1813,13 +1813,13 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) ...@@ -1813,13 +1813,13 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
{ {
struct regulator_dev *r; struct regulator_dev *r;
struct device *dev = rdev->dev.parent; struct device *dev = rdev->dev.parent;
int ret; int ret = 0;
/* No supply to resolve? */ /* No supply to resolve? */
if (!rdev->supply_name) if (!rdev->supply_name)
return 0; return 0;
/* Supply already resolved? */ /* Supply already resolved? (fast-path without locking contention) */
if (rdev->supply) if (rdev->supply)
return 0; return 0;
...@@ -1829,7 +1829,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) ...@@ -1829,7 +1829,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
/* Did the lookup explicitly defer for us? */ /* Did the lookup explicitly defer for us? */
if (ret == -EPROBE_DEFER) if (ret == -EPROBE_DEFER)
return ret; goto out;
if (have_full_constraints()) { if (have_full_constraints()) {
r = dummy_regulator_rdev; r = dummy_regulator_rdev;
...@@ -1837,15 +1837,18 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) ...@@ -1837,15 +1837,18 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
} else { } else {
dev_err(dev, "Failed to resolve %s-supply for %s\n", dev_err(dev, "Failed to resolve %s-supply for %s\n",
rdev->supply_name, rdev->desc->name); rdev->supply_name, rdev->desc->name);
return -EPROBE_DEFER; ret = -EPROBE_DEFER;
goto out;
} }
} }
if (r == rdev) { if (r == rdev) {
dev_err(dev, "Supply for %s (%s) resolved to itself\n", dev_err(dev, "Supply for %s (%s) resolved to itself\n",
rdev->desc->name, rdev->supply_name); rdev->desc->name, rdev->supply_name);
if (!have_full_constraints()) if (!have_full_constraints()) {
return -EINVAL; ret = -EINVAL;
goto out;
}
r = dummy_regulator_rdev; r = dummy_regulator_rdev;
get_device(&r->dev); get_device(&r->dev);
} }
...@@ -1859,7 +1862,8 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) ...@@ -1859,7 +1862,8 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
if (r->dev.parent && r->dev.parent != rdev->dev.parent) { if (r->dev.parent && r->dev.parent != rdev->dev.parent) {
if (!device_is_bound(r->dev.parent)) { if (!device_is_bound(r->dev.parent)) {
put_device(&r->dev); put_device(&r->dev);
return -EPROBE_DEFER; ret = -EPROBE_DEFER;
goto out;
} }
} }
...@@ -1867,15 +1871,32 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) ...@@ -1867,15 +1871,32 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
ret = regulator_resolve_supply(r); ret = regulator_resolve_supply(r);
if (ret < 0) { if (ret < 0) {
put_device(&r->dev); put_device(&r->dev);
return ret; goto out;
}
/*
* Recheck rdev->supply with rdev->mutex lock held to avoid a race
* between rdev->supply null check and setting rdev->supply in
* set_supply() from concurrent tasks.
*/
regulator_lock(rdev);
/* Supply just resolved by a concurrent task? */
if (rdev->supply) {
regulator_unlock(rdev);
put_device(&r->dev);
goto out;
} }
ret = set_supply(rdev, r); ret = set_supply(rdev, r);
if (ret < 0) { if (ret < 0) {
regulator_unlock(rdev);
put_device(&r->dev); put_device(&r->dev);
return ret; goto out;
} }
regulator_unlock(rdev);
/* /*
* In set_machine_constraints() we may have turned this regulator on * In set_machine_constraints() we may have turned this regulator on
* but we couldn't propagate to the supply if it hadn't been resolved * but we couldn't propagate to the supply if it hadn't been resolved
...@@ -1886,11 +1907,12 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) ...@@ -1886,11 +1907,12 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
if (ret < 0) { if (ret < 0) {
_regulator_put(rdev->supply); _regulator_put(rdev->supply);
rdev->supply = NULL; rdev->supply = NULL;
return ret; goto out;
} }
} }
return 0; out:
return ret;
} }
/* Internal regulator request function */ /* Internal regulator request function */
......
...@@ -331,6 +331,12 @@ regulator_get_exclusive(struct device *dev, const char *id) ...@@ -331,6 +331,12 @@ regulator_get_exclusive(struct device *dev, const char *id)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
static inline struct regulator *__must_check
devm_regulator_get_exclusive(struct device *dev, const char *id)
{
return ERR_PTR(-ENODEV);
}
static inline struct regulator *__must_check static inline struct regulator *__must_check
regulator_get_optional(struct device *dev, const char *id) regulator_get_optional(struct device *dev, const char *id)
{ {
...@@ -486,6 +492,11 @@ static inline int regulator_get_voltage(struct regulator *regulator) ...@@ -486,6 +492,11 @@ static inline int regulator_get_voltage(struct regulator *regulator)
return -EINVAL; return -EINVAL;
} }
static inline int regulator_sync_voltage(struct regulator *regulator)
{
return -EINVAL;
}
static inline int regulator_is_supported_voltage(struct regulator *regulator, static inline int regulator_is_supported_voltage(struct regulator *regulator,
int min_uV, int max_uV) int min_uV, int max_uV)
{ {
...@@ -578,6 +589,25 @@ static inline int devm_regulator_unregister_notifier(struct regulator *regulator ...@@ -578,6 +589,25 @@ static inline int devm_regulator_unregister_notifier(struct regulator *regulator
return 0; return 0;
} }
static inline int regulator_suspend_enable(struct regulator_dev *rdev,
suspend_state_t state)
{
return -EINVAL;
}
static inline int regulator_suspend_disable(struct regulator_dev *rdev,
suspend_state_t state)
{
return -EINVAL;
}
static inline int regulator_set_suspend_voltage(struct regulator *regulator,
int min_uV, int max_uV,
suspend_state_t state)
{
return -EINVAL;
}
static inline void *regulator_get_drvdata(struct regulator *regulator) static inline void *regulator_get_drvdata(struct regulator *regulator)
{ {
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment