diff options
Diffstat (limited to 'v4l_experimental/pvrusb2/pvrusb2-io.c')
-rw-r--r-- | v4l_experimental/pvrusb2/pvrusb2-io.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/v4l_experimental/pvrusb2/pvrusb2-io.c b/v4l_experimental/pvrusb2/pvrusb2-io.c index 935978a14..c170bede0 100644 --- a/v4l_experimental/pvrusb2/pvrusb2-io.c +++ b/v4l_experimental/pvrusb2/pvrusb2-io.c @@ -1,6 +1,6 @@ /* * - * $Id: pvrusb2-io.c,v 1.1 2005/11/14 13:31:24 mchehab Exp $ + * $Id: pvrusb2-io.c,v 1.2 2006/01/09 06:54:46 mcisely Exp $ * * Copyright (C) 2005 Mike Isely <isely@pobox.com> * @@ -86,6 +86,9 @@ struct pvr2_stream { /* Overhead for mutex enforcement */ spinlock_t list_lock; struct semaphore sem; + /* Tracking state for tolerating errors */ + unsigned int fail_count; + unsigned int fail_tolerance; }; struct pvr2_buffer { @@ -437,19 +440,38 @@ static void buffer_complete(struct urb *urb, struct pt_regs *regs) { struct pvr2_buffer *bp = urb->context; struct pvr2_stream *sp; + unsigned long irq_flags; BUFFER_CHECK(bp); sp = bp->stream; bp->used_count = 0; + bp->status = 0; pvr2_trace(PVR2_TRACE_BUF_FLOW, "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d", bp,urb->status,urb->actual_length); + spin_lock_irqsave(&sp->list_lock,irq_flags); if ((!(urb->status)) || (urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (urb->status == -ESHUTDOWN)) { bp->used_count = urb->actual_length; + if (sp->fail_count) { + pvr2_trace(PVR2_TRACE_TOLERANCE, + "stream %p transfer ok" + " - fail count reset",sp); + sp->fail_count = 0; + } + } else if (sp->fail_count < sp->fail_tolerance) { + // We can tolerate this error, because we're below the + // threshold... + (sp->fail_count)++; + pvr2_trace(PVR2_TRACE_TOLERANCE, + "stream %p ignoring error %d" + " - fail count increased to %u", + sp,urb->status,sp->fail_count); + } else { + bp->status = urb->status; } - bp->status = urb->status; + spin_unlock_irqrestore(&sp->list_lock,irq_flags); pvr2_buffer_set_ready(bp); if (sp && sp->callback_func) { sp->callback_func(sp->callback_data); @@ -477,12 +499,14 @@ void pvr2_stream_destroy(struct pvr2_stream *sp) void pvr2_stream_setup(struct pvr2_stream *sp, struct usb_device *dev, - int endpoint) + int endpoint, + unsigned int tolerance) { down(&sp->sem); do { pvr2_stream_internal_flush(sp); sp->dev = dev; sp->endpoint = endpoint; + sp->fail_tolerance = tolerance; } while(0); up(&sp->sem); } |