usbtuner: improve stability of bulk transfer mode
Terry Heo [Fri, 22 May 2015 07:49:43 +0000 (16:49 +0900)]
Fix memory leak issue on cx231xx_uninit_bulk().
And clear halt on cx231xx_init_bulk().

Bug: 20509486
Bug: 21312311

Bug 1736911

Change-Id: I5eb7c152263c09151853fe3ea27cf67e0d0d9fca
Signed-off-by: Terry Heo <terryheo@google.com>
Reviewed-on: http://git-master/r/1029829
(cherry picked from commit cc4b60a9ab1ffd77d0ea904928c634fecd187abb)
Reviewed-on: http://git-master/r/1311287
GVS: Gerrit_Virtual_Submit
Tested-by: Jean Huang <jeanh@nvidia.com>
Reviewed-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/1456501
Tested-by: Patrick Horng <phorng@nvidia.com>
Reviewed-by: Manish Tuteja <mtuteja@nvidia.com>

drivers/media/usb/cx231xx/cx231xx-core.c

index 3a1aa86..70f317e 100644 (file)
@@ -924,6 +924,7 @@ EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc);
  */
 void cx231xx_uninit_bulk(struct cx231xx *dev)
 {
+       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
        struct urb *urb;
        int i;
 
@@ -953,10 +954,12 @@ void cx231xx_uninit_bulk(struct cx231xx *dev)
 
        kfree(dev->video_mode.bulk_ctl.urb);
        kfree(dev->video_mode.bulk_ctl.transfer_buffer);
+       kfree(dma_q->p_left_data);
 
        dev->video_mode.bulk_ctl.urb = NULL;
        dev->video_mode.bulk_ctl.transfer_buffer = NULL;
        dev->video_mode.bulk_ctl.num_bufs = 0;
+       dma_q->p_left_data = NULL;
 
        if (dev->mode_tv == 0)
                cx231xx_capture_start(dev, 0, Raw_Video);
@@ -1203,6 +1206,15 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
                                  sb_size, cx231xx_bulk_irq_callback, dma_q);
        }
 
+       /* clear halt */
+       rc = usb_clear_halt(dev->udev, dev->video_mode.bulk_ctl.urb[0]->pipe);
+       if (rc < 0) {
+               cx231xx_err("failed to clear USB bulk endpoint stall/halt condition (error=%i)\n",
+                                       rc);
+               cx231xx_uninit_bulk(dev);
+               return rc;
+       }
+
        init_waitqueue_head(&dma_q->wq);
 
        /* submit urbs and enables IRQ */