forked from Minki/linux
pinctrl: Don't copy function name when requesting a pin
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>
This commit is contained in:
parent
9af1e44fb4
commit
5d2eaf8090
@ -59,8 +59,7 @@ struct pin_desc {
|
|||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
/* These fields only added when supporting pinmux drivers */
|
/* These fields only added when supporting pinmux drivers */
|
||||||
#ifdef CONFIG_PINMUX
|
#ifdef CONFIG_PINMUX
|
||||||
bool mux_requested;
|
const char *mux_function;
|
||||||
char mux_function[16];
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,14 +130,13 @@ static int pin_request(struct pinctrl_dev *pctldev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&desc->lock);
|
spin_lock(&desc->lock);
|
||||||
if (desc->mux_requested) {
|
if (desc->mux_function) {
|
||||||
spin_unlock(&desc->lock);
|
spin_unlock(&desc->lock);
|
||||||
dev_err(&pctldev->dev,
|
dev_err(&pctldev->dev,
|
||||||
"pin already requested\n");
|
"pin already requested\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
desc->mux_requested = true;
|
desc->mux_function = function;
|
||||||
strncpy(desc->mux_function, function, sizeof(desc->mux_function));
|
|
||||||
spin_unlock(&desc->lock);
|
spin_unlock(&desc->lock);
|
||||||
|
|
||||||
/* Let each pin increase references to this module */
|
/* Let each pin increase references to this module */
|
||||||
@ -168,8 +167,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
|
|||||||
out_free_pin:
|
out_free_pin:
|
||||||
if (status) {
|
if (status) {
|
||||||
spin_lock(&desc->lock);
|
spin_lock(&desc->lock);
|
||||||
desc->mux_requested = false;
|
desc->mux_function = NULL;
|
||||||
desc->mux_function[0] = '\0';
|
|
||||||
spin_unlock(&desc->lock);
|
spin_unlock(&desc->lock);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
@ -184,8 +182,9 @@ out:
|
|||||||
* pin_free() - release a single muxed in pin so something else can be muxed
|
* pin_free() - release a single muxed in pin so something else can be muxed
|
||||||
* @pctldev: pin controller device handling this pin
|
* @pctldev: pin controller device handling this pin
|
||||||
* @pin: the pin to free
|
* @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;
|
const struct pinmux_ops *ops = pctldev->desc->pmxops;
|
||||||
struct pin_desc *desc;
|
struct pin_desc *desc;
|
||||||
@ -201,8 +200,9 @@ static void pin_free(struct pinctrl_dev *pctldev, int pin)
|
|||||||
ops->free(pctldev, pin);
|
ops->free(pctldev, pin);
|
||||||
|
|
||||||
spin_lock(&desc->lock);
|
spin_lock(&desc->lock);
|
||||||
desc->mux_requested = false;
|
if (free_func)
|
||||||
desc->mux_function[0] = '\0';
|
kfree(desc->mux_function);
|
||||||
|
desc->mux_function = NULL;
|
||||||
spin_unlock(&desc->lock);
|
spin_unlock(&desc->lock);
|
||||||
module_put(pctldev->owner);
|
module_put(pctldev->owner);
|
||||||
}
|
}
|
||||||
@ -214,6 +214,7 @@ static void pin_free(struct pinctrl_dev *pctldev, int pin)
|
|||||||
int pinmux_request_gpio(unsigned gpio)
|
int pinmux_request_gpio(unsigned gpio)
|
||||||
{
|
{
|
||||||
char gpiostr[16];
|
char gpiostr[16];
|
||||||
|
const char *function;
|
||||||
struct pinctrl_dev *pctldev;
|
struct pinctrl_dev *pctldev;
|
||||||
struct pinctrl_gpio_range *range;
|
struct pinctrl_gpio_range *range;
|
||||||
int ret;
|
int ret;
|
||||||
@ -229,7 +230,15 @@ int pinmux_request_gpio(unsigned gpio)
|
|||||||
/* Conjure some name stating what chip and pin this is taken by */
|
/* Conjure some name stating what chip and pin this is taken by */
|
||||||
snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
|
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);
|
EXPORT_SYMBOL_GPL(pinmux_request_gpio);
|
||||||
|
|
||||||
@ -251,7 +260,7 @@ void pinmux_free_gpio(unsigned gpio)
|
|||||||
/* Convert to the pin controllers number space */
|
/* Convert to the pin controllers number space */
|
||||||
pin = gpio - range->base;
|
pin = gpio - range->base;
|
||||||
|
|
||||||
pin_free(pctldev, pin);
|
pin_free(pctldev, pin, true);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pinmux_free_gpio);
|
EXPORT_SYMBOL_GPL(pinmux_free_gpio);
|
||||||
|
|
||||||
@ -351,7 +360,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
|
|||||||
/* On error release all taken pins */
|
/* On error release all taken pins */
|
||||||
i--; /* this pin just failed */
|
i--; /* this pin just failed */
|
||||||
for (; i >= 0; i--)
|
for (; i >= 0; i--)
|
||||||
pin_free(pctldev, pins[i]);
|
pin_free(pctldev, pins[i], false);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -381,7 +390,7 @@ static void release_pins(struct pinctrl_dev *pctldev,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (i = 0; i < num_pins; i++)
|
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,
|
seq_printf(s, "pin %d (%s): %s\n", pin,
|
||||||
desc->name ? desc->name : "unnamed",
|
desc->name ? desc->name : "unnamed",
|
||||||
desc->mux_requested ? desc->mux_function : "UNCLAIMED");
|
desc->mux_function ? desc->mux_function
|
||||||
|
: "UNCLAIMED");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user