pinctrl: mediatek: use devm_gpiochip_add_data() for GPIO chip

The gpio_chip is allocated with device-managed memory but registered with
the non-managed gpiochip_add_data(). This was harmless while the drivers
were built-in, but once they can be built as modules and unbound/rmmod'd,
devm frees the gpio_chip's memory while it is still registered, causing a
use-after-free.

Register it with devm_gpiochip_add_data() so it shares the same
device-managed lifecycle, which also lets the manual gpiochip_remove()
error paths go away.

Fixes: a6df410d42 ("pinctrl: mediatek: Add Pinctrl/GPIO driver for mt8135.")
Fixes: 805250982b ("pinctrl: mediatek: add pinctrl-paris that implements the vendor dt-bindings")
Fixes: e78d57b2f8 ("pinctrl: mediatek: add pinctrl-moore that implements the generic pinctrl dt-bindings")
Signed-off-by: Justin Yeh <justin.yeh@mediatek.com>
Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
Signed-off-by: Linus Walleij <linusw@kernel.org>
This commit is contained in:
Justin Yeh 2026-07-23 11:58:12 +08:00 committed by Linus Walleij
parent a2fd5a9f09
commit 9c650317ba
3 changed files with 7 additions and 15 deletions

View File

@ -594,7 +594,7 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw)
chip->base = -1;
chip->ngpio = hw->soc->npins;
ret = gpiochip_add_data(chip, hw);
ret = devm_gpiochip_add_data(hw->dev, chip, hw);
if (ret < 0)
return ret;
@ -608,10 +608,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw)
if (!of_property_present(hw->dev->of_node, "gpio-ranges")) {
ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
chip->ngpio);
if (ret < 0) {
gpiochip_remove(chip);
if (ret < 0)
return ret;
}
}
return 0;

View File

@ -1130,30 +1130,24 @@ int mtk_pctrl_init(struct platform_device *pdev,
pctl->chip->parent = &pdev->dev;
pctl->chip->base = -1;
ret = gpiochip_add_data(pctl->chip, pctl);
ret = devm_gpiochip_add_data(&pdev->dev, pctl->chip, pctl);
if (ret)
return -EINVAL;
/* Register the GPIO to pin mappings. */
ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
0, 0, pctl->devdata->npins);
if (ret) {
ret = -EINVAL;
goto chip_error;
}
if (ret)
return -EINVAL;
/* Only initialize EINT if we have EINT pins */
if (data->eint_hw.ap_num > 0) {
ret = mtk_eint_init(pctl, pdev);
if (ret)
goto chip_error;
return ret;
}
return 0;
chip_error:
gpiochip_remove(pctl->chip);
return ret;
}
int mtk_pctrl_common_probe(struct platform_device *pdev)

View File

@ -957,7 +957,7 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw)
chip->base = -1;
chip->ngpio = hw->soc->npins;
ret = gpiochip_add_data(chip, hw);
ret = devm_gpiochip_add_data(hw->dev, chip, hw);
if (ret < 0)
return ret;