X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fvideobuf-core.c;h=89a44f16f0ba50892be204f19f66c576cf46a2e1;hb=6d435365dd49ac5f7fe6f0e757e942875b1d1550;hp=ca67f80184bdfb69fd9e44a6e420036793dd58c4;hpb=00f98d0804c88c29bef81cb98c861f13c9b33f30;p=linux-2.6 diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index ca67f80184..89a44f16f0 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -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); } @@ -316,7 +329,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, goto done; } - req->count = count; + req->count = retval; done: mutex_unlock(&q->lock); @@ -504,7 +517,6 @@ int videobuf_dqbuf(struct videobuf_queue *q, int videobuf_streamon(struct videobuf_queue *q) { struct videobuf_buffer *buf; - struct list_head *list; unsigned long flags=0; int retval; @@ -518,11 +530,9 @@ int videobuf_streamon(struct videobuf_queue *q) q->streaming = 1; if (q->irqlock) spin_lock_irqsave(q->irqlock,flags); - list_for_each(list,&q->stream) { - buf = list_entry(list, struct videobuf_buffer, stream); + 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); @@ -664,7 +674,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* Copy to userspace */ - retval=CALL(q,copy_to_user,q,data,count,nonblocking); + retval=CALL(q,video_copy_to_user,q,data,count,nonblocking); if (retval<0) goto done; @@ -685,7 +695,7 @@ int videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; unsigned long flags=0; - int count = 0, size = 0; + unsigned int count = 0, size = 0; int err, i; q->ops->buf_setup(q,&count,&size); @@ -696,9 +706,11 @@ int videobuf_read_start(struct videobuf_queue *q) size = PAGE_ALIGN(size); err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); - if (err) + if (err < 0) return err; + count = err; + for (i = 0; i < count; i++) { field = videobuf_next_field(q); err = q->ops->buf_prepare(q,q->bufs[i],field); @@ -771,7 +783,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; @@ -863,6 +875,9 @@ int videobuf_mmap_setup(struct videobuf_queue *q, for (i = 0; i < bcount; i++) { q->bufs[i] = videobuf_alloc(q); + if (q->bufs[i] == NULL) + break; + q->bufs[i]->i = i; q->bufs[i]->input = UNSET; q->bufs[i]->memory = memory; @@ -878,10 +893,13 @@ int videobuf_mmap_setup(struct videobuf_queue *q, } } + if (!i) + return -ENOMEM; + dprintk(1,"mmap setup: %d buffers, %d bytes each\n", - bcount,bsize); + i, bsize); - return 0; + return i; } int videobuf_mmap_free(struct videobuf_queue *q) @@ -949,6 +967,7 @@ int videobuf_cgmbuf(struct videobuf_queue *q, return 0; } +EXPORT_SYMBOL_GPL(videobuf_cgmbuf); #endif /* --------------------------------------------------------------------- */ @@ -958,7 +977,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); @@ -967,7 +986,6 @@ EXPORT_SYMBOL_GPL(videobuf_reqbufs); EXPORT_SYMBOL_GPL(videobuf_querybuf); EXPORT_SYMBOL_GPL(videobuf_qbuf); EXPORT_SYMBOL_GPL(videobuf_dqbuf); -EXPORT_SYMBOL_GPL(videobuf_cgmbuf); EXPORT_SYMBOL_GPL(videobuf_streamon); EXPORT_SYMBOL_GPL(videobuf_streamoff);