Skip to content

Commit 8b8c8d6

Browse files
brooniegregkh
authored andcommitted
regulator: Defer init completion for a while after late_initcall
commit 55576cf upstream. 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/[email protected] Signed-off-by: Mark Brown <[email protected]> Tested-by: Lee Jones <[email protected]> Cc: [email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 65b7a5a commit 8b8c8d6

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

drivers/regulator/core.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4452,7 +4452,7 @@ static int __init regulator_init(void)
44524452
/* init early to allow our consumers to complete system booting */
44534453
core_initcall(regulator_init);
44544454

4455-
static int __init regulator_late_cleanup(struct device *dev, void *data)
4455+
static int regulator_late_cleanup(struct device *dev, void *data)
44564456
{
44574457
struct regulator_dev *rdev = dev_to_rdev(dev);
44584458
const struct regulator_ops *ops = rdev->desc->ops;
@@ -4501,17 +4501,8 @@ static int __init regulator_late_cleanup(struct device *dev, void *data)
45014501
return 0;
45024502
}
45034503

4504-
static int __init regulator_init_complete(void)
4504+
static void regulator_init_complete_work_function(struct work_struct *work)
45054505
{
4506-
/*
4507-
* Since DT doesn't provide an idiomatic mechanism for
4508-
* enabling full constraints and since it's much more natural
4509-
* with DT to provide them just assume that a DT enabled
4510-
* system has full constraints.
4511-
*/
4512-
if (of_have_populated_dt())
4513-
has_full_constraints = true;
4514-
45154506
/*
45164507
* Regulators may had failed to resolve their input supplies
45174508
* when were registered, either because the input supply was
@@ -4529,6 +4520,35 @@ static int __init regulator_init_complete(void)
45294520
*/
45304521
class_for_each_device(&regulator_class, NULL, NULL,
45314522
regulator_late_cleanup);
4523+
}
4524+
4525+
static DECLARE_DELAYED_WORK(regulator_init_complete_work,
4526+
regulator_init_complete_work_function);
4527+
4528+
static int __init regulator_init_complete(void)
4529+
{
4530+
/*
4531+
* Since DT doesn't provide an idiomatic mechanism for
4532+
* enabling full constraints and since it's much more natural
4533+
* with DT to provide them just assume that a DT enabled
4534+
* system has full constraints.
4535+
*/
4536+
if (of_have_populated_dt())
4537+
has_full_constraints = true;
4538+
4539+
/*
4540+
* We punt completion for an arbitrary amount of time since
4541+
* systems like distros will load many drivers from userspace
4542+
* so consumers might not always be ready yet, this is
4543+
* particularly an issue with laptops where this might bounce
4544+
* the display off then on. Ideally we'd get a notification
4545+
* from userspace when this happens but we don't so just wait
4546+
* a bit and hope we waited long enough. It'd be better if
4547+
* we'd only do this on systems that need it, and a kernel
4548+
* command line option might be useful.
4549+
*/
4550+
schedule_delayed_work(&regulator_init_complete_work,
4551+
msecs_to_jiffies(30000));
45324552

45334553
return 0;
45344554
}

0 commit comments

Comments
 (0)