summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/pinmux.c60
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;
}
/**
OpenPOWER on IntegriCloud