diff options
Diffstat (limited to 'drivers/pinctrl/pinmux.c')
-rw-r--r-- | drivers/pinctrl/pinmux.c | 60 |
1 files changed, 29 insertions, 31 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index f6e7d583998c..a11681b4bd91 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -33,7 +33,7 @@ | |||
33 | static DEFINE_MUTEX(pinmux_list_mutex); | 33 | static DEFINE_MUTEX(pinmux_list_mutex); |
34 | static LIST_HEAD(pinmux_list); | 34 | static LIST_HEAD(pinmux_list); |
35 | 35 | ||
36 | /* Global pinmux maps, we allow one set only */ | 36 | /* Global pinmux maps */ |
37 | static struct pinmux_map *pinmux_maps; | 37 | static struct pinmux_map *pinmux_maps; |
38 | static unsigned pinmux_maps_num; | 38 | static unsigned pinmux_maps_num; |
39 | 39 | ||
@@ -347,48 +347,30 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); | |||
347 | int __init pinmux_register_mappings(struct pinmux_map const *maps, | 347 | int __init pinmux_register_mappings(struct pinmux_map const *maps, |
348 | unsigned num_maps) | 348 | unsigned num_maps) |
349 | { | 349 | { |
350 | int ret = 0; | 350 | void *tmp_maps; |
351 | int i; | 351 | int i; |
352 | 352 | ||
353 | if (pinmux_maps_num != 0) { | ||
354 | pr_err("pinmux mappings already registered, you can only " | ||
355 | "register one set of maps\n"); | ||
356 | return -EINVAL; | ||
357 | } | ||
358 | |||
359 | pr_debug("add %d pinmux maps\n", num_maps); | 353 | pr_debug("add %d pinmux maps\n", num_maps); |
360 | 354 | ||
361 | /* | 355 | /* First sanity check the new mapping */ |
362 | * Make a copy of the map array - string pointers will end up in the | ||
363 | * kernel const section anyway so these do not need to be deep copied. | ||
364 | */ | ||
365 | pinmux_maps = kmemdup(maps, sizeof(struct pinmux_map) * num_maps, | ||
366 | GFP_KERNEL); | ||
367 | if (!pinmux_maps) | ||
368 | return -ENOMEM; | ||
369 | |||
370 | for (i = 0; i < num_maps; i++) { | 356 | for (i = 0; i < num_maps; i++) { |
371 | /* Sanity check the mapping while copying it */ | ||
372 | if (!maps[i].name) { | 357 | if (!maps[i].name) { |
373 | pr_err("failed to register map %d: " | 358 | pr_err("failed to register map %d: " |
374 | "no map name given\n", i); | 359 | "no map name given\n", i); |
375 | ret = -EINVAL; | 360 | return -EINVAL; |
376 | goto err_out_free; | ||
377 | } | 361 | } |
378 | 362 | ||
379 | if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { | 363 | if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { |
380 | pr_err("failed to register map %s (%d): " | 364 | pr_err("failed to register map %s (%d): " |
381 | "no pin control device given\n", | 365 | "no pin control device given\n", |
382 | maps[i].name, i); | 366 | maps[i].name, i); |
383 | ret = -EINVAL; | 367 | return -EINVAL; |
384 | goto err_out_free; | ||
385 | } | 368 | } |
386 | 369 | ||
387 | if (!maps[i].function) { | 370 | if (!maps[i].function) { |
388 | pr_err("failed to register map %s (%d): " | 371 | pr_err("failed to register map %s (%d): " |
389 | "no function ID given\n", maps[i].name, i); | 372 | "no function ID given\n", maps[i].name, i); |
390 | ret = -EINVAL; | 373 | return -EINVAL; |
391 | goto err_out_free; | ||
392 | } | 374 | } |
393 | 375 | ||
394 | if (!maps[i].dev && !maps[i].dev_name) | 376 | if (!maps[i].dev && !maps[i].dev_name) |
@@ -399,17 +381,33 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, | |||
399 | pr_debug("register map %s, function %s\n", | 381 | pr_debug("register map %s, function %s\n", |
400 | maps[i].name, | 382 | maps[i].name, |
401 | maps[i].function); | 383 | maps[i].function); |
384 | } | ||
402 | 385 | ||
403 | pinmux_maps_num++; | 386 | /* |
387 | * Make a copy of the map array - string pointers will end up in the | ||
388 | * kernel const section anyway so these do not need to be deep copied. | ||
389 | */ | ||
390 | if (!pinmux_maps_num) { | ||
391 | /* On first call, just copy them */ | ||
392 | tmp_maps = kmemdup(maps, | ||
393 | sizeof(struct pinmux_map) * num_maps, | ||
394 | GFP_KERNEL); | ||
395 | if (!tmp_maps) | ||
396 | return -ENOMEM; | ||
397 | } else { | ||
398 | /* Subsequent calls, reallocate array to new size */ | ||
399 | size_t oldsize = sizeof(struct pinmux_map) * pinmux_maps_num; | ||
400 | size_t newsize = sizeof(struct pinmux_map) * num_maps; | ||
401 | |||
402 | tmp_maps = krealloc(pinmux_maps, oldsize + newsize, GFP_KERNEL); | ||
403 | if (!tmp_maps) | ||
404 | return -ENOMEM; | ||
405 | memcpy((tmp_maps + oldsize), maps, newsize); | ||
404 | } | 406 | } |
405 | 407 | ||
408 | pinmux_maps = tmp_maps; | ||
409 | pinmux_maps_num += num_maps; | ||
406 | return 0; | 410 | return 0; |
407 | |||
408 | err_out_free: | ||
409 | kfree(pinmux_maps); | ||
410 | pinmux_maps = NULL; | ||
411 | pinmux_maps_num = 0; | ||
412 | return ret; | ||
413 | } | 411 | } |
414 | 412 | ||
415 | /** | 413 | /** |