Commit aac997df authored by Christian Gromm's avatar Christian Gromm Committed by Greg Kroah-Hartman
Browse files

staging: most: add poll syscall to AIM cdev



This patch adds the implementation of the poll syscall to the AIM cdev.
To have the full functionality, a helper function is needed in the
core module to retrieve the instantaneous availability of tx buffers.

Signed-off-by: default avatarChristian Gromm <christian.gromm@microchip.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 48ab5a33
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/poll.h>
#include <linux/kfifo.h>
#include <linux/uaccess.h>
#include <linux/idr.h>
@@ -31,6 +32,7 @@ static struct most_aim cdev_aim;

struct aim_channel {
	wait_queue_head_t wq;
	wait_queue_head_t poll_wq;
	struct cdev cdev;
	struct device *dev;
	struct mutex io_mutex;
@@ -271,6 +273,28 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
	return retval;
}

static inline bool __must_check IS_ERR_OR_FALSE(int x)
{
	return x <= 0;
}

static unsigned int aim_poll(struct file *filp, poll_table *wait)
{
	struct aim_channel *c = filp->private_data;
	unsigned int mask = 0;

	poll_wait(filp, &c->poll_wq, wait);

	if (c->cfg->direction == MOST_CH_RX) {
		if (!kfifo_is_empty(&c->fifo))
			mask |= POLLIN | POLLRDNORM;
	} else {
		if (!IS_ERR_OR_FALSE(channel_has_mbo(c->iface, c->channel_id)))
			mask |= POLLOUT | POLLWRNORM;
	}
	return mask;
}

/**
 * Initialization of struct file_operations
 */
@@ -280,6 +304,7 @@ static const struct file_operations channel_fops = {
	.write = aim_write,
	.open = aim_open,
	.release = aim_close,
	.poll = aim_poll,
};

/**
@@ -434,6 +459,7 @@ static int aim_probe(struct most_interface *iface, int channel_id,
		goto error_alloc_kfifo;
	}
	init_waitqueue_head(&channel->wq);
	init_waitqueue_head(&channel->poll_wq);
	mutex_init(&channel->io_mutex);
	spin_lock_irqsave(&ch_list_lock, cl_flags);
	list_add_tail(&channel->list, &channel_list);
+16 −0
Original line number Diff line number Diff line
@@ -1383,6 +1383,22 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
	return i->channel[id];
}

int channel_has_mbo(struct most_interface *iface, int id)
{
	struct most_c_obj *c = get_channel_by_iface(iface, id);
	unsigned long flags;
	int empty;

	if (unlikely(!c))
		return -EINVAL;

	spin_lock_irqsave(&c->fifo_lock, flags);
	empty = list_empty(&c->fifo);
	spin_unlock_irqrestore(&c->fifo_lock, flags);
	return !empty;
}
EXPORT_SYMBOL_GPL(channel_has_mbo);

/**
 * most_get_mbo - get pointer to an MBO of pool
 * @iface: pointer to interface instance
+1 −0
Original line number Diff line number Diff line
@@ -311,6 +311,7 @@ int most_deregister_aim(struct most_aim *aim);
struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
			 struct most_aim *);
void most_put_mbo(struct mbo *mbo);
int channel_has_mbo(struct most_interface *iface, int channel_idx);
int most_start_channel(struct most_interface *iface, int channel_idx,
		       struct most_aim *);
int most_stop_channel(struct most_interface *iface, int channel_idx,