summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2022-12-08 16:50:35 -0800
committerRay Chi <raychi@google.com>2023-04-28 11:36:35 +0000
commit2340d931ca78432e962713ec384bf8176e17ba68 (patch)
tree56642b94e90a06f684c515bd89eaa466444f7fba
parent59111294854008e97217c4e8e7c8013168eba954 (diff)
downloadgs-2340d931ca78432e962713ec384bf8176e17ba68.tar.gz
BACKPORT: usb: dwc3: gadget: Ignore End Transfer delay on teardown
If we delay sending End Transfer for Setup TRB to be prepared, we need to check if the End Transfer was in preparation for a driver teardown/soft-disconnect. In those cases, just send the End Transfer command without delay. In the case of soft-disconnect, there's a very small chance the command may not go through immediately. But should it happen, the Setup TRB will be prepared during the polling of the controller halted state, allowing the command to go through then. In the case of disabling endpoint due to reconfiguration (e.g. set_interface(alt-setting) or usb reset), then it's driven by the host. Typically the host wouldn't immediately cancel the control request and send another control transfer to trigger the End Transfer command timeout. Bug: 276227797 Fixes: 4db0fbb60136 ("usb: dwc3: gadget: Don't delay End Transfer on delayed_status") Cc: stable@vger.kernel.org Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/f1617a323e190b9cc408fb8b65456e32b5814113.1670546756.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit c4e3ef568539) Bug: 279882628 Change-Id: If49c07d3822e8d637f7dca337c895b0fd1a156f2 Signed-off-by: Ray Chi <raychi@google.com> (cherry picked from 2f2c6f2cf0602ca2b82c70c49aa4e3dab0ab8e11)
-rw-r--r--drivers/usb/dwc3/gadget.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 43aee7bc3d43..04e673d1ecd7 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1690,6 +1690,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
else if (!ret)
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+ dep->flags &= ~DWC3_EP_DELAY_STOP;
return ret;
}
@@ -3662,8 +3663,10 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
if (dep->number <= 1 && dwc->ep0state != EP0_DATA_PHASE)
return;
+ if (interrupt && (dep->flags & DWC3_EP_DELAY_STOP))
+ return;
+
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
- (dep->flags & DWC3_EP_DELAY_STOP) ||
(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
return;