]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
pinctrl: Allow modules to use pinctrl_[un]register_mappings
authorHans de Goede <hdegoede@redhat.com>
Mon, 16 Dec 2019 20:51:18 +0000 (21:51 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 30 Dec 2019 13:27:17 +0000 (14:27 +0100)
Currently only the drivers/pinctrl/devicetree.c code allows registering
pinctrl-mappings which may later be unregistered, all other mappings
are assumed to be permanent.

Non-dt platforms may also want to register pinctrl mappings from code which
is build as a module, which requires being able to unregister the mapping
when the module is unloaded to avoid dangling pointers.

To allow unregistering the mappings the devicetree code uses 2 internal
functions: pinctrl_register_map and pinctrl_unregister_map.

pinctrl_register_map allows the devicetree code to tell the core to
not memdup the mappings as it retains ownership of them and
pinctrl_unregister_map does the unregistering, note this only works
when the mappings where not memdupped.

The only code relying on the memdup/shallow-copy done by
pinctrl_register_mappings is arch/arm/mach-u300/core.c this commit
replaces the __initdata with const, so that the shallow-copy is no
longer necessary.

After that we can get rid of the internal pinctrl_unregister_map function
and just use pinctrl_register_mappings directly everywhere.

This commit also renames pinctrl_unregister_map to
pinctrl_unregister_mappings so that its naming matches its
pinctrl_register_mappings counter-part and exports it.

Together these 2 changes will allow non-dt platform code to
register pinctrl-mappings from modules without breaking things on
module unload (as they can now unregister the mapping on unload).

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20191216205122.1850923-2-hdegoede@redhat.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
arch/arm/mach-u300/core.c
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/devicetree.c
include/linux/pinctrl/machine.h

index a79fa3b0c8eda50f0ac42cf190f42cf6d4127606..a1694d977ec94cf3c33ac61ad573a375cd873128 100644 (file)
@@ -201,7 +201,7 @@ static unsigned long pin_highz_conf[] = {
 };
 
 /* Pin control settings */
-static struct pinctrl_map __initdata u300_pinmux_map[] = {
+static const struct pinctrl_map u300_pinmux_map[] = {
        /* anonymous maps for chip power and EMIFs */
        PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "power"),
        PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif0"),
index 2bbd8ee935075b7a419851bad3767efb4475d05d..b0eea728455de0d5e974d6c6369a07d202cb5988 100644 (file)
@@ -1376,8 +1376,15 @@ void devm_pinctrl_put(struct pinctrl *p)
 }
 EXPORT_SYMBOL_GPL(devm_pinctrl_put);
 
-int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps,
-                        bool dup)
+/**
+ * pinctrl_register_mappings() - register a set of pin controller mappings
+ * @maps: the pincontrol mappings table to register. Note the pinctrl-core
+ *     keeps a reference to the passed in maps, so they should _not_ be
+ *     marked with __initdata.
+ * @num_maps: the number of maps in the mapping table
+ */
+int pinctrl_register_mappings(const struct pinctrl_map *maps,
+                             unsigned num_maps)
 {
        int i, ret;
        struct pinctrl_maps *maps_node;
@@ -1430,17 +1437,8 @@ int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps,
        if (!maps_node)
                return -ENOMEM;
 
+       maps_node->maps = maps;
        maps_node->num_maps = num_maps;
-       if (dup) {
-               maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
-                                         GFP_KERNEL);
-               if (!maps_node->maps) {
-                       kfree(maps_node);
-                       return -ENOMEM;
-               }
-       } else {
-               maps_node->maps = maps;
-       }
 
        mutex_lock(&pinctrl_maps_mutex);
        list_add_tail(&maps_node->node, &pinctrl_maps);
@@ -1448,22 +1446,14 @@ int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(pinctrl_register_mappings);
 
 /**
- * pinctrl_register_mappings() - register a set of pin controller mappings
- * @maps: the pincontrol mappings table to register. This should probably 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
+ * pinctrl_unregister_mappings() - unregister a set of pin controller mappings
+ * @maps: the pincontrol mappings table passed to pinctrl_register_mappings()
+ *     when registering the mappings.
  */
-int pinctrl_register_mappings(const struct pinctrl_map *maps,
-                             unsigned num_maps)
-{
-       return pinctrl_register_map(maps, num_maps, true);
-}
-EXPORT_SYMBOL_GPL(pinctrl_register_mappings);
-
-void pinctrl_unregister_map(const struct pinctrl_map *map)
+void pinctrl_unregister_mappings(const struct pinctrl_map *map)
 {
        struct pinctrl_maps *maps_node;
 
@@ -1478,6 +1468,7 @@ void pinctrl_unregister_map(const struct pinctrl_map *map)
        }
        mutex_unlock(&pinctrl_maps_mutex);
 }
+EXPORT_SYMBOL_GPL(pinctrl_unregister_mappings);
 
 /**
  * pinctrl_force_sleep() - turn a given controller device into sleep state
index 7f34167a0405f6f79b913ef9bcfaff98c2383f5a..840103c40c14ad6a6b5965c9d4ec516ef97707f9 100644 (file)
@@ -236,10 +236,6 @@ extern struct pinctrl_gpio_range *
 pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev,
                                        unsigned int pin);
 
-int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps,
-                        bool dup);
-void pinctrl_unregister_map(const struct pinctrl_map *map);
-
 extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev);
 extern int pinctrl_force_default(struct pinctrl_dev *pctldev);
 
index 674920daac26994ea64db186e14736315bc75501..9357f7c46cf3ee0d8567eb757d6f528b846e2fbe 100644 (file)
@@ -51,7 +51,7 @@ void pinctrl_dt_free_maps(struct pinctrl *p)
        struct pinctrl_dt_map *dt_map, *n1;
 
        list_for_each_entry_safe(dt_map, n1, &p->dt_maps, node) {
-               pinctrl_unregister_map(dt_map->map);
+               pinctrl_unregister_mappings(dt_map->map);
                list_del(&dt_map->node);
                dt_free_map(dt_map->pctldev, dt_map->map,
                            dt_map->num_maps);
@@ -92,7 +92,7 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
        dt_map->num_maps = num_maps;
        list_add_tail(&dt_map->node, &p->dt_maps);
 
-       return pinctrl_register_map(map, num_maps, false);
+       return pinctrl_register_mappings(map, num_maps);
 
 err_free_map:
        dt_free_map(pctldev, map, num_maps);
index ddd1b2773431b869636bcbe0b8c289b2a51a29e3..e987dc9fd2afb78fce6b833e0b358d37dbd61288 100644 (file)
@@ -153,6 +153,7 @@ struct pinctrl_map {
 
 extern int pinctrl_register_mappings(const struct pinctrl_map *map,
                                unsigned num_maps);
+extern void pinctrl_unregister_mappings(const struct pinctrl_map *map);
 extern void pinctrl_provide_dummies(void);
 #else
 
@@ -162,6 +163,10 @@ static inline int pinctrl_register_mappings(const struct pinctrl_map *map,
        return 0;
 }
 
+static inline void pinctrl_unregister_mappings(const struct pinctrl_map *map)
+{
+}
+
 static inline void pinctrl_provide_dummies(void)
 {
 }