pinctrl: samsung: drop pin banks references on error paths

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: ab663789d6 ("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
This commit is contained in:
Krzysztof Kozlowski 2022-01-11 21:13:59 +01:00
parent e783362eb5
commit 50ebd19e35
1 changed files with 23 additions and 7 deletions

View 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;
}
/*