pinctrl: Don't copy function name when requesting a pin
Stephen Warren [Wed, 19 Oct 2011 22:19:28 +0000 (16:19 -0600)]
Instead, store a pointer to the currently assigned function.

This allows us to delete the mux_requested variable from pin_desc; a pin
is requested if its currently assigned function is non-NULL.

When a pin is requested as a GPIO rather than a regular function, the
assigned function name is dynamically constructed. In this case, we have
to kstrdup() the dynamically constructed name, so that mux_function doesn't
pointed at stack data. This requires pin_free to be told whether to free
the mux_function pointer or not.

This removes the hard-coded maximum function name length.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

drivers/pinctrl/core.h
drivers/pinctrl/pinmux.c

index e431aa5..472fa13 100644 (file)
@@ -59,8 +59,7 @@ struct pin_desc {
        spinlock_t lock;
        /* These fields only added when supporting pinmux drivers */
 #ifdef CONFIG_PINMUX
-       bool    mux_requested;
-       char    mux_function[16];
+       const char *mux_function;
 #endif
 };
 
index 90fb00d..a5467f8 100644 (file)
@@ -130,14 +130,13 @@ static int pin_request(struct pinctrl_dev *pctldev,
        }
 
        spin_lock(&desc->lock);
-       if (desc->mux_requested) {
+       if (desc->mux_function) {
                spin_unlock(&desc->lock);
                dev_err(&pctldev->dev,
                        "pin already requested\n");
                goto out;
        }
-       desc->mux_requested = true;
-       strncpy(desc->mux_function, function, sizeof(desc->mux_function));
+       desc->mux_function = function;
        spin_unlock(&desc->lock);
 
        /* Let each pin increase references to this module */
@@ -168,8 +167,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
 out_free_pin:
        if (status) {
                spin_lock(&desc->lock);
-               desc->mux_requested = false;
-               desc->mux_function[0] = '\0';
+               desc->mux_function = NULL;
                spin_unlock(&desc->lock);
        }
 out:
@@ -184,8 +182,9 @@ out:
  * pin_free() - release a single muxed in pin so something else can be muxed
  * @pctldev: pin controller device handling this pin
  * @pin: the pin to free
+ * @free_func: whether to free the pin's assigned function name string
  */
-static void pin_free(struct pinctrl_dev *pctldev, int pin)
+static void pin_free(struct pinctrl_dev *pctldev, int pin, int free_func)
 {
        const struct pinmux_ops *ops = pctldev->desc->pmxops;
        struct pin_desc *desc;
@@ -201,8 +200,9 @@ static void pin_free(struct pinctrl_dev *pctldev, int pin)
                ops->free(pctldev, pin);
 
        spin_lock(&desc->lock);
-       desc->mux_requested = false;
-       desc->mux_function[0] = '\0';
+       if (free_func)
+               kfree(desc->mux_function);
+       desc->mux_function = NULL;
        spin_unlock(&desc->lock);
        module_put(pctldev->owner);
 }
@@ -214,6 +214,7 @@ static void pin_free(struct pinctrl_dev *pctldev, int pin)
 int pinmux_request_gpio(unsigned gpio)
 {
        char gpiostr[16];
+       const char *function;
        struct pinctrl_dev *pctldev;
        struct pinctrl_gpio_range *range;
        int ret;
@@ -229,7 +230,15 @@ int pinmux_request_gpio(unsigned gpio)
        /* Conjure some name stating what chip and pin this is taken by */
        snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
 
-       return pin_request(pctldev, pin, gpiostr, true, range);
+       function = kstrdup(gpiostr, GFP_KERNEL);
+       if (!function)
+               return -EINVAL;
+
+       ret = pin_request(pctldev, pin, function, true, range);
+       if (ret < 0)
+               kfree(function);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(pinmux_request_gpio);
 
@@ -251,7 +260,7 @@ void pinmux_free_gpio(unsigned gpio)
        /* Convert to the pin controllers number space */
        pin = gpio - range->base;
 
-       pin_free(pctldev, pin);
+       pin_free(pctldev, pin, true);
 }
 EXPORT_SYMBOL_GPL(pinmux_free_gpio);
 
@@ -351,7 +360,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
                        /* On error release all taken pins */
                        i--; /* this pin just failed */
                        for (; i >= 0; i--)
-                               pin_free(pctldev, pins[i]);
+                               pin_free(pctldev, pins[i], false);
                        return -ENODEV;
                }
        }
@@ -381,7 +390,7 @@ static void release_pins(struct pinctrl_dev *pctldev,
                return;
        }
        for (i = 0; i < num_pins; i++)
-               pin_free(pctldev, pins[i]);
+               pin_free(pctldev, pins[i], false);
 }
 
 /**
@@ -1013,7 +1022,8 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
 
                seq_printf(s, "pin %d (%s): %s\n", pin,
                           desc->name ? desc->name : "unnamed",
-                          desc->mux_requested ? desc->mux_function : "UNCLAIMED");
+                          desc->mux_function ? desc->mux_function
+                                             : "UNCLAIMED");
        }
 
        return 0;