UPSTREAM: usb: dwc3: gadget: Don't delay End Transfer on delayed_status
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. Bug: 254441685 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> Link: https://lore.kernel.org/r/3f9f59e5d74efcbaee444cf4b30ef639cc7b124e.1666146954.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 4db0fbb601361767144e712beb96704b966339f5) Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: I308536a4d5482c838a1b75c84a1e1127e43f3b95
This commit is contained in:
parent
37b3a6153f
commit
f74be44246
@ -1683,6 +1683,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;
|
||||
|
||||
@ -3710,7 +3720,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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user