1414
1515#include <linux/array_size.h>
1616#include <linux/ctype.h>
17+ #include <linux/cleanup.h>
1718#include <linux/debugfs.h>
1819#include <linux/device.h>
1920#include <linux/err.h>
@@ -93,6 +94,7 @@ bool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned int pin)
9394 if (!desc || !ops )
9495 return true;
9596
97+ guard (mutex )(& desc -> mux_lock );
9698 if (ops -> strict && desc -> mux_usecount )
9799 return false;
98100
@@ -127,29 +129,31 @@ static int pin_request(struct pinctrl_dev *pctldev,
127129 dev_dbg (pctldev -> dev , "request pin %d (%s) for %s\n" ,
128130 pin , desc -> name , owner );
129131
130- if ((!gpio_range || ops -> strict ) &&
131- desc -> mux_usecount && strcmp (desc -> mux_owner , owner )) {
132- dev_err (pctldev -> dev ,
133- "pin %s already requested by %s; cannot claim for %s\n" ,
134- desc -> name , desc -> mux_owner , owner );
135- goto out ;
136- }
132+ scoped_guard (mutex , & desc -> mux_lock ) {
133+ if ((!gpio_range || ops -> strict ) &&
134+ desc -> mux_usecount && strcmp (desc -> mux_owner , owner )) {
135+ dev_err (pctldev -> dev ,
136+ "pin %s already requested by %s; cannot claim for %s\n" ,
137+ desc -> name , desc -> mux_owner , owner );
138+ goto out ;
139+ }
137140
138- if ((gpio_range || ops -> strict ) && desc -> gpio_owner ) {
139- dev_err (pctldev -> dev ,
140- "pin %s already requested by %s; cannot claim for %s\n" ,
141- desc -> name , desc -> gpio_owner , owner );
142- goto out ;
143- }
141+ if ((gpio_range || ops -> strict ) && desc -> gpio_owner ) {
142+ dev_err (pctldev -> dev ,
143+ "pin %s already requested by %s; cannot claim for %s\n" ,
144+ desc -> name , desc -> gpio_owner , owner );
145+ goto out ;
146+ }
144147
145- if (gpio_range ) {
146- desc -> gpio_owner = owner ;
147- } else {
148- desc -> mux_usecount ++ ;
149- if (desc -> mux_usecount > 1 )
150- return 0 ;
148+ if (gpio_range ) {
149+ desc -> gpio_owner = owner ;
150+ } else {
151+ desc -> mux_usecount ++ ;
152+ if (desc -> mux_usecount > 1 )
153+ return 0 ;
151154
152- desc -> mux_owner = owner ;
155+ desc -> mux_owner = owner ;
156+ }
153157 }
154158
155159 /* Let each pin increase references to this module */
@@ -178,12 +182,14 @@ static int pin_request(struct pinctrl_dev *pctldev,
178182
179183out_free_pin :
180184 if (status ) {
181- if (gpio_range ) {
182- desc -> gpio_owner = NULL ;
183- } else {
184- desc -> mux_usecount -- ;
185- if (!desc -> mux_usecount )
186- desc -> mux_owner = NULL ;
185+ scoped_guard (mutex , & desc -> mux_lock ) {
186+ if (gpio_range ) {
187+ desc -> gpio_owner = NULL ;
188+ } else {
189+ desc -> mux_usecount -- ;
190+ if (!desc -> mux_usecount )
191+ desc -> mux_owner = NULL ;
192+ }
187193 }
188194 }
189195out :
@@ -219,15 +225,17 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
219225 return NULL ;
220226 }
221227
222- if (!gpio_range ) {
223- /*
224- * A pin should not be freed more times than allocated.
225- */
226- if (WARN_ON (!desc -> mux_usecount ))
227- return NULL ;
228- desc -> mux_usecount -- ;
229- if (desc -> mux_usecount )
230- return NULL ;
228+ scoped_guard (mutex , & desc -> mux_lock ) {
229+ if (!gpio_range ) {
230+ /*
231+ * A pin should not be freed more times than allocated.
232+ */
233+ if (WARN_ON (!desc -> mux_usecount ))
234+ return NULL ;
235+ desc -> mux_usecount -- ;
236+ if (desc -> mux_usecount )
237+ return NULL ;
238+ }
231239 }
232240
233241 /*
@@ -239,13 +247,15 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
239247 else if (ops -> free )
240248 ops -> free (pctldev , pin );
241249
242- if (gpio_range ) {
243- owner = desc -> gpio_owner ;
244- desc -> gpio_owner = NULL ;
245- } else {
246- owner = desc -> mux_owner ;
247- desc -> mux_owner = NULL ;
248- desc -> mux_setting = NULL ;
250+ scoped_guard (mutex , & desc -> mux_lock ) {
251+ if (gpio_range ) {
252+ owner = desc -> gpio_owner ;
253+ desc -> gpio_owner = NULL ;
254+ } else {
255+ owner = desc -> mux_owner ;
256+ desc -> mux_owner = NULL ;
257+ desc -> mux_setting = NULL ;
258+ }
249259 }
250260
251261 module_put (pctldev -> owner );
@@ -458,7 +468,8 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting)
458468 pins [i ]);
459469 continue ;
460470 }
461- desc -> mux_setting = & (setting -> data .mux );
471+ scoped_guard (mutex , & desc -> mux_lock )
472+ desc -> mux_setting = & (setting -> data .mux );
462473 }
463474
464475 ret = ops -> set_mux (pctldev , setting -> data .mux .func ,
@@ -472,8 +483,10 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting)
472483err_set_mux :
473484 for (i = 0 ; i < num_pins ; i ++ ) {
474485 desc = pin_desc_get (pctldev , pins [i ]);
475- if (desc )
476- desc -> mux_setting = NULL ;
486+ if (desc ) {
487+ scoped_guard (mutex , & desc -> mux_lock )
488+ desc -> mux_setting = NULL ;
489+ }
477490 }
478491err_pin_request :
479492 /* On error release all taken pins */
@@ -492,6 +505,7 @@ void pinmux_disable_setting(const struct pinctrl_setting *setting)
492505 unsigned int num_pins = 0 ;
493506 int i ;
494507 struct pin_desc * desc ;
508+ bool is_equal ;
495509
496510 if (pctlops -> get_group_pins )
497511 ret = pctlops -> get_group_pins (pctldev , setting -> data .mux .group ,
@@ -517,7 +531,10 @@ void pinmux_disable_setting(const struct pinctrl_setting *setting)
517531 pins [i ]);
518532 continue ;
519533 }
520- if (desc -> mux_setting == & (setting -> data .mux )) {
534+ scoped_guard (mutex , & desc -> mux_lock )
535+ is_equal = (desc -> mux_setting == & (setting -> data .mux ));
536+
537+ if (is_equal ) {
521538 pin_free (pctldev , pins [i ], NULL );
522539 } else {
523540 const char * gname ;
@@ -608,40 +625,42 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
608625 if (desc == NULL )
609626 continue ;
610627
611- if (desc -> mux_owner &&
612- !strcmp (desc -> mux_owner , pinctrl_dev_get_name (pctldev )))
613- is_hog = true;
614-
615- if (pmxops -> strict ) {
616- if (desc -> mux_owner )
617- seq_printf (s , "pin %d (%s): device %s%s" ,
618- pin , desc -> name , desc -> mux_owner ,
628+ scoped_guard (mutex , & desc -> mux_lock ) {
629+ if (desc -> mux_owner &&
630+ !strcmp (desc -> mux_owner , pinctrl_dev_get_name (pctldev )))
631+ is_hog = true;
632+
633+ if (pmxops -> strict ) {
634+ if (desc -> mux_owner )
635+ seq_printf (s , "pin %d (%s): device %s%s" ,
636+ pin , desc -> name , desc -> mux_owner ,
637+ is_hog ? " (HOG)" : "" );
638+ else if (desc -> gpio_owner )
639+ seq_printf (s , "pin %d (%s): GPIO %s" ,
640+ pin , desc -> name , desc -> gpio_owner );
641+ else
642+ seq_printf (s , "pin %d (%s): UNCLAIMED" ,
643+ pin , desc -> name );
644+ } else {
645+ /* For non-strict controllers */
646+ seq_printf (s , "pin %d (%s): %s %s%s" , pin , desc -> name ,
647+ desc -> mux_owner ? desc -> mux_owner
648+ : "(MUX UNCLAIMED)" ,
649+ desc -> gpio_owner ? desc -> gpio_owner
650+ : "(GPIO UNCLAIMED)" ,
619651 is_hog ? " (HOG)" : "" );
620- else if (desc -> gpio_owner )
621- seq_printf (s , "pin %d (%s): GPIO %s" ,
622- pin , desc -> name , desc -> gpio_owner );
652+ }
653+
654+ /* If mux: print function+group claiming the pin */
655+ if (desc -> mux_setting )
656+ seq_printf (s , " function %s group %s\n" ,
657+ pmxops -> get_function_name (pctldev ,
658+ desc -> mux_setting -> func ),
659+ pctlops -> get_group_name (pctldev ,
660+ desc -> mux_setting -> group ));
623661 else
624- seq_printf (s , "pin %d (%s): UNCLAIMED" ,
625- pin , desc -> name );
626- } else {
627- /* For non-strict controllers */
628- seq_printf (s , "pin %d (%s): %s %s%s" , pin , desc -> name ,
629- desc -> mux_owner ? desc -> mux_owner
630- : "(MUX UNCLAIMED)" ,
631- desc -> gpio_owner ? desc -> gpio_owner
632- : "(GPIO UNCLAIMED)" ,
633- is_hog ? " (HOG)" : "" );
662+ seq_putc (s , '\n' );
634663 }
635-
636- /* If mux: print function+group claiming the pin */
637- if (desc -> mux_setting )
638- seq_printf (s , " function %s group %s\n" ,
639- pmxops -> get_function_name (pctldev ,
640- desc -> mux_setting -> func ),
641- pctlops -> get_group_name (pctldev ,
642- desc -> mux_setting -> group ));
643- else
644- seq_putc (s , '\n' );
645664 }
646665
647666 mutex_unlock (& pctldev -> mutex );
0 commit comments