Skip to content

Commit 6efcfe1

Browse files
committed
Merge tag 'gpio-fixes-for-v6.14-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski: "The first fix is a backport from my v6.15-rc1 queue that turned out to be needed in v6.14 as well but as the former diverged from my fixes branch I had to adjust the patch a bit. The second one fixes a regression observed in user-space where closing a file descriptor associated with a GPIO device results in a ~10ms delay due to the atomic notifier calling rcu_synchronize() when unregistering. Summary: - don't check the return value of gpio_chip::get_direction() when registering a GPIO chip - use raw notifier for line state events" * tag 'gpio-fixes-for-v6.14-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: cdev: use raw notifier for line state events gpiolib: don't check the retval of get_direction() when registering a chip
2 parents b1144bc + dcb73cb commit 6efcfe1

File tree

3 files changed

+29
-26
lines changed

3 files changed

+29
-26
lines changed

drivers/gpio/gpiolib-cdev.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2729,8 +2729,9 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
27292729
cdev->gdev = gpio_device_get(gdev);
27302730

27312731
cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
2732-
ret = atomic_notifier_chain_register(&gdev->line_state_notifier,
2733-
&cdev->lineinfo_changed_nb);
2732+
scoped_guard(write_lock_irqsave, &gdev->line_state_lock)
2733+
ret = raw_notifier_chain_register(&gdev->line_state_notifier,
2734+
&cdev->lineinfo_changed_nb);
27342735
if (ret)
27352736
goto out_free_bitmap;
27362737

@@ -2754,8 +2755,9 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
27542755
blocking_notifier_chain_unregister(&gdev->device_notifier,
27552756
&cdev->device_unregistered_nb);
27562757
out_unregister_line_notifier:
2757-
atomic_notifier_chain_unregister(&gdev->line_state_notifier,
2758-
&cdev->lineinfo_changed_nb);
2758+
scoped_guard(write_lock_irqsave, &gdev->line_state_lock)
2759+
raw_notifier_chain_unregister(&gdev->line_state_notifier,
2760+
&cdev->lineinfo_changed_nb);
27592761
out_free_bitmap:
27602762
gpio_device_put(gdev);
27612763
bitmap_free(cdev->watched_lines);
@@ -2779,8 +2781,9 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file)
27792781

27802782
blocking_notifier_chain_unregister(&gdev->device_notifier,
27812783
&cdev->device_unregistered_nb);
2782-
atomic_notifier_chain_unregister(&gdev->line_state_notifier,
2783-
&cdev->lineinfo_changed_nb);
2784+
scoped_guard(write_lock_irqsave, &gdev->line_state_lock)
2785+
raw_notifier_chain_unregister(&gdev->line_state_notifier,
2786+
&cdev->lineinfo_changed_nb);
27842787
bitmap_free(cdev->watched_lines);
27852788
gpio_device_put(gdev);
27862789
kfree(cdev);

drivers/gpio/gpiolib.c

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
10251025
}
10261026
}
10271027

1028-
ATOMIC_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
1028+
rwlock_init(&gdev->line_state_lock);
1029+
RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
10291030
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
10301031

10311032
ret = init_srcu_struct(&gdev->srcu);
@@ -1056,24 +1057,19 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
10561057

10571058
desc->gdev = gdev;
10581059

1059-
if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) {
1060-
ret = gc->get_direction(gc, desc_index);
1061-
if (ret < 0)
1062-
/*
1063-
* FIXME: Bail-out here once all GPIO drivers
1064-
* are updated to not return errors in
1065-
* situations that can be considered normal
1066-
* operation.
1067-
*/
1068-
dev_warn(&gdev->dev,
1069-
"%s: get_direction failed: %d\n",
1070-
__func__, ret);
1071-
1072-
assign_bit(FLAG_IS_OUT, &desc->flags, !ret);
1073-
} else {
1060+
/*
1061+
* We would typically want to check the return value of
1062+
* get_direction() here but we must not check the return value
1063+
* and bail-out as pin controllers can have pins configured to
1064+
* alternate functions and return -EINVAL. Also: there's no
1065+
* need to take the SRCU lock here.
1066+
*/
1067+
if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index))
1068+
assign_bit(FLAG_IS_OUT, &desc->flags,
1069+
!gc->get_direction(gc, desc_index));
1070+
else
10741071
assign_bit(FLAG_IS_OUT,
10751072
&desc->flags, !gc->direction_input);
1076-
}
10771073
}
10781074

10791075
ret = of_gpiochip_add(gc);
@@ -4193,8 +4189,9 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);
41934189

41944190
void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action)
41954191
{
4196-
atomic_notifier_call_chain(&desc->gdev->line_state_notifier,
4197-
action, desc);
4192+
guard(read_lock_irqsave)(&desc->gdev->line_state_lock);
4193+
4194+
raw_notifier_call_chain(&desc->gdev->line_state_notifier, action, desc);
41984195
}
41994196

42004197
/**

drivers/gpio/gpiolib.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/gpio/driver.h>
1717
#include <linux/module.h>
1818
#include <linux/notifier.h>
19+
#include <linux/spinlock.h>
1920
#include <linux/srcu.h>
2021
#include <linux/workqueue.h>
2122

@@ -45,6 +46,7 @@
4546
* @list: links gpio_device:s together for traversal
4647
* @line_state_notifier: used to notify subscribers about lines being
4748
* requested, released or reconfigured
49+
* @line_state_lock: RW-spinlock protecting the line state notifier
4850
* @line_state_wq: used to emit line state events from a separate thread in
4951
* process context
5052
* @device_notifier: used to notify character device wait queues about the GPIO
@@ -72,7 +74,8 @@ struct gpio_device {
7274
const char *label;
7375
void *data;
7476
struct list_head list;
75-
struct atomic_notifier_head line_state_notifier;
77+
struct raw_notifier_head line_state_notifier;
78+
rwlock_t line_state_lock;
7679
struct workqueue_struct *line_state_wq;
7780
struct blocking_notifier_head device_notifier;
7881
struct srcu_struct srcu;

0 commit comments

Comments
 (0)