summaryrefslogtreecommitdiff
path: root/v4l_experimental/pvrusb2/pvrusb2-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'v4l_experimental/pvrusb2/pvrusb2-io.c')
-rw-r--r--v4l_experimental/pvrusb2/pvrusb2-io.c30
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);
}