During regulator registration the regulator framework checks that the regulator is: a) enabled b) has a supplier and if both are true, it calls regulator_enable() on the supplier, which has the side effect of incrementing its use count. This puts the regulator framework in an inconsistent state. Consider the following example:
regY --supplies--> regX regX is turned on by hardware, bootloader, or driver ops (as a result of the boot_on or always_on flag being set), so during registration both (a) and (b) are true. regulator_enable(regY) is invoked, and now regY.use_count == 1, regX.use_count == 0. Later on, the regulator framework iterates over the registered regulators and turns off unused ones using driver ops. Due to the use_count values, regX is disabled, while regY is not. Due to the use of driver ops, instead of regulator_disable(), the use_count of regY is not updated when regX is disabled. We now have a situation where regY has a minimum use_count of 1, and will never be turned off. The underlying issue is that we are updating regulator metadata that exists to keep track of function invocations (regulator_enable, regulator_disable) as a result of something that isn't said function invocations. The state of regX is not the result of a regulator_enable call, so use_count increments should not be propogated on the supply dependency chain. Instead, if there's a need for regX to be enabled on boot, the boot_on flag should be used for all the regulators on the supply chain. Cc: Liam Girdwood <lgirdw...@gmail.com> Cc: Mark Brown <broo...@kernel.org> Signed-off-by: Nikita Kiryanov <nik...@compulab.co.il> Signed-off-by: Igor Grinberg <grinb...@compulab.co.il> --- drivers/regulator/core.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a01b8b3..7070d5c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3440,13 +3440,6 @@ regulator_register(const struct regulator_desc *regulator_desc, ret = set_supply(rdev, r); if (ret < 0) goto scrub; - - /* Enable supply if rail is enabled */ - if (_regulator_is_enabled(rdev)) { - ret = regulator_enable(rdev->supply); - if (ret < 0) - goto scrub; - } } add_dev: -- 1.8.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/