diff options
author | Devin Heitmueller <dheitmueller@kernellabs.com> | 2017-04-20 02:13:55 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-06-06 13:52:20 +0300 |
commit | 53460c53b7619c14e8564a3ba2c60fc27f303f6b (patch) | |
tree | 11420d14544ff03e8d5a8791b3422ef2ad637bea /drivers/media/usb | |
parent | d7590b5704d6489ec5e6c7f65e90f8126a910b23 (diff) | |
download | linux-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.c | 30 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828.h | 2 |
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 */ |