diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index ea9da175225290d91f9efb4215bc2311bfad737d..794dad7d68d8ac1adec371c4a71a9f789e4d414e 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -182,7 +182,7 @@ int pinconf_generic_parse_dt_config(struct device_node *np, unsigned long **configs, unsigned int *nconfigs) { - unsigned long cfg[ARRAY_SIZE(dt_params)]; + unsigned long *cfg; unsigned int ncfg = 0; int ret; int i; @@ -191,6 +191,11 @@ int pinconf_generic_parse_dt_config(struct device_node *np, if (!np) return -EINVAL; + /* allocate a temporary array big enough to hold one of each option */ + cfg = kzalloc(sizeof(*cfg) * ARRAY_SIZE(dt_params), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(dt_params); i++) { struct pinconf_generic_dt_params *par = &dt_params[i]; ret = of_property_read_u32(np, par->property, &val); @@ -208,11 +213,13 @@ int pinconf_generic_parse_dt_config(struct device_node *np, ncfg++; } + ret = 0; + /* no configs found at all */ if (ncfg == 0) { *configs = NULL; *nconfigs = 0; - return 0; + goto out; } /* @@ -220,11 +227,16 @@ int pinconf_generic_parse_dt_config(struct device_node *np, * found properties. */ *configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL); - if (!*configs) - return -ENOMEM; + if (!*configs) { + ret = -ENOMEM; + goto out; + } - memcpy(*configs, &cfg, ncfg * sizeof(unsigned long)); + memcpy(*configs, cfg, ncfg * sizeof(unsigned long)); *nconfigs = ncfg; - return 0; + +out: + kfree(cfg); + return ret; } #endif