aboutsummaryrefslogtreecommitdiff
path: root/drivers/pinctrl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinmux.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index f3e4f031fe1c..f6e7d583998c 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -33,7 +34,7 @@ static DEFINE_MUTEX(pinmux_list_mutex);
static LIST_HEAD(pinmux_list);
/* Global pinmux maps, we allow one set only */
-static struct pinmux_map const *pinmux_maps;
+static struct pinmux_map *pinmux_maps;
static unsigned pinmux_maps_num;
/**
@@ -333,7 +334,9 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
/**
* pinmux_register_mappings() - register a set of pinmux mappings
- * @maps: the pinmux mappings table to register
+ * @maps: the pinmux mappings table to register, this should be marked with
+ * __initdata so it can be discarded after boot, this function will
+ * perform a shallow copy for the mapping entries.
* @num_maps: the number of maps in the mapping table
*
* Only call this once during initialization of your machine, the function is
@@ -344,32 +347,48 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
int __init pinmux_register_mappings(struct pinmux_map const *maps,
unsigned num_maps)
{
+ int ret = 0;
int i;
- if (pinmux_maps != NULL) {
+ 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;
+
for (i = 0; i < num_maps; i++) {
- /* Sanity check the mapping */
+ /* Sanity check the mapping while copying it */
if (!maps[i].name) {
pr_err("failed to register map %d: "
"no map name given\n", i);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_out_free;
}
+
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);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_out_free;
}
+
if (!maps[i].function) {
pr_err("failed to register map %s (%d): "
"no function ID given\n", maps[i].name, i);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_out_free;
}
if (!maps[i].dev && !maps[i].dev_name)
@@ -380,12 +399,17 @@ 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 = maps;
- pinmux_maps_num = num_maps;
+ pinmux_maps_num++;
+ }
return 0;
+
+err_out_free:
+ kfree(pinmux_maps);
+ pinmux_maps = NULL;
+ pinmux_maps_num = 0;
+ return ret;
}
/**