diff options
| author | Thinh Nguyen <Thinh.Nguyen@synopsys.com> | 2022-04-21 19:22:57 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-02-23 08:55:11 +0100 |
| commit | 487341852fbc4328d8767753a3adc0c582697961 (patch) | |
| tree | ade3437303ac49322550216221b4f47216f55a00 | |
| parent | 9273bd26b06d31cae0911c8405f69862db3bbc83 (diff) | |
| download | linux-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.c | 11 |
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)) |
