[mythtv-users] mythtv/pvr 250: why does it sometimes stop recording?

marduk marduk at python.net
Thu Oct 23 10:30:05 EDT 2003


Thanks for the patch (you guys are cool).  I'll give it a try tonite.

--a

On Thu, 2003-10-23 at 08:32, Jens Axboe wrote:
> 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);



More information about the mythtv-users mailing list