From f8970d341eec73c976a3462b9ecdb02b60b84dd6 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Tue, 17 Sep 2019 17:40:21 +0200 Subject: regulator: core: make regulator_register() EPROBE_DEFER aware Sometimes it can happen that the regulator_of_get_init_data() can't retrieve the config due to a not probed device the regulator depends on. Fix that by checking the return value of of_parse_cb() and return EPROBE_DEFER in such cases. Signed-off-by: Marco Felsch Link: https://lore.kernel.org/r/20190917154021.14693-4-m.felsch@pengutronix.de Signed-off-by: Mark Brown --- drivers/regulator/core.c | 13 +++++++++++++ drivers/regulator/of_regulator.c | 19 ++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index afe94470b67f..a46be221dbdc 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5053,6 +5053,19 @@ regulator_register(const struct regulator_desc *regulator_desc, init_data = regulator_of_get_init_data(dev, regulator_desc, config, &rdev->dev.of_node); + + /* + * Sometimes not all resources are probed already so we need to take + * that into account. This happens most the time if the ena_gpiod comes + * from a gpio extender or something else. + */ + if (PTR_ERR(init_data) == -EPROBE_DEFER) { + kfree(config); + kfree(rdev); + ret = -EPROBE_DEFER; + goto rinse; + } + /* * We need to keep track of any GPIO descriptor coming from the * device tree until we have handled it over to the core. If the diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 38dd06fbab38..ef7198b76e50 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -445,11 +445,20 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, goto error; } - if (desc->of_parse_cb && desc->of_parse_cb(child, desc, config)) { - dev_err(dev, - "driver callback failed to parse DT for regulator %pOFn\n", - child); - goto error; + if (desc->of_parse_cb) { + int ret; + + ret = desc->of_parse_cb(child, desc, config); + if (ret) { + if (ret == -EPROBE_DEFER) { + of_node_put(child); + return ERR_PTR(-EPROBE_DEFER); + } + dev_err(dev, + "driver callback failed to parse DT for regulator %pOFn\n", + child); + goto error; + } } *node = child; -- cgit v1.2.3-59-g8ed1b