Message ID | 3f9f59e5d74efcbaee444cf4b30ef639cc7b124e.1666146954.git.Thinh.Nguyen@synopsys.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 4db0fbb601361767144e712beb96704b966339f5 |
Headers | show |
Series | [v2] usb: dwc3: gadget: Don't delay End Transfer on delayed_status | expand |
On 10/18/2022 7:39 PM, Thinh Nguyen wrote: > The gadget driver may wait on the request completion when it sets the > USB_GADGET_DELAYED_STATUS. Make sure that the End Transfer command can > go through if the dwc->delayed_status is set so that the request can > complete. When the delayed_status is set, the Setup packet is already > processed, and the next phase should be either Data or Status. It's > unlikely that the host would cancel the control transfer and send a new > Setup packet during End Transfer command. But if that's the case, we can > try again when ep0state returns to EP0_SETUP_PHASE. Hi Thinh, In the scenario you saw your issue in, was there something else that triggered the EP0 stall and restart to bring back EP0 to SETUP state? (which will do the retry) Just wanted to make sure, because there were situations that I had to add that sequence for the endxfer retry to happen. (ie in the disconnect interrupt) Thanks Wesley Cheng > > Fixes: e1ee843488d5 ("usb: dwc3: gadget: Force sending delayed status during soft disconnect") > Cc: stable@vger.kernel.org > Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> > --- > Changes in v2: > - Fix build issue due to cherry-picking... > > drivers/usb/dwc3/gadget.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index 079cd333632e..dd8ecbe61bec 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -1698,6 +1698,16 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int > cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); > memset(¶ms, 0, sizeof(params)); > ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); > + /* > + * If the End Transfer command was timed out while the device is > + * not in SETUP phase, it's possible that an incoming Setup packet > + * may prevent the command's completion. Let's retry when the > + * ep0state returns to EP0_SETUP_PHASE. > + */ > + if (ret == -ETIMEDOUT && dep->dwc->ep0state != EP0_SETUP_PHASE) { > + dep->flags |= DWC3_EP_DELAY_STOP; > + return 0; > + } > WARN_ON_ONCE(ret); > dep->resource_index = 0; > > @@ -3719,7 +3729,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, > * timeout. Delay issuing the End Transfer command until the Setup TRB is > * prepared. > */ > - if (dwc->ep0state != EP0_SETUP_PHASE) { > + if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) { > dep->flags |= DWC3_EP_DELAY_STOP; > return; > } > > base-commit: 9abf2313adc1ca1b6180c508c25f22f9395cc780
On Wed, Oct 19, 2022, Wesley Cheng wrote: > > > On 10/18/2022 7:39 PM, Thinh Nguyen wrote: > > The gadget driver may wait on the request completion when it sets the > > USB_GADGET_DELAYED_STATUS. Make sure that the End Transfer command can > > go through if the dwc->delayed_status is set so that the request can > > complete. When the delayed_status is set, the Setup packet is already > > processed, and the next phase should be either Data or Status. It's > > unlikely that the host would cancel the control transfer and send a new > > Setup packet during End Transfer command. But if that's the case, we can > > try again when ep0state returns to EP0_SETUP_PHASE. > > Hi Thinh, > > In the scenario you saw your issue in, was there something else that > triggered the EP0 stall and restart to bring back EP0 to SETUP state? (which > will do the retry) Just wanted to make sure, because there were situations > that I had to add that sequence for the endxfer retry to happen. (ie in the > disconnect interrupt) > My scenario happens while the device is connected and not related to soft-disconnect. It doesn't involve cancellation of the control transfer. The scenario you mentioned in your change is related to soft-disconnect right? "Ocasionally, a host may abort the current SETUP transaction, by issuing a subsequent SETUP token. In those situations, it would result in an endxfer timeout as well." I added a check to retry End Transfer to account for the scenario you reported. Thanks, Thinh
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 079cd333632e..dd8ecbe61bec 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1698,6 +1698,16 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); memset(¶ms, 0, sizeof(params)); ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); + /* + * If the End Transfer command was timed out while the device is + * not in SETUP phase, it's possible that an incoming Setup packet + * may prevent the command's completion. Let's retry when the + * ep0state returns to EP0_SETUP_PHASE. + */ + if (ret == -ETIMEDOUT && dep->dwc->ep0state != EP0_SETUP_PHASE) { + dep->flags |= DWC3_EP_DELAY_STOP; + return 0; + } WARN_ON_ONCE(ret); dep->resource_index = 0; @@ -3719,7 +3729,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, * timeout. Delay issuing the End Transfer command until the Setup TRB is * prepared. */ - if (dwc->ep0state != EP0_SETUP_PHASE) { + if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) { dep->flags |= DWC3_EP_DELAY_STOP; return; }
The gadget driver may wait on the request completion when it sets the USB_GADGET_DELAYED_STATUS. Make sure that the End Transfer command can go through if the dwc->delayed_status is set so that the request can complete. When the delayed_status is set, the Setup packet is already processed, and the next phase should be either Data or Status. It's unlikely that the host would cancel the control transfer and send a new Setup packet during End Transfer command. But if that's the case, we can try again when ep0state returns to EP0_SETUP_PHASE. Fixes: e1ee843488d5 ("usb: dwc3: gadget: Force sending delayed status during soft disconnect") Cc: stable@vger.kernel.org Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> --- Changes in v2: - Fix build issue due to cherry-picking... drivers/usb/dwc3/gadget.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) base-commit: 9abf2313adc1ca1b6180c508c25f22f9395cc780