[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