regulator: Fixes for v5.11
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. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmAQDo0ACgkQJNaLcl1U h9CQ9wf+JfSpktYitQdZ2y9KG02GkGDeYC2Q2dmy69ad1Mfa3je6XaEX6KmoXBuL 35C/otbIgPtFzSekihCSXlUunF6mKr/mgLdFcqF72ku+bv2frZV2szowPBNYXgsK b4d+i5rdJs4HG5soxAk5iGN9S720OA7eRh7zXyd+VUvSuYgIrmrvA3Dkr+NPLeZN IR08kkZXBj/a8LDQg1qLrTjfSFnNpMO2A8+yESw1y6XjsB5bFeMguo2SssE63iTC ho4kN/3DgpptydUtPboMeHNBsCeNZ5EOun7Dq3dMKA2e6iW4eoBZ/rY+QOLaGXPB tby99/MGKpV1sOplxDIkhirLEHVecA== =zqHT -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
5bec2487ff
@ -1813,13 +1813,13 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
|
||||
{
|
||||
struct regulator_dev *r;
|
||||
struct device *dev = rdev->dev.parent;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* No supply to resolve? */
|
||||
if (!rdev->supply_name)
|
||||
return 0;
|
||||
|
||||
/* Supply already resolved? */
|
||||
/* Supply already resolved? (fast-path without locking contention) */
|
||||
if (rdev->supply)
|
||||
return 0;
|
||||
|
||||
@ -1829,7 +1829,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
|
||||
|
||||
/* Did the lookup explicitly defer for us? */
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
if (have_full_constraints()) {
|
||||
r = dummy_regulator_rdev;
|
||||
@ -1837,15 +1837,18 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
|
||||
} else {
|
||||
dev_err(dev, "Failed to resolve %s-supply for %s\n",
|
||||
rdev->supply_name, rdev->desc->name);
|
||||
return -EPROBE_DEFER;
|
||||
ret = -EPROBE_DEFER;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (r == rdev) {
|
||||
dev_err(dev, "Supply for %s (%s) resolved to itself\n",
|
||||
rdev->desc->name, rdev->supply_name);
|
||||
if (!have_full_constraints())
|
||||
return -EINVAL;
|
||||
if (!have_full_constraints()) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
r = dummy_regulator_rdev;
|
||||
get_device(&r->dev);
|
||||
}
|
||||
@ -1859,7 +1862,8 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
|
||||
if (r->dev.parent && r->dev.parent != rdev->dev.parent) {
|
||||
if (!device_is_bound(r->dev.parent)) {
|
||||
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)
|
||||
ret = regulator_resolve_supply(r);
|
||||
if (ret < 0) {
|
||||
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);
|
||||
if (ret < 0) {
|
||||
regulator_unlock(rdev);
|
||||
put_device(&r->dev);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
regulator_unlock(rdev);
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -1886,11 +1907,12 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
|
||||
if (ret < 0) {
|
||||
_regulator_put(rdev->supply);
|
||||
rdev->supply = NULL;
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Internal regulator request function */
|
||||
|
@ -331,6 +331,12 @@ regulator_get_exclusive(struct device *dev, const char *id)
|
||||
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
|
||||
regulator_get_optional(struct device *dev, const char *id)
|
||||
{
|
||||
@ -486,6 +492,11 @@ static inline int regulator_get_voltage(struct regulator *regulator)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regulator_sync_voltage(struct regulator *regulator)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regulator_is_supported_voltage(struct regulator *regulator,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
@ -578,6 +589,25 @@ static inline int devm_regulator_unregister_notifier(struct regulator *regulator
|
||||
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)
|
||||
{
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user