[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