aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinconf.c
diff options
context:
space:
mode:
authorPatrice Chotard <patrice.chotard@st.com>2013-04-11 05:01:27 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-04-26 11:01:35 -0400
commit42fed7ba44e4e8c1fb27b28ad14490cb1daff3c7 (patch)
tree3caafd69ed9807e9a15f14d6c482fa1f1a697a8b /drivers/pinctrl/pinconf.c
parentcb6d315dc36ce56bc017051befa9ac9391300eb9 (diff)
pinctrl: move subsystem mutex to pinctrl_dev struct
This mutex avoids deadlock in case of use of multiple pin controllers. Before this modification, by using a global mutex, deadlock appeared when, for example, a call to pinctrl_pins_show() locked the pinctrl_mutex, called the ops->pin_dbg_show of a particular pin controller. If this pin controller needs I2C access to retrieve configuration information and I2C driver is using pinctrl to drive its pins, a call to pinctrl_select_state() try to lock again pinctrl_mutex which leads to a deadlock. Notice that the mutex grab from the two direction functions was moved into pinctrl_gpio_direction(). For several cases, we can't replace pinctrl_mutex by pctldev->mutex, because at this stage, pctldev is not accessible : - pinctrl_get()/pinctrl_put() - pinctrl_register_maps() So add respectively pinctrl_list_mutex and pinctrl_maps_mutex in order to protect pinctrl_list and pinctrl_maps list instead. Reintroduce pinctrldev_list_mutex in find_pinctrl_by_of_node(), pinctrl_find_and_add_gpio_range() pinctrl_request_gpio(), pinctrl_free_gpio(), pinctrl_gpio_direction(), pinctrl_devices_show(), pinctrl_register() and pinctrl_unregister() to protect pinctrldev_list. Changes v2->v3: - Fix a missing EXPORT_SYMBOL_GPL() for pinctrl_select_state(). Changes v1->v2: - pinctrl_select_state_locked() is removed, all lock mechanism is located inside pinctrl_select_state(). When parsing the state->setting list, take the per-pin-controller driver lock. (Patrice). - Introduce pinctrldev_list_mutex to protect pinctrldev_list in all functions which parse or modify pictrldev_list. (Patrice). - move find_pinctrl_by_of_node() from pinctrl/devicetree.c to pinctrl/core.c in order to protect pinctrldev_list. (Patrice). - Sink mutex:es into some functions and remove some _locked variants down to where the lists are actually accessed to make things simpler. (Linus) - Drop *all* mutexes completely from pinctrl_lookup_state() and pinctrl_select_state() - no relevant mutex was taken and it was unclear what this was protecting against. (Linus) Reported by : Seraphin Bonnaffe <seraphin.bonnaffe@stericsson.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinconf.c')
-rw-r--r--drivers/pinctrl/pinconf.c46
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index 32f96808202a..c67c37e23dd7 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -89,14 +89,14 @@ int pin_config_get(const char *dev_name, const char *name,
89 struct pinctrl_dev *pctldev; 89 struct pinctrl_dev *pctldev;
90 int pin; 90 int pin;
91 91
92 mutex_lock(&pinctrl_mutex);
93
94 pctldev = get_pinctrl_dev_from_devname(dev_name); 92 pctldev = get_pinctrl_dev_from_devname(dev_name);
95 if (!pctldev) { 93 if (!pctldev) {
96 pin = -EINVAL; 94 pin = -EINVAL;
97 goto unlock; 95 return pin;
98 } 96 }
99 97
98 mutex_lock(&pctldev->mutex);
99
100 pin = pin_get_from_name(pctldev, name); 100 pin = pin_get_from_name(pctldev, name);
101 if (pin < 0) 101 if (pin < 0)
102 goto unlock; 102 goto unlock;
@@ -104,7 +104,7 @@ int pin_config_get(const char *dev_name, const char *name,
104 pin = pin_config_get_for_pin(pctldev, pin, config); 104 pin = pin_config_get_for_pin(pctldev, pin, config);
105 105
106unlock: 106unlock:
107 mutex_unlock(&pinctrl_mutex); 107 mutex_unlock(&pctldev->mutex);
108 return pin; 108 return pin;
109} 109}
110EXPORT_SYMBOL(pin_config_get); 110EXPORT_SYMBOL(pin_config_get);
@@ -145,14 +145,14 @@ int pin_config_set(const char *dev_name, const char *name,
145 struct pinctrl_dev *pctldev; 145 struct pinctrl_dev *pctldev;
146 int pin, ret; 146 int pin, ret;
147 147
148 mutex_lock(&pinctrl_mutex);
149
150 pctldev = get_pinctrl_dev_from_devname(dev_name); 148 pctldev = get_pinctrl_dev_from_devname(dev_name);
151 if (!pctldev) { 149 if (!pctldev) {
152 ret = -EINVAL; 150 ret = -EINVAL;
153 goto unlock; 151 return ret;
154 } 152 }
155 153
154 mutex_lock(&pctldev->mutex);
155
156 pin = pin_get_from_name(pctldev, name); 156 pin = pin_get_from_name(pctldev, name);
157 if (pin < 0) { 157 if (pin < 0) {
158 ret = pin; 158 ret = pin;
@@ -162,7 +162,7 @@ int pin_config_set(const char *dev_name, const char *name,
162 ret = pin_config_set_for_pin(pctldev, pin, config); 162 ret = pin_config_set_for_pin(pctldev, pin, config);
163 163
164unlock: 164unlock:
165 mutex_unlock(&pinctrl_mutex); 165 mutex_unlock(&pctldev->mutex);
166 return ret; 166 return ret;
167} 167}
168EXPORT_SYMBOL(pin_config_set); 168EXPORT_SYMBOL(pin_config_set);
@@ -174,13 +174,14 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
174 const struct pinconf_ops *ops; 174 const struct pinconf_ops *ops;
175 int selector, ret; 175 int selector, ret;
176 176
177 mutex_lock(&pinctrl_mutex);
178
179 pctldev = get_pinctrl_dev_from_devname(dev_name); 177 pctldev = get_pinctrl_dev_from_devname(dev_name);
180 if (!pctldev) { 178 if (!pctldev) {
181 ret = -EINVAL; 179 ret = -EINVAL;
182 goto unlock; 180 return ret;
183 } 181 }
182
183 mutex_lock(&pctldev->mutex);
184
184 ops = pctldev->desc->confops; 185 ops = pctldev->desc->confops;
185 186
186 if (!ops || !ops->pin_config_group_get) { 187 if (!ops || !ops->pin_config_group_get) {
@@ -200,7 +201,7 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
200 ret = ops->pin_config_group_get(pctldev, selector, config); 201 ret = ops->pin_config_group_get(pctldev, selector, config);
201 202
202unlock: 203unlock:
203 mutex_unlock(&pinctrl_mutex); 204 mutex_unlock(&pctldev->mutex);
204 return ret; 205 return ret;
205} 206}
206EXPORT_SYMBOL(pin_config_group_get); 207EXPORT_SYMBOL(pin_config_group_get);
@@ -217,13 +218,14 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
217 int ret; 218 int ret;
218 int i; 219 int i;
219 220
220 mutex_lock(&pinctrl_mutex);
221
222 pctldev = get_pinctrl_dev_from_devname(dev_name); 221 pctldev = get_pinctrl_dev_from_devname(dev_name);
223 if (!pctldev) { 222 if (!pctldev) {
224 ret = -EINVAL; 223 ret = -EINVAL;
225 goto unlock; 224 return ret;
226 } 225 }
226
227 mutex_lock(&pctldev->mutex);
228
227 ops = pctldev->desc->confops; 229 ops = pctldev->desc->confops;
228 pctlops = pctldev->desc->pctlops; 230 pctlops = pctldev->desc->pctlops;
229 231
@@ -279,7 +281,7 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
279 ret = 0; 281 ret = 0;
280 282
281unlock: 283unlock:
282 mutex_unlock(&pinctrl_mutex); 284 mutex_unlock(&pctldev->mutex);
283 285
284 return ret; 286 return ret;
285} 287}
@@ -487,7 +489,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
487 seq_puts(s, "Pin config settings per pin\n"); 489 seq_puts(s, "Pin config settings per pin\n");
488 seq_puts(s, "Format: pin (name): configs\n"); 490 seq_puts(s, "Format: pin (name): configs\n");
489 491
490 mutex_lock(&pinctrl_mutex); 492 mutex_lock(&pctldev->mutex);
491 493
492 /* The pin number can be retrived from the pin controller descriptor */ 494 /* The pin number can be retrived from the pin controller descriptor */
493 for (i = 0; i < pctldev->desc->npins; i++) { 495 for (i = 0; i < pctldev->desc->npins; i++) {
@@ -507,7 +509,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
507 seq_printf(s, "\n"); 509 seq_printf(s, "\n");
508 } 510 }
509 511
510 mutex_unlock(&pinctrl_mutex); 512 mutex_unlock(&pctldev->mutex);
511 513
512 return 0; 514 return 0;
513} 515}
@@ -608,7 +610,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
608 bool found = false; 610 bool found = false;
609 unsigned long config; 611 unsigned long config;
610 612
611 mutex_lock(&pinctrl_mutex); 613 mutex_lock(&pctldev->mutex);
612 614
613 /* Parse the pinctrl map and look for the elected pin/state */ 615 /* Parse the pinctrl map and look for the elected pin/state */
614 for_each_maps(maps_node, i, map) { 616 for_each_maps(maps_node, i, map) {
@@ -657,7 +659,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
657 confops->pin_config_config_dbg_show(pctldev, s, config); 659 confops->pin_config_config_dbg_show(pctldev, s, config);
658 660
659exit: 661exit:
660 mutex_unlock(&pinctrl_mutex); 662 mutex_unlock(&pctldev->mutex);
661 663
662 return 0; 664 return 0;
663} 665}
@@ -747,7 +749,7 @@ static int pinconf_dbg_config_write(struct file *file,
747 return -EINVAL; 749 return -EINVAL;
748 strncpy(config, token, MAX_NAME_LEN); 750 strncpy(config, token, MAX_NAME_LEN);
749 751
750 mutex_lock(&pinctrl_mutex); 752 mutex_lock(&pinctrl_maps_mutex);
751 753
752 /* Parse the pinctrl map and look for the selected dev/state/pin */ 754 /* Parse the pinctrl map and look for the selected dev/state/pin */
753 for_each_maps(maps_node, i, map) { 755 for_each_maps(maps_node, i, map) {
@@ -785,7 +787,7 @@ static int pinconf_dbg_config_write(struct file *file,
785 } 787 }
786 788
787exit: 789exit:
788 mutex_unlock(&pinctrl_mutex); 790 mutex_unlock(&pinctrl_maps_mutex);
789 791
790 return count; 792 return count;
791} 793}