diff mbox series

[5/5] gpio: cdev: wake up lineevent poll() on device unbind

Message ID 20230816122032.15548-6-brgl@bgdev.pl
State New
Headers show
Series gpio: cdev: bail out of poll() if the device goes down | expand

Commit Message

Bartosz Golaszewski Aug. 16, 2023, 12:20 p.m. UTC
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

Extend struct lineevent_data with a notifier block and use it to receive
the GPIO device unregister event. Upon reception, 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 | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

Comments

kernel test robot Aug. 17, 2023, 9:12 a.m. UTC | #1
Hi Bartosz,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brgl/gpio/for-next]
[also build test WARNING on linus/master v6.5-rc6 next-20230817]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/gpio-cdev-ignore-notifications-other-than-line-status-changes/20230816-202408
base:   https://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git gpio/for-next
patch link:    https://lore.kernel.org/r/20230816122032.15548-6-brgl%40bgdev.pl
patch subject: [PATCH 5/5] gpio: cdev: wake up lineevent poll() on device unbind
config: x86_64-randconfig-x016-20230817 (https://download.01.org/0day-ci/archive/20230817/202308171736.864z7YNW-lkp@intel.com/config)
compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07)
reproduce: (https://download.01.org/0day-ci/archive/20230817/202308171736.864z7YNW-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308171736.864z7YNW-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpiolib-cdev.c:1835: warning: Function parameter or member 'nb' not described in 'lineevent_state'


vim +1835 drivers/gpio/gpiolib-cdev.c

925ca36913fc7d Kent Gibson         2020-06-16  1807  
925ca36913fc7d Kent Gibson         2020-06-16  1808  /*
925ca36913fc7d Kent Gibson         2020-06-16  1809   * GPIO line event management
925ca36913fc7d Kent Gibson         2020-06-16  1810   */
925ca36913fc7d Kent Gibson         2020-06-16  1811  
925ca36913fc7d Kent Gibson         2020-06-16  1812  /**
925ca36913fc7d Kent Gibson         2020-06-16  1813   * struct lineevent_state - contains the state of a userspace event
925ca36913fc7d Kent Gibson         2020-06-16  1814   * @gdev: the GPIO device the event pertains to
925ca36913fc7d Kent Gibson         2020-06-16  1815   * @label: consumer label used to tag descriptors
925ca36913fc7d Kent Gibson         2020-06-16  1816   * @desc: the GPIO descriptor held by this event
925ca36913fc7d Kent Gibson         2020-06-16  1817   * @eflags: the event flags this line was requested with
925ca36913fc7d Kent Gibson         2020-06-16  1818   * @irq: the interrupt that trigger in response to events on this GPIO
925ca36913fc7d Kent Gibson         2020-06-16  1819   * @wait: wait queue that handles blocking reads of events
925ca36913fc7d Kent Gibson         2020-06-16  1820   * @events: KFIFO for the GPIO events
925ca36913fc7d Kent Gibson         2020-06-16  1821   * @timestamp: cache for the timestamp storing it between hardirq
925ca36913fc7d Kent Gibson         2020-06-16  1822   * and IRQ thread, used to bring the timestamp close to the actual
925ca36913fc7d Kent Gibson         2020-06-16  1823   * event
925ca36913fc7d Kent Gibson         2020-06-16  1824   */
925ca36913fc7d Kent Gibson         2020-06-16  1825  struct lineevent_state {
925ca36913fc7d Kent Gibson         2020-06-16  1826  	struct gpio_device *gdev;
925ca36913fc7d Kent Gibson         2020-06-16  1827  	const char *label;
925ca36913fc7d Kent Gibson         2020-06-16  1828  	struct gpio_desc *desc;
925ca36913fc7d Kent Gibson         2020-06-16  1829  	u32 eflags;
925ca36913fc7d Kent Gibson         2020-06-16  1830  	int irq;
925ca36913fc7d Kent Gibson         2020-06-16  1831  	wait_queue_head_t wait;
925ca36913fc7d Kent Gibson         2020-06-16  1832  	DECLARE_KFIFO(events, struct gpioevent_data, 16);
35c059f377b978 Bartosz Golaszewski 2023-08-16  1833  	struct notifier_block nb;
925ca36913fc7d Kent Gibson         2020-06-16  1834  	u64 timestamp;
925ca36913fc7d Kent Gibson         2020-06-16 @1835  };
925ca36913fc7d Kent Gibson         2020-06-16  1836
diff mbox series

Patch

diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 0b21ea04fa52..bb6a011f7857 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -1830,9 +1830,15 @@  struct lineevent_state {
 	int irq;
 	wait_queue_head_t wait;
 	DECLARE_KFIFO(events, struct gpioevent_data, 16);
+	struct notifier_block nb;
 	u64 timestamp;
 };
 
+static struct lineevent_state *to_lineevent_state(struct notifier_block *nb)
+{
+	return container_of(nb, struct lineevent_state, nb);
+}
+
 #define GPIOEVENT_REQUEST_VALID_FLAGS \
 	(GPIOEVENT_REQUEST_RISING_EDGE | \
 	GPIOEVENT_REQUEST_FALLING_EDGE)
@@ -1947,6 +1953,9 @@  static ssize_t lineevent_read(struct file *file, char __user *buf,
 
 static void lineevent_free(struct lineevent_state *le)
 {
+	if (le->nb.notifier_call)
+		blocking_notifier_chain_unregister(&le->gdev->notifier,
+						   &le->nb);
 	if (le->irq)
 		free_irq(le->irq, le);
 	if (le->desc)
@@ -2084,6 +2093,22 @@  static irqreturn_t lineevent_irq_handler(int irq, void *p)
 	return IRQ_WAKE_THREAD;
 }
 
+static int lineevent_notify(struct notifier_block *nb, unsigned long action,
+			    void *data)
+{
+	struct lineevent_state *le = to_lineevent_state(nb);
+
+	switch (action) {
+	case GPIO_CDEV_UNREGISTERED:
+		wake_up_poll(&le->wait, EPOLLIN | EPOLLERR);
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
 static int lineevent_create(struct gpio_device *gdev, void __user *ip)
 {
 	struct gpioevent_request eventreq;
@@ -2175,6 +2200,11 @@  static int lineevent_create(struct gpio_device *gdev, void __user *ip)
 	INIT_KFIFO(le->events);
 	init_waitqueue_head(&le->wait);
 
+	le->nb.notifier_call = lineevent_notify;
+	ret = blocking_notifier_chain_register(&gdev->notifier, &le->nb);
+	if (ret)
+		goto out_free_le;
+
 	/* Request a thread to read the events */
 	ret = request_threaded_irq(irq,
 				   lineevent_irq_handler,