From b4b7ff4b08e691656c9d77c758fc355833128ac0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 20 Jan 2016 14:01:31 -0300 Subject: Linux-libre 4.4-gnu --- drivers/staging/most/aim-cdev/cdev.c | 68 ++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'drivers/staging/most/aim-cdev/cdev.c') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 0a13d8d0f..dc3fb25b5 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ static dev_t aim_devno; static struct class *aim_class; static struct ida minor_id; static unsigned int major; +static struct most_aim cdev_aim; struct aim_channel { wait_queue_head_t wq; @@ -44,11 +46,11 @@ struct aim_channel { atomic_t access_ref; struct list_head list; }; + #define to_channel(d) container_of(d, struct aim_channel, cdev) static struct list_head channel_list; static spinlock_t ch_list_lock; - static struct aim_channel *get_channel(struct most_interface *iface, int id) { struct aim_channel *channel, *tmp; @@ -85,8 +87,8 @@ static int aim_open(struct inode *inode, struct file *filp) filp->private_data = channel; if (((channel->cfg->direction == MOST_CH_RX) && - ((filp->f_flags & O_ACCMODE) != O_RDONLY)) - || ((channel->cfg->direction == MOST_CH_TX) && + ((filp->f_flags & O_ACCMODE) != O_RDONLY)) || + ((channel->cfg->direction == MOST_CH_TX) && ((filp->f_flags & O_ACCMODE) != O_WRONLY))) { pr_info("WARN: Access flags mismatch\n"); return -EACCES; @@ -97,7 +99,8 @@ static int aim_open(struct inode *inode, struct file *filp) return -EBUSY; } - ret = most_start_channel(channel->iface, channel->channel_id); + ret = most_start_channel(channel->iface, channel->channel_id, + &cdev_aim); if (ret) atomic_dec(&channel->access_ref); return ret; @@ -131,11 +134,11 @@ static int aim_close(struct inode *inode, struct file *filp) } mutex_unlock(&channel->io_mutex); - while (0 != kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1)) + while (kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1)) most_put_mbo(mbo); - if (channel->keep_mbo == true) + if (channel->keep_mbo) most_put_mbo(channel->stacked_mbo); - ret = most_stop_channel(channel->iface, channel->channel_id); + ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim); atomic_dec(&channel->access_ref); wake_up_interruptible(&channel->wq); return ret; @@ -165,16 +168,17 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, } mutex_unlock(&channel->io_mutex); - mbo = most_get_mbo(channel->iface, channel->channel_id); + mbo = most_get_mbo(channel->iface, channel->channel_id, &cdev_aim); - if (!mbo && channel->dev) { + if (!mbo) { if ((filp->f_flags & O_NONBLOCK)) return -EAGAIN; if (wait_event_interruptible( channel->wq, (mbo = most_get_mbo(channel->iface, - channel->channel_id)) || - (channel->dev == NULL))) + channel->channel_id, + &cdev_aim)) || + (!channel->dev))) return -ERESTARTSYS; } @@ -204,8 +208,7 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, } return actual_len - retval; error: - if (mbo) - most_put_mbo(mbo); + most_put_mbo(mbo); return err; } @@ -224,18 +227,17 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) struct mbo *mbo; struct aim_channel *channel = filp->private_data; - if (channel->keep_mbo == true) { + if (channel->keep_mbo) { mbo = channel->stacked_mbo; channel->keep_mbo = false; goto start_copy; } - while ((0 == kfifo_out(&channel->fifo, &mbo, 1)) - && (channel->dev != NULL)) { + while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; if (wait_event_interruptible(channel->wq, (!kfifo_is_empty(&channel->fifo) || - (channel->dev == NULL)))) + (!channel->dev)))) return -ERESTARTSYS; } @@ -259,7 +261,7 @@ start_copy: retval = not_copied ? proc_len - not_copied : proc_len; - if (channel->keep_mbo == true) { + if (channel->keep_mbo) { channel->mbo_offs = retval; channel->stacked_mbo = mbo; } else { @@ -270,6 +272,28 @@ start_copy: 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->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 */ @@ -279,6 +303,7 @@ static const struct file_operations channel_fops = { .write = aim_write, .open = aim_open, .release = aim_close, + .poll = aim_poll, }; /** @@ -300,7 +325,7 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) } channel = get_channel(iface, channel_id); - if (channel == NULL) + if (!channel) return -ENXIO; mutex_lock(&channel->io_mutex); @@ -337,7 +362,7 @@ static int aim_rx_completion(struct mbo *mbo) return -EINVAL; channel = get_channel(mbo->ifp, mbo->hdm_channel_id); - if (channel == NULL) + if (!channel) return -ENXIO; kfifo_in(&channel->fifo, &mbo, 1); @@ -370,7 +395,7 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) } channel = get_channel(iface, channel_id); - if (channel == NULL) + if (!channel) return -ENXIO; wake_up_interruptible(&channel->wq); return 0; @@ -413,7 +438,6 @@ static int aim_probe(struct most_interface *iface, int channel_id, channel = kzalloc(sizeof(*channel), GFP_KERNEL); if (!channel) { - pr_info("failed to alloc channel object\n"); retval = -ENOMEM; goto error_alloc_channel; } -- cgit v1.2.3-54-g00ecf