[mythtv-users] mythtv/pvr 250: why does it sometimes stop
recording?
Jens Axboe
mythtv-users at kernel.dk
Thu Oct 23 16:32:20 EDT 2003
On Thu, Oct 23 2003, marduk wrote:
> It's an Intel chipset, but ...
>
> 1. It's an SMP machine, dunno if that could have something to do
> with it.
> 2. I'm running Linux 2.6.0-test8.
>
> I'll take it up with the ivtv people.
The ivtv driver is very racy in a lot of places... I just started
working through it this morning, a little progress is attached. A lot
more to be done, though. It would probably also be a really good idea to
make sure you don't have preempt enabled.
diff -ur ivtv.vanilla/driver/ivtv-driver.c ivtv/driver/ivtv-driver.c
--- ivtv.vanilla/driver/ivtv-driver.c 2003-10-03 07:17:14.000000000 +0200
+++ ivtv/driver/ivtv-driver.c 2003-10-23 13:19:44.000000000 +0200
@@ -165,21 +165,30 @@
}
}
-/* Adds buffers to the tail, effectively making a queue */
-int ivtv_enq_buf(struct ivtv_buffer_list *queue, struct ivtv_buffer *buf) {
+int ivtv_get_free_elements(struct ivtv_buffer_list *queue)
+{
unsigned long flags;
+ int elements;
spin_lock_irqsave(&queue->lock, flags);
+ elements = queue->elements;
+ spin_unlock_irqrestore(&queue->lock, flags);
+
+ return elements;
+}
+
+/* Adds buffers to the tail, effectively making a queue */
+int ivtv_enq_buf(struct ivtv_buffer_list *queue, struct ivtv_buffer *buf) {
+ unsigned long flags;
if (buf == NULL) {
IVTV_DEBUG(IVTV_DEBUG_ERR,"EnQ NULL buffer!\n");
- spin_unlock_irqrestore(&queue->lock, flags);
return -EINVAL;
}
+ spin_lock_irqsave(&queue->lock, flags);
list_add_tail(&buf->list, &queue->list);
queue->elements++;
-
spin_unlock_irqrestore(&queue->lock, flags);
return 0;
@@ -209,16 +218,13 @@
}
/* removes buffer from the head */
-struct ivtv_buffer *ivtv_deq_buf(struct ivtv_buffer_list *queue) {
+struct ivtv_buffer *__ivtv_deq_buf(struct ivtv_buffer_list *queue) {
struct ivtv_buffer *buf;
- unsigned long flags;
- spin_lock_irqsave(&queue->lock, flags);
/* make sure list has something to DeQ */
if (list_empty(&queue->list)) {
IVTV_DEBUG(IVTV_DEBUG_INFO,"DeQ from empty list!\n");
queue->elements = 0;
- spin_unlock_irqrestore(&queue->lock, flags);
return NULL;
}
@@ -230,6 +236,15 @@
queue->elements--;
+ return buf;
+}
+
+struct ivtv_buffer *ivtv_deq_buf(struct ivtv_buffer_list *queue) {
+ struct ivtv_buffer *buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->lock, flags);
+ buf = __ivtv_deq_buf(queue);
spin_unlock_irqrestore(&queue->lock, flags);
return buf;
@@ -260,6 +275,7 @@
int ivtv_free_queue(struct ivtv_buffer_list *queue) {
struct ivtv_buffer *item;
+ unsigned long flags;
struct ivtv *itv;
int x;
@@ -268,20 +284,22 @@
return -EINVAL;
}
+ spin_lock_irqsave(&queue->lock, flags);
+
/* FIXME ugly */
/* verify ivtv before continuing */
for (x = 0; x < ivtv_cards_active; x++) {
if (queue->vdev->priv == &ivtv_cards[x]) break;
if (x == (ivtv_cards_active - 1)) {
queue->elements = 0;
- return 0;
+ goto out;
}
}
itv=(struct ivtv *)queue->vdev->priv;
while (list_empty(&queue->list) == 0) {
- item = ivtv_deq_buf(queue);
+ item = __ivtv_deq_buf(queue);
/* FIXME no check to see if it's mapped or not */
pci_unmap_single(itv->dev, item->dma_handle,
IVTV_DMA_BUF_SIZE, PCI_DMA_TODEVICE);
@@ -294,7 +312,8 @@
}
queue->elements = 0;
-
+out:
+ spin_unlock_irqrestore(&queue->lock, flags);
return 0;
}
@@ -976,36 +995,19 @@
/* clean up queues */
/* move free_q to full_q to clean up partially-filled buffers */
- while (itv->v4l2.streams[id->type].free_q.elements > 0) {
- buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].free_q);
- if (buf == NULL) {
- IVTV_DEBUG(IVTV_DEBUG_ERR,
- "NULL buffer in close_stream (b)\n");
- break;
- }
+ while ((buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].free_q))) {
buf->buffer.bytesused=0;
buf->readpos=0;
ivtv_enq_buf(&itv->v4l2.streams[id->type].full_q, buf);
}
- while (itv->v4l2.streams[id->type].full_q.elements > 0) {
- buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].full_q);
- if (buf == NULL) {
- IVTV_DEBUG(IVTV_DEBUG_ERR,
- "NULL buffer in close_stream (a)\n");
- break;
- }
+ while ((buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].full_q))) {
buf->buffer.bytesused=0;
buf->readpos=0;
ivtv_enq_buf(&itv->v4l2.streams[id->type].free_q, buf);
}
- while (itv->v4l2.streams[id->type].dma_q.elements > 0) {
- buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].dma_q);
- if (buf == NULL) {
- IVTV_DEBUG(IVTV_DEBUG_ERR,
- "NULL buffer in close_stream (b)\n");
- break;
- }
+
+ while ((buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].dma_q))) {
buf->buffer.bytesused=0;
buf->readpos=0;
ivtv_enq_buf(&itv->v4l2.streams[id->type].free_q, buf);
--
Jens Axboe
More information about the mythtv-users
mailing list