aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/videobuf-core.c96
-rw-r--r--include/media/videobuf-core.h2
2 files changed, 78 insertions, 20 deletions
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index 1ba3aaa29dd0..3ab556093ca7 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -141,6 +141,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
141 BUG_ON(!q->int_ops); 141 BUG_ON(!q->int_ops);
142 142
143 mutex_init(&q->vb_lock); 143 mutex_init(&q->vb_lock);
144 init_waitqueue_head(&q->wait);
144 INIT_LIST_HEAD(&q->stream); 145 INIT_LIST_HEAD(&q->stream);
145} 146}
146 147
@@ -188,6 +189,10 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
188 unsigned long flags = 0; 189 unsigned long flags = 0;
189 int i; 190 int i;
190 191
192 q->streaming = 0;
193 q->reading = 0;
194 wake_up_interruptible_sync(&q->wait);
195
191 /* remove queued buffers from list */ 196 /* remove queued buffers from list */
192 if (q->irqlock) 197 if (q->irqlock)
193 spin_lock_irqsave(q->irqlock, flags); 198 spin_lock_irqsave(q->irqlock, flags);
@@ -565,6 +570,7 @@ int videobuf_qbuf(struct videobuf_queue *q,
565 } 570 }
566 dprintk(1, "qbuf: succeded\n"); 571 dprintk(1, "qbuf: succeded\n");
567 retval = 0; 572 retval = 0;
573 wake_up_interruptible_sync(&q->wait);
568 574
569 done: 575 done:
570 mutex_unlock(&q->vb_lock); 576 mutex_unlock(&q->vb_lock);
@@ -575,37 +581,88 @@ int videobuf_qbuf(struct videobuf_queue *q,
575 return retval; 581 return retval;
576} 582}
577 583
578int videobuf_dqbuf(struct videobuf_queue *q, 584
579 struct v4l2_buffer *b, int nonblocking) 585/* Locking: Caller holds q->vb_lock */
586static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
580{ 587{
581 struct videobuf_buffer *buf;
582 int retval; 588 int retval;
583 589
584 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); 590checks:
585 591 if (!q->streaming) {
586 mutex_lock(&q->vb_lock); 592 dprintk(1, "next_buffer: Not streaming\n");
587 retval = -EBUSY; 593 retval = -EINVAL;
588 if (q->reading) {
589 dprintk(1, "dqbuf: Reading running...\n");
590 goto done;
591 }
592 retval = -EINVAL;
593 if (b->type != q->type) {
594 dprintk(1, "dqbuf: Wrong type.\n");
595 goto done; 594 goto done;
596 } 595 }
596
597 if (list_empty(&q->stream)) { 597 if (list_empty(&q->stream)) {
598 dprintk(1, "dqbuf: stream running\n"); 598 if (noblock) {
599 goto done; 599 retval = -EAGAIN;
600 dprintk(2, "next_buffer: no buffers to dequeue\n");
601 goto done;
602 } else {
603 dprintk(2, "next_buffer: waiting on buffer\n");
604
605 /* Drop lock to avoid deadlock with qbuf */
606 mutex_unlock(&q->vb_lock);
607
608 /* Checking list_empty and streaming is safe without
609 * locks because we goto checks to validate while
610 * holding locks before proceeding */
611 retval = wait_event_interruptible(q->wait,
612 !list_empty(&q->stream) || !q->streaming);
613 mutex_lock(&q->vb_lock);
614
615 if (retval)
616 goto done;
617
618 goto checks;
619 }
600 } 620 }
621
622 retval = 0;
623
624done:
625 return retval;
626}
627
628
629/* Locking: Caller holds q->vb_lock */
630static int stream_next_buffer(struct videobuf_queue *q,
631 struct videobuf_buffer **vb, int nonblocking)
632{
633 int retval;
634 struct videobuf_buffer *buf = NULL;
635
636 retval = stream_next_buffer_check_queue(q, nonblocking);
637 if (retval)
638 goto done;
639
601 buf = list_entry(q->stream.next, struct videobuf_buffer, stream); 640 buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
602 mutex_unlock(&q->vb_lock);
603 retval = videobuf_waiton(buf, nonblocking, 1); 641 retval = videobuf_waiton(buf, nonblocking, 1);
642 if (retval < 0)
643 goto done;
644
645 *vb = buf;
646done:
647 return retval;
648}
649
650int videobuf_dqbuf(struct videobuf_queue *q,
651 struct v4l2_buffer *b, int nonblocking)
652{
653 struct videobuf_buffer *buf = NULL;
654 int retval;
655
656 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
657
604 mutex_lock(&q->vb_lock); 658 mutex_lock(&q->vb_lock);
659
660 retval = stream_next_buffer(q, &buf, nonblocking);
605 if (retval < 0) { 661 if (retval < 0) {
606 dprintk(1, "dqbuf: waiton returned %d\n", retval); 662 dprintk(1, "dqbuf: next_buffer error: %i\n", retval);
607 goto done; 663 goto done;
608 } 664 }
665
609 switch (buf->state) { 666 switch (buf->state) {
610 case VIDEOBUF_ERROR: 667 case VIDEOBUF_ERROR:
611 dprintk(1, "dqbuf: state is error\n"); 668 dprintk(1, "dqbuf: state is error\n");
@@ -654,6 +711,7 @@ int videobuf_streamon(struct videobuf_queue *q)
654 if (q->irqlock) 711 if (q->irqlock)
655 spin_unlock_irqrestore(q->irqlock, flags); 712 spin_unlock_irqrestore(q->irqlock, flags);
656 713
714 wake_up_interruptible_sync(&q->wait);
657 done: 715 done:
658 mutex_unlock(&q->vb_lock); 716 mutex_unlock(&q->vb_lock);
659 return retval; 717 return retval;
@@ -666,7 +724,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q)
666 return -EINVAL; 724 return -EINVAL;
667 725
668 videobuf_queue_cancel(q); 726 videobuf_queue_cancel(q);
669 q->streaming = 0;
670 727
671 return 0; 728 return 0;
672} 729}
@@ -869,7 +926,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
869 q->bufs[i] = NULL; 926 q->bufs[i] = NULL;
870 } 927 }
871 q->read_buf = NULL; 928 q->read_buf = NULL;
872 q->reading = 0;
873 929
874} 930}
875 931
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
index fcdffdd63304..377a6c6e931b 100644
--- a/include/media/videobuf-core.h
+++ b/include/media/videobuf-core.h
@@ -153,6 +153,8 @@ struct videobuf_queue {
153 spinlock_t *irqlock; 153 spinlock_t *irqlock;
154 struct device *dev; 154 struct device *dev;
155 155
156 wait_queue_head_t wait; /* wait if queue is empty */
157
156 enum v4l2_buf_type type; 158 enum v4l2_buf_type type;
157 unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ 159 unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */
158 unsigned int msize; 160 unsigned int msize;