Skip to content

Commit 8d38423

Browse files
andredbroonie
authored andcommitted
regulator: core: don't fail regulator_register() with missing required supply
Since commit 98e48cd ("regulator: core: resolve supply for boot-on/always-on regulators"), the regulator core returns -EPROBE_DEFER if a supply can not be resolved at regulator_register() time due to set_machine_constraints() requiring that supply (e.g. because of always-on or boot-on). In some hardware designs, multiple PMICs are used where individual rails of each act as supplies for rails of the other, and vice-versa. In such a design no PMIC driver can probe when registering one top- level regulator device (as is common practice for almost all regulator drivers in Linux) since that commit. Supplies are only considered when their driver has fully bound, but because in a design like the above two drivers / devices depend on each other, neither will have fully bound while the other probes. The Google Pixel 6 and 6 Pro (oriole and raven) are examples of such a design. One way to make this work would be to register each rail as an individual device, rather than just one top-level regulator device. Then, fw-devlink and Linux' driver core could do their usual handling of deferred device probe as each rail would be probed individually. This approach was dismissed in [1] as each regulator driver would have to take care of this itself. Alternatively, we can change the regulator core to not fail regulator_register() if a rail's required supply can not be resolved while keeping the intended change from above mentioned commit, and instead retry whenever a new rail is registered. This commit implements such an approach: If set_machine_constraints() requests probe deferral, regulator_register() still succeeds and we retry setting constraints as part of regulator_resolve_supply(). We still do not enable the regulator or allow consumers to use it until constraints have been set (including resolution of the supply) to prevent enabling of a regulator before its supply. With this change, we keep track of regulators with missing required supplies and can therefore try to resolve them again and try to set the constraints again once more regulators become available. Care has to be taken to not allow consumers to use regulators that haven't had their constraints set yet. regulator_get() ensures that and now returns -EPROBE_DEFER in that case. The implementation is straight-forward, thanks to our newly introduced regulator-bus. Locking in regulator_resolve_supply() has to be done carefully, as a combination of regulator_(un)lock_two() and regulator_(un)lock_dependent() is needed. The reason is that set_machine_constraints() might call regulator_enable() which needs rdev and all its dependents locked, but everything else requires to only have rdev and its supply locked. Link: https://lore.kernel.org/all/aRn_-o-vie_QoDXD@sirena.co.uk/ [1] Signed-off-by: André Draszik <andre.draszik@linaro.org> Link: https://patch.msgid.link/20260109-regulators-defer-v2-8-1a25dc968e60@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 304f578 commit 8d38423

2 files changed

Lines changed: 119 additions & 30 deletions

File tree

drivers/regulator/core.c

Lines changed: 118 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct regulator_event_work {
9898
unsigned long event;
9999
};
100100

101+
static int _regulator_enable(struct regulator *regulator);
101102
static int _regulator_is_enabled(struct regulator_dev *rdev);
102103
static int _regulator_disable(struct regulator *regulator);
103104
static int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags);
@@ -1432,6 +1433,7 @@ static int handle_notify_limits(struct regulator_dev *rdev,
14321433
/**
14331434
* set_machine_constraints - sets regulator constraints
14341435
* @rdev: regulator source
1436+
* @is_locked: whether or not this is called with locks held already
14351437
*
14361438
* Allows platform initialisation code to define and constrain
14371439
* regulator circuits e.g. valid voltage/current ranges, etc. NOTE:
@@ -1441,7 +1443,8 @@ static int handle_notify_limits(struct regulator_dev *rdev,
14411443
*
14421444
* Return: 0 on success or a negative error number on failure.
14431445
*/
1444-
static int set_machine_constraints(struct regulator_dev *rdev)
1446+
static int set_machine_constraints(struct regulator_dev *rdev,
1447+
bool is_locked)
14451448
{
14461449
int ret = 0;
14471450
const struct regulator_ops *ops = rdev->desc->ops;
@@ -1653,7 +1656,9 @@ static int set_machine_constraints(struct regulator_dev *rdev)
16531656
if (rdev->supply &&
16541657
(rdev->constraints->always_on ||
16551658
!regulator_is_enabled(rdev->supply))) {
1656-
ret = regulator_enable(rdev->supply);
1659+
ret = (is_locked
1660+
? _regulator_enable(rdev->supply)
1661+
: regulator_enable(rdev->supply));
16571662
if (ret < 0) {
16581663
_regulator_put(rdev->supply);
16591664
rdev->supply = NULL;
@@ -1781,6 +1786,15 @@ static int register_regulator_event_forwarding(struct regulator_dev *rdev)
17811786
return 0;
17821787
}
17831788

1789+
static void unregister_regulator_event_forwarding(struct regulator_dev *rdev)
1790+
{
1791+
if (!rdev->supply_fwd_nb.notifier_call)
1792+
return;
1793+
1794+
regulator_unregister_notifier(rdev->supply, &rdev->supply_fwd_nb);
1795+
rdev->supply_fwd_nb.notifier_call = NULL;
1796+
}
1797+
17841798
/**
17851799
* set_supply - set regulator supply regulator
17861800
* @rdev: regulator (locked)
@@ -2169,14 +2183,16 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
21692183
struct regulator_dev *r;
21702184
struct device *dev = rdev->dev.parent;
21712185
struct ww_acquire_ctx ww_ctx;
2186+
struct regulator *supply;
2187+
bool do_final_setup;
21722188
int ret = 0;
21732189

21742190
/* No supply to resolve? */
21752191
if (!rdev->supply_name)
21762192
return 0;
21772193

21782194
/* Supply already resolved? (fast-path without locking contention) */
2179-
if (rdev->supply)
2195+
if (rdev->supply && !rdev->constraints_pending)
21802196
return 0;
21812197

21822198
/* first do a dt based lookup on the node described in the virtual
@@ -2257,46 +2273,115 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
22572273

22582274
/* Supply just resolved by a concurrent task? */
22592275
if (rdev->supply) {
2276+
/* Constraints might still be pending due to concurrency. */
2277+
bool done = !rdev->constraints_pending;
2278+
2279+
supply = rdev->supply;
2280+
22602281
regulator_unlock_two(rdev, r, &ww_ctx);
22612282
put_device(&r->dev);
2262-
goto out;
2263-
}
22642283

2265-
ret = set_supply(rdev, r);
2266-
if (ret < 0) {
2284+
/*
2285+
* Supply resolved by concurrent task, and constraints set as
2286+
* well (or not required): fast path.
2287+
*/
2288+
if (done)
2289+
goto out;
2290+
2291+
do_final_setup = false;
2292+
} else {
2293+
ret = set_supply(rdev, r);
2294+
if (ret < 0) {
2295+
regulator_unlock_two(rdev, r, &ww_ctx);
2296+
put_device(&r->dev);
2297+
goto out;
2298+
}
2299+
2300+
supply = rdev->supply;
2301+
2302+
/*
2303+
* Automatically register for event forwarding from the new
2304+
* supply. This creates the downstream propagation link for
2305+
* events like under-voltage.
2306+
*/
2307+
ret = register_regulator_event_forwarding(rdev);
2308+
if (ret < 0) {
2309+
rdev_warn(rdev,
2310+
"Failed to register event forwarding: %pe\n",
2311+
ERR_PTR(ret));
2312+
2313+
goto unset_supply;
2314+
}
2315+
22672316
regulator_unlock_two(rdev, r, &ww_ctx);
2268-
put_device(&r->dev);
2269-
goto out;
2317+
2318+
do_final_setup = true;
22702319
}
22712320

22722321
/*
2273-
* Automatically register for event forwarding from the new supply.
2274-
* This creates the downstream propagation link for events like
2275-
* under-voltage.
2322+
* Now that we have the supply, we can retry setting the machine
2323+
* constraints, if necessary.
22762324
*/
2277-
ret = register_regulator_event_forwarding(rdev);
2278-
if (ret < 0) {
2279-
struct regulator *supply;
2280-
2281-
rdev_warn(rdev, "Failed to register event forwarding: %pe\n",
2282-
ERR_PTR(ret));
2283-
2284-
supply = rdev->supply;
2285-
rdev->supply = NULL;
2325+
regulator_lock_dependent(rdev, &ww_ctx);
2326+
if (rdev->constraints_pending) {
2327+
if (!rdev->supply) {
2328+
/*
2329+
* Supply could have been released by another task that
2330+
* failed to set the constraints or event forwarding.
2331+
*/
2332+
regulator_unlock_dependent(rdev, &ww_ctx);
2333+
ret = -EPROBE_DEFER;
2334+
goto out;
2335+
}
22862336

2287-
regulator_unlock_two(rdev, supply->rdev, &ww_ctx);
2337+
ret = set_machine_constraints(rdev, true);
2338+
if (ret < 0) {
2339+
regulator_unlock_dependent(rdev, &ww_ctx);
2340+
2341+
rdev_warn(rdev,
2342+
"Failed to set machine constraints: %pe\n",
2343+
ERR_PTR(ret));
2344+
2345+
regulator_lock_two(rdev, r, &ww_ctx);
2346+
2347+
if (supply != rdev->supply) {
2348+
/*
2349+
* Supply could have been released by another
2350+
* task that got here before us. If it did, it
2351+
* will have released 'supply' (i.e. the
2352+
* previous rdev->supply) and we shouldn't do
2353+
* that again via unset_supply.
2354+
*/
2355+
regulator_unlock_two(rdev, r, &ww_ctx);
2356+
goto out;
2357+
}
22882358

2289-
regulator_put(supply);
2290-
goto out;
2359+
unregister_regulator_event_forwarding(rdev);
2360+
rdev->constraints_pending = true;
2361+
goto unset_supply;
2362+
}
2363+
rdev->constraints_pending = false;
22912364
}
2365+
regulator_unlock_dependent(rdev, &ww_ctx);
22922366

2293-
regulator_unlock_two(rdev, r, &ww_ctx);
2367+
if (!do_final_setup)
2368+
goto out;
22942369

22952370
/* rdev->supply was created in set_supply() */
2296-
link_and_create_debugfs(rdev->supply, r, &rdev->dev);
2371+
link_and_create_debugfs(rdev->supply, rdev->supply->rdev, &rdev->dev);
22972372

22982373
out:
22992374
return ret;
2375+
2376+
unset_supply:
2377+
lockdep_assert_held_once(&rdev->mutex.base);
2378+
lockdep_assert_held_once(&r->mutex.base);
2379+
rdev->supply = NULL;
2380+
regulator_unlock_two(rdev, supply->rdev, &ww_ctx);
2381+
2382+
regulator_put(supply);
2383+
2384+
return ret;
23002385
}
23012386

23022387
/* common pre-checks for regulator requests */
@@ -6067,7 +6152,7 @@ regulator_register(struct device *dev,
60676152
dangling_of_gpiod = false;
60686153
}
60696154

6070-
ret = set_machine_constraints(rdev);
6155+
ret = set_machine_constraints(rdev, false);
60716156
if (ret == -EPROBE_DEFER) {
60726157
/* Regulator might be in bypass mode or an always-on or boot-on
60736158
* regulator and so needs its supply to set the constraints or
@@ -6081,14 +6166,17 @@ regulator_register(struct device *dev,
60816166
rdev->supply_name);
60826167
ret = regulator_resolve_supply(rdev);
60836168
if (!ret)
6084-
ret = set_machine_constraints(rdev);
6169+
ret = set_machine_constraints(rdev, false);
60856170
else
60866171
rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
60876172
ERR_PTR(ret));
60886173
tried_supply_resolve = true;
60896174
}
6090-
if (ret < 0)
6091-
goto wash;
6175+
if (ret < 0) {
6176+
if (ret != -EPROBE_DEFER)
6177+
goto wash;
6178+
rdev->constraints_pending = true;
6179+
}
60926180

60936181
ret = regulator_init_coupling(rdev);
60946182
if (ret < 0)

include/linux/regulator/driver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ struct regulator_dev {
650650
struct regulator_enable_gpio *ena_pin;
651651
unsigned int ena_gpio_state:1;
652652

653+
unsigned int constraints_pending:1;
653654
unsigned int is_switch:1;
654655

655656
/* time when this regulator was disabled last time */

0 commit comments

Comments
 (0)