From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
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 <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpiolib-cdev.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index f95e1b110311..8b081c9b8d27 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -2320,6 +2320,7 @@ struct gpio_chardev_data {
wait_queue_head_t wait;
DECLARE_KFIFO(events, struct gpio_v2_line_info_changed, 32);
struct notifier_block lineinfo_changed_nb;
+ struct notifier_block device_unregistered_nb;
unsigned long *watched_lines;
#ifdef CONFIG_GPIO_CDEV_V1
atomic_t watch_abi_version;
@@ -2518,6 +2519,18 @@ static int lineinfo_changed_notify(struct notifier_block *nb,
return NOTIFY_OK;
}
+static int gpio_device_unregistered_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct gpio_chardev_data *cdev = container_of(nb,
+ struct gpio_chardev_data,
+ device_unregistered_nb);
+
+ wake_up_poll(&cdev->wait, EPOLLIN | EPOLLERR);
+
+ return NOTIFY_OK;
+}
+
static __poll_t lineinfo_watch_poll_unlocked(struct file *file,
struct poll_table_struct *pollt)
{
@@ -2672,17 +2685,27 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
if (ret)
goto out_free_bitmap;
+ cdev->device_unregistered_nb.notifier_call =
+ gpio_device_unregistered_notify;
+ ret = blocking_notifier_chain_register(&gdev->device_notifier,
+ &cdev->device_unregistered_nb);
+ if (ret)
+ goto out_unregister_line_notifier;
+
file->private_data = cdev;
ret = nonseekable_open(inode, file);
if (ret)
- goto out_unregister_notifier;
+ goto out_unregister_device_notifier;
up_read(&gdev->sem);
return ret;
-out_unregister_notifier:
+out_unregister_device_notifier:
+ blocking_notifier_chain_unregister(&gdev->device_notifier,
+ &cdev->device_unregistered_nb);
+out_unregister_line_notifier:
blocking_notifier_chain_unregister(&gdev->line_state_notifier,
&cdev->lineinfo_changed_nb);
out_free_bitmap:
@@ -2707,6 +2730,8 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file)
struct gpio_device *gdev = cdev->gdev;
bitmap_free(cdev->watched_lines);
+ blocking_notifier_chain_unregister(&gdev->device_notifier,
+ &cdev->device_unregistered_nb);
blocking_notifier_chain_unregister(&gdev->line_state_notifier,
&cdev->lineinfo_changed_nb);
gpio_device_put(gdev);
--
2.39.2
On Thu, Aug 17, 2023 at 08:49:56PM +0200, Bartosz Golaszewski wrote: > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> > > 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. ... > + struct gpio_chardev_data *cdev = container_of(nb, > + struct gpio_chardev_data, > + device_unregistered_nb); struct gpio_chardev_data *cdev = container_of(nb, struct gpio_chardev_data, device_unregistered_nb); ? -- With Best Regards, Andy Shevchenko
On Fri, Aug 18, 2023 at 12:31 PM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > > On Thu, Aug 17, 2023 at 08:49:56PM +0200, Bartosz Golaszewski wrote: > > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> > > > > 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. > > ... > > > + struct gpio_chardev_data *cdev = container_of(nb, > > + struct gpio_chardev_data, > > + device_unregistered_nb); > > struct gpio_chardev_data *cdev = > container_of(nb, struct gpio_chardev_data, device_unregistered_nb); > Ah, this goes over 80 chars. I will leave it as it is, I will fix the other one when applying. Bart > ? > > -- > With Best Regards, > Andy Shevchenko > >
On Fri, Aug 18, 2023 at 12:31 PM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > > On Thu, Aug 17, 2023 at 08:49:56PM +0200, Bartosz Golaszewski wrote: > > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> > > > > 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. > > ... > > > + struct gpio_chardev_data *cdev = container_of(nb, > > + struct gpio_chardev_data, > > + device_unregistered_nb); > > struct gpio_chardev_data *cdev = > container_of(nb, struct gpio_chardev_data, device_unregistered_nb); > > ? I could live with the other version but sure, why not. I will send a v3 with a helper wrapper around blocking_notifier_call_chain() for more brevity. Bart
On Mon, Aug 21, 2023 at 2:43 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote: > > On Fri, Aug 18, 2023 at 12:31 PM Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: > > > > On Thu, Aug 17, 2023 at 08:49:56PM +0200, Bartosz Golaszewski wrote: > > > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> > > > > > > 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. > > > > ... > > > > > + struct gpio_chardev_data *cdev = container_of(nb, > > > + struct gpio_chardev_data, > > > + device_unregistered_nb); > > > > struct gpio_chardev_data *cdev = > > container_of(nb, struct gpio_chardev_data, device_unregistered_nb); > > > > ? > > I could live with the other version but sure, why not. > > I will send a v3 with a helper wrapper around > blocking_notifier_call_chain() for more brevity. > Scratch that, I need coffee. This was supposed to go under the line state notifications patch. Bart
© 2016 - 2025 Red Hat, Inc.