From: Terry Heo Date: Thu, 28 Jul 2016 09:52:04 +0000 (-0300) Subject: [media] cx231xx: reset pipe endpoint when it is stalled X-Git-Tag: v4.9-rc1~43^2~468 X-Git-Url: http://git.cascardo.eti.br/?a=commitdiff_plain;h=69b17abf38eda6e02bc208cb779c948b13f2ad90;p=cascardo%2Flinux.git [media] cx231xx: reset pipe endpoint when it is stalled Sometimes, the USB pipe could enter into a stalled state, and may need a reset to rework. Add such logic. [mchehab@osg.samsung.com: ported from Android's source: https://android.googlesource.com/kernel/x86_64/+/3a322adc0084fd277b43070712c7dc0dc9245435%5E%21] Signed-off-by: Terry Heo Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index 630f4fc5155f..3e304bac3a70 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -799,7 +799,7 @@ static void cx231xx_isoc_irq_callback(struct urb *urb) case -ESHUTDOWN: return; default: /* error */ - cx231xx_isocdbg("urb completition error %d.\n", urb->status); + cx231xx_isocdbg("urb completion error %d.\n", urb->status); break; } @@ -842,8 +842,11 @@ static void cx231xx_bulk_irq_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: return; + case -EPIPE: /* stall */ + cx231xx_isocdbg("urb completion error - device is stalled.\n"); + return; default: /* error */ - cx231xx_isocdbg("urb completition error %d.\n", urb->status); + cx231xx_isocdbg("urb completion error %d.\n", urb->status); break; } @@ -867,6 +870,7 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; struct urb *urb; int i; + bool broken_pipe = false; cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n"); @@ -886,12 +890,19 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) transfer_buffer[i], urb->transfer_dma); } + if (urb->status == -EPIPE) { + broken_pipe = true; + } usb_free_urb(urb); dev->video_mode.isoc_ctl.urb[i] = NULL; } dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL; } + if (broken_pipe) { + cx231xx_isocdbg("Reset endpoint to recover broken pipe."); + usb_reset_endpoint(dev->udev, dev->video_mode.end_point_addr); + } kfree(dev->video_mode.isoc_ctl.urb); kfree(dev->video_mode.isoc_ctl.transfer_buffer); kfree(dma_q->p_left_data); @@ -918,6 +929,7 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; struct urb *urb; int i; + bool broken_pipe = false; cx231xx_isocdbg("cx231xx: called cx231xx_uninit_bulk\n"); @@ -937,12 +949,19 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) transfer_buffer[i], urb->transfer_dma); } + if (urb->status == -EPIPE) { + broken_pipe = true; + } usb_free_urb(urb); dev->video_mode.bulk_ctl.urb[i] = NULL; } dev->video_mode.bulk_ctl.transfer_buffer[i] = NULL; } + if (broken_pipe) { + cx231xx_isocdbg("Reset endpoint to recover broken pipe."); + usb_reset_endpoint(dev->udev, dev->video_mode.end_point_addr); + } kfree(dev->video_mode.bulk_ctl.urb); kfree(dev->video_mode.bulk_ctl.transfer_buffer); kfree(dma_q->p_left_data);