aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2007-07-17 17:29:43 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-07-30 15:26:24 -0400
commite42af83f4874ebb2c6af59a05dbe5d45114fb0ed (patch)
tree7659c0d8dfc1851594ed133bce3ed1368b7ab8ea /drivers/media
parentc812b67ca4ed13fa5ec60f06c4ed8f648722a186 (diff)
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 <xyzzy@speakeasy.org> Acked-by: Ronald S. Bultje <rbultje@ronald.bitfreak.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/zoran_driver.c59
1 files changed, 33 insertions, 26 deletions
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index fac97cb5a828..37e25c25279b 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -4213,8 +4213,8 @@ zoran_poll (struct file *file,
4213{ 4213{
4214 struct zoran_fh *fh = file->private_data; 4214 struct zoran_fh *fh = file->private_data;
4215 struct zoran *zr = fh->zr; 4215 struct zoran *zr = fh->zr;
4216 wait_queue_head_t *queue = NULL;
4217 int res = 0, frame; 4216 int res = 0, frame;
4217 unsigned long flags;
4218 4218
4219 /* we should check whether buffers are ready to be synced on 4219 /* we should check whether buffers are ready to be synced on
4220 * (w/o waits - O_NONBLOCK) here 4220 * (w/o waits - O_NONBLOCK) here
@@ -4228,51 +4228,58 @@ zoran_poll (struct file *file,
4228 4228
4229 switch (fh->map_mode) { 4229 switch (fh->map_mode) {
4230 case ZORAN_MAP_MODE_RAW: 4230 case ZORAN_MAP_MODE_RAW:
4231 if (fh->v4l_buffers.active == ZORAN_FREE || 4231 poll_wait(file, &zr->v4l_capq, wait);
4232 zr->v4l_pend_head == zr->v4l_pend_tail) { 4232 frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
4233 dprintk(1, 4233
4234 "%s: zoran_poll() - no buffers queued\n", 4234 spin_lock_irqsave(&zr->spinlock, flags);
4235 ZR_DEVNAME(zr)); 4235 dprintk(3,
4236 res = POLLNVAL; 4236 KERN_DEBUG
4237 goto poll_unlock_and_return; 4237 "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
4238 } 4238 ZR_DEVNAME(zr), __FUNCTION__,
4239 queue = &zr->v4l_capq; 4239 "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
4240 frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; 4240 "UPMD"[zr->v4l_buffers.buffer[frame].state],
4241 poll_wait(file, queue, wait); 4241 zr->v4l_pend_tail, zr->v4l_pend_head);
4242 if (fh->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) 4242 /* Process is the one capturing? */
4243 if (fh->v4l_buffers.active != ZORAN_FREE &&
4244 /* Buffer ready to DQBUF? */
4245 zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
4243 res = POLLIN | POLLRDNORM; 4246 res = POLLIN | POLLRDNORM;
4247 spin_unlock_irqrestore(&zr->spinlock, flags);
4248
4244 break; 4249 break;
4245 4250
4246 case ZORAN_MAP_MODE_JPG_REC: 4251 case ZORAN_MAP_MODE_JPG_REC:
4247 case ZORAN_MAP_MODE_JPG_PLAY: 4252 case ZORAN_MAP_MODE_JPG_PLAY:
4248 if (fh->jpg_buffers.active == ZORAN_FREE || 4253 poll_wait(file, &zr->jpg_capq, wait);
4249 zr->jpg_que_head == zr->jpg_que_tail) {
4250 dprintk(1,
4251 "%s: zoran_poll() - no buffers queued\n",
4252 ZR_DEVNAME(zr));
4253 res = POLLNVAL;
4254 goto poll_unlock_and_return;
4255 }
4256 queue = &zr->jpg_capq;
4257 frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; 4254 frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
4258 poll_wait(file, queue, wait); 4255
4259 if (fh->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { 4256 spin_lock_irqsave(&zr->spinlock, flags);
4257 dprintk(3,
4258 KERN_DEBUG
4259 "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
4260 ZR_DEVNAME(zr), __FUNCTION__,
4261 "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
4262 "UPMD"[zr->jpg_buffers.buffer[frame].state],
4263 zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
4264 if (fh->jpg_buffers.active != ZORAN_FREE &&
4265 zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
4260 if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) 4266 if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
4261 res = POLLIN | POLLRDNORM; 4267 res = POLLIN | POLLRDNORM;
4262 else 4268 else
4263 res = POLLOUT | POLLWRNORM; 4269 res = POLLOUT | POLLWRNORM;
4264 } 4270 }
4271 spin_unlock_irqrestore(&zr->spinlock, flags);
4272
4265 break; 4273 break;
4266 4274
4267 default: 4275 default:
4268 dprintk(1, 4276 dprintk(1,
4277 KERN_ERR
4269 "%s: zoran_poll() - internal error, unknown map_mode=%d\n", 4278 "%s: zoran_poll() - internal error, unknown map_mode=%d\n",
4270 ZR_DEVNAME(zr), fh->map_mode); 4279 ZR_DEVNAME(zr), fh->map_mode);
4271 res = POLLNVAL; 4280 res = POLLNVAL;
4272 goto poll_unlock_and_return;
4273 } 4281 }
4274 4282
4275poll_unlock_and_return:
4276 mutex_unlock(&zr->resource_lock); 4283 mutex_unlock(&zr->resource_lock);
4277 4284
4278 return res; 4285 return res;