]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/videobuf-core.c
V4L/DVB (6292): videobuf_core init always require callback implementation
[linux-2.6-omap-h63xx.git] / drivers / media / video / videobuf-core.c
index eb3b98400c1b6c802a292a0deb61e54d678862c4..f5c5ea8b6b0866f8632011b897c767507d9ebcab 100644 (file)
@@ -94,29 +94,39 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
        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);
 }
 
 /* --------------------------------------------------------------------- */
 
 
-void videobuf_queue_init(struct videobuf_queue* q,
+void videobuf_queue_core_init(struct videobuf_queue* q,
                         struct videobuf_queue_ops *ops,
                         void *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
                         unsigned int msize,
-                        void *priv)
+                        void *priv,
+                        struct videobuf_qtype_ops *int_ops)
 {
        memset(q,0,sizeof(*q));
-       q->irqlock = irqlock;
-       q->dev     = dev;
-       q->type    = type;
-       q->field   = field;
-       q->msize   = msize;
-       q->ops     = ops;
+       q->irqlock   = irqlock;
+       q->dev       = dev;
+       q->type      = type;
+       q->field     = field;
+       q->msize     = msize;
+       q->ops       = ops;
        q->priv_data = priv;
+       q->int_ops   = int_ops;
 
        /* All buffer operations are mandatory */
        BUG_ON (!q->ops->buf_setup);
@@ -124,6 +134,9 @@ void videobuf_queue_init(struct videobuf_queue* q,
        BUG_ON (!q->ops->buf_queue);
        BUG_ON (!q->ops->buf_release);
 
+       /* Having implementations for abstract methods are mandatory */
+       BUG_ON (!q->int_ops);
+
        mutex_init(&q->lock);
        INIT_LIST_HEAD(&q->stream);
 }
@@ -149,7 +162,7 @@ int videobuf_queue_is_busy(struct videobuf_queue *q)
        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                if (NULL == q->bufs[i])
                        continue;
-               if (CALL(q,is_mmapped,q->bufs[i])) {
+               if (q->bufs[i]->map) {
                        dprintk(1,"busy: buffer #%d mapped\n",i);
                        return 1;
                }
@@ -238,7 +251,7 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
        }
 
        b->flags    = 0;
-       if (CALL(q,is_mmapped,vb))
+       if (vb->map)
                b->flags |= V4L2_BUF_FLAG_MAPPED;
 
        switch (vb->state) {
@@ -289,16 +302,18 @@ int videobuf_reqbufs(struct videobuf_queue *q,
                return -EINVAL;
        }
 
+       mutex_lock(&q->lock);
        if (q->streaming) {
                dprintk(1,"reqbufs: streaming already exists\n");
-               return -EBUSY;
+               retval = -EBUSY;
+               goto done;
        }
        if (!list_empty(&q->stream)) {
                dprintk(1,"reqbufs: stream running\n");
-               return -EBUSY;
+               retval = -EBUSY;
+               goto done;
        }
 
-       mutex_lock(&q->lock);
        count = req->count;
        if (count > VIDEO_MAX_FRAME)
                count = VIDEO_MAX_FRAME;
@@ -349,6 +364,9 @@ int videobuf_qbuf(struct videobuf_queue *q,
 
        MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
 
+       if (b->memory == V4L2_MEMORY_MMAP)
+               down_read(&current->mm->mmap_sem);
+
        mutex_lock(&q->lock);
        retval = -EBUSY;
        if (q->reading) {
@@ -434,6 +452,10 @@ int videobuf_qbuf(struct videobuf_queue *q,
 
  done:
        mutex_unlock(&q->lock);
+
+       if (b->memory == V4L2_MEMORY_MMAP)
+               up_read(&current->mm->mmap_sem);
+
        return retval;
 }
 
@@ -762,7 +784,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
                }
 
                if (q->read_buf->state == STATE_DONE) {
-                       rc = CALL (q,copy_stream, q, data, count,
+                       rc = CALL (q,copy_stream, q, data + retval, count,
                                        retval, vbihack, nonblocking);
                        if (rc < 0) {
                                retval = rc;
@@ -949,7 +971,7 @@ EXPORT_SYMBOL_GPL(videobuf_iolock);
 
 EXPORT_SYMBOL_GPL(videobuf_alloc);
 
-EXPORT_SYMBOL_GPL(videobuf_queue_init);
+EXPORT_SYMBOL_GPL(videobuf_queue_core_init);
 EXPORT_SYMBOL_GPL(videobuf_queue_cancel);
 EXPORT_SYMBOL_GPL(videobuf_queue_is_busy);