V4L/DVB (8701): cx18: Add missing lock for when the irq handler manipulates the queues
cx18: Add missing lock for when the irq handler manipulates the queues. This was a potential source of stream queue corruption. Also changed the name of cx18_queue_find_buf() to cx18_queue_get_buf_irq(). Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
46f2c21cfd
commit
0058717a1e
@@ -61,7 +61,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
|
|||||||
CX18_WARN("Ack struct = %d for %s\n",
|
CX18_WARN("Ack struct = %d for %s\n",
|
||||||
mb->args[2], s->name);
|
mb->args[2], s->name);
|
||||||
id = read_enc(off);
|
id = read_enc(off);
|
||||||
buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
|
buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4));
|
||||||
CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
|
CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
cx18_buf_sync_for_cpu(s, buf);
|
cx18_buf_sync_for_cpu(s, buf);
|
||||||
|
@@ -78,12 +78,13 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
|
struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
|
||||||
u32 bytesused)
|
u32 bytesused)
|
||||||
{
|
{
|
||||||
struct cx18 *cx = s->cx;
|
struct cx18 *cx = s->cx;
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
|
|
||||||
|
spin_lock(&s->qlock);
|
||||||
list_for_each(p, &s->q_free.list) {
|
list_for_each(p, &s->q_free.list) {
|
||||||
struct cx18_buffer *buf =
|
struct cx18_buffer *buf =
|
||||||
list_entry(p, struct cx18_buffer, list);
|
list_entry(p, struct cx18_buffer, list);
|
||||||
@@ -92,17 +93,19 @@ struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
|
|||||||
continue;
|
continue;
|
||||||
buf->bytesused = bytesused;
|
buf->bytesused = bytesused;
|
||||||
/* the transport buffers are handled differently,
|
/* the transport buffers are handled differently,
|
||||||
so there is no need to move them to the full queue */
|
they are not moved to the full queue */
|
||||||
if (s->type == CX18_ENC_STREAM_TYPE_TS)
|
if (s->type != CX18_ENC_STREAM_TYPE_TS) {
|
||||||
return buf;
|
s->q_free.buffers--;
|
||||||
s->q_free.buffers--;
|
s->q_free.length -= s->buf_size;
|
||||||
s->q_free.length -= s->buf_size;
|
s->q_full.buffers++;
|
||||||
s->q_full.buffers++;
|
s->q_full.length += s->buf_size;
|
||||||
s->q_full.length += s->buf_size;
|
s->q_full.bytesused += buf->bytesused;
|
||||||
s->q_full.bytesused += buf->bytesused;
|
list_move_tail(&buf->list, &s->q_full.list);
|
||||||
list_move_tail(&buf->list, &s->q_full.list);
|
}
|
||||||
|
spin_unlock(&s->qlock);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
spin_unlock(&s->qlock);
|
||||||
CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
|
CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,7 @@ void cx18_queue_init(struct cx18_queue *q);
|
|||||||
void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
|
void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
|
||||||
struct cx18_queue *q);
|
struct cx18_queue *q);
|
||||||
struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
|
struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
|
||||||
struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
|
struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
|
||||||
u32 bytesused);
|
u32 bytesused);
|
||||||
void cx18_flush_queues(struct cx18_stream *s);
|
void cx18_flush_queues(struct cx18_stream *s);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user