Skip to content

Commit d2e2586

Browse files
author
Bartosz Golaszewski
committed
gpio: cdev: wake up chardev poll() on device unbind
Add a notifier block to the gpio_chardev_data structure and register it with the gpio_device's device notifier. Upon reception of an event, wake up the wait queue so that the user-space be forced out of poll() and need to go into a new system call which will then fail due to the chip being gone. Signed-off-by: Bartosz Golaszewski <[email protected]> Reviewed-by: Linus Walleij <[email protected]> Reviewed-by: Kent Gibson <[email protected]>
1 parent a067419 commit d2e2586

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

drivers/gpio/gpiolib-cdev.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,6 +2320,7 @@ struct gpio_chardev_data {
23202320
wait_queue_head_t wait;
23212321
DECLARE_KFIFO(events, struct gpio_v2_line_info_changed, 32);
23222322
struct notifier_block lineinfo_changed_nb;
2323+
struct notifier_block device_unregistered_nb;
23232324
unsigned long *watched_lines;
23242325
#ifdef CONFIG_GPIO_CDEV_V1
23252326
atomic_t watch_abi_version;
@@ -2517,6 +2518,18 @@ static int lineinfo_changed_notify(struct notifier_block *nb,
25172518
return NOTIFY_OK;
25182519
}
25192520

2521+
static int gpio_device_unregistered_notify(struct notifier_block *nb,
2522+
unsigned long action, void *data)
2523+
{
2524+
struct gpio_chardev_data *cdev = container_of(nb,
2525+
struct gpio_chardev_data,
2526+
device_unregistered_nb);
2527+
2528+
wake_up_poll(&cdev->wait, EPOLLIN | EPOLLERR);
2529+
2530+
return NOTIFY_OK;
2531+
}
2532+
25202533
static __poll_t lineinfo_watch_poll_unlocked(struct file *file,
25212534
struct poll_table_struct *pollt)
25222535
{
@@ -2671,17 +2684,27 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
26712684
if (ret)
26722685
goto out_free_bitmap;
26732686

2687+
cdev->device_unregistered_nb.notifier_call =
2688+
gpio_device_unregistered_notify;
2689+
ret = blocking_notifier_chain_register(&gdev->device_notifier,
2690+
&cdev->device_unregistered_nb);
2691+
if (ret)
2692+
goto out_unregister_line_notifier;
2693+
26742694
file->private_data = cdev;
26752695

26762696
ret = nonseekable_open(inode, file);
26772697
if (ret)
2678-
goto out_unregister_notifier;
2698+
goto out_unregister_device_notifier;
26792699

26802700
up_read(&gdev->sem);
26812701

26822702
return ret;
26832703

2684-
out_unregister_notifier:
2704+
out_unregister_device_notifier:
2705+
blocking_notifier_chain_unregister(&gdev->device_notifier,
2706+
&cdev->device_unregistered_nb);
2707+
out_unregister_line_notifier:
26852708
blocking_notifier_chain_unregister(&gdev->line_state_notifier,
26862709
&cdev->lineinfo_changed_nb);
26872710
out_free_bitmap:
@@ -2706,6 +2729,8 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file)
27062729
struct gpio_device *gdev = cdev->gdev;
27072730

27082731
bitmap_free(cdev->watched_lines);
2732+
blocking_notifier_chain_unregister(&gdev->device_notifier,
2733+
&cdev->device_unregistered_nb);
27092734
blocking_notifier_chain_unregister(&gdev->line_state_notifier,
27102735
&cdev->lineinfo_changed_nb);
27112736
gpio_device_put(gdev);

0 commit comments

Comments
 (0)