[media] saa6588: add support for non-blocking mode
authorHans Verkuil <hans.verkuil@cisco.com>
Sat, 14 Dec 2013 11:28:36 +0000 (08:28 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Tue, 7 Jan 2014 09:42:19 +0000 (07:42 -0200)
saa6588 always blocked while waiting for data, even if the filehandle
was in non-blocking mode.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/i2c/saa6588.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/saa7134/saa7134-video.c
include/media/saa6588.h

index 21cf940..2960b5a 100644 (file)
@@ -150,14 +150,14 @@ static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd)
 
 /* ---------------------------------------------------------------------- */
 
-static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf)
+static bool block_from_buf(struct saa6588 *s, unsigned char *buf)
 {
        int i;
 
        if (s->rd_index == s->wr_index) {
                if (debug > 2)
                        dprintk(PREFIX "Read: buffer empty.\n");
-               return 0;
+               return false;
        }
 
        if (debug > 2) {
@@ -166,8 +166,7 @@ static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf)
                        dprintk("0x%02x ", s->buffer[i]);
        }
 
-       if (copy_to_user(user_buf, &s->buffer[s->rd_index], 3))
-               return -EFAULT;
+       memcpy(buf, &s->buffer[s->rd_index], 3);
 
        s->rd_index += 3;
        if (s->rd_index >= s->buf_size)
@@ -177,22 +176,22 @@ static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf)
        if (debug > 2)
                dprintk("%d blocks total.\n", s->block_count);
 
-       return 1;
+       return true;
 }
 
 static void read_from_buf(struct saa6588 *s, struct saa6588_command *a)
 {
-       unsigned long flags;
-
        unsigned char __user *buf_ptr = a->buffer;
-       unsigned int i;
+       unsigned char buf[3];
+       unsigned long flags;
        unsigned int rd_blocks;
+       unsigned int i;
 
        a->result = 0;
        if (!a->buffer)
                return;
 
-       while (!s->data_available_for_read) {
+       while (!a->nonblocking && !s->data_available_for_read) {
                int ret = wait_event_interruptible(s->read_queue,
                                             s->data_available_for_read);
                if (ret == -ERESTARTSYS) {
@@ -201,24 +200,31 @@ static void read_from_buf(struct saa6588 *s, struct saa6588_command *a)
                }
        }
 
-       spin_lock_irqsave(&s->lock, flags);
        rd_blocks = a->block_count;
+       spin_lock_irqsave(&s->lock, flags);
        if (rd_blocks > s->block_count)
                rd_blocks = s->block_count;
+       spin_unlock_irqrestore(&s->lock, flags);
 
-       if (!rd_blocks) {
-               spin_unlock_irqrestore(&s->lock, flags);
+       if (!rd_blocks)
                return;
-       }
 
        for (i = 0; i < rd_blocks; i++) {
-               if (block_to_user_buf(s, buf_ptr)) {
-                       buf_ptr += 3;
-                       a->result++;
-               } else
+               bool got_block;
+
+               spin_lock_irqsave(&s->lock, flags);
+               got_block = block_from_buf(s, buf);
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (!got_block)
                        break;
+               if (copy_to_user(buf_ptr, buf, 3)) {
+                       a->result = -EFAULT;
+                       return;
+               }
+               buf_ptr += 3;
+               a->result += 3;
        }
-       a->result *= 3;
+       spin_lock_irqsave(&s->lock, flags);
        s->data_available_for_read = (s->block_count > 0);
        spin_unlock_irqrestore(&s->lock, flags);
 }
@@ -408,9 +414,8 @@ static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
                /* --- poll() for /dev/radio --- */
        case SAA6588_CMD_POLL:
                a->result = 0;
-               if (s->data_available_for_read) {
+               if (s->data_available_for_read)
                        a->result |= POLLIN | POLLRDNORM;
-               }
                poll_wait(a->instance, &s->read_queue, a->event_list);
                break;
 
index 92a06fd..c2aaadc 100644 (file)
@@ -3266,7 +3266,9 @@ static ssize_t radio_read(struct file *file, char __user *data,
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
        struct saa6588_command cmd;
-       cmd.block_count = count/3;
+
+       cmd.block_count = count / 3;
+       cmd.nonblocking = file->f_flags & O_NONBLOCK;
        cmd.buffer = data;
        cmd.instance = file;
        cmd.result = -ENODEV;
index 88e6405..36026b1 100644 (file)
@@ -1285,6 +1285,7 @@ static ssize_t radio_read(struct file *file, char __user *data,
        struct saa6588_command cmd;
 
        cmd.block_count = count/3;
+       cmd.nonblocking = file->f_flags & O_NONBLOCK;
        cmd.buffer = data;
        cmd.instance = file;
        cmd.result = -ENODEV;
index 1489a52..b5ec1aa 100644 (file)
@@ -27,6 +27,7 @@
 
 struct saa6588_command {
        unsigned int  block_count;
+       bool          nonblocking;
        int           result;
        unsigned char __user *buffer;
        struct file   *instance;