summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2022-04-21 19:22:57 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-02-23 08:55:11 +0100
commit487341852fbc4328d8767753a3adc0c582697961 (patch)
treeade3437303ac49322550216221b4f47216f55a00
parent9273bd26b06d31cae0911c8405f69862db3bbc83 (diff)
downloadlinux-487341852fbc4328d8767753a3adc0c582697961.tar.gz
linux-487341852fbc4328d8767753a3adc0c582697961.tar.bz2
linux-487341852fbc4328d8767753a3adc0c582697961.zip
usb: dwc3: gadget: Only End Transfer for ep0 data phase
[ Upstream commit ace17b6ee4f92ab0375d12a1b42494f8590a96b6 ] The driver shouldn't be able to issue End Transfer to the control endpoint at anytime. Typically we should only do so in error cases such as invalid/unexpected direction of Data Phase as described in the control transfer flow of the programming guide. It _may_ end started data phase during controller deinitialization from soft disconnect or driver removal. However, that should not happen because the driver should be maintained in EP0_SETUP_PHASE during driver tear-down. On soft-connect, the controller should be reset from a soft-reset and there should be no issue starting the control endpoint. Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/3c6643678863a26702e4115e9e19d7d94a30d49c.1650593829.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Stable-dep-of: 730e12fbec53 ("usb: dwc3: gadget: Handle EP0 request dequeuing properly") Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/usb/dwc3/gadget.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 2afe6784f1df..4d830ba7d824 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -3647,6 +3647,17 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt)
{
+ struct dwc3 *dwc = dep->dwc;
+
+ /*
+ * Only issue End Transfer command to the control endpoint of a started
+ * Data Phase. Typically we should only do so in error cases such as
+ * invalid/unexpected direction as described in the control transfer
+ * flow of the programming guide.
+ */
+ if (dep->number <= 1 && dwc->ep0state != EP0_DATA_PHASE)
+ return;
+
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
(dep->flags & DWC3_EP_DELAY_STOP) ||
(dep->flags & DWC3_EP_END_TRANSFER_PENDING))