aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-01-24 19:28:08 -0500
committerLinus Walleij <linus.walleij@linaro.org>2012-01-26 08:13:11 -0500
commitb9130b776ee481acbc27a7e56d98df75680de369 (patch)
treeb7933b4d3e562e806c3dc61544352e46f35820cb
parent9e2551e10b5c7ba550849bd9ed519e498cc30e68 (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>
-rw-r--r--drivers/pinctrl/core.c36
-rw-r--r--drivers/pinctrl/pinconf.c4
-rw-r--r--drivers/pinctrl/pinconf.h4
-rw-r--r--drivers/pinctrl/pinmux.c17
-rw-r--r--drivers/pinctrl/pinmux.h4
5 files changed, 41 insertions, 24 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index d9d35fcbfc6b..8fe15cf15ac8 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -583,40 +583,40 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
583 if (pctldesc->name == NULL) 583 if (pctldesc->name == NULL)
584 return NULL; 584 return NULL;
585 585
586 pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
587 if (pctldev == NULL)
588 return NULL;
589
590 /* Initialize pin control device struct */
591 pctldev->owner = pctldesc->owner;
592 pctldev->desc = pctldesc;
593 pctldev->driver_data = driver_data;
594 INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
595 spin_lock_init(&pctldev->pin_desc_tree_lock);
596 INIT_LIST_HEAD(&pctldev->gpio_ranges);
597 mutex_init(&pctldev->gpio_ranges_lock);
598 pctldev->dev = dev;
599
586 /* If we're implementing pinmuxing, check the ops for sanity */ 600 /* If we're implementing pinmuxing, check the ops for sanity */
587 if (pctldesc->pmxops) { 601 if (pctldesc->pmxops) {
588 ret = pinmux_check_ops(pctldesc->pmxops); 602 ret = pinmux_check_ops(pctldev);
589 if (ret) { 603 if (ret) {
590 pr_err("%s pinmux ops lacks necessary functions\n", 604 pr_err("%s pinmux ops lacks necessary functions\n",
591 pctldesc->name); 605 pctldesc->name);
592 return NULL; 606 goto out_err;
593 } 607 }
594 } 608 }
595 609
596 /* If we're implementing pinconfig, check the ops for sanity */ 610 /* If we're implementing pinconfig, check the ops for sanity */
597 if (pctldesc->confops) { 611 if (pctldesc->confops) {
598 ret = pinconf_check_ops(pctldesc->confops); 612 ret = pinconf_check_ops(pctldev);
599 if (ret) { 613 if (ret) {
600 pr_err("%s pin config ops lacks necessary functions\n", 614 pr_err("%s pin config ops lacks necessary functions\n",
601 pctldesc->name); 615 pctldesc->name);
602 return NULL; 616 goto out_err;
603 } 617 }
604 } 618 }
605 619
606 pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
607 if (pctldev == NULL)
608 return NULL;
609
610 /* Initialize pin control device struct */
611 pctldev->owner = pctldesc->owner;
612 pctldev->desc = pctldesc;
613 pctldev->driver_data = driver_data;
614 INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
615 spin_lock_init(&pctldev->pin_desc_tree_lock);
616 INIT_LIST_HEAD(&pctldev->gpio_ranges);
617 mutex_init(&pctldev->gpio_ranges_lock);
618 pctldev->dev = dev;
619
620 /* Register all the pins */ 620 /* Register all the pins */
621 pr_debug("try to register %d pins on %s...\n", 621 pr_debug("try to register %d pins on %s...\n",
622 pctldesc->npins, pctldesc->name); 622 pctldesc->npins, pctldesc->name);
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index 1892a3794b99..9fb75456824c 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -205,8 +205,10 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
205} 205}
206EXPORT_SYMBOL(pin_config_group_set); 206EXPORT_SYMBOL(pin_config_group_set);
207 207
208int pinconf_check_ops(const struct pinconf_ops *ops) 208int pinconf_check_ops(struct pinctrl_dev *pctldev)
209{ 209{
210 const struct pinconf_ops *ops = pctldev->desc->confops;
211
210 /* We must be able to read out pin status */ 212 /* We must be able to read out pin status */
211 if (!ops->pin_config_get && !ops->pin_config_group_get) 213 if (!ops->pin_config_get && !ops->pin_config_group_get)
212 return -EINVAL; 214 return -EINVAL;
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index e7dc6165032a..006b77fa737e 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -13,7 +13,7 @@
13 13
14#ifdef CONFIG_PINCONF 14#ifdef CONFIG_PINCONF
15 15
16int pinconf_check_ops(const struct pinconf_ops *ops); 16int pinconf_check_ops(struct pinctrl_dev *pctldev);
17void pinconf_init_device_debugfs(struct dentry *devroot, 17void pinconf_init_device_debugfs(struct dentry *devroot,
18 struct pinctrl_dev *pctldev); 18 struct pinctrl_dev *pctldev);
19int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, 19int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
@@ -23,7 +23,7 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
23 23
24#else 24#else
25 25
26static inline int pinconf_check_ops(const struct pinconf_ops *ops) 26static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
27{ 27{
28 return 0; 28 return 0;
29} 29}
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}
890EXPORT_SYMBOL_GPL(pinmux_disable); 890EXPORT_SYMBOL_GPL(pinmux_disable);
891 891
892int pinmux_check_ops(const struct pinmux_ops *ops) 892int 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
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h
index 844500b3331b..97f52223fbc2 100644
--- a/drivers/pinctrl/pinmux.h
+++ b/drivers/pinctrl/pinmux.h
@@ -12,7 +12,7 @@
12 */ 12 */
13#ifdef CONFIG_PINMUX 13#ifdef CONFIG_PINMUX
14 14
15int pinmux_check_ops(const struct pinmux_ops *ops); 15int pinmux_check_ops(struct pinctrl_dev *pctldev);
16void pinmux_init_device_debugfs(struct dentry *devroot, 16void pinmux_init_device_debugfs(struct dentry *devroot,
17 struct pinctrl_dev *pctldev); 17 struct pinctrl_dev *pctldev);
18void pinmux_init_debugfs(struct dentry *subsys_root); 18void pinmux_init_debugfs(struct dentry *subsys_root);
@@ -21,7 +21,7 @@ void pinmux_unhog_maps(struct pinctrl_dev *pctldev);
21 21
22#else 22#else
23 23
24static inline int pinmux_check_ops(const struct pinmux_ops *ops) 24static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
25{ 25{
26 return 0; 26 return 0;
27} 27}