Hi Robert,

On Tuesday 05 January 2010 13:49:34 Robert Lukassen wrote:
> Hi,
> 
> In Ubuntu 9.10, support for Video Out devices (bulk-only) has been added.

That's right. Just out of curiosity, could you tell me which video output 
device you're working with ? I'm only aware of a single one so far.

Support for isochronous video output devices could also be implemented, feel 
free to contact me if needed.

>  We noticed that when such a device is disconnected from a non-root hub,
>  the queued urbs are returned with usb->status == -EPROTO. The video
>  completion callback cancels the queue, and does not re-submit the urb.
> 
> Because the hub driver needs some time to process the disconnect properly,
>  there is a brief interval in time where queued urbs for the disconnected
>  device do not result in -ESHUTDOWN, as expected, but with other error
>  codes (such as EPROTO).
> 
> We have found that (in case of status == -EPROTO) resubmitting the urb and
>  not canceling the queue results in the correct behaviour. Eventually one
>  of the urbs indeed comes back with status == -ESHUTDOWN and the device is
>  properly administrated as disconnected. Subsequent QBUF attempts then also
>  result in correct user-space experience.
>
> We propose the following simple patch:
> 
> In uvc_video.c:
> 
> static void uvc_video_complete(struct urb *urb)
> {
>       struct uvc_video_device *video = urb->context;
>       struct uvc_video_queue *queue = &video->queue;
>       struct uvc_buffer *buf = NULL;
>       unsigned long flags;
>       int ret;
> 
>       switch (urb->status) {
>       case 0:
>               break;
> 
>       default:
>               uvc_printk(KERN_WARNING, "Non-zero status (%d) in video "
>                       "completion handler.\n", urb->status);
> +             break;
> 
>       case -ENOENT:           /* usb_kill_urb() called. */
>               if (video->frozen)
>                       return;
> 
>       case -ECONNRESET:       /* usb_unlink_urb() called. */
>       case -ESHUTDOWN:        /* The endpoint is being disabled. */
>               uvc_queue_cancel(queue, urb->status == -ESHUTDOWN);
>               return;
>       }
> 
>       spin_lock_irqsave(&queue->irqlock, flags);
>       if (!list_empty(&queue->irqqueue))
>               buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
>                                      queue);
>       spin_unlock_irqrestore(&queue->irqlock, flags);
> 
>       video->decode(urb, video, buf);
> 
>       if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
>               uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
>                       ret);
>       }
> }

That would work in your case, but devices that constantly return -EPROTO will 
never see their queue canceled and will flood the kernel log.

A possible solution would be to count the number of URBs returning with the -
EPROTO status and cancel the queue only when a hardcoded limit is reached. 
Could you count how many URBs you get back with a -EPROTO state before the 
driver receives -ESHUTDOWN ?

Another solution would be to cancel all buffer queues when the uvc_disconnect 
function is called. The QBUF ioctl could still be called during to "EPROTO - 
ESHUTDOWN" window, but buffers would be woken up again when uvc_disconnect is 
called.

The best solution might be a mix between those two: ignore -EPROTO/-EILSEQ/-
ETIME errors up to a maximum number (the threshold could be the total number 
or errors, or the number of consecutive errors), and cancel the queues anyway 
when the device is disconnected. What's your opinion ?

-- 
Regards,

Laurent Pinchart
_______________________________________________
Linux-uvc-devel mailing list
Linux-uvc-devel@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel

Reply via email to