pinctrl: generic: free maps on pinctrl_generic_to_map() failure

pinctrl_generic_to_map() parses DT configuration and allocates pinctrl
maps via pinctrl_utils_reserve_map().

If subsequent steps (such as pinctrl_utils_add_map_mux(),
pinctrl_generic_add_group(), pinconf_generic_parse_dt_config(), or
pinctrl_utils_add_map_configs()) return an error, *maps may contain
partially allocated map entries. Returning the error directly without
freeing *maps leaks the allocated mapping memory across all drivers
that rely on pinctrl_generic_to_map().

Fix this by calling pinctrl_utils_free_map() and resetting *maps,
*num_maps, and *num_reserved_maps in the error path of
pinctrl_generic_to_map().

Fixes: aaaf31be04 ("pinctrl: extract pinctrl_generic_to_map() from pinctrl_generic_pins_function_dt_node_to_map()")
Signed-off-by: Surendra Singh Chouhan <kr494167@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
This commit is contained in:
Surendra Singh Chouhan
2026-07-29 13:24:37 +05:30
committed by Linus Walleij
parent f9af1329b9
commit 17007cd700

View File

@@ -42,33 +42,44 @@ int pinctrl_generic_to_map(struct pinctrl_dev *pctldev, struct device_node *pare
ret = pinctrl_utils_add_map_mux(pctldev, maps, num_reserved_maps, num_maps, group_name,
parent->name);
if (ret < 0)
return ret;
goto err_free_map;
ret = pinctrl_generic_add_group(pctldev, group_name, pins, npins, data);
if (ret < 0)
return dev_err_probe(dev, ret, "failed to add group %s: %d\n",
if (ret < 0) {
dev_err_probe(dev, ret, "failed to add group %s: %d\n",
group_name, ret);
goto err_free_map;
}
ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs);
if (ret)
return dev_err_probe(dev, ret, "failed to parse pin config of group %s\n",
if (ret) {
dev_err_probe(dev, ret, "failed to parse pin config of group %s\n",
group_name);
goto err_free_map;
}
if (num_configs == 0)
return 0;
ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
if (ret)
return ret;
goto err_free_map;
ret = pinctrl_utils_add_map_configs(pctldev, maps, num_reserved_maps, num_maps, group_name,
configs,
num_configs, PIN_MAP_TYPE_CONFIGS_GROUP);
kfree(configs);
if (ret)
return ret;
goto err_free_map;
return 0;
err_free_map:
pinctrl_utils_free_map(pctldev, *maps, *num_maps);
*maps = NULL;
*num_maps = 0;
*num_reserved_maps = 0;
return ret;
};
EXPORT_SYMBOL_GPL(pinctrl_generic_to_map);