aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorBrandon Philips <bphilips@suse.de>2008-03-28 13:18:33 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:09:16 -0400
commit0cf4daee31d88086cf3508d1d8d1f4e451c27906 (patch)
tree522c7f2fa9bbac4682dd00776b606278c485bad5 /drivers/media/video
parentaa9479ed508d78dcd06479dc6274c9b02d1398df (diff)
V4L/DVB (7562): videobuf: Require spinlocks for all videobuf users
A spinlock is necessary for queue_cancel to work with every driver in the tree. Otherwise a race exists between IRQ handlers removing buffers from the queue and queue_cancel invalidating the queue. Signed-off-by: Brandon Philips <bphilips@suse.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/videobuf-core.c46
1 files changed, 18 insertions, 28 deletions
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index 45a8cbdf417d..848a2d0e1233 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -123,6 +123,9 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
123 BUG_ON(!q->ops->buf_queue); 123 BUG_ON(!q->ops->buf_queue);
124 BUG_ON(!q->ops->buf_release); 124 BUG_ON(!q->ops->buf_release);
125 125
126 /* Lock is mandatory for queue_cancel to work */
127 BUG_ON(!irqlock);
128
126 /* Having implementations for abstract methods are mandatory */ 129 /* Having implementations for abstract methods are mandatory */
127 BUG_ON(!q->int_ops); 130 BUG_ON(!q->int_ops);
128 131
@@ -180,8 +183,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
180 wake_up_interruptible_sync(&q->wait); 183 wake_up_interruptible_sync(&q->wait);
181 184
182 /* remove queued buffers from list */ 185 /* remove queued buffers from list */
183 if (q->irqlock) 186 spin_lock_irqsave(q->irqlock, flags);
184 spin_lock_irqsave(q->irqlock, flags);
185 for (i = 0; i < VIDEO_MAX_FRAME; i++) { 187 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
186 if (NULL == q->bufs[i]) 188 if (NULL == q->bufs[i])
187 continue; 189 continue;
@@ -191,8 +193,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
191 wake_up_all(&q->bufs[i]->done); 193 wake_up_all(&q->bufs[i]->done);
192 } 194 }
193 } 195 }
194 if (q->irqlock) 196 spin_unlock_irqrestore(q->irqlock, flags);
195 spin_unlock_irqrestore(q->irqlock, flags);
196 197
197 /* free all buffers + clear queue */ 198 /* free all buffers + clear queue */
198 for (i = 0; i < VIDEO_MAX_FRAME; i++) { 199 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
@@ -548,11 +549,9 @@ int videobuf_qbuf(struct videobuf_queue *q,
548 549
549 list_add_tail(&buf->stream, &q->stream); 550 list_add_tail(&buf->stream, &q->stream);
550 if (q->streaming) { 551 if (q->streaming) {
551 if (q->irqlock) 552 spin_lock_irqsave(q->irqlock, flags);
552 spin_lock_irqsave(q->irqlock, flags);
553 q->ops->buf_queue(q, buf); 553 q->ops->buf_queue(q, buf);
554 if (q->irqlock) 554 spin_unlock_irqrestore(q->irqlock, flags);
555 spin_unlock_irqrestore(q->irqlock, flags);
556 } 555 }
557 dprintk(1, "qbuf: succeded\n"); 556 dprintk(1, "qbuf: succeded\n");
558 retval = 0; 557 retval = 0;
@@ -689,13 +688,11 @@ int videobuf_streamon(struct videobuf_queue *q)
689 if (q->streaming) 688 if (q->streaming)
690 goto done; 689 goto done;
691 q->streaming = 1; 690 q->streaming = 1;
692 if (q->irqlock) 691 spin_lock_irqsave(q->irqlock, flags);
693 spin_lock_irqsave(q->irqlock, flags);
694 list_for_each_entry(buf, &q->stream, stream) 692 list_for_each_entry(buf, &q->stream, stream)
695 if (buf->state == VIDEOBUF_PREPARED) 693 if (buf->state == VIDEOBUF_PREPARED)
696 q->ops->buf_queue(q, buf); 694 q->ops->buf_queue(q, buf);
697 if (q->irqlock) 695 spin_unlock_irqrestore(q->irqlock, flags);
698 spin_unlock_irqrestore(q->irqlock, flags);
699 696
700 wake_up_interruptible_sync(&q->wait); 697 wake_up_interruptible_sync(&q->wait);
701 done: 698 done:
@@ -751,11 +748,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
751 goto done; 748 goto done;
752 749
753 /* start capture & wait */ 750 /* start capture & wait */
754 if (q->irqlock) 751 spin_lock_irqsave(q->irqlock, flags);
755 spin_lock_irqsave(q->irqlock, flags);
756 q->ops->buf_queue(q, q->read_buf); 752 q->ops->buf_queue(q, q->read_buf);
757 if (q->irqlock) 753 spin_unlock_irqrestore(q->irqlock, flags);
758 spin_unlock_irqrestore(q->irqlock, flags);
759 retval = videobuf_waiton(q->read_buf, 0, 0); 754 retval = videobuf_waiton(q->read_buf, 0, 0);
760 if (0 == retval) { 755 if (0 == retval) {
761 CALL(q, sync, q, q->read_buf); 756 CALL(q, sync, q, q->read_buf);
@@ -816,12 +811,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
816 q->read_buf = NULL; 811 q->read_buf = NULL;
817 goto done; 812 goto done;
818 } 813 }
819 if (q->irqlock)
820 spin_lock_irqsave(q->irqlock, flags);
821 814
815 spin_lock_irqsave(q->irqlock, flags);
822 q->ops->buf_queue(q, q->read_buf); 816 q->ops->buf_queue(q, q->read_buf);
823 if (q->irqlock) 817 spin_unlock_irqrestore(q->irqlock, flags);
824 spin_unlock_irqrestore(q->irqlock, flags); 818
825 q->read_off = 0; 819 q->read_off = 0;
826 } 820 }
827 821
@@ -887,12 +881,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
887 return err; 881 return err;
888 list_add_tail(&q->bufs[i]->stream, &q->stream); 882 list_add_tail(&q->bufs[i]->stream, &q->stream);
889 } 883 }
890 if (q->irqlock) 884 spin_lock_irqsave(q->irqlock, flags);
891 spin_lock_irqsave(q->irqlock, flags);
892 for (i = 0; i < count; i++) 885 for (i = 0; i < count; i++)
893 q->ops->buf_queue(q, q->bufs[i]); 886 q->ops->buf_queue(q, q->bufs[i]);
894 if (q->irqlock) 887 spin_unlock_irqrestore(q->irqlock, flags);
895 spin_unlock_irqrestore(q->irqlock, flags);
896 q->reading = 1; 888 q->reading = 1;
897 return 0; 889 return 0;
898} 890}
@@ -1004,11 +996,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
1004 if (q->read_off == q->read_buf->size) { 996 if (q->read_off == q->read_buf->size) {
1005 list_add_tail(&q->read_buf->stream, 997 list_add_tail(&q->read_buf->stream,
1006 &q->stream); 998 &q->stream);
1007 if (q->irqlock) 999 spin_lock_irqsave(q->irqlock, flags);
1008 spin_lock_irqsave(q->irqlock, flags);
1009 q->ops->buf_queue(q, q->read_buf); 1000 q->ops->buf_queue(q, q->read_buf);
1010 if (q->irqlock) 1001 spin_unlock_irqrestore(q->irqlock, flags);
1011 spin_unlock_irqrestore(q->irqlock, flags);
1012 q->read_buf = NULL; 1002 q->read_buf = NULL;
1013 } 1003 }
1014 if (retval < 0) 1004 if (retval < 0)