diff options
author | Tony Lindgren <tony@atomide.com> | 2012-01-24 19:28:08 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-01-26 08:13:11 -0500 |
commit | b9130b776ee481acbc27a7e56d98df75680de369 (patch) | |
tree | b7933b4d3e562e806c3dc61544352e46f35820cb /drivers/pinctrl/pinmux.c | |
parent | 9e2551e10b5c7ba550849bd9ed519e498cc30e68 (diff) |
pinctrl: add checks for empty function names
This is needed as otherwise we can get the following when
dealing with buggy data in a pinmux driver for
pinmux_search_function:
Unable to handle kernel NULL pointer dereference at virtual
address 00000000
...
PC is at strcmp+0xc/0x34
LR is at pinmux_get+0x350/0x8f4
...
As we need pctldev initialized to call ops->list_functions,
let's initialize it before check_ops calls and pass the
pctldev to the check_ops functions. Do this for both pinmux
and pinconf check_ops functions.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinmux.c')
-rw-r--r-- | drivers/pinctrl/pinmux.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 3ffa9324ed82..7c3193f7a044 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -889,8 +889,11 @@ void pinmux_disable(struct pinmux *pmx) | |||
889 | } | 889 | } |
890 | EXPORT_SYMBOL_GPL(pinmux_disable); | 890 | EXPORT_SYMBOL_GPL(pinmux_disable); |
891 | 891 | ||
892 | int pinmux_check_ops(const struct pinmux_ops *ops) | 892 | int pinmux_check_ops(struct pinctrl_dev *pctldev) |
893 | { | 893 | { |
894 | const struct pinmux_ops *ops = pctldev->desc->pmxops; | ||
895 | unsigned selector = 0; | ||
896 | |||
894 | /* Check that we implement required operations */ | 897 | /* Check that we implement required operations */ |
895 | if (!ops->list_functions || | 898 | if (!ops->list_functions || |
896 | !ops->get_function_name || | 899 | !ops->get_function_name || |
@@ -899,6 +902,18 @@ int pinmux_check_ops(const struct pinmux_ops *ops) | |||
899 | !ops->disable) | 902 | !ops->disable) |
900 | return -EINVAL; | 903 | return -EINVAL; |
901 | 904 | ||
905 | /* Check that all functions registered have names */ | ||
906 | while (ops->list_functions(pctldev, selector) >= 0) { | ||
907 | const char *fname = ops->get_function_name(pctldev, | ||
908 | selector); | ||
909 | if (!fname) { | ||
910 | pr_err("pinmux ops has no name for function%u\n", | ||
911 | selector); | ||
912 | return -EINVAL; | ||
913 | } | ||
914 | selector++; | ||
915 | } | ||
916 | |||
902 | return 0; | 917 | return 0; |
903 | } | 918 | } |
904 | 919 | ||