diff options
-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 f6e7d58..a11681b 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -33,7 +33,7 @@ static DEFINE_MUTEX(pinmux_list_mutex); static LIST_HEAD(pinmux_list); -/* Global pinmux maps, we allow one set only */ +/* Global pinmux maps */ static struct pinmux_map *pinmux_maps; static unsigned pinmux_maps_num; @@ -347,48 +347,30 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); int __init pinmux_register_mappings(struct pinmux_map const *maps, unsigned num_maps) { - int ret = 0; + void *tmp_maps; int i; - if (pinmux_maps_num != 0) { - pr_err("pinmux mappings already registered, you can only " - "register one set of maps\n"); - return -EINVAL; - } - pr_debug("add %d pinmux maps\n", num_maps); - /* - * Make a copy of the map array - string pointers will end up in the - * kernel const section anyway so these do not need to be deep copied. - */ - pinmux_maps = kmemdup(maps, sizeof(struct pinmux_map) * num_maps, - GFP_KERNEL); - if (!pinmux_maps) - return -ENOMEM; - + /* First sanity check the new mapping */ for (i = 0; i < num_maps; i++) { - /* Sanity check the mapping while copying it */ if (!maps[i].name) { pr_err("failed to register map %d: " "no map name given\n", i); - ret = -EINVAL; - goto err_out_free; + return -EINVAL; } if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { pr_err("failed to register map %s (%d): " "no pin control device given\n", maps[i].name, i); - ret = -EINVAL; - goto err_out_free; + return -EINVAL; } if (!maps[i].function) { pr_err("failed to register map %s (%d): " "no function ID given\n", maps[i].name, i); - ret = -EINVAL; - goto err_out_free; + return -EINVAL; } if (!maps[i].dev && !maps[i].dev_name) @@ -399,17 +381,33 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, pr_debug("register map %s, function %s\n", maps[i].name, maps[i].function); + } - pinmux_maps_num++; + /* + * Make a copy of the map array - string pointers will end up in the + * kernel const section anyway so these do not need to be deep copied. + */ + if (!pinmux_maps_num) { + /* On first call, just copy them */ + tmp_maps = kmemdup(maps, + sizeof(struct pinmux_map) * num_maps, + GFP_KERNEL); + if (!tmp_maps) + return -ENOMEM; + } else { + /* Subsequent calls, reallocate array to new size */ + size_t oldsize = sizeof(struct pinmux_map) * pinmux_maps_num; + size_t newsize = sizeof(struct pinmux_map) * num_maps; + + tmp_maps = krealloc(pinmux_maps, oldsize + newsize, GFP_KERNEL); + if (!tmp_maps) + return -ENOMEM; + memcpy((tmp_maps + oldsize), maps, newsize); } + pinmux_maps = tmp_maps; + pinmux_maps_num += num_maps; return 0; - -err_out_free: - kfree(pinmux_maps); - pinmux_maps = NULL; - pinmux_maps_num = 0; - return ret; } /** |