diff options
| author | Heiko Stübner <heiko@sntech.de> | 2013-06-14 11:43:55 -0400 |
|---|---|---|
| committer | Linus Walleij <linus.walleij@linaro.org> | 2013-06-17 12:18:31 -0400 |
| commit | 6abab2d4bec982bcefbe99201ddee5f25227daf4 (patch) | |
| tree | bc70b4fb53bb9154d3c44c6b592f25a78274e536 | |
| parent | e4a8844c04c00a1a64c6779692e1baff3851c1f7 (diff) | |
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.c | 24 |
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, | |||
| 182 | unsigned long **configs, | 182 | unsigned long **configs, |
| 183 | unsigned int *nconfigs) | 183 | unsigned int *nconfigs) |
| 184 | { | 184 | { |
| 185 | unsigned long cfg[ARRAY_SIZE(dt_params)]; | 185 | unsigned long *cfg; |
| 186 | unsigned int ncfg = 0; | 186 | unsigned int ncfg = 0; |
| 187 | int ret; | 187 | int ret; |
| 188 | int i; | 188 | int i; |
| @@ -191,6 +191,11 @@ int pinconf_generic_parse_dt_config(struct device_node *np, | |||
| 191 | if (!np) | 191 | if (!np) |
| 192 | return -EINVAL; | 192 | return -EINVAL; |
| 193 | 193 | ||
| 194 | /* allocate a temporary array big enough to hold one of each option */ | ||
| 195 | cfg = kzalloc(sizeof(*cfg) * ARRAY_SIZE(dt_params), GFP_KERNEL); | ||
| 196 | if (!cfg) | ||
| 197 | return -ENOMEM; | ||
| 198 | |||
| 194 | for (i = 0; i < ARRAY_SIZE(dt_params); i++) { | 199 | for (i = 0; i < ARRAY_SIZE(dt_params); i++) { |
| 195 | struct pinconf_generic_dt_params *par = &dt_params[i]; | 200 | struct pinconf_generic_dt_params *par = &dt_params[i]; |
| 196 | ret = of_property_read_u32(np, par->property, &val); | 201 | ret = of_property_read_u32(np, par->property, &val); |
| @@ -208,11 +213,13 @@ int pinconf_generic_parse_dt_config(struct device_node *np, | |||
| 208 | ncfg++; | 213 | ncfg++; |
| 209 | } | 214 | } |
| 210 | 215 | ||
| 216 | ret = 0; | ||
| 217 | |||
| 211 | /* no configs found at all */ | 218 | /* no configs found at all */ |
| 212 | if (ncfg == 0) { | 219 | if (ncfg == 0) { |
| 213 | *configs = NULL; | 220 | *configs = NULL; |
| 214 | *nconfigs = 0; | 221 | *nconfigs = 0; |
| 215 | return 0; | 222 | goto out; |
| 216 | } | 223 | } |
| 217 | 224 | ||
| 218 | /* | 225 | /* |
| @@ -220,11 +227,16 @@ int pinconf_generic_parse_dt_config(struct device_node *np, | |||
| 220 | * found properties. | 227 | * found properties. |
| 221 | */ | 228 | */ |
| 222 | *configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL); | 229 | *configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL); |
| 223 | if (!*configs) | 230 | if (!*configs) { |
| 224 | return -ENOMEM; | 231 | ret = -ENOMEM; |
| 232 | goto out; | ||
| 233 | } | ||
| 225 | 234 | ||
| 226 | memcpy(*configs, &cfg, ncfg * sizeof(unsigned long)); | 235 | memcpy(*configs, cfg, ncfg * sizeof(unsigned long)); |
| 227 | *nconfigs = ncfg; | 236 | *nconfigs = ncfg; |
| 228 | return 0; | 237 | |
| 238 | out: | ||
| 239 | kfree(cfg); | ||
| 240 | return ret; | ||
| 229 | } | 241 | } |
| 230 | #endif | 242 | #endif |
