]> Pileus Git - ~andy/linux/blobdiff - drivers/media/i2c/saa6588.c
Merge branch 'for_3.14-rcx/clk-fixes' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / drivers / media / i2c / saa6588.c
index 70bc72e795d04b30814e32eb599f3b42f1de4328..2960b5a8362a4965c6f5198404ea76a86693d1f8 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);
 }
@@ -394,14 +400,11 @@ static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
        struct saa6588_command *a = arg;
 
        switch (cmd) {
-               /* --- open() for /dev/radio --- */
-       case SAA6588_CMD_OPEN:
-               a->result = 0;  /* return error if chip doesn't work ??? */
-               break;
                /* --- close() for /dev/radio --- */
        case SAA6588_CMD_CLOSE:
                s->data_available_for_read = 1;
                wake_up_interruptible(&s->read_queue);
+               s->data_available_for_read = 0;
                a->result = 0;
                break;
                /* --- read() for /dev/radio --- */
@@ -411,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;