Hi Jun, On 10/31/2019 2:04 PM, Jun Chen wrote: > From: Jun Chen <jun.chen@xxxxxxxxxx> > > According to USB2.0 spec 8.5.3, "If the control sequence > has no Data stage, then it consists of a Setup stage > followed by a Status stage consisting of an IN transaction." > > But when doing control read in some HOST (like MS Windows), > after a SETUP transaction with no Data stage, the sequence > stay in the Status stage of an OUT transaction until timeout. > Could you please provide debug log of above scenario? > This patch Stall both IN and OUT on ep0 in status stage, > fix the unhandling state when we got an error command > with zero length control read request. > > It's also based on the USB2.0 spec 8.5.3.4, > "The protocol STALL condition lasts until the receipt of > the next SETUP transaction, and the function will return > STALL in response to any IN or OUT transaction on the pipe > until the SETUP transaction is received." > > Signed-off-by: Jun Chen <jun.chen@xxxxxxxxxx> > --- > drivers/usb/dwc2/gadget.c | 33 ++++++++++++++++++++------------- > 1 file changed, 20 insertions(+), 13 deletions(-) > > diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c > index 6be10e496..73b5944 100644 > --- a/drivers/usb/dwc2/gadget.c > +++ b/drivers/usb/dwc2/gadget.c > @@ -1853,23 +1853,30 @@ static void dwc2_hsotg_stall_ep0(struct dwc2_hsotg *hsotg) > struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; > u32 reg; > u32 ctrl; > + u32 direction; > > - dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); > - reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0; > + direction = ep0->dir_in; > + do { > + dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); > + reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0; > > - /* > - * DxEPCTL_Stall will be cleared by EP once it has > - * taken effect, so no need to clear later. > - */ > + /* > + * DxEPCTL_Stall will be cleared by EP once it has > + * taken effect, so no need to clear later. > + */ > > - ctrl = dwc2_readl(hsotg, reg); > - ctrl |= DXEPCTL_STALL; > - ctrl |= DXEPCTL_CNAK; > - dwc2_writel(hsotg, ctrl, reg); > + ctrl = dwc2_readl(hsotg, reg); > + ctrl |= DXEPCTL_STALL; > + ctrl |= DXEPCTL_CNAK; > + dwc2_writel(hsotg, ctrl, reg); > > - dev_dbg(hsotg->dev, > - "written DXEPCTL=0x%08x to %08x (DXEPCTL=0x%08x)\n", > - ctrl, reg, dwc2_readl(hsotg, reg)); > + dev_dbg(hsotg->dev, > + "written DXEPCTL=0x%08x to %08x (DXEPCTL=0x%08x)\n", > + ctrl, reg, dwc2_readl(hsotg, reg)); > + > + if (hsotg->ep0_state == DWC2_EP0_STATUS_IN) > + ep0->dir_in = (ep0->dir_in == 1) ? 0 : 1; > + } while (ep0->dir_in != direction); > > /* > * complete won't be called, so we enqueue > Thanks, Minas