summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Stübner <heiko@sntech.de>2013-06-14 17:43:55 +0200
committerLinus Walleij <linus.walleij@linaro.org>2013-06-17 18:18:31 +0200
commit6abab2d4bec982bcefbe99201ddee5f25227daf4 (patch)
treebc70b4fb53bb9154d3c44c6b592f25a78274e536
parentpinctrl: handle zero found dt pinconfig properties better (diff)
downloadlinux-6abab2d4bec982bcefbe99201ddee5f25227daf4.tar.xz
linux-6abab2d4bec982bcefbe99201ddee5f25227daf4.zip
pinctrl: dynamically alloc temp array when parsing dt pinconf options
Allocating the temorary array in pinconf_generic_parse_dt_config on stack might cause problems later on, when the number of options grows over time. Therefore also allocate this array dynamically to be on the safe side. Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: James Hogan <james.hogan@imgtec.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/pinctrl/pinconf-generic.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index ea9da1752252..794dad7d68d8 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