Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2f0a48f authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Jonathan Cameron
Browse files

iio: Wakeup poll and blocking reads when the device is unregistered



Once the device has been unregistered there won't be any new data no matter how
long a userspace application waits, so we might as well wake them up and let
them know.

Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent f18e7a06
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer)

void iio_disable_all_buffers(struct iio_dev *indio_dev);
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);

#else

@@ -57,11 +58,13 @@ void iio_disable_all_buffers(struct iio_dev *indio_dev);
#define iio_buffer_read_first_n_outer_addr NULL

static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}

#endif

int iio_device_register_eventset(struct iio_dev *indio_dev);
void iio_device_unregister_eventset(struct iio_dev *indio_dev);
void iio_device_wakeup_eventset(struct iio_dev *indio_dev);
int iio_event_getfd(struct iio_dev *indio_dev);

#endif
+16 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/sched.h>

#include <linux/iio/iio.h>
#include "iio_core.h"
@@ -75,6 +76,21 @@ unsigned int iio_buffer_poll(struct file *filp,
	return 0;
}

/**
 * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
 * @indio_dev: The IIO device
 *
 * Wakes up the event waitqueue used for poll(). Should usually
 * be called when the device is unregistered.
 */
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
{
	if (!indio_dev->buffer)
		return;

	wake_up(&indio_dev->buffer->pollq);
}

void iio_buffer_init(struct iio_buffer *buffer)
{
	INIT_LIST_HEAD(&buffer->demux_list);
+4 −0
Original line number Diff line number Diff line
@@ -1139,6 +1139,10 @@ void iio_device_unregister(struct iio_dev *indio_dev)
	iio_disable_all_buffers(indio_dev);

	indio_dev->info = NULL;

	iio_device_wakeup_eventset(indio_dev);
	iio_buffer_wakeup_poll(indio_dev);

	mutex_unlock(&indio_dev->info_exist_lock);
}
EXPORT_SYMBOL(iio_device_unregister);
+20 −1
Original line number Diff line number Diff line
@@ -113,9 +113,14 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
		}
		/* Blocking on device; waiting for something to be there */
		ret = wait_event_interruptible_locked_irq(ev_int->wait,
					!kfifo_is_empty(&ev_int->det_events));
					!kfifo_is_empty(&ev_int->det_events) ||
					indio_dev->info == NULL);
		if (ret)
			goto error_unlock;
		if (indio_dev->info == NULL) {
			ret = -ENODEV;
			goto error_unlock;
		}
		/* Single access device so no one else can get the data */
	}

@@ -454,6 +459,20 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
	return ret;
}

/**
 * iio_device_wakeup_eventset - Wakes up the event waitqueue
 * @indio_dev: The IIO device
 *
 * Wakes up the event waitqueue used for poll() and blocking read().
 * Should usually be called when the device is unregistered.
 */
void iio_device_wakeup_eventset(struct iio_dev *indio_dev)
{
	if (indio_dev->event_interface == NULL)
		return;
	wake_up(&indio_dev->event_interface->wait);
}

void iio_device_unregister_eventset(struct iio_dev *indio_dev)
{
	if (indio_dev->event_interface == NULL)