提交 f576ceef 编写于 作者: A Andy Walls 提交者: Mauro Carvalho Chehab

V4L/DVB (9722): cx18: Convert per stream queue spinlocks into mutexes

Convert the per stream queue spinlocks into mutexes.  All queue
manipulation happens via the work queue or system calls into the driver, and
not in an interrupt context.  This reduces the amout of time the cx18 driver
keeps interrupts disabled.
Signed-off-by: NAndy Walls <awalls@radix.net>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 18b5dc2e
...@@ -271,7 +271,7 @@ struct cx18_stream { ...@@ -271,7 +271,7 @@ struct cx18_stream {
unsigned mdl_offset; unsigned mdl_offset;
u32 id; u32 id;
spinlock_t qlock; /* locks access to the queues */ struct mutex qlock; /* locks access to the queues */
unsigned long s_flags; /* status flags, see above */ unsigned long s_flags; /* status flags, see above */
int dma; /* can be PCI_DMA_TODEVICE, int dma; /* can be PCI_DMA_TODEVICE,
PCI_DMA_FROMDEVICE or PCI_DMA_FROMDEVICE or
......
...@@ -44,34 +44,31 @@ void cx18_queue_init(struct cx18_queue *q) ...@@ -44,34 +44,31 @@ 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)
{ {
unsigned long flags = 0;
/* clear the buffer if it is going to be enqueued to the free queue */ /* clear the buffer if it is going to be enqueued to the free queue */
if (q == &s->q_free) { if (q == &s->q_free) {
buf->bytesused = 0; buf->bytesused = 0;
buf->readpos = 0; buf->readpos = 0;
buf->b_flags = 0; buf->b_flags = 0;
} }
spin_lock_irqsave(&s->qlock, flags); mutex_lock(&s->qlock);
list_add_tail(&buf->list, &q->list); list_add_tail(&buf->list, &q->list);
atomic_inc(&q->buffers); atomic_inc(&q->buffers);
q->bytesused += buf->bytesused - buf->readpos; q->bytesused += buf->bytesused - buf->readpos;
spin_unlock_irqrestore(&s->qlock, flags); mutex_unlock(&s->qlock);
} }
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 *buf = NULL; struct cx18_buffer *buf = NULL;
unsigned long flags = 0;
spin_lock_irqsave(&s->qlock, flags); mutex_lock(&s->qlock);
if (!list_empty(&q->list)) { if (!list_empty(&q->list)) {
buf = list_entry(q->list.next, struct cx18_buffer, list); buf = list_entry(q->list.next, struct cx18_buffer, list);
list_del_init(q->list.next); list_del_init(q->list.next);
atomic_dec(&q->buffers); atomic_dec(&q->buffers);
q->bytesused -= buf->bytesused - buf->readpos; q->bytesused -= buf->bytesused - buf->readpos;
} }
spin_unlock_irqrestore(&s->qlock, flags); mutex_unlock(&s->qlock);
return buf; return buf;
} }
...@@ -80,9 +77,8 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, ...@@ -80,9 +77,8 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id,
{ {
struct cx18 *cx = s->cx; struct cx18 *cx = s->cx;
struct list_head *p; struct list_head *p;
unsigned long flags = 0;
spin_lock_irqsave(&s->qlock, flags); mutex_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);
...@@ -102,10 +98,10 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, ...@@ -102,10 +98,10 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id,
list_move_tail(&buf->list, &s->q_full.list); list_move_tail(&buf->list, &s->q_full.list);
} }
spin_unlock_irqrestore(&s->qlock, flags); mutex_unlock(&s->qlock);
return buf; return buf;
} }
spin_unlock_irqrestore(&s->qlock, flags); mutex_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;
} }
...@@ -113,13 +109,12 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, ...@@ -113,13 +109,12 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id,
/* Move all buffers of a queue to q_free, while flushing the buffers */ /* Move all buffers of a queue to q_free, while flushing the buffers */
static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
{ {
unsigned long flags;
struct cx18_buffer *buf; struct cx18_buffer *buf;
if (q == &s->q_free) if (q == &s->q_free)
return; return;
spin_lock_irqsave(&s->qlock, flags); mutex_lock(&s->qlock);
while (!list_empty(&q->list)) { while (!list_empty(&q->list)) {
buf = list_entry(q->list.next, struct cx18_buffer, list); buf = list_entry(q->list.next, struct cx18_buffer, list);
list_move_tail(q->list.next, &s->q_free.list); list_move_tail(q->list.next, &s->q_free.list);
...@@ -127,7 +122,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) ...@@ -127,7 +122,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
atomic_inc(&s->q_free.buffers); atomic_inc(&s->q_free.buffers);
} }
cx18_queue_init(q); cx18_queue_init(q);
spin_unlock_irqrestore(&s->qlock, flags); mutex_unlock(&s->qlock);
} }
void cx18_flush_queues(struct cx18_stream *s) void cx18_flush_queues(struct cx18_stream *s)
......
...@@ -132,7 +132,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) ...@@ -132,7 +132,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
s->buffers = 63; s->buffers = 63;
s->buf_size = (max_size / s->buffers) & ~0xfff; s->buf_size = (max_size / s->buffers) & ~0xfff;
} }
spin_lock_init(&s->qlock); mutex_init(&s->qlock);
init_waitqueue_head(&s->waitq); init_waitqueue_head(&s->waitq);
s->id = -1; s->id = -1;
cx18_queue_init(&s->q_free); cx18_queue_init(&s->q_free);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册