Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regulator: Defer init completion for a while after late_initcall

The kernel has no way of knowing when we have finished instantiating
drivers, between deferred probe and systems that build key drivers as
modules we might be doing this long after userspace has booted. This has
always been a bit of an issue with regulator_init_complete since it can
power off hardware that's not had it's driver loaded which can result in
user visible effects, the main case is powering off displays. Practically
speaking it's not been an issue in real systems since most systems that
use the regulator API are embedded and build in key drivers anyway but
with Arm laptops coming on the market it's becoming more of an issue so
let's do something about it.

In the absence of any better idea just defer the powering off for 30s
after late_initcall(), this is obviously a hack but it should mask the
issue for now and it's no more arbitrary than late_initcall() itself.
Ideally we'd have some heuristics to detect if we're on an affected
system and tune or skip the delay appropriately, and there may be some
need for a command line option to be added.

Link: https://lore.kernel.org/r/20190904124250.25844-1-broonie@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Tested-by: Lee Jones <lee.jones@linaro.org>
Cc: stable@vger.kernel.org

+31 -11
+31 -11
drivers/regulator/core.c
··· 5644 5644 /* init early to allow our consumers to complete system booting */ 5645 5645 core_initcall(regulator_init); 5646 5646 5647 - static int __init regulator_late_cleanup(struct device *dev, void *data) 5647 + static int regulator_late_cleanup(struct device *dev, void *data) 5648 5648 { 5649 5649 struct regulator_dev *rdev = dev_to_rdev(dev); 5650 5650 const struct regulator_ops *ops = rdev->desc->ops; ··· 5693 5693 return 0; 5694 5694 } 5695 5695 5696 - static int __init regulator_init_complete(void) 5696 + static void regulator_init_complete_work_function(struct work_struct *work) 5697 5697 { 5698 - /* 5699 - * Since DT doesn't provide an idiomatic mechanism for 5700 - * enabling full constraints and since it's much more natural 5701 - * with DT to provide them just assume that a DT enabled 5702 - * system has full constraints. 5703 - */ 5704 - if (of_have_populated_dt()) 5705 - has_full_constraints = true; 5706 - 5707 5698 /* 5708 5699 * Regulators may had failed to resolve their input supplies 5709 5700 * when were registered, either because the input supply was ··· 5712 5721 */ 5713 5722 class_for_each_device(&regulator_class, NULL, NULL, 5714 5723 regulator_late_cleanup); 5724 + } 5725 + 5726 + static DECLARE_DELAYED_WORK(regulator_init_complete_work, 5727 + regulator_init_complete_work_function); 5728 + 5729 + static int __init regulator_init_complete(void) 5730 + { 5731 + /* 5732 + * Since DT doesn't provide an idiomatic mechanism for 5733 + * enabling full constraints and since it's much more natural 5734 + * with DT to provide them just assume that a DT enabled 5735 + * system has full constraints. 5736 + */ 5737 + if (of_have_populated_dt()) 5738 + has_full_constraints = true; 5739 + 5740 + /* 5741 + * We punt completion for an arbitrary amount of time since 5742 + * systems like distros will load many drivers from userspace 5743 + * so consumers might not always be ready yet, this is 5744 + * particularly an issue with laptops where this might bounce 5745 + * the display off then on. Ideally we'd get a notification 5746 + * from userspace when this happens but we don't so just wait 5747 + * a bit and hope we waited long enough. It'd be better if 5748 + * we'd only do this on systems that need it, and a kernel 5749 + * command line option might be useful. 5750 + */ 5751 + schedule_delayed_work(&regulator_init_complete_work, 5752 + msecs_to_jiffies(30000)); 5715 5753 5716 5754 return 0; 5717 5755 }