From 4e1e21117e7e1275477ba80e634c769a511249bd Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 6 Oct 2023 13:17:07 -0700 Subject: pinctrl: samsung: Annotate struct exynos_muxed_weint_data with __counted_by Prepare for the coming implementation by GCC and Clang of the __counted_by attribute. Flexible array members annotated with __counted_by can have their accesses bounds-checked at run-time via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions). As found with Coccinelle[1], add __counted_by for struct exynos_muxed_weint_data. Additionally, since the element count member must be set before accessing the annotated flexible array member, move its initialization earlier. Cc: Tomasz Figa Cc: Krzysztof Kozlowski Cc: Sylwester Nawrocki Cc: Alim Akhtar Cc: Linus Walleij Cc: "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: linux-gpio@vger.kernel.org Cc: linux-hardening@vger.kernel.org Link: https://github.com/kees/kernel-tools/blob/trunk/coccinelle/examples/counted_by.cocci [1] Signed-off-by: Kees Cook Reviewed-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20231006201707.work.405-kees@kernel.org Signed-off-by: Krzysztof Kozlowski --- drivers/pinctrl/samsung/pinctrl-exynos.c | 2 +- drivers/pinctrl/samsung/pinctrl-exynos.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index a8212fc126bf..6b58ec84e34b 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -616,6 +616,7 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL); if (!muxed_data) return -ENOMEM; + muxed_data->nr_banks = muxed_banks; irq_set_chained_handler_and_data(irq, exynos_irq_demux_eint16_31, muxed_data); @@ -628,7 +629,6 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) muxed_data->banks[idx++] = bank; } - muxed_data->nr_banks = muxed_banks; return 0; } diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h index 7bd6d82c9f36..3ac52c2cf998 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.h +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h @@ -159,7 +159,7 @@ struct exynos_weint_data { */ struct exynos_muxed_weint_data { unsigned int nr_banks; - struct samsung_pin_bank *banks[]; + struct samsung_pin_bank *banks[] __counted_by(nr_banks); }; int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d); -- cgit v1.2.3 From 2aca5c591ef4ecc4bcb9be3c9a9360d3d5238866 Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Fri, 6 Oct 2023 14:55:54 +0200 Subject: pinctrl: samsung: defer pinctrl_enable dev_pinctrl_register function immediately enables the pinctrl subsystem, which is unpreferable in general, since drivers might be unable to handle calls immediately. Hence devm_pinctrl_register_and_init, which does not call pinctrl_enable, is preferred. In case of our driver using the old function does not seem to be problematic for now, but will become an issue when we postpone parts of pinctrl initialization in a future commit, and it is a good idea to move off a deprecated-ish function anyway. Signed-off-by: Mateusz Majewski Reviewed-by: Sam Protsenko Tested-by: Sam Protsenko Tested-by: Marek Szyprowski Link: https://lore.kernel.org/r/20231006125557.212681-2-m.majewski2@samsung.com Signed-off-by: Krzysztof Kozlowski --- drivers/pinctrl/samsung/pinctrl-samsung.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index e54847040b4a..e496af72a587 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -904,11 +904,11 @@ static int samsung_pinctrl_register(struct platform_device *pdev, if (ret) return ret; - drvdata->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, - drvdata); - if (IS_ERR(drvdata->pctl_dev)) { + ret = devm_pinctrl_register_and_init(&pdev->dev, ctrldesc, drvdata, + &drvdata->pctl_dev); + if (ret) { dev_err(&pdev->dev, "could not register pinctrl driver\n"); - return PTR_ERR(drvdata->pctl_dev); + return ret; } for (bank = 0; bank < drvdata->nr_banks; ++bank) { @@ -1176,6 +1176,10 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) if (ret) goto err_unregister; + ret = pinctrl_enable(drvdata->pctl_dev); + if (ret) + goto err_unregister; + platform_set_drvdata(pdev, drvdata); return 0; -- cgit v1.2.3 From bf128c1f0fe1fd4801fb84660c324095990c533a Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Fri, 6 Oct 2023 14:55:55 +0200 Subject: pinctrl: samsung: use add_pin_ranges method to add pinctrl ranges This is preferable since we can read the base in the global GPIO numberspace from the chip instead of needing to select it ourselves. Past versions could not do this, since they needed to add all the ranges before enabling the pinctrl subsystem, which was done before registering the GPIO chip. However, right now we enable the pinctrl subsystem after registering the chip and so this became possible. Signed-off-by: Mateusz Majewski Reviewed-by: Sam Protsenko Tested-by: Sam Protsenko Tested-by: Marek Szyprowski Link: https://lore.kernel.org/r/20231006125557.212681-3-m.majewski2@samsung.com Signed-off-by: Krzysztof Kozlowski --- drivers/pinctrl/samsung/pinctrl-samsung.c | 31 ++++++++++++++++++------------- drivers/pinctrl/samsung/pinctrl-samsung.h | 2 ++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index e496af72a587..511a3ac51f76 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -665,6 +665,21 @@ static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset) return (virq) ? : -ENXIO; } +static int samsung_add_pin_ranges(struct gpio_chip *gc) +{ + struct samsung_pin_bank *bank = gpiochip_get_data(gc); + + bank->grange.name = bank->name; + bank->grange.id = bank->id; + bank->grange.pin_base = bank->drvdata->pin_base + bank->pin_base; + bank->grange.base = gc->base; + bank->grange.npins = bank->nr_pins; + bank->grange.gc = &bank->gpio_chip; + pinctrl_add_gpio_range(bank->drvdata->pctl_dev, &bank->grange); + + return 0; +} + static struct samsung_pin_group *samsung_pinctrl_create_groups( struct device *dev, struct samsung_pinctrl_drv_data *drvdata, @@ -892,6 +907,7 @@ static int samsung_pinctrl_register(struct platform_device *pdev, /* for each pin, the name of the pin is pin-bank name + pin number */ for (bank = 0; bank < drvdata->nr_banks; bank++) { pin_bank = &drvdata->pin_banks[bank]; + pin_bank->id = bank; for (pin = 0; pin < pin_bank->nr_pins; pin++) { sprintf(pin_names, "%s-%d", pin_bank->name, pin); pdesc = pindesc + pin_bank->pin_base + pin; @@ -911,18 +927,6 @@ static int samsung_pinctrl_register(struct platform_device *pdev, return ret; } - for (bank = 0; bank < drvdata->nr_banks; ++bank) { - pin_bank = &drvdata->pin_banks[bank]; - pin_bank->grange.name = pin_bank->name; - pin_bank->grange.id = bank; - pin_bank->grange.pin_base = drvdata->pin_base - + pin_bank->pin_base; - pin_bank->grange.base = pin_bank->grange.pin_base; - pin_bank->grange.npins = pin_bank->nr_pins; - pin_bank->grange.gc = &pin_bank->gpio_chip; - pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange); - } - return 0; } @@ -947,6 +951,7 @@ static const struct gpio_chip samsung_gpiolib_chip = { .direction_input = samsung_gpio_direction_input, .direction_output = samsung_gpio_direction_output, .to_irq = samsung_gpio_to_irq, + .add_pin_ranges = samsung_add_pin_ranges, .owner = THIS_MODULE, }; @@ -963,7 +968,7 @@ static int samsung_gpiolib_register(struct platform_device *pdev, bank->gpio_chip = samsung_gpiolib_chip; gc = &bank->gpio_chip; - gc->base = bank->grange.base; + gc->base = drvdata->pin_base + bank->pin_base; gc->ngpio = bank->nr_pins; gc->parent = &pdev->dev; gc->fwnode = bank->fwnode; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 9af93e3d8d9f..173db20f70d3 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -148,6 +148,7 @@ struct samsung_pin_bank_data { * @eint_mask: bit mask of pins which support EINT function. * @eint_offset: SoC-specific EINT register or interrupt offset of bank. * @name: name to be prefixed for each pin in this pin bank. + * @id: id of the bank, propagated to the pin range. * @pin_base: starting pin number of the bank. * @soc_priv: per-bank private data for SoC-specific code. * @of_node: OF node of the bank. @@ -170,6 +171,7 @@ struct samsung_pin_bank { u32 eint_mask; u32 eint_offset; const char *name; + u32 id; u32 pin_base; void *soc_priv; -- cgit v1.2.3 From deb79167e1dadc0ac0a9e3aa67130e60c5d011ef Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Fri, 6 Oct 2023 14:55:56 +0200 Subject: pinctrl: samsung: choose GPIO numberspace base dynamically Selecting it statically is deprecated and results in a warning while booting the system: gpio gpiochip0: Static allocation of GPIO base is deprecated, use dynamic allocation. Signed-off-by: Mateusz Majewski Reviewed-by: Sam Protsenko Tested-by: Sam Protsenko Tested-by: Marek Szyprowski Link: https://lore.kernel.org/r/20231006125557.212681-4-m.majewski2@samsung.com Signed-off-by: Krzysztof Kozlowski --- drivers/pinctrl/samsung/pinctrl-samsung.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 511a3ac51f76..952aeeebb679 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -968,7 +968,7 @@ static int samsung_gpiolib_register(struct platform_device *pdev, bank->gpio_chip = samsung_gpiolib_chip; gc = &bank->gpio_chip; - gc->base = drvdata->pin_base + bank->pin_base; + gc->base = -1; /* Dynamic allocation */ gc->ngpio = bank->nr_pins; gc->parent = &pdev->dev; gc->fwnode = bank->fwnode; -- cgit v1.2.3 From 8aec97decfd0f444a69a765b2f00d64b42752824 Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Fri, 6 Oct 2023 14:55:57 +0200 Subject: pinctrl: samsung: do not offset pinctrl numberspaces Past versions of this driver have manually calculated base values for both the pinctrl numberspace and the global GPIO numberspace, giving both the same values. This was necessary for the global GPIO numberspace, since its values need to be unique system-wide. However, it was not necessary for the pinctrl numberspace, since its values only need to be unique for a single instance of the pinctrl device. It was just convenient to use the same values for both spaces. Right now those calculations are only used for the pinctrl numberspace, since GPIO numberspace bases are selected by the GPIO subsystem. Therefore, those calculations are unnecessary. Signed-off-by: Mateusz Majewski Reviewed-by: Sam Protsenko Tested-by: Sam Protsenko Tested-by: Marek Szyprowski Link: https://lore.kernel.org/r/20231006125557.212681-5-m.majewski2@samsung.com Signed-off-by: Krzysztof Kozlowski --- drivers/pinctrl/samsung/pinctrl-samsung.c | 15 ++++----------- drivers/pinctrl/samsung/pinctrl-samsung.h | 2 -- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 952aeeebb679..79babbb39ced 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -45,8 +45,6 @@ static struct pin_config { { "samsung,pin-val", PINCFG_TYPE_DAT }, }; -static unsigned int pin_base; - static int samsung_get_group_count(struct pinctrl_dev *pctldev) { struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev); @@ -389,8 +387,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, func = &drvdata->pmx_functions[selector]; grp = &drvdata->pin_groups[group]; - pin_to_reg_bank(drvdata, grp->pins[0] - drvdata->pin_base, - ®, &pin_offset, &bank); + pin_to_reg_bank(drvdata, grp->pins[0], ®, &pin_offset, &bank); type = bank->type; mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1; shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC]; @@ -441,8 +438,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long flags; drvdata = pinctrl_dev_get_drvdata(pctldev); - pin_to_reg_bank(drvdata, pin - drvdata->pin_base, ®_base, - &pin_offset, &bank); + pin_to_reg_bank(drvdata, pin, ®_base, &pin_offset, &bank); type = bank->type; if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type]) @@ -671,7 +667,7 @@ static int samsung_add_pin_ranges(struct gpio_chip *gc) bank->grange.name = bank->name; bank->grange.id = bank->id; - bank->grange.pin_base = bank->drvdata->pin_base + bank->pin_base; + bank->grange.pin_base = bank->pin_base; bank->grange.base = gc->base; bank->grange.npins = bank->nr_pins; bank->grange.gc = &bank->gpio_chip; @@ -891,7 +887,7 @@ static int samsung_pinctrl_register(struct platform_device *pdev, /* dynamically populate the pin number and pin name for pindesc */ for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++) - pdesc->number = pin + drvdata->pin_base; + pdesc->number = pin; /* * allocate space for storing the dynamically generated names for all @@ -1129,9 +1125,6 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, samsung_banks_node_get(&pdev->dev, d); - d->pin_base = pin_base; - pin_base += d->nr_pins; - return ctrl; } diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 173db20f70d3..9b3db50adef3 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -269,7 +269,6 @@ struct samsung_pin_ctrl { * @nr_groups: number of such pin groups. * @pmx_functions: list of pin functions available to the driver. * @nr_function: number of such pin functions. - * @pin_base: starting system wide pin number. * @nr_pins: number of pins supported by the controller. * @retention_ctrl: retention control runtime data. * @suspend: platform specific suspend callback, executed during pin controller @@ -293,7 +292,6 @@ struct samsung_pinctrl_drv_data { struct samsung_pin_bank *pin_banks; unsigned int nr_banks; - unsigned int pin_base; unsigned int nr_pins; struct samsung_retention_ctrl *retention_ctrl; -- cgit v1.2.3