summaryrefslogtreecommitdiff
path: root/drivers/media/usb
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2017-04-20 02:13:55 +0300
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-06-06 13:52:20 +0300
commit53460c53b7619c14e8564a3ba2c60fc27f303f6b (patch)
tree11420d14544ff03e8d5a8791b3422ef2ad637bea /drivers/media/usb
parentd7590b5704d6489ec5e6c7f65e90f8126a910b23 (diff)
downloadlinux-53460c53b7619c14e8564a3ba2c60fc27f303f6b.tar.xz
[media] au0828: Add timer to restart TS stream if no data arrives on bulk endpoint
For reasons unclear, we intermittently see a case where the tune is successful but the bulk stream fails to deliver any packets. Add a timer to automatically stop/start the data pump if we encounter such a case. Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/au0828/au0828-dvb.c30
-rw-r--r--drivers/media/usb/au0828/au0828.h2
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
index 7e0c9b795e52..34dc7e062471 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -105,6 +105,15 @@ static struct tda18271_config hauppauge_woodbury_tunerconfig = {
static void au0828_restart_dvb_streaming(struct work_struct *work);
+static void au0828_bulk_timeout(unsigned long data)
+{
+ struct au0828_dev *dev = (struct au0828_dev *) data;
+
+ dprintk(1, "%s called\n", __func__);
+ dev->bulk_timeout_running = 0;
+ schedule_work(&dev->restart_streaming);
+}
+
/*-------------------------------------------------------------------*/
static void urb_completion(struct urb *purb)
{
@@ -138,6 +147,13 @@ static void urb_completion(struct urb *purb)
ptr[0], purb->actual_length);
schedule_work(&dev->restart_streaming);
return;
+ } else if (dev->bulk_timeout_running == 1) {
+ /* The URB handler has fired, so cancel timer which would
+ * restart endpoint if we hadn't
+ */
+ dprintk(1, "%s cancelling bulk timeout\n", __func__);
+ dev->bulk_timeout_running = 0;
+ del_timer(&dev->bulk_timeout);
}
/* Feed the transport payload into the kernel demux */
@@ -160,6 +176,11 @@ static int stop_urb_transfer(struct au0828_dev *dev)
if (!dev->urb_streaming)
return 0;
+ if (dev->bulk_timeout_running == 1) {
+ dev->bulk_timeout_running = 0;
+ del_timer(&dev->bulk_timeout);
+ }
+
dev->urb_streaming = false;
for (i = 0; i < URB_COUNT; i++) {
if (dev->urbs[i]) {
@@ -232,6 +253,11 @@ static int start_urb_transfer(struct au0828_dev *dev)
}
dev->urb_streaming = true;
+
+ /* If we don't valid data within 1 second, restart stream */
+ mod_timer(&dev->bulk_timeout, jiffies + (HZ));
+ dev->bulk_timeout_running = 1;
+
return 0;
}
@@ -622,6 +648,10 @@ int au0828_dvb_register(struct au0828_dev *dev)
return ret;
}
+ dev->bulk_timeout.function = au0828_bulk_timeout;
+ dev->bulk_timeout.data = (unsigned long) dev;
+ init_timer(&dev->bulk_timeout);
+
return 0;
}
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 88e59748ebc2..05e445fe0b77 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -195,6 +195,8 @@ struct au0828_dev {
/* Digital */
struct au0828_dvb dvb;
struct work_struct restart_streaming;
+ struct timer_list bulk_timeout;
+ int bulk_timeout_running;
#ifdef CONFIG_VIDEO_AU0828_V4L2
/* Analog */