Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e42af83f4874ebb2c6af59a05dbe5d45114fb0ed
Commit:     e42af83f4874ebb2c6af59a05dbe5d45114fb0ed
Parent:     c812b67ca4ed13fa5ec60f06c4ed8f648722a186
Author:     Trent Piepho <[EMAIL PROTECTED]>
AuthorDate: Tue Jul 17 18:29:43 2007 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Mon Jul 30 16:26:24 2007 -0300

    V4L/DVB (5887): zr36067: Fix poll() operation
    
    During uncompressed capture, the poll() function was looking the wrong 
frame.
    It was using the frame the driver was going to capture into next 
(pend_tail),
    when it should have been looking at the next frame to be de-queued with
    DQBUF/SYNC (sync_tail).
    
    It also wasn't looking in the right spot.  It was looking at the file 
handle's
    copy of the buffer status, rather than the driver core copy.  The interrupt
    routine marks frames as done in the driver core copy, the file handle copy
    isn't updated.  So even if poll() looked at the right frame, it would never
    see it transition to done and return POLLIN.
    
    The compressed capture code has this same problem, looking in 
fh->jpg_buffers
    when it should have used zr->jpg_buffers.
    
    There was some logic to detect when there was no current capture in process
    nor any frames queued and try to return an error, which ends up being a bad
    idea.  It's possible to call select() from one thread while no capture is in
    process, or no frames queued, and then start a capture or queue frames from
    another thread.
    
    The buffer state variables are protected by a spin lock, which the code 
wasn't
    acquiring.  That is fixed too.
    
    Signed-off-by: Trent Piepho <[EMAIL PROTECTED]>
    Acked-by: Ronald S. Bultje <[EMAIL PROTECTED]>
    Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]>
---
 drivers/media/video/zoran_driver.c |   59 ++++++++++++++++++++----------------
 1 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/drivers/media/video/zoran_driver.c 
b/drivers/media/video/zoran_driver.c
index fac97cb..37e25c2 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -4213,8 +4213,8 @@ zoran_poll (struct file *file,
 {
        struct zoran_fh *fh = file->private_data;
        struct zoran *zr = fh->zr;
-       wait_queue_head_t *queue = NULL;
        int res = 0, frame;
+       unsigned long flags;
 
        /* we should check whether buffers are ready to be synced on
         * (w/o waits - O_NONBLOCK) here
@@ -4228,51 +4228,58 @@ zoran_poll (struct file *file,
 
        switch (fh->map_mode) {
        case ZORAN_MAP_MODE_RAW:
-               if (fh->v4l_buffers.active == ZORAN_FREE ||
-                   zr->v4l_pend_head == zr->v4l_pend_tail) {
-                       dprintk(1,
-                               "%s: zoran_poll() - no buffers queued\n",
-                               ZR_DEVNAME(zr));
-                       res = POLLNVAL;
-                       goto poll_unlock_and_return;
-               }
-               queue = &zr->v4l_capq;
-               frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME];
-               poll_wait(file, queue, wait);
-               if (fh->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
+               poll_wait(file, &zr->v4l_capq, wait);
+               frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() raw - active=%c, sync_tail=%lu/%c, 
pend_tail=%lu, pend_head=%lu\n",
+                       ZR_DEVNAME(zr), __FUNCTION__,
+                       "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
+                       "UPMD"[zr->v4l_buffers.buffer[frame].state],
+                       zr->v4l_pend_tail, zr->v4l_pend_head);
+               /* Process is the one capturing? */
+               if (fh->v4l_buffers.active != ZORAN_FREE &&
+                   /* Buffer ready to DQBUF? */
+                   zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
                        res = POLLIN | POLLRDNORM;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
                break;
 
        case ZORAN_MAP_MODE_JPG_REC:
        case ZORAN_MAP_MODE_JPG_PLAY:
-               if (fh->jpg_buffers.active == ZORAN_FREE ||
-                   zr->jpg_que_head == zr->jpg_que_tail) {
-                       dprintk(1,
-                               "%s: zoran_poll() - no buffers queued\n",
-                               ZR_DEVNAME(zr));
-                       res = POLLNVAL;
-                       goto poll_unlock_and_return;
-               }
-               queue = &zr->jpg_capq;
+               poll_wait(file, &zr->jpg_capq, wait);
                frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-               poll_wait(file, queue, wait);
-               if (fh->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() jpg - active=%c, que_tail=%lu/%c, 
que_head=%lu, dma=%lu/%lu\n",
+                       ZR_DEVNAME(zr), __FUNCTION__,
+                       "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
+                       "UPMD"[zr->jpg_buffers.buffer[frame].state],
+                       zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
+               if (fh->jpg_buffers.active != ZORAN_FREE &&
+                   zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
                        if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
                                res = POLLIN | POLLRDNORM;
                        else
                                res = POLLOUT | POLLWRNORM;
                }
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
                break;
 
        default:
                dprintk(1,
+                       KERN_ERR
                        "%s: zoran_poll() - internal error, unknown 
map_mode=%d\n",
                        ZR_DEVNAME(zr), fh->map_mode);
                res = POLLNVAL;
-               goto poll_unlock_and_return;
        }
 
-poll_unlock_and_return:
        mutex_unlock(&zr->resource_lock);
 
        return res;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to