summaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2/gadget.c
diff options
context:
space:
mode:
authorVahram Aharonyan <vahrama@synopsys.com>2016-11-14 19:16:48 -0800
committerFelipe Balbi <felipe.balbi@linux.intel.com>2016-11-18 13:54:48 +0200
commitf0afdb424162c896e534a70cac858ccb7a516bad (patch)
tree3ac2cf1b6f09dcca0b2c54cd1ffb6e219ba34174 /drivers/usb/dwc2/gadget.c
parent95d2b0370d3ce21796b98b41d166f6524e3610c6 (diff)
downloadlinux-f0afdb424162c896e534a70cac858ccb7a516bad.tar.bz2
usb: dwc2: gadget: For DDMA parse setup only after SetUp interrupt
Tests with various hosts show that depend on time difference between host sending SETUP packet and IN/OUT token SW could get Xfercomplete interrupt without SetUp interrupt. On the other hand, SW should parse received SETUP packet only after ensuring that Host has moved to either Data or Status stage of control transfer. For this purpose added checking in the dwc2_hsotg_epint() function to not handle xfercomplete and postpone SETUP packet analysis till SW's getting of setup phase done interrupt. Signed-off-by: Vahram Aharonyan <vahrama@synopsys.com> Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/dwc2/gadget.c')
-rw-r--r--drivers/usb/dwc2/gadget.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index d2442f421485..5930b1a3c8f0 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2838,6 +2838,16 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
if (idx == 0 && (ints & (DXEPINT_SETUP | DXEPINT_SETUP_RCVD)))
ints &= ~DXEPINT_XFERCOMPL;
+ /*
+ * Don't process XferCompl interrupt in DDMA if EP0 is still in SETUP
+ * stage and xfercomplete was generated without SETUP phase done
+ * interrupt. SW should parse received setup packet only after host's
+ * exit from setup phase of control transfer.
+ */
+ if (using_desc_dma(hsotg) && idx == 0 && !hs_ep->dir_in &&
+ hsotg->ep0_state == DWC2_EP0_SETUP && !(ints & DXEPINT_SETUP))
+ ints &= ~DXEPINT_XFERCOMPL;
+
if (ints & DXEPINT_XFERCOMPL) {
dev_dbg(hsotg->dev,
"%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n",