From d3e500796dd16111a3df6bc7b530acffed6b135d Mon Sep 17 00:00:00 2001 From: William Wu Date: Wed, 15 Mar 2017 10:15:24 +0800 Subject: [PATCH] usb: dwc_otg_310: pcd: fix isoc in ep transfer issue When test usb gadget uvc function, we find a isoc in ep transfer bug that will cause uvc data transfer fail. The error case is: 1. The current EP request is done, call complete_ep() to completes the request, and then call start_next_request() to check the EP request queue, in this error case, the queue is empty, so it doesn't start next request, just set ep frame_num to 0xFFFFFFFF. 2. NAK Interrutp is triggered, check isoc ep frame_num is 0xFFFFFFFF, then reset the frame_num to 0, and then call start_next_request() to check the EP request queue, in this error case, the queue is still empty, so set ep frame_num to 0xFFFFFFFF again. But afer the above operation, the current code will modify the ep frame_num in NAK Interrutp handler by add ep bInterval to frame_num, this cause frame_num change again, but not keep in 0xFFFFFFFF, so the next NAK Interrutp handler doesn't start next request any more. This patch reset the frame_num to the current frame number got from DSTS SOFFN register if detect the frame_num is 0xFFFFFFFF in NAK Interrutp handler. And modify the frame_num in NAK Interrutp handler only when the frame_num is not 0xFFFFFFFF. TEST=Set usb gadget as webcam, use Ubuntu Guvcview to preview the webcam, observe the preview screen and the error log "There are no more ISOC requests". Change-Id: I4403a67b1d5d257d092a2a71d5666c5d6fd5af3c Signed-off-by: William Wu --- drivers/usb/dwc_otg_310/dwc_otg_pcd_intr.c | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/usb/dwc_otg_310/dwc_otg_pcd_intr.c b/drivers/usb/dwc_otg_310/dwc_otg_pcd_intr.c index ab0de79be9b7..5d7d1178ca19 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_pcd_intr.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd_intr.c @@ -4182,7 +4182,7 @@ do { \ depctl_data_t depctl; if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { ep->dwc_ep.frame_num = - core_if->frame_num; + dwc_otg_get_frame_number(core_if); if (ep->dwc_ep.bInterval > 1) { depctl.d32 = 0; depctl.d32 = @@ -4213,13 +4213,20 @@ do { \ } start_next_request(ep); } - ep->dwc_ep.frame_num += - ep->dwc_ep.bInterval; - if (dwc_ep->frame_num > 0x3FFF) { - dwc_ep->frm_overrun = 1; - dwc_ep->frame_num &= 0x3FFF; - } else - dwc_ep->frm_overrun = 0; + + if (ep->dwc_ep.frame_num != + 0xFFFFFFFF) { + ep->dwc_ep.frame_num += + ep->dwc_ep.bInterval; + if (dwc_ep->frame_num > + 0x3FFF) { + dwc_ep->frm_overrun = 1; + dwc_ep->frame_num &= + 0x3FFF; + } else { + dwc_ep->frm_overrun = 0; + } + } } CLEAR_IN_EP_INTR(core_if, epnum, nak); -- 2.34.1