| From ace17b6ee4f92ab0375d12a1b42494f8590a96b6 Mon Sep 17 00:00:00 2001 |
| From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> |
| Date: Thu, 21 Apr 2022 19:22:57 -0700 |
| Subject: [PATCH] usb: dwc3: gadget: Only End Transfer for ep0 data phase |
| Git-commit: ace17b6ee4f92ab0375d12a1b42494f8590a96b6 |
| References: git-fixes |
| Patch-mainline: v5.19-rc1 |
| |
| 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> |
| Signed-off-by: Oliver Neukum <oneukum@suse.com> |
| |
| drivers/usb/dwc3/gadget.c | 11 +++++++++++ |
| 1 file changed, 11 insertions(+) |
| |
| diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c |
| index 5e3311e3cc16..4f445f836d32 100644 |
| |
| |
| @@ -3685,6 +3685,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)) |
| -- |
| 2.40.1 |
| |