Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 7765ffe

Browse files
author
Bartosz Golaszewski
committed
gpiolib: use a single SRCU struct for all GPIO descriptors
We used a per-descriptor SRCU struct in order to not impose a wait with synchronize_srcu() for descriptor X on read-only operations of descriptor Y. Now that we no longer call synchronize_srcu() on descriptor label change but only when releasing descriptor resources, we can use a single SRCU structure for all GPIO descriptors in a given chip. Suggested-by: "Paul E. McKenney" <paulmck@kernel.org> Acked-by: "Paul E. McKenney" <paulmck@kernel.org> Link: https://lore.kernel.org/r/20240507172414.28513-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
1 parent a86d276 commit 7765ffe

File tree

3 files changed

+25
-28
lines changed

3 files changed

+25
-28
lines changed

drivers/gpio/gpiolib-cdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2351,7 +2351,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
23512351

23522352
dflags = READ_ONCE(desc->flags);
23532353

2354-
scoped_guard(srcu, &desc->srcu) {
2354+
scoped_guard(srcu, &desc->gdev->desc_srcu) {
23552355
label = gpiod_get_label(desc);
23562356
if (label && test_bit(FLAG_REQUESTED, &dflags))
23572357
strscpy(info->consumer, label,

drivers/gpio/gpiolib.c

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ const char *gpiod_get_label(struct gpio_desc *desc)
112112
if (!test_bit(FLAG_REQUESTED, &flags))
113113
return NULL;
114114

115-
label = srcu_dereference_check(desc->label, &desc->srcu,
116-
srcu_read_lock_held(&desc->srcu));
115+
label = srcu_dereference_check(desc->label, &desc->gdev->desc_srcu,
116+
srcu_read_lock_held(&desc->gdev->desc_srcu));
117117

118118
return label->str;
119119
}
@@ -138,7 +138,7 @@ static int desc_set_label(struct gpio_desc *desc, const char *label)
138138

139139
old = rcu_replace_pointer(desc->label, new, 1);
140140
if (old)
141-
call_srcu(&desc->srcu, &old->rh, desc_free_label);
141+
call_srcu(&desc->gdev->desc_srcu, &old->rh, desc_free_label);
142142

143143
return 0;
144144
}
@@ -709,13 +709,10 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
709709
static void gpiodev_release(struct device *dev)
710710
{
711711
struct gpio_device *gdev = to_gpio_device(dev);
712-
unsigned int i;
713712

714-
for (i = 0; i < gdev->ngpio; i++) {
715-
/* Free pending label. */
716-
synchronize_srcu(&gdev->descs[i].srcu);
717-
cleanup_srcu_struct(&gdev->descs[i].srcu);
718-
}
713+
/* Call pending kfree()s for descriptor labels. */
714+
synchronize_srcu(&gdev->desc_srcu);
715+
cleanup_srcu_struct(&gdev->desc_srcu);
719716

720717
ida_free(&gpio_ida, gdev->id);
721718
kfree_const(gdev->label);
@@ -992,30 +989,30 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
992989
if (ret)
993990
goto err_remove_from_list;
994991

992+
ret = init_srcu_struct(&gdev->desc_srcu);
993+
if (ret)
994+
goto err_cleanup_gdev_srcu;
995+
995996
#ifdef CONFIG_PINCTRL
996997
INIT_LIST_HEAD(&gdev->pin_ranges);
997998
#endif
998999

9991000
if (gc->names) {
10001001
ret = gpiochip_set_desc_names(gc);
10011002
if (ret)
1002-
goto err_cleanup_gdev_srcu;
1003+
goto err_cleanup_desc_srcu;
10031004
}
10041005
ret = gpiochip_set_names(gc);
10051006
if (ret)
1006-
goto err_cleanup_gdev_srcu;
1007+
goto err_cleanup_desc_srcu;
10071008

10081009
ret = gpiochip_init_valid_mask(gc);
10091010
if (ret)
1010-
goto err_cleanup_gdev_srcu;
1011+
goto err_cleanup_desc_srcu;
10111012

10121013
for (desc_index = 0; desc_index < gc->ngpio; desc_index++) {
10131014
struct gpio_desc *desc = &gdev->descs[desc_index];
10141015

1015-
ret = init_srcu_struct(&desc->srcu);
1016-
if (ret)
1017-
goto err_cleanup_desc_srcu;
1018-
10191016
if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) {
10201017
assign_bit(FLAG_IS_OUT,
10211018
&desc->flags, !gc->get_direction(gc, desc_index));
@@ -1027,7 +1024,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
10271024

10281025
ret = of_gpiochip_add(gc);
10291026
if (ret)
1030-
goto err_cleanup_desc_srcu;
1027+
goto err_free_valid_mask;
10311028

10321029
ret = gpiochip_add_pin_ranges(gc);
10331030
if (ret)
@@ -1074,10 +1071,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
10741071
gpiochip_remove_pin_ranges(gc);
10751072
err_remove_of_chip:
10761073
of_gpiochip_remove(gc);
1077-
err_cleanup_desc_srcu:
1078-
while (desc_index--)
1079-
cleanup_srcu_struct(&gdev->descs[desc_index].srcu);
1074+
err_free_valid_mask:
10801075
gpiochip_free_valid_mask(gc);
1076+
err_cleanup_desc_srcu:
1077+
cleanup_srcu_struct(&gdev->desc_srcu);
10811078
err_cleanup_gdev_srcu:
10821079
cleanup_srcu_struct(&gdev->srcu);
10831080
err_remove_from_list:
@@ -2407,7 +2404,7 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
24072404
if (!test_bit(FLAG_REQUESTED, &desc->flags))
24082405
return NULL;
24092406

2410-
guard(srcu)(&desc->srcu);
2407+
guard(srcu)(&desc->gdev->desc_srcu);
24112408

24122409
label = kstrdup(gpiod_get_label(desc), GFP_KERNEL);
24132410
if (!label)
@@ -4798,7 +4795,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
47984795
}
47994796

48004797
for_each_gpio_desc(gc, desc) {
4801-
guard(srcu)(&desc->srcu);
4798+
guard(srcu)(&desc->gdev->desc_srcu);
48024799
if (test_bit(FLAG_REQUESTED, &desc->flags)) {
48034800
gpiod_get_direction(desc);
48044801
is_out = test_bit(FLAG_IS_OUT, &desc->flags);

drivers/gpio/gpiolib.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
* @chip: pointer to the corresponding gpiochip, holding static
3232
* data for this device
3333
* @descs: array of ngpio descriptors.
34+
* @desc_srcu: ensures consistent state of GPIO descriptors exposed to users
3435
* @ngpio: the number of GPIO lines on this GPIO device, equal to the size
3536
* of the @descs array.
3637
* @can_sleep: indicate whether the GPIO chip driver's callbacks can sleep
@@ -61,6 +62,7 @@ struct gpio_device {
6162
struct module *owner;
6263
struct gpio_chip __rcu *chip;
6364
struct gpio_desc *descs;
65+
struct srcu_struct desc_srcu;
6466
int base;
6567
u16 ngpio;
6668
bool can_sleep;
@@ -150,7 +152,6 @@ struct gpio_desc_label {
150152
* @label: Name of the consumer
151153
* @name: Line name
152154
* @hog: Pointer to the device node that hogs this line (if any)
153-
* @srcu: SRCU struct protecting the label pointer.
154155
*
155156
* These are obtained using gpiod_get() and are preferable to the old
156157
* integer-based handles.
@@ -188,7 +189,6 @@ struct gpio_desc {
188189
#ifdef CONFIG_OF_DYNAMIC
189190
struct device_node *hog;
190191
#endif
191-
struct srcu_struct srcu;
192192
};
193193

194194
#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
@@ -256,23 +256,23 @@ static inline int gpio_chip_hwgpio(const struct gpio_desc *desc)
256256

257257
#define gpiod_err(desc, fmt, ...) \
258258
do { \
259-
scoped_guard(srcu, &desc->srcu) { \
259+
scoped_guard(srcu, &desc->gdev->desc_srcu) { \
260260
pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), \
261261
gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \
262262
} \
263263
} while (0)
264264

265265
#define gpiod_warn(desc, fmt, ...) \
266266
do { \
267-
scoped_guard(srcu, &desc->srcu) { \
267+
scoped_guard(srcu, &desc->gdev->desc_srcu) { \
268268
pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), \
269269
gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \
270270
} \
271271
} while (0)
272272

273273
#define gpiod_dbg(desc, fmt, ...) \
274274
do { \
275-
scoped_guard(srcu, &desc->srcu) { \
275+
scoped_guard(srcu, &desc->gdev->desc_srcu) { \
276276
pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), \
277277
gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \
278278
} \

0 commit comments

Comments
 (0)