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

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
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/poll.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/idr.h> #include <linux/idr.h>
...@@ -31,6 +32,7 @@ static struct most_aim cdev_aim; ...@@ -31,6 +32,7 @@ static struct most_aim cdev_aim;
struct aim_channel { struct aim_channel {
wait_queue_head_t wq; wait_queue_head_t wq;
wait_queue_head_t poll_wq;
struct cdev cdev; struct cdev cdev;
struct device *dev; struct device *dev;
struct mutex io_mutex; struct mutex io_mutex;
...@@ -271,6 +273,28 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) ...@@ -271,6 +273,28 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
return retval; 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 * Initialization of struct file_operations
*/ */
...@@ -280,6 +304,7 @@ static const struct file_operations channel_fops = { ...@@ -280,6 +304,7 @@ static const struct file_operations channel_fops = {
.write = aim_write, .write = aim_write,
.open = aim_open, .open = aim_open,
.release = aim_close, .release = aim_close,
.poll = aim_poll,
}; };
/** /**
...@@ -434,6 +459,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, ...@@ -434,6 +459,7 @@ static int aim_probe(struct most_interface *iface, int channel_id,
goto error_alloc_kfifo; goto error_alloc_kfifo;
} }
init_waitqueue_head(&channel->wq); init_waitqueue_head(&channel->wq);
init_waitqueue_head(&channel->poll_wq);
mutex_init(&channel->io_mutex); mutex_init(&channel->io_mutex);
spin_lock_irqsave(&ch_list_lock, cl_flags); spin_lock_irqsave(&ch_list_lock, cl_flags);
list_add_tail(&channel->list, &channel_list); list_add_tail(&channel->list, &channel_list);
......
...@@ -1383,6 +1383,22 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) ...@@ -1383,6 +1383,22 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
return i->channel[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 * most_get_mbo - get pointer to an MBO of pool
* @iface: pointer to interface instance * @iface: pointer to interface instance
......
...@@ -311,6 +311,7 @@ int most_deregister_aim(struct most_aim *aim); ...@@ -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 mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
struct most_aim *); struct most_aim *);
void most_put_mbo(struct mbo *mbo); 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, int most_start_channel(struct most_interface *iface, int channel_idx,
struct most_aim *); struct most_aim *);
int most_stop_channel(struct most_interface *iface, int channel_idx, int most_stop_channel(struct most_interface *iface, int channel_idx,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment