pinctrl: samsung: drop pin banks references on error paths
authorKrzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Tue, 11 Jan 2022 20:13:59 +0000 (21:13 +0100)
committerKrzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Sun, 23 Jan 2022 11:21:56 +0000 (12:21 +0100)
The driver iterates over its devicetree children with
for_each_child_of_node() and stores for later found node pointer.  This
has to be put in error paths to avoid leak during re-probing.

Fixes: ab663789d697 ("pinctrl: samsung: Match pin banks with their device nodes")
Cc: <stable@vger.kernel.org>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Chanho Park <chanho61.park@samsung.com>
Link: https://lore.kernel.org/r/20220111201426.326777-2-krzysztof.kozlowski@canonical.com
drivers/pinctrl/samsung/pinctrl-samsung.c

index 0f6e9305fec58c7bef531d8ff8714a2392f27cb3..c4175fea7d7415bb8e0f56d6473ac37baa823c9a 100644 (file)
@@ -1002,6 +1002,16 @@ samsung_pinctrl_get_soc_data_for_of_alias(struct platform_device *pdev)
        return &(of_data->ctrl[id]);
 }
 
+static void samsung_banks_of_node_put(struct samsung_pinctrl_drv_data *d)
+{
+       struct samsung_pin_bank *bank;
+       unsigned int i;
+
+       bank = d->pin_banks;
+       for (i = 0; i < d->nr_banks; ++i, ++bank)
+               of_node_put(bank->of_node);
+}
+
 /* retrieve the soc specific data */
 static const struct samsung_pin_ctrl *
 samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
@@ -1117,19 +1127,19 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
        if (ctrl->retention_data) {
                drvdata->retention_ctrl = ctrl->retention_data->init(drvdata,
                                                          ctrl->retention_data);
-               if (IS_ERR(drvdata->retention_ctrl))
-                       return PTR_ERR(drvdata->retention_ctrl);
+               if (IS_ERR(drvdata->retention_ctrl)) {
+                       ret = PTR_ERR(drvdata->retention_ctrl);
+                       goto err_put_banks;
+               }
        }
 
        ret = samsung_pinctrl_register(pdev, drvdata);
        if (ret)
-               return ret;
+               goto err_put_banks;
 
        ret = samsung_gpiolib_register(pdev, drvdata);
-       if (ret) {
-               samsung_pinctrl_unregister(pdev, drvdata);
-               return ret;
-       }
+       if (ret)
+               goto err_unregister;
 
        if (ctrl->eint_gpio_init)
                ctrl->eint_gpio_init(drvdata);
@@ -1139,6 +1149,12 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, drvdata);
 
        return 0;
+
+err_unregister:
+       samsung_pinctrl_unregister(pdev, drvdata);
+err_put_banks:
+       samsung_banks_of_node_put(drvdata);
+       return ret;
 }
 
 /*