regulator: core: make regulator_register() EPROBE_DEFER aware
authorMarco Felsch <m.felsch@pengutronix.de>
Tue, 17 Sep 2019 15:40:21 +0000 (17:40 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 17 Sep 2019 15:59:38 +0000 (16:59 +0100)
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>
drivers/regulator/core.c
drivers/regulator/of_regulator.c

index afe9447..a46be22 100644 (file)
@@ -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
index 38dd06f..ef7198b 100644 (file)
@@ -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;