usb: dwc3: gadget: Only End Transfer for ep0 data phase

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>
This commit is contained in:
Thinh Nguyen 2022-04-21 19:22:57 -07:00 committed by Greg Kroah-Hartman
parent c96683798e
commit ace17b6ee4

View File

@ -3685,6 +3685,17 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt) 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) || if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
(dep->flags & DWC3_EP_DELAY_STOP) || (dep->flags & DWC3_EP_DELAY_STOP) ||
(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) (dep->flags & DWC3_EP_END_TRANSFER_PENDING))