| From c0f4a91e640fa3781409bd37104482ccc3924a88 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 17 Aug 2022 11:23:52 -0700 |
| Subject: usb: dwc3: gadget: Force sending delayed status during soft |
| disconnect |
| |
| From: Wesley Cheng <quic_wcheng@quicinc.com> |
| |
| [ Upstream commit e1ee843488d58099a89979627ef85d5bd6c5cacd ] |
| |
| If any function drivers request for a delayed status phase, this leads to a |
| SETUP transfer timeout error, since the function may take longer to process |
| the DATA stage. This eventually results in end transfer timeouts, as there |
| is a pending SETUP transaction. |
| |
| In addition, allow the DWC3_EP_DELAY_STOP to be set for if there is a |
| delayed status requested. Ocasionally, a host may abort the current SETUP |
| transaction, by issuing a subsequent SETUP token. In those situations, it |
| would result in an endxfer timeout as well. |
| |
| Reviewed-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> |
| Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com> |
| Link: https://lore.kernel.org/r/20220817182359.13550-3-quic_wcheng@quicinc.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> |
| --- |
| drivers/usb/dwc3/gadget.c | 5 ++++- |
| 1 file changed, 4 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c |
| index b978e42ace75..ba1b2e70b351 100644 |
| --- a/drivers/usb/dwc3/gadget.c |
| +++ b/drivers/usb/dwc3/gadget.c |
| @@ -2470,6 +2470,9 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc) |
| if (dwc->ep0state != EP0_SETUP_PHASE) { |
| int ret; |
| |
| + if (dwc->delayed_status) |
| + dwc3_ep0_send_delayed_status(dwc); |
| + |
| reinit_completion(&dwc->ep0_in_setup); |
| |
| spin_unlock_irqrestore(&dwc->lock, flags); |
| @@ -3662,7 +3665,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, |
| * timeout. Delay issuing the End Transfer command until the Setup TRB is |
| * prepared. |
| */ |
| - if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) { |
| + if (dwc->ep0state != EP0_SETUP_PHASE) { |
| dep->flags |= DWC3_EP_DELAY_STOP; |
| return; |
| } |
| -- |
| 2.43.0 |
| |