From 16a6d2e685e8f9a2f51dd5a363d3f97fcad35e22 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Thu, 26 Sep 2024 16:11:02 +0200 Subject: [PATCH 1/9] pinctrl: intel: platform: fix error path in device_for_each_child_node() The device_for_each_child_node() loop requires calls to fwnode_handle_put() upon early returns to decrement the refcount of the child node and avoid leaking memory if that error path is triggered. There is one early returns within that loop in intel_platform_pinctrl_prepare_community(), but fwnode_handle_put() is missing. Instead of adding the missing call, the scoped version of the loop can be used to simplify the code and avoid mistakes in the future if new early returns are added, as the child node is only used for parsing, and it is never assigned. Cc: stable@vger.kernel.org Fixes: c5860e4a2737 ("pinctrl: intel: Add a generic Intel pin control platform driver") Signed-off-by: Javier Carrasco Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel-platform.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel-platform.c b/drivers/pinctrl/intel/pinctrl-intel-platform.c index 4a19ab3b4ba7..2d5ba8278fb9 100644 --- a/drivers/pinctrl/intel/pinctrl-intel-platform.c +++ b/drivers/pinctrl/intel/pinctrl-intel-platform.c @@ -90,7 +90,6 @@ static int intel_platform_pinctrl_prepare_community(struct device *dev, struct intel_community *community, struct intel_platform_pins *pins) { - struct fwnode_handle *child; struct intel_padgroup *gpps; unsigned int group; size_t ngpps; @@ -131,7 +130,7 @@ static int intel_platform_pinctrl_prepare_community(struct device *dev, return -ENOMEM; group = 0; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct intel_padgroup *gpp = &gpps[group]; gpp->reg_num = group; From d594de8956883f233f30b2559a10266dc0fc446a Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Thu, 26 Sep 2024 16:11:03 +0200 Subject: [PATCH 2/9] pinctrl: intel: platform: use semicolon instead of comma in ncommunities assignment Substitute the comma with a semicolon in the `ncommunities` assignment for better readability and consistency with common C coding style. Signed-off-by: Javier Carrasco Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel-platform.c b/drivers/pinctrl/intel/pinctrl-intel-platform.c index 2d5ba8278fb9..016a9f62eecc 100644 --- a/drivers/pinctrl/intel/pinctrl-intel-platform.c +++ b/drivers/pinctrl/intel/pinctrl-intel-platform.c @@ -158,7 +158,7 @@ static int intel_platform_pinctrl_prepare_soc_data(struct device *dev, int ret; /* Version 1.0 of the specification assumes only a single community per device node */ - ncommunities = 1, + ncommunities = 1; communities = devm_kcalloc(dev, ncommunities, sizeof(*communities), GFP_KERNEL); if (!communities) return -ENOMEM; From 665a58fe663ac7a9ea618dc0b29881649324b116 Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Thu, 5 Sep 2024 10:09:17 +0800 Subject: [PATCH 3/9] pinctrl: apple: check devm_kasprintf() returned value devm_kasprintf() can return a NULL pointer on failure but this returned value is not checked. Fix this lack and check the returned value. Found by code review. Cc: stable@vger.kernel.org Fixes: a0f160ffcb83 ("pinctrl: add pinctrl/GPIO driver for Apple SoCs") Signed-off-by: Ma Ke Reviewed-by: Christophe JAILLET Link: https://lore.kernel.org/20240905020917.356534-1-make24@iscas.ac.cn Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-apple-gpio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pinctrl/pinctrl-apple-gpio.c b/drivers/pinctrl/pinctrl-apple-gpio.c index 3751c7de37aa..f861e63f4115 100644 --- a/drivers/pinctrl/pinctrl-apple-gpio.c +++ b/drivers/pinctrl/pinctrl-apple-gpio.c @@ -474,6 +474,9 @@ static int apple_gpio_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < npins; i++) { pins[i].number = i; pins[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "PIN%u", i); + if (!pins[i].name) + return -ENOMEM; + pins[i].drv_data = pctl; pin_names[i] = pins[i].name; pin_nums[i] = i; From b0f0e3f0552a566def55c844b0d44250c58e4df6 Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Fri, 6 Sep 2024 18:03:26 +0800 Subject: [PATCH 4/9] pinctrl: stm32: check devm_kasprintf() returned value devm_kasprintf() can return a NULL pointer on failure but this returned value is not checked. Fix this lack and check the returned value. Found by code review. Cc: stable@vger.kernel.org Fixes: 32c170ff15b0 ("pinctrl: stm32: set default gpio line names using pin names") Signed-off-by: Ma Ke Link: https://lore.kernel.org/20240906100326.624445-1-make24@iscas.ac.cn Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index a8673739871d..5b7fa77c1184 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -1374,10 +1374,15 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode for (i = 0; i < npins; i++) { stm32_pin = stm32_pctrl_get_desc_pin_from_gpio(pctl, bank, i); - if (stm32_pin && stm32_pin->pin.name) + if (stm32_pin && stm32_pin->pin.name) { names[i] = devm_kasprintf(dev, GFP_KERNEL, "%s", stm32_pin->pin.name); - else + if (!names[i]) { + err = -ENOMEM; + goto err_clk; + } + } else { names[i] = NULL; + } } bank->gpio_chip.names = (const char * const *)names; From 393c554093c0c4cbc8e2f178d36df169016384da Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 1 Oct 2024 14:27:22 -0700 Subject: [PATCH 5/9] pinctrl: aw9523: add missing mutex_destroy Otherwise the mutex remains after a failed kzalloc. Signed-off-by: Rosen Penev Link: https://lore.kernel.org/20241001212724.309320-1-rosenp@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-aw9523.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-aw9523.c b/drivers/pinctrl/pinctrl-aw9523.c index b5e1c467625b..1374f30166bc 100644 --- a/drivers/pinctrl/pinctrl-aw9523.c +++ b/drivers/pinctrl/pinctrl-aw9523.c @@ -987,8 +987,10 @@ static int aw9523_probe(struct i2c_client *client) lockdep_set_subclass(&awi->i2c_lock, i2c_adapter_depth(client->adapter)); pdesc = devm_kzalloc(dev, sizeof(*pdesc), GFP_KERNEL); - if (!pdesc) - return -ENOMEM; + if (!pdesc) { + ret = -ENOMEM; + goto err_disable_vregs; + } ret = aw9523_hw_init(awi); if (ret) From 37756257093bf1bda0bb034f4f1bd3219c7b2a40 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 2 Oct 2024 18:00:36 +0300 Subject: [PATCH 6/9] pinctrl: intel: platform: Add Panther Lake to the list of supported Intel Panther Lake is supported by the generic platform driver, so add it to the list of supported in Kconfig. Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig index 2101d30bd66c..14c26c023590 100644 --- a/drivers/pinctrl/intel/Kconfig +++ b/drivers/pinctrl/intel/Kconfig @@ -46,6 +46,7 @@ config PINCTRL_INTEL_PLATFORM of Intel PCH pins and using them as GPIOs. Currently the following Intel SoCs / platforms require this to be functional: - Lunar Lake + - Panther Lake config PINCTRL_ALDERLAKE tristate "Intel Alder Lake pinctrl and GPIO driver" From 4575962aeed63aca975756852ab0c550164f849f Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Thu, 10 Oct 2024 04:18:18 -0700 Subject: [PATCH 7/9] pinctrl: sophgo: fix double free in cv1800_pctrl_dt_node_to_map() 'map' is allocated using devm_* which takes care of freeing the allocated data, but in error paths there is a call to pinctrl_utils_free_map() which also does kfree(map) which leads to a double free. Use kcalloc() instead of devm_kcalloc() as freeing is manually handled. Fixes: a29d8e93e710 ("pinctrl: sophgo: add support for CV1800B SoC") Signed-off-by: Harshit Mogalapalli Link: https://lore.kernel.org/20241010111830.3474719-1-harshit.m.mogalapalli@oracle.com Signed-off-by: Linus Walleij --- drivers/pinctrl/sophgo/pinctrl-cv18xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c index d18fc5aa84f7..57f2674e75d6 100644 --- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c +++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c @@ -221,7 +221,7 @@ static int cv1800_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, if (!grpnames) return -ENOMEM; - map = devm_kcalloc(dev, ngroups * 2, sizeof(*map), GFP_KERNEL); + map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL); if (!map) return -ENOMEM; From 3fd976afe9743110f20a23f93b7ff9693f2be4bf Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Thu, 10 Oct 2024 13:52:37 -0700 Subject: [PATCH 8/9] pinctrl: nuvoton: fix a double free in ma35_pinctrl_dt_node_to_map_func() 'new_map' is allocated using devm_* which takes care of freeing the allocated data on device removal, call to .dt_free_map = pinconf_generic_dt_free_map double frees the map as pinconf_generic_dt_free_map() calls pinctrl_utils_free_map(). Fix this by using kcalloc() instead of auto-managed devm_kcalloc(). Cc: stable@vger.kernel.org Fixes: f805e356313b ("pinctrl: nuvoton: Add ma35d1 pinctrl and GPIO driver") Reported-by: Christophe JAILLET Signed-off-by: Harshit Mogalapalli Link: https://lore.kernel.org/20241010205237.1245318-1-harshit.m.mogalapalli@oracle.com Signed-off-by: Linus Walleij --- drivers/pinctrl/nuvoton/pinctrl-ma35.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c b/drivers/pinctrl/nuvoton/pinctrl-ma35.c index 1fa00a23534a..59c4e7c6cdde 100644 --- a/drivers/pinctrl/nuvoton/pinctrl-ma35.c +++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c @@ -218,7 +218,7 @@ static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev, } map_num += grp->npins; - new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map), GFP_KERNEL); + new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL); if (!new_map) return -ENOMEM; From 93b8ddc54507a227087c60a0013ed833b6ae7d3c Mon Sep 17 00:00:00 2001 From: Sergey Matsievskiy Date: Sat, 12 Oct 2024 13:57:43 +0300 Subject: [PATCH 9/9] pinctrl: ocelot: fix system hang on level based interrupts The current implementation only calls chained_irq_enter() and chained_irq_exit() if it detects pending interrupts. ``` for (i = 0; i < info->stride; i++) { uregmap_read(info->map, id_reg + 4 * i, ®); if (!reg) continue; chained_irq_enter(parent_chip, desc); ``` However, in case of GPIO pin configured in level mode and the parent controller configured in edge mode, GPIO interrupt might be lowered by the hardware. In the result, if the interrupt is short enough, the parent interrupt is still pending while the GPIO interrupt is cleared; chained_irq_enter() never gets called and the system hangs trying to service the parent interrupt. Moving chained_irq_enter() and chained_irq_exit() outside the for loop ensures that they are called even when GPIO interrupt is lowered by the hardware. The similar code with chained_irq_enter() / chained_irq_exit() functions wrapping interrupt checking loop may be found in many other drivers: ``` grep -r -A 10 chained_irq_enter drivers/pinctrl ``` Cc: stable@vger.kernel.org Signed-off-by: Sergey Matsievskiy Reviewed-by: Alexandre Belloni Link: https://lore.kernel.org/20241012105743.12450-2-matsievskiysv@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ocelot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index be9b8c010167..d1ab8450ea93 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -1955,21 +1955,21 @@ static void ocelot_irq_handler(struct irq_desc *desc) unsigned int reg = 0, irq, i; unsigned long irqs; + chained_irq_enter(parent_chip, desc); + for (i = 0; i < info->stride; i++) { regmap_read(info->map, id_reg + 4 * i, ®); if (!reg) continue; - chained_irq_enter(parent_chip, desc); - irqs = reg; for_each_set_bit(irq, &irqs, min(32U, info->desc->npins - 32 * i)) generic_handle_domain_irq(chip->irq.domain, irq + 32 * i); - - chained_irq_exit(parent_chip, desc); } + + chained_irq_exit(parent_chip, desc); } static int ocelot_gpiochip_register(struct platform_device *pdev,