Re: uvcvideo kernel panic when using libv4l

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With that patch, libv4l throws an error at some point, no crashes so far though:

libv4l2: error dequeuing buf: Invalid argument
read error 22, Invalid argument

On Tue, Dec 15, 2009 at 9:12 PM, Laurent Pinchart
<laurent.pinchart@xxxxxxxxxxxxxxxx> wrote:
> Hi Leandro and Pablo,
>
> could you please try the following patch ? It closes a race window that I
> believe could be at the core of your kernel panic.
>
> diff -r c1f376eae978 linux/drivers/media/video/uvc/uvc_queue.c
> --- a/linux/drivers/media/video/uvc/uvc_queue.c Sat Dec 12 18:57:17 2009 +0100
> +++ b/linux/drivers/media/video/uvc/uvc_queue.c Wed Dec 16 01:10:21 2009 +0100
> @@ -59,7 +59,7 @@
>  *    returns immediately.
>  *
>  *    When the buffer is full, the completion handler removes it from the irq
> - *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
> + *    queue, marks it as ready (UVC_BUF_STATE_READY) and wakes its wait queue.
>  *    At that point, any process waiting on the buffer will be woken up. If a
>  *    process tries to dequeue a buffer after it has been marked ready, the
>  *    dequeing will succeed immediately.
> @@ -196,11 +196,12 @@
>
>        switch (buf->state) {
>        case UVC_BUF_STATE_ERROR:
> -       case UVC_BUF_STATE_DONE:
> +       case UVC_BUF_STATE_READY:
>                v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
>                break;
>        case UVC_BUF_STATE_QUEUED:
>        case UVC_BUF_STATE_ACTIVE:
> +       case UVC_BUF_STATE_DONE:
>                v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
>                break;
>        case UVC_BUF_STATE_IDLE:
> @@ -341,13 +342,14 @@
>                uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
>                        "(transmission error).\n");
>                ret = -EIO;
> -       case UVC_BUF_STATE_DONE:
> +       case UVC_BUF_STATE_READY:
>                buf->state = UVC_BUF_STATE_IDLE;
>                break;
>
>        case UVC_BUF_STATE_IDLE:
>        case UVC_BUF_STATE_QUEUED:
>        case UVC_BUF_STATE_ACTIVE:
> +       case UVC_BUF_STATE_DONE:
>        default:
>                uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
>                        "(driver bug?).\n", buf->state);
> @@ -383,7 +385,7 @@
>        buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
>
>        poll_wait(file, &buf->wait, wait);
> -       if (buf->state == UVC_BUF_STATE_DONE ||
> +       if (buf->state == UVC_BUF_STATE_READY ||
>            buf->state == UVC_BUF_STATE_ERROR)
>                mask |= POLLIN | POLLRDNORM;
>
> @@ -489,6 +491,7 @@
>
>        spin_lock_irqsave(&queue->irqlock, flags);
>        list_del(&buf->queue);
> +       buf->state = UVC_BUF_STATE_READY;
>        if (!list_empty(&queue->irqqueue))
>                nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
>                                           queue);
> diff -r c1f376eae978 linux/drivers/media/video/uvc/uvc_video.c
> --- a/linux/drivers/media/video/uvc/uvc_video.c Sat Dec 12 18:57:17 2009 +0100
> +++ b/linux/drivers/media/video/uvc/uvc_video.c Wed Dec 16 01:10:21 2009 +0100
> @@ -578,8 +578,7 @@
>                uvc_video_decode_end(stream, buf, mem,
>                        urb->iso_frame_desc[i].actual_length);
>
> -               if (buf->state == UVC_BUF_STATE_DONE ||
> -                   buf->state == UVC_BUF_STATE_ERROR)
> +               if (buf->state == UVC_BUF_STATE_DONE)
>                        buf = uvc_queue_next_buffer(&stream->queue, buf);
>        }
>  }
> @@ -637,8 +636,7 @@
>                if (!stream->bulk.skip_payload && buf != NULL) {
>                        uvc_video_decode_end(stream, buf, stream->bulk.header,
>                                stream->bulk.payload_size);
> -                       if (buf->state == UVC_BUF_STATE_DONE ||
> -                           buf->state == UVC_BUF_STATE_ERROR)
> +                       if (buf->state == UVC_BUF_STATE_DONE)
>                                buf = uvc_queue_next_buffer(&stream->queue,
>                                                            buf);
>                }
> diff -r c1f376eae978 linux/drivers/media/video/uvc/uvcvideo.h
> --- a/linux/drivers/media/video/uvc/uvcvideo.h  Sat Dec 12 18:57:17 2009 +0100
> +++ b/linux/drivers/media/video/uvc/uvcvideo.h  Wed Dec 16 01:10:21 2009 +0100
> @@ -370,7 +370,8 @@
>        UVC_BUF_STATE_QUEUED    = 1,
>        UVC_BUF_STATE_ACTIVE    = 2,
>        UVC_BUF_STATE_DONE      = 3,
> -       UVC_BUF_STATE_ERROR     = 4,
> +       UVC_BUF_STATE_READY     = 4,
> +       UVC_BUF_STATE_ERROR     = 5,
>  };
>
>  struct uvc_buffer {
>
> --
> Regards,
>
> Laurent Pinchart
>



-- 
"Not possessing the gift of reflection, a dog does not know that he
does not know, and does not understand that he understands nothing;
we, on the other hand, are aware of both. If we behave otherwise, it
is from stupidity, or else from self-deception, to preserve our peace
of mind."
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux