X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fvideobuf-core.c;h=b7b05842cf281bda10b27572df02ff9301fb823d;hb=30650961907368b1077cade35455fe931b14da6b;hp=81f77d2b4bd39c48edeff93d548b66ff989f518f;hpb=19fb1457990b6b7e15586ec7331541a184233acc;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 81f77d2..b7b0584 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -16,35 +16,39 @@ #include #include #include +#include #include #include #include #define MAGIC_BUFFER 0x20070728 -#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ - { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } +#define MAGIC_CHECK(is, should) do { \ + if (unlikely((is) != (should))) { \ + printk(KERN_ERR "magic mismatch: %x (expected %x)\n", is, should); \ + BUG(); } } while (0) -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_DESCRIPTION("helper module to manage video4linux buffers"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); -#define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "vbuf: " fmt , ## arg) +#define dprintk(level, fmt, arg...) do { \ + if (debug >= level) \ + printk(KERN_DEBUG "vbuf: " fmt , ## arg); } while (0) /* --------------------------------------------------------------------- */ #define CALL(q, f, arg...) \ - ( (q->int_ops->f)? q->int_ops->f(arg) : 0) + ((q->int_ops->f) ? q->int_ops->f(arg) : 0) -void* videobuf_alloc(struct videobuf_queue* q) +void *videobuf_alloc(struct videobuf_queue *q) { struct videobuf_buffer *vb; - BUG_ON (q->msizemsize < sizeof(*vb)); if (!q->int_ops || !q->int_ops->alloc) { printk(KERN_ERR "No specific ops defined!\n"); @@ -61,56 +65,52 @@ void* videobuf_alloc(struct videobuf_queue* q) return vb; } +#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ + vb->state != VIDEOBUF_QUEUED) int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) { - int retval = 0; - DECLARE_WAITQUEUE(wait, current); + MAGIC_CHECK(vb->magic, MAGIC_BUFFER); - MAGIC_CHECK(vb->magic,MAGIC_BUFFER); - add_wait_queue(&vb->done, &wait); - while (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) { - if (non_blocking) { - retval = -EAGAIN; - break; - } - set_current_state(intr ? TASK_INTERRUPTIBLE - : TASK_UNINTERRUPTIBLE); - if (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) - schedule(); - set_current_state(TASK_RUNNING); - if (intr && signal_pending(current)) { - dprintk(1,"buffer waiton: -EINTR\n"); - retval = -EINTR; - break; - } + if (non_blocking) { + if (WAITON_CONDITION) + return 0; + else + return -EAGAIN; } - remove_wait_queue(&vb->done, &wait); - return retval; + + if (intr) + return wait_event_interruptible(vb->done, WAITON_CONDITION); + else + wait_event(vb->done, WAITON_CONDITION); + + return 0; } -int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, +int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) { - MAGIC_CHECK(vb->magic,MAGIC_BUFFER); - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(vb->magic, MAGIC_BUFFER); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - /* FIXME: This is required to avoid OOPS on some cases, since mmap_mapper() - method should be called before _iolock. - On some cases, the mmap_mapper() is called only after scheduling. - - However, this way is just too dirty! Better to wait for some event. - */ - schedule_timeout(HZ); + return CALL(q, iolock, q, vb, fbuf); +} - return CALL(q,iolock,q,vb,fbuf); +void *videobuf_queue_to_vmalloc (struct videobuf_queue *q, + struct videobuf_buffer *buf) +{ + if (q->int_ops->vmalloc) + return q->int_ops->vmalloc(buf); + else + return NULL; } +EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc); /* --------------------------------------------------------------------- */ -void videobuf_queue_core_init(struct videobuf_queue* q, +void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -118,7 +118,7 @@ void videobuf_queue_core_init(struct videobuf_queue* q, void *priv, struct videobuf_qtype_ops *int_ops) { - memset(q,0,sizeof(*q)); + memset(q, 0, sizeof(*q)); q->irqlock = irqlock; q->dev = dev; q->type = type; @@ -129,15 +129,19 @@ void videobuf_queue_core_init(struct videobuf_queue* q, q->int_ops = int_ops; /* All buffer operations are mandatory */ - BUG_ON (!q->ops->buf_setup); - BUG_ON (!q->ops->buf_prepare); - BUG_ON (!q->ops->buf_queue); - BUG_ON (!q->ops->buf_release); + BUG_ON(!q->ops->buf_setup); + BUG_ON(!q->ops->buf_prepare); + BUG_ON(!q->ops->buf_queue); + BUG_ON(!q->ops->buf_release); + + /* Lock is mandatory for queue_cancel to work */ + BUG_ON(!irqlock); /* Having implementations for abstract methods are mandatory */ - BUG_ON (!q->int_ops); + BUG_ON(!q->int_ops); - mutex_init(&q->lock); + mutex_init(&q->vb_lock); + init_waitqueue_head(&q->wait); INIT_LIST_HEAD(&q->stream); } @@ -146,71 +150,74 @@ int videobuf_queue_is_busy(struct videobuf_queue *q) { int i; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); if (q->streaming) { - dprintk(1,"busy: streaming active\n"); + dprintk(1, "busy: streaming active\n"); return 1; } if (q->reading) { - dprintk(1,"busy: pending read #1\n"); + dprintk(1, "busy: pending read #1\n"); return 1; } if (q->read_buf) { - dprintk(1,"busy: pending read #2\n"); + dprintk(1, "busy: pending read #2\n"); return 1; } for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; if (q->bufs[i]->map) { - dprintk(1,"busy: buffer #%d mapped\n",i); + dprintk(1, "busy: buffer #%d mapped\n", i); return 1; } - if (q->bufs[i]->state == STATE_QUEUED) { - dprintk(1,"busy: buffer #%d queued\n",i); + if (q->bufs[i]->state == VIDEOBUF_QUEUED) { + dprintk(1, "busy: buffer #%d queued\n", i); return 1; } - if (q->bufs[i]->state == STATE_ACTIVE) { - dprintk(1,"busy: buffer #%d avtive\n",i); + if (q->bufs[i]->state == VIDEOBUF_ACTIVE) { + dprintk(1, "busy: buffer #%d avtive\n", i); return 1; } } return 0; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ void videobuf_queue_cancel(struct videobuf_queue *q) { - unsigned long flags=0; + unsigned long flags = 0; int i; + q->streaming = 0; + q->reading = 0; + wake_up_interruptible_sync(&q->wait); + /* remove queued buffers from list */ - if (q->irqlock) - spin_lock_irqsave(q->irqlock,flags); + spin_lock_irqsave(q->irqlock, flags); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; - if (q->bufs[i]->state == STATE_QUEUED) { + if (q->bufs[i]->state == VIDEOBUF_QUEUED) { list_del(&q->bufs[i]->queue); - q->bufs[i]->state = STATE_ERROR; + q->bufs[i]->state = VIDEOBUF_ERROR; + wake_up_all(&q->bufs[i]->done); } } - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock,flags); + spin_unlock_irqrestore(q->irqlock, flags); /* free all buffers + clear queue */ for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; - q->ops->buf_release(q,q->bufs[i]); + q->ops->buf_release(q, q->bufs[i]); } INIT_LIST_HEAD(&q->stream); } /* --------------------------------------------------------------------- */ -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) { enum v4l2_field field = q->field; @@ -229,12 +236,12 @@ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) return field; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, struct videobuf_buffer *vb, enum v4l2_buf_type type) { - MAGIC_CHECK(vb->magic,MAGIC_BUFFER); - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(vb->magic, MAGIC_BUFFER); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); b->index = vb->i; b->type = type; @@ -259,17 +266,17 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, b->flags |= V4L2_BUF_FLAG_MAPPED; switch (vb->state) { - case STATE_PREPARED: - case STATE_QUEUED: - case STATE_ACTIVE: + case VIDEOBUF_PREPARED: + case VIDEOBUF_QUEUED: + case VIDEOBUF_ACTIVE: b->flags |= V4L2_BUF_FLAG_QUEUED; break; - case STATE_DONE: - case STATE_ERROR: + case VIDEOBUF_DONE: + case VIDEOBUF_ERROR: b->flags |= V4L2_BUF_FLAG_DONE; break; - case STATE_NEEDS_INIT: - case STATE_IDLE: + case VIDEOBUF_NEEDS_INIT: + case VIDEOBUF_IDLE: /* nothing */ break; } @@ -285,7 +292,7 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, b->sequence = vb->field_count >> 1; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static int __videobuf_mmap_free(struct videobuf_queue *q) { int i; @@ -294,16 +301,20 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) if (!q) return 0; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); + + + rc = CALL(q, mmap_free, q); + + q->is_mmapped = 0; - rc = CALL(q,mmap_free,q); - if (rc<0) + if (rc < 0) return rc; for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; - q->ops->buf_release(q,q->bufs[i]); + q->ops->buf_release(q, q->bufs[i]); kfree(q->bufs[i]); q->bufs[i] = NULL; } @@ -314,21 +325,21 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) int videobuf_mmap_free(struct videobuf_queue *q) { int ret; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); ret = __videobuf_mmap_free(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return ret; } -/* Locking: Caller holds q->lock */ -static int __videobuf_mmap_setup(struct videobuf_queue *q, +/* Locking: Caller holds q->vb_lock */ +int __videobuf_mmap_setup(struct videobuf_queue *q, unsigned int bcount, unsigned int bsize, enum v4l2_memory memory) { unsigned int i; int err; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); err = __videobuf_mmap_free(q); if (0 != err) @@ -359,7 +370,7 @@ static int __videobuf_mmap_setup(struct videobuf_queue *q, if (!i) return -ENOMEM; - dprintk(1,"mmap setup: %d buffers, %d bytes each\n", + dprintk(1, "mmap setup: %d buffers, %d bytes each\n", i, bsize); return i; @@ -370,44 +381,44 @@ int videobuf_mmap_setup(struct videobuf_queue *q, enum v4l2_memory memory) { int ret; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); ret = __videobuf_mmap_setup(q, bcount, bsize, memory); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return ret; } int videobuf_reqbufs(struct videobuf_queue *q, struct v4l2_requestbuffers *req) { - unsigned int size,count; + unsigned int size, count; int retval; if (req->count < 1) { - dprintk(1,"reqbufs: count invalid (%d)\n",req->count); + dprintk(1, "reqbufs: count invalid (%d)\n", req->count); return -EINVAL; } if (req->memory != V4L2_MEMORY_MMAP && req->memory != V4L2_MEMORY_USERPTR && req->memory != V4L2_MEMORY_OVERLAY) { - dprintk(1,"reqbufs: memory type invalid\n"); + dprintk(1, "reqbufs: memory type invalid\n"); return -EINVAL; } - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (req->type != q->type) { - dprintk(1,"reqbufs: queue type invalid\n"); + dprintk(1, "reqbufs: queue type invalid\n"); retval = -EINVAL; goto done; } if (q->streaming) { - dprintk(1,"reqbufs: streaming already exists\n"); + dprintk(1, "reqbufs: streaming already exists\n"); retval = -EBUSY; goto done; } if (!list_empty(&q->stream)) { - dprintk(1,"reqbufs: stream running\n"); + dprintk(1, "reqbufs: stream running\n"); retval = -EBUSY; goto done; } @@ -416,21 +427,21 @@ int videobuf_reqbufs(struct videobuf_queue *q, if (count > VIDEO_MAX_FRAME) count = VIDEO_MAX_FRAME; size = 0; - q->ops->buf_setup(q,&count,&size); + q->ops->buf_setup(q, &count, &size); size = PAGE_ALIGN(size); - dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n", + dprintk(1, "reqbufs: bufs=%d, size=0x%x [%d pages total]\n", count, size, (count*size)>>PAGE_SHIFT); - retval = __videobuf_mmap_setup(q,count,size,req->memory); + retval = __videobuf_mmap_setup(q, count, size, req->memory); if (retval < 0) { - dprintk(1,"reqbufs: mmap setup returned %d\n",retval); + dprintk(1, "reqbufs: mmap setup returned %d\n", retval); goto done; } req->count = retval; done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } @@ -438,25 +449,25 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) { int ret = -EINVAL; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (unlikely(b->type != q->type)) { - dprintk(1,"querybuf: Wrong type.\n"); + dprintk(1, "querybuf: Wrong type.\n"); goto done; } if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { - dprintk(1,"querybuf: index out of range.\n"); + dprintk(1, "querybuf: index out of range.\n"); goto done; } if (unlikely(NULL == q->bufs[b->index])) { - dprintk(1,"querybuf: buffer is null.\n"); + dprintk(1, "querybuf: buffer is null.\n"); goto done; } - videobuf_status(q,b,q->bufs[b->index],q->type); + videobuf_status(q, b, q->bufs[b->index], q->type); ret = 0; done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return ret; } @@ -465,47 +476,47 @@ int videobuf_qbuf(struct videobuf_queue *q, { struct videobuf_buffer *buf; enum v4l2_field field; - unsigned long flags=0; + unsigned long flags = 0; int retval; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); if (b->memory == V4L2_MEMORY_MMAP) down_read(¤t->mm->mmap_sem); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->reading) { - dprintk(1,"qbuf: Reading running...\n"); + dprintk(1, "qbuf: Reading running...\n"); goto done; } retval = -EINVAL; if (b->type != q->type) { - dprintk(1,"qbuf: Wrong type.\n"); + dprintk(1, "qbuf: Wrong type.\n"); goto done; } if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) { - dprintk(1,"qbuf: index out of range.\n"); + dprintk(1, "qbuf: index out of range.\n"); goto done; } buf = q->bufs[b->index]; if (NULL == buf) { - dprintk(1,"qbuf: buffer is null.\n"); + dprintk(1, "qbuf: buffer is null.\n"); goto done; } - MAGIC_CHECK(buf->magic,MAGIC_BUFFER); + MAGIC_CHECK(buf->magic, MAGIC_BUFFER); if (buf->memory != b->memory) { - dprintk(1,"qbuf: memory type is wrong.\n"); + dprintk(1, "qbuf: memory type is wrong.\n"); goto done; } - if (buf->state != STATE_NEEDS_INIT && buf->state != STATE_IDLE) { - dprintk(1,"qbuf: buffer is already queued or active.\n"); + if (buf->state != VIDEOBUF_NEEDS_INIT && buf->state != VIDEOBUF_IDLE) { + dprintk(1, "qbuf: buffer is already queued or active.\n"); goto done; } if (b->flags & V4L2_BUF_FLAG_INPUT) { if (b->input >= q->inputs) { - dprintk(1,"qbuf: wrong input.\n"); + dprintk(1, "qbuf: wrong input.\n"); goto done; } buf->input = b->input; @@ -516,48 +527,49 @@ int videobuf_qbuf(struct videobuf_queue *q, switch (b->memory) { case V4L2_MEMORY_MMAP: if (0 == buf->baddr) { - dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n"); + dprintk(1, "qbuf: mmap requested " + "but buffer addr is zero!\n"); goto done; } break; case V4L2_MEMORY_USERPTR: if (b->length < buf->bsize) { - dprintk(1,"qbuf: buffer length is not enough\n"); + dprintk(1, "qbuf: buffer length is not enough\n"); goto done; } - if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) - q->ops->buf_release(q,buf); + if (VIDEOBUF_NEEDS_INIT != buf->state && + buf->baddr != b->m.userptr) + q->ops->buf_release(q, buf); buf->baddr = b->m.userptr; break; case V4L2_MEMORY_OVERLAY: buf->boff = b->m.offset; break; default: - dprintk(1,"qbuf: wrong memory type\n"); + dprintk(1, "qbuf: wrong memory type\n"); goto done; } - dprintk(1,"qbuf: requesting next field\n"); + dprintk(1, "qbuf: requesting next field\n"); field = videobuf_next_field(q); - retval = q->ops->buf_prepare(q,buf,field); + retval = q->ops->buf_prepare(q, buf, field); if (0 != retval) { - dprintk(1,"qbuf: buffer_prepare returned %d\n",retval); + dprintk(1, "qbuf: buffer_prepare returned %d\n", retval); goto done; } - list_add_tail(&buf->stream,&q->stream); + list_add_tail(&buf->stream, &q->stream); if (q->streaming) { - if (q->irqlock) - spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(q,buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock,flags); + spin_lock_irqsave(q->irqlock, flags); + q->ops->buf_queue(q, buf); + spin_unlock_irqrestore(q->irqlock, flags); } - dprintk(1,"qbuf: succeded\n"); + dprintk(1, "qbuf: succeded\n"); retval = 0; + wake_up_interruptible_sync(&q->wait); done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); if (b->memory == V4L2_MEMORY_MMAP) up_read(¤t->mm->mmap_sem); @@ -565,68 +577,121 @@ int videobuf_qbuf(struct videobuf_queue *q, return retval; } -int videobuf_dqbuf(struct videobuf_queue *q, - struct v4l2_buffer *b, int nonblocking) + +/* Locking: Caller holds q->vb_lock */ +static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) { - struct videobuf_buffer *buf; int retval; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); - - mutex_lock(&q->lock); - retval = -EBUSY; - if (q->reading) { - dprintk(1,"dqbuf: Reading running...\n"); - goto done; - } - retval = -EINVAL; - if (b->type != q->type) { - dprintk(1,"dqbuf: Wrong type.\n"); +checks: + if (!q->streaming) { + dprintk(1, "next_buffer: Not streaming\n"); + retval = -EINVAL; goto done; } + if (list_empty(&q->stream)) { - dprintk(1,"dqbuf: stream running\n"); - goto done; + if (noblock) { + retval = -EAGAIN; + dprintk(2, "next_buffer: no buffers to dequeue\n"); + goto done; + } else { + dprintk(2, "next_buffer: waiting on buffer\n"); + + /* Drop lock to avoid deadlock with qbuf */ + mutex_unlock(&q->vb_lock); + + /* Checking list_empty and streaming is safe without + * locks because we goto checks to validate while + * holding locks before proceeding */ + retval = wait_event_interruptible(q->wait, + !list_empty(&q->stream) || !q->streaming); + mutex_lock(&q->vb_lock); + + if (retval) + goto done; + + goto checks; + } } + + retval = 0; + +done: + return retval; +} + + +/* Locking: Caller holds q->vb_lock */ +static int stream_next_buffer(struct videobuf_queue *q, + struct videobuf_buffer **vb, int nonblocking) +{ + int retval; + struct videobuf_buffer *buf = NULL; + + retval = stream_next_buffer_check_queue(q, nonblocking); + if (retval) + goto done; + buf = list_entry(q->stream.next, struct videobuf_buffer, stream); retval = videobuf_waiton(buf, nonblocking, 1); + if (retval < 0) + goto done; + + *vb = buf; +done: + return retval; +} + +int videobuf_dqbuf(struct videobuf_queue *q, + struct v4l2_buffer *b, int nonblocking) +{ + struct videobuf_buffer *buf = NULL; + int retval; + + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); + + mutex_lock(&q->vb_lock); + + retval = stream_next_buffer(q, &buf, nonblocking); if (retval < 0) { - dprintk(1,"dqbuf: waiton returned %d\n",retval); + dprintk(1, "dqbuf: next_buffer error: %i\n", retval); goto done; } + switch (buf->state) { - case STATE_ERROR: - dprintk(1,"dqbuf: state is error\n"); + case VIDEOBUF_ERROR: + dprintk(1, "dqbuf: state is error\n"); retval = -EIO; - CALL(q,sync,q, buf); - buf->state = STATE_IDLE; + CALL(q, sync, q, buf); + buf->state = VIDEOBUF_IDLE; break; - case STATE_DONE: - dprintk(1,"dqbuf: state is done\n"); - CALL(q,sync,q, buf); - buf->state = STATE_IDLE; + case VIDEOBUF_DONE: + dprintk(1, "dqbuf: state is done\n"); + CALL(q, sync, q, buf); + buf->state = VIDEOBUF_IDLE; break; default: - dprintk(1,"dqbuf: state invalid\n"); + dprintk(1, "dqbuf: state invalid\n"); retval = -EINVAL; goto done; } list_del(&buf->stream); - memset(b,0,sizeof(*b)); - videobuf_status(q,b,buf,q->type); + memset(b, 0, sizeof(*b)); + videobuf_status(q, b, buf, q->type); done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } int videobuf_streamon(struct videobuf_queue *q) { struct videobuf_buffer *buf; - unsigned long flags=0; + unsigned long flags = 0; int retval; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->reading) goto done; @@ -634,27 +699,25 @@ int videobuf_streamon(struct videobuf_queue *q) if (q->streaming) goto done; q->streaming = 1; - if (q->irqlock) - spin_lock_irqsave(q->irqlock,flags); + spin_lock_irqsave(q->irqlock, flags); list_for_each_entry(buf, &q->stream, stream) - if (buf->state == STATE_PREPARED) - q->ops->buf_queue(q,buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock,flags); + if (buf->state == VIDEOBUF_PREPARED) + q->ops->buf_queue(q, buf); + spin_unlock_irqrestore(q->irqlock, flags); + wake_up_interruptible_sync(&q->wait); done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static int __videobuf_streamoff(struct videobuf_queue *q) { if (!q->streaming) return -EINVAL; videobuf_queue_cancel(q); - q->streaming = 0; return 0; } @@ -663,23 +726,23 @@ int videobuf_streamoff(struct videobuf_queue *q) { int retval; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = __videobuf_streamoff(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos) { enum v4l2_field field; - unsigned long flags=0; + unsigned long flags = 0; int retval; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); /* setup stuff */ q->read_buf = videobuf_alloc(q); @@ -691,20 +754,18 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, q->read_buf->bsize = count; field = videobuf_next_field(q); - retval = q->ops->buf_prepare(q,q->read_buf,field); + retval = q->ops->buf_prepare(q, q->read_buf, field); if (0 != retval) goto done; /* start capture & wait */ - if (q->irqlock) - spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(q,q->read_buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock,flags); - retval = videobuf_waiton(q->read_buf,0,0); + spin_lock_irqsave(q->irqlock, flags); + q->ops->buf_queue(q, q->read_buf); + spin_unlock_irqrestore(q->irqlock, flags); + retval = videobuf_waiton(q->read_buf, 0, 0); if (0 == retval) { - CALL(q,sync,q,q->read_buf); - if (STATE_ERROR == q->read_buf->state) + CALL(q, sync, q, q->read_buf); + if (VIDEOBUF_ERROR == q->read_buf->state) retval = -EIO; else retval = q->read_buf->size; @@ -712,7 +773,7 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, done: /* cleanup */ - q->ops->buf_release(q,q->read_buf); + q->ops->buf_release(q, q->read_buf); kfree(q->read_buf); q->read_buf = NULL; return retval; @@ -723,21 +784,20 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, int nonblocking) { enum v4l2_field field; - unsigned long flags=0; - unsigned size, nbufs; + unsigned long flags = 0; + unsigned size = 0, nbufs = 1; int retval; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); - nbufs = 1; size = 0; - q->ops->buf_setup(q,&nbufs,&size); + q->ops->buf_setup(q, &nbufs, &size); if (NULL == q->read_buf && count >= size && !nonblocking) { - retval = videobuf_read_zerocopy(q,data,count,ppos); + retval = videobuf_read_zerocopy(q, data, count, ppos); if (retval >= 0 || retval == -EIO) /* ok, all done */ goto done; @@ -749,25 +809,24 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, retval = -ENOMEM; q->read_buf = videobuf_alloc(q); - dprintk(1,"video alloc=0x%p\n", q->read_buf); + dprintk(1, "video alloc=0x%p\n", q->read_buf); if (NULL == q->read_buf) goto done; q->read_buf->memory = V4L2_MEMORY_USERPTR; q->read_buf->bsize = count; /* preferred size */ field = videobuf_next_field(q); - retval = q->ops->buf_prepare(q,q->read_buf,field); + retval = q->ops->buf_prepare(q, q->read_buf, field); if (0 != retval) { - kfree (q->read_buf); + kfree(q->read_buf); q->read_buf = NULL; goto done; } - if (q->irqlock) - spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(q,q->read_buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock,flags); + spin_lock_irqsave(q->irqlock, flags); + q->ops->buf_queue(q, q->read_buf); + spin_unlock_irqrestore(q->irqlock, flags); + q->read_off = 0; } @@ -776,11 +835,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, if (0 != retval) goto done; - CALL(q,sync,q,q->read_buf); + CALL(q, sync, q, q->read_buf); - if (STATE_ERROR == q->read_buf->state) { + if (VIDEOBUF_ERROR == q->read_buf->state) { /* catch I/O errors */ - q->ops->buf_release(q,q->read_buf); + q->ops->buf_release(q, q->read_buf); kfree(q->read_buf); q->read_buf = NULL; retval = -EIO; @@ -788,32 +847,32 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* Copy to userspace */ - retval=CALL(q,video_copy_to_user,q,data,count,nonblocking); - if (retval<0) + retval = CALL(q, video_copy_to_user, q, data, count, nonblocking); + if (retval < 0) goto done; q->read_off += retval; if (q->read_off == q->read_buf->size) { /* all data copied, cleanup */ - q->ops->buf_release(q,q->read_buf); + q->ops->buf_release(q, q->read_buf); kfree(q->read_buf); q->read_buf = NULL; } done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } -/* Locking: Caller holds q->lock */ -int __videobuf_read_start(struct videobuf_queue *q) +/* Locking: Caller holds q->vb_lock */ +static int __videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; - unsigned long flags=0; + unsigned long flags = 0; unsigned int count = 0, size = 0; int err, i; - q->ops->buf_setup(q,&count,&size); + q->ops->buf_setup(q, &count, &size); if (count < 2) count = 2; if (count > VIDEO_MAX_FRAME) @@ -828,17 +887,15 @@ int __videobuf_read_start(struct videobuf_queue *q) for (i = 0; i < count; i++) { field = videobuf_next_field(q); - err = q->ops->buf_prepare(q,q->bufs[i],field); + err = q->ops->buf_prepare(q, q->bufs[i], field); if (err) return err; list_add_tail(&q->bufs[i]->stream, &q->stream); } - if (q->irqlock) - spin_lock_irqsave(q->irqlock,flags); + spin_lock_irqsave(q->irqlock, flags); for (i = 0; i < count; i++) - q->ops->buf_queue(q,q->bufs[i]); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock,flags); + q->ops->buf_queue(q, q->bufs[i]); + spin_unlock_irqrestore(q->irqlock, flags); q->reading = 1; return 0; } @@ -847,7 +904,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q) { int i; - videobuf_queue_cancel(q); __videobuf_mmap_free(q); INIT_LIST_HEAD(&q->stream); @@ -858,31 +914,30 @@ static void __videobuf_read_stop(struct videobuf_queue *q) q->bufs[i] = NULL; } q->read_buf = NULL; - q->reading = 0; - + } int videobuf_read_start(struct videobuf_queue *q) { int rc; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); rc = __videobuf_read_start(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return rc; } void videobuf_read_stop(struct videobuf_queue *q) { - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); __videobuf_read_stop(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); } void videobuf_stop(struct videobuf_queue *q) { - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (q->streaming) __videobuf_streamoff(q); @@ -890,7 +945,7 @@ void videobuf_stop(struct videobuf_queue *q) if (q->reading) __videobuf_read_stop(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); } @@ -899,17 +954,17 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, int vbihack, int nonblocking) { int rc, retval; - unsigned long flags=0; + unsigned long flags = 0; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - dprintk(2,"%s\n",__FUNCTION__); - mutex_lock(&q->lock); + dprintk(2, "%s\n", __func__); + mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->streaming) goto done; if (!q->reading) { - retval = videobuf_read_start(q); + retval = __videobuf_read_start(q); if (retval < 0) goto done; } @@ -931,8 +986,8 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, break; } - if (q->read_buf->state == STATE_DONE) { - rc = CALL (q,copy_stream, q, data + retval, count, + if (q->read_buf->state == VIDEOBUF_DONE) { + rc = CALL(q, copy_stream, q, data + retval, count, retval, vbihack, nonblocking); if (rc < 0) { retval = rc; @@ -952,11 +1007,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, if (q->read_off == q->read_buf->size) { list_add_tail(&q->read_buf->stream, &q->stream); - if (q->irqlock) - spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(q,q->read_buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock,flags); + spin_lock_irqsave(q->irqlock, flags); + q->ops->buf_queue(q, q->read_buf); + spin_unlock_irqrestore(q->irqlock, flags); q->read_buf = NULL; } if (retval < 0) @@ -964,7 +1017,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, } done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } @@ -975,14 +1028,14 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer *buf = NULL; unsigned int rc = 0; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (q->streaming) { if (!list_empty(&q->stream)) buf = list_entry(q->stream.next, struct videobuf_buffer, stream); } else { if (!q->reading) - videobuf_read_start(q); + __videobuf_read_start(q); if (!q->reading) { rc = POLLERR; } else if (NULL == q->read_buf) { @@ -999,11 +1052,11 @@ unsigned int videobuf_poll_stream(struct file *file, if (0 == rc) { poll_wait(file, &buf->done, wait); - if (buf->state == STATE_DONE || - buf->state == STATE_ERROR) + if (buf->state == VIDEOBUF_DONE || + buf->state == VIDEOBUF_ERROR) rc = POLLIN|POLLRDNORM; } - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return rc; } @@ -1012,11 +1065,12 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, { int retval; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - mutex_lock(&q->lock); - retval=CALL(q,mmap_mapper,q,vma); - mutex_unlock(&q->lock); + mutex_lock(&q->vb_lock); + retval = CALL(q, mmap_mapper, q, vma); + q->is_mmapped = 1; + mutex_unlock(&q->vb_lock); return retval; } @@ -1026,15 +1080,15 @@ int videobuf_cgmbuf(struct videobuf_queue *q, struct video_mbuf *mbuf, int count) { struct v4l2_requestbuffers req; - int rc,i; + int rc, i; - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - memset(&req,0,sizeof(req)); + memset(&req, 0, sizeof(req)); req.type = q->type; req.count = count; req.memory = V4L2_MEMORY_MMAP; - rc = videobuf_reqbufs(q,&req); + rc = videobuf_reqbufs(q, &req); if (rc < 0) return rc; @@ -1076,12 +1130,7 @@ EXPORT_SYMBOL_GPL(videobuf_read_stream); EXPORT_SYMBOL_GPL(videobuf_read_one); EXPORT_SYMBOL_GPL(videobuf_poll_stream); +EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); EXPORT_SYMBOL_GPL(videobuf_mmap_setup); EXPORT_SYMBOL_GPL(videobuf_mmap_free); EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */