| From 2a32999e444a243f7c4fdbe30e7f054861bcabeb Mon Sep 17 00:00:00 2001 |
| From: Marco Felsch <m.felsch@pengutronix.de> |
| Date: Tue, 17 Sep 2019 17:40:21 +0200 |
| Subject: [PATCH] regulator: core: make regulator_register() EPROBE_DEFER aware |
| |
| commit f8970d341eec73c976a3462b9ecdb02b60b84dd6 upstream. |
| |
| 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 <m.felsch@pengutronix.de> |
| Link: https://lore.kernel.org/r/20190917154021.14693-4-m.felsch@pengutronix.de |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c |
| index 997e25a315f7..8f321d22916d 100644 |
| --- a/drivers/regulator/core.c |
| +++ b/drivers/regulator/core.c |
| @@ -4989,6 +4989,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 921afd116f43..d0c2aecd2734 100644 |
| --- a/drivers/regulator/of_regulator.c |
| +++ b/drivers/regulator/of_regulator.c |
| @@ -443,11 +443,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; |
| -- |
| 2.27.0 |
| |