Commit d1ba9a2f authored by Alessandro Rubini's avatar Alessandro Rubini

Merge branch 'pollerr'

This branche adds POLLERR support (see commit messages).
Federico gave his acked-by, but the original commit is already in
production, so I am not changing the commit messages.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
Acked-by: 's avatarFederico Vaga <federico.vaga@gmail.com>
parents abcd24ed a90aba09
......@@ -290,7 +290,7 @@ static int zio_can_r_ctrl(struct zio_f_priv *priv)
{
struct zio_channel *chan = priv->chan;
struct zio_bi *bi = chan->bi;
const int can_read = POLLIN | POLLRDNORM;
const int ret_ok = POLLIN | POLLRDNORM;
int ret;
dev_dbg(&bi->head.dev, "%s: channel %d in cset %d", __func__,
......@@ -306,12 +306,18 @@ static int zio_can_r_ctrl(struct zio_f_priv *priv)
chan->user_block = NULL;
} else{
mutex_unlock(&chan->user_lock);
return can_read;
return ret_ok;
}
}
/* We want to re-read control. Get a new block */
chan->user_block = zio_buffer_retr_block(bi);
ret = chan->user_block ? can_read : 0;
ret = 0;
if (chan->user_block)
ret = ret_ok;
else if (unlikely(bi->cset->ti->flags & ZIO_DISABLED))
ret = POLLERR;
mutex_unlock(&chan->user_lock);
return ret;
}
......@@ -321,7 +327,7 @@ static int zio_can_r_data(struct zio_f_priv *priv)
struct zio_channel *chan = priv->chan;
struct zio_block *block;
struct zio_bi *bi = chan->bi;
const int can_read = POLLIN | POLLRDNORM;
const int ret_ok = POLLIN | POLLRDNORM;
if (!chan->cset->ssize)
return 0;
......@@ -330,12 +336,12 @@ static int zio_can_r_data(struct zio_f_priv *priv)
block = chan->user_block;
if (block) {
mutex_unlock(&chan->user_lock);
return can_read;
return ret_ok;
}
block = chan->user_block = zio_buffer_retr_block(bi);
mutex_unlock(&chan->user_lock);
if (block)
return can_read;
return ret_ok;
return 0;
}
......@@ -354,7 +360,8 @@ static int zio_can_w_ctrl(struct zio_f_priv *priv)
struct zio_bi *bi = chan->bi;
struct zio_block *block;
struct zio_control *ctrl;
const int can_write = POLLOUT | POLLWRNORM;
const int ret_ok = POLLOUT | POLLWRNORM;
int ret;
/*
* A control can always be written. Writing a control means a
......@@ -378,8 +385,12 @@ static int zio_can_w_ctrl(struct zio_f_priv *priv)
/* if no block is there, get a new one */
if (!block)
block = chan->user_block = __zio_write_allocblock(bi);
mutex_unlock(&chan->user_lock);
return block ? can_write : 0;
ret = 0;
if (block)
ret = ret_ok;
else if (unlikely(bi->cset->ti->flags & ZIO_DISABLED))
ret = POLLERR;
return ret;
}
static int zio_can_w_data(struct zio_f_priv *priv)
......@@ -387,7 +398,7 @@ static int zio_can_w_data(struct zio_f_priv *priv)
struct zio_channel *chan = priv->chan;
struct zio_bi *bi = chan->bi;
struct zio_block *block;
const int can_write = POLLOUT | POLLWRNORM;
const int ret_ok = POLLOUT | POLLWRNORM;
if (!chan->cset->ssize)
return 0;
......@@ -397,7 +408,7 @@ static int zio_can_w_data(struct zio_f_priv *priv)
if (!block)
block = chan->user_block = __zio_write_allocblock(bi);
mutex_unlock(&chan->user_lock);
return block ? can_write : 0;
return block ? ret_ok : 0;
}
/*
......@@ -413,7 +424,7 @@ static ssize_t zio_generic_read(struct file *f, char __user *ubuf,
struct zio_bi *bi = chan->bi;
struct zio_block *block;
int (*can_read)(struct zio_f_priv *);
int fault;
int fault, rflags;
dev_dbg(&bi->head.dev, "%s:%d type %s\n", __func__, __LINE__,
priv->type == ZIO_CDEV_CTRL ? "ctrl" : "data");
......@@ -429,7 +440,8 @@ static ssize_t zio_generic_read(struct file *f, char __user *ubuf,
}
while (1) {
if (!can_read(priv)) {
rflags = can_read(priv);
if (rflags == 0 || rflags == POLLERR) {
if (f->f_flags & O_NONBLOCK)
return -EAGAIN;
wait_event_interruptible(bi->q, can_read(priv));
......@@ -486,7 +498,7 @@ static ssize_t zio_generic_write(struct file *f, const char __user *ubuf,
struct zio_bi *bi = chan->bi;
struct zio_block *block;
int (*can_write)(struct zio_f_priv *);
int fault;
int fault, wflags;
dev_dbg(&bi->head.dev, "%s:%d type %s\n", __func__, __LINE__,
priv->type == ZIO_CDEV_CTRL ? "ctrl" : "data");
......@@ -502,7 +514,8 @@ static ssize_t zio_generic_write(struct file *f, const char __user *ubuf,
}
while(1) {
if (!can_write(priv)) {
wflags = can_write(priv);
if (wflags == 0 || wflags == POLLERR) {
if (f->f_flags & O_NONBLOCK)
return -EAGAIN;
wait_event_interruptible(bi->q, can_write(priv));
......
......@@ -12,6 +12,7 @@
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/sysfs.h>
#include <linux/version.h>
......@@ -418,10 +419,9 @@ static void __zobj_enable(struct device *dev, unsigned int enable)
dev_dbg(dev, "(dev)\n");
zdev = to_zio_dev(dev);
/* enable/disable all cset */
/* enable/disable all csets */
for (i = 0; i < zdev->n_cset; ++i)
__zobj_enable(&zdev->cset[i].head.dev, enable);
/* device callback */
break;
case ZIO_CSET:
dev_dbg(dev, "(cset)\n");
......@@ -429,10 +429,9 @@ static void __zobj_enable(struct device *dev, unsigned int enable)
cset = to_zio_cset(dev);
/* enable/disable trigger instance */
__zobj_enable(&cset->ti->head.dev, enable);
/* enable/disable all channel*/
/* enable/disable all channels */
for (i = 0; i < cset->n_chan; ++i)
__zobj_enable(&cset->chan[i].head.dev, enable);
/* cset callback */
break;
case ZIO_CHAN:
dev_dbg(dev, "(chan)\n");
......@@ -443,23 +442,25 @@ static void __zobj_enable(struct device *dev, unsigned int enable)
__ctrl_update_nsamples(chan->cset->ti);
__chan_enable_interleave(chan, enable);
}
/* channel callback */
break;
case ZIO_TI:
dev_dbg(dev, "(ti)\n");
ti = to_zio_ti(dev);
cset = ti->cset;
zio_trigger_abort_disable(ti->cset, 0);
spin_lock_irqsave(&ti->cset->lock, flags);
/* trigger instance callback */
if (ti->t_op->change_status)
ti->t_op->change_status(ti, status);
spin_unlock_irqrestore(&ti->cset->lock, flags);
/* A user-forced disable sends POLLERR to waiters */
for (i = 0; i < cset->n_chan; ++i) {
chan = cset->chan + i;
wake_up_interruptible(&chan->bi->q);
}
break;
/* following objects can't be enabled/disabled */
case ZIO_BUF:
case ZIO_TRG:
case ZIO_BI:
dev_dbg(dev, "(buf)\n");
/*
......@@ -469,6 +470,8 @@ static void __zobj_enable(struct device *dev, unsigned int enable)
* the channel is disabled. Only ZIO can disable a buffer
* instance during flush.
*/
case ZIO_BUF:
case ZIO_TRG:
break;
default:
WARN(1, "ZIO: unknown zio object %i\n", head->zobj_type);
......@@ -558,18 +561,14 @@ static ssize_t zobj_store_enable(struct device *dev,
spinlock_t *lock;
err = strict_strtol(buf, 0, &val);
if (err)
if (err || val < 0 || val > 1)
return -EINVAL;
lock = __get_spinlock(to_zio_head(dev));
/* change enable status */
if (unlikely(strcmp(attr->attr.name, ZOBJ_SYSFS_ENABLE) == 0 &&
(val == 0 || val == 1))) {
spin_lock(lock);
__zobj_enable(dev, val);
spin_unlock(lock);
return count;
}
spin_lock(lock);
__zobj_enable(dev, val);
spin_unlock(lock);
return count;
return count;
}
......
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