diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2011-11-29 06:52:39 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-01-03 03:10:02 -0500 |
commit | 97607d157c133ab18dfcd77fa836e37fa950a44a (patch) | |
tree | f9ac62a9534295f24ab40a2890bfd285bc157a03 /drivers/pinctrl | |
parent | 542e704f3ffee1dc4539c9e8191e4dc215220f5e (diff) |
pinctrl: make a copy of pinmux map
This makes a deep copy of the pinmux function map instead of
keeping the copy supplied from the platform around. This makes
it possible to tag the platforms map with __initdata as is also
done as part of this patch.
Rationale: a certain target platform (PXA) has numerous
pinmux maps, many of which will be lying around unused after
boot in a multi-platform binary. Instead, deep-copy the one
we're going to use and tag them all __initdata so they go away
after boot.
ChangeLog v1->v2:
- Fixup the deep copy, missed a few items on the struct,
plus mark bool member non-const since we're making runtime
copies if this stuff now.
ChangeLog v2->v3:
- Make a shallow copy (just copy the array of map structs)
as Arnd noticed, string constants never get discarded by the
kernel anyway, so these pointers may be safely copied over.
Reviewed-by: Arnd Bergmann <arnd.bergmann@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/pinmux.c | 44 |
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 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/string.h> | ||
24 | #include <linux/sysfs.h> | 25 | #include <linux/sysfs.h> |
25 | #include <linux/debugfs.h> | 26 | #include <linux/debugfs.h> |
26 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
@@ -33,7 +34,7 @@ static DEFINE_MUTEX(pinmux_list_mutex); | |||
33 | static LIST_HEAD(pinmux_list); | 34 | static LIST_HEAD(pinmux_list); |
34 | 35 | ||
35 | /* Global pinmux maps, we allow one set only */ | 36 | /* Global pinmux maps, we allow one set only */ |
36 | static struct pinmux_map const *pinmux_maps; | 37 | static struct pinmux_map *pinmux_maps; |
37 | static unsigned pinmux_maps_num; | 38 | static unsigned pinmux_maps_num; |
38 | 39 | ||
39 | /** | 40 | /** |
@@ -333,7 +334,9 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); | |||
333 | 334 | ||
334 | /** | 335 | /** |
335 | * pinmux_register_mappings() - register a set of pinmux mappings | 336 | * pinmux_register_mappings() - register a set of pinmux mappings |
336 | * @maps: the pinmux mappings table to register | 337 | * @maps: the pinmux mappings table to register, this should be marked with |
338 | * __initdata so it can be discarded after boot, this function will | ||
339 | * perform a shallow copy for the mapping entries. | ||
337 | * @num_maps: the number of maps in the mapping table | 340 | * @num_maps: the number of maps in the mapping table |
338 | * | 341 | * |
339 | * Only call this once during initialization of your machine, the function is | 342 | * Only call this once during initialization of your machine, the function is |
@@ -344,32 +347,48 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); | |||
344 | int __init pinmux_register_mappings(struct pinmux_map const *maps, | 347 | int __init pinmux_register_mappings(struct pinmux_map const *maps, |
345 | unsigned num_maps) | 348 | unsigned num_maps) |
346 | { | 349 | { |
350 | int ret = 0; | ||
347 | int i; | 351 | int i; |
348 | 352 | ||
349 | if (pinmux_maps != NULL) { | 353 | if (pinmux_maps_num != 0) { |
350 | pr_err("pinmux mappings already registered, you can only " | 354 | pr_err("pinmux mappings already registered, you can only " |
351 | "register one set of maps\n"); | 355 | "register one set of maps\n"); |
352 | return -EINVAL; | 356 | return -EINVAL; |
353 | } | 357 | } |
354 | 358 | ||
355 | pr_debug("add %d pinmux maps\n", num_maps); | 359 | pr_debug("add %d pinmux maps\n", num_maps); |
360 | |||
361 | /* | ||
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 | |||
356 | for (i = 0; i < num_maps; i++) { | 370 | for (i = 0; i < num_maps; i++) { |
357 | /* Sanity check the mapping */ | 371 | /* Sanity check the mapping while copying it */ |
358 | if (!maps[i].name) { | 372 | if (!maps[i].name) { |
359 | pr_err("failed to register map %d: " | 373 | pr_err("failed to register map %d: " |
360 | "no map name given\n", i); | 374 | "no map name given\n", i); |
361 | return -EINVAL; | 375 | ret = -EINVAL; |
376 | goto err_out_free; | ||
362 | } | 377 | } |
378 | |||
363 | if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { | 379 | if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { |
364 | pr_err("failed to register map %s (%d): " | 380 | pr_err("failed to register map %s (%d): " |
365 | "no pin control device given\n", | 381 | "no pin control device given\n", |
366 | maps[i].name, i); | 382 | maps[i].name, i); |
367 | return -EINVAL; | 383 | ret = -EINVAL; |
384 | goto err_out_free; | ||
368 | } | 385 | } |
386 | |||
369 | if (!maps[i].function) { | 387 | if (!maps[i].function) { |
370 | pr_err("failed to register map %s (%d): " | 388 | pr_err("failed to register map %s (%d): " |
371 | "no function ID given\n", maps[i].name, i); | 389 | "no function ID given\n", maps[i].name, i); |
372 | return -EINVAL; | 390 | ret = -EINVAL; |
391 | goto err_out_free; | ||
373 | } | 392 | } |
374 | 393 | ||
375 | if (!maps[i].dev && !maps[i].dev_name) | 394 | if (!maps[i].dev && !maps[i].dev_name) |
@@ -380,12 +399,17 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, | |||
380 | pr_debug("register map %s, function %s\n", | 399 | pr_debug("register map %s, function %s\n", |
381 | maps[i].name, | 400 | maps[i].name, |
382 | maps[i].function); | 401 | maps[i].function); |
383 | } | ||
384 | 402 | ||
385 | pinmux_maps = maps; | 403 | pinmux_maps_num++; |
386 | pinmux_maps_num = num_maps; | 404 | } |
387 | 405 | ||
388 | return 0; | 406 | return 0; |
407 | |||
408 | err_out_free: | ||
409 | kfree(pinmux_maps); | ||
410 | pinmux_maps = NULL; | ||
411 | pinmux_maps_num = 0; | ||
412 | return ret; | ||
389 | } | 413 | } |
390 | 414 | ||
391 | /** | 415 | /** |