Commit 69b17abf authored by Terry Heo's avatar Terry Heo Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarTerry Heo <terryheo@google.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 292eaf50
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -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);