Re: [PATCH] usb: dwc3: gadget: Clear DWC3_EP_PENDING_REQUEST from non-0 endpoints

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Thinh

On 31/05/2023 09:55, Daniel Scally wrote:
The DWC3_EP_PENDING_REQUEST flag is set against an endpoint when
there are no pending or started requests available. This flag is
cleared on queuing to the endpoint for endpoint 0, but not for any
other endpoints. This can exacerbate timing problems by allowing a
queue to go ahead for an isochronous endpoint that should not be
started, so clear the flag upon a successful dwc3_gadget_ep_queue().

Signed-off-by: Daniel Scally <dan.scally@xxxxxxxxxxxxxxxx>
---


Just wanted to give some background on the timing issues that this is helping to relieve; we spotted this issue as a result of a "No resource for ep1in" error being thrown occasionally during repeated stream on/off tests for the UVC gadget on a platform using the DWC3; following the error stream won't restart unless you reboot. That error occurs when the gadget's workqueue function runs usb_ep_queue() whilst usb_ep_disable() is running during stream off. The DWC3 gadget code's locking plus the nulling of the endpoint descriptor during __dwc3_gadget_ep_disable() [1] and the check for that situation in __dwc3_gadget_ep_queue() [2] should make that harmless, but what occasionally happens is the dwc3_gadget_ep_queue() call sometimes manages to grab the lock when it's briefly unlocked during dwc3_gadget_giveback() [3]. That happens after the Stop Transfer command has been sent, so __dwc3_gadget_ep_queue() running through triggers a Start Transfer command, the dwc3_gadget_ep_disable() then finishes and stream shuts down, but when it's started back up again another Start Transfer command is sent and triggers the error. This patch ameliorates the impact of that race in my case, because clearing the flag prevents __dwc3_gadget_ep_queue() from running either __dwc3_gadget_start_isoc() or __dwc3_gadget_kick_transfer() for a non started isoc endpoint - but the race is still there. I think the potential for races is probably unavoidable given the unlock, but I thought it was worth explaining what lead to the patch in case it raises some issue that I'm missing.


Thanks

Dan


[1] https://elixir.bootlin.com/linux/latest/source/drivers/usb/dwc3/gadget.c#L1044
[2] https://elixir.bootlin.com/linux/latest/source/drivers/usb/dwc3/gadget.c#L1923
[3] https://elixir.bootlin.com/linux/latest/source/drivers/usb/dwc3/gadget.c#L216

  drivers/usb/dwc3/gadget.c | 8 ++++++--
  1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 578804dc29ca..bc1d93c56d82 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1988,13 +1988,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
  	 */
  	if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
  		if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) {
+			int ret = 0;
+
  			if ((dep->flags & DWC3_EP_PENDING_REQUEST))
-				return __dwc3_gadget_start_isoc(dep);
+				ret = __dwc3_gadget_start_isoc(dep);
- return 0;
+			dep->flags &= ~DWC3_EP_PENDING_REQUEST;
+			return ret;
  		}
  	}
+ dep->flags &= ~DWC3_EP_PENDING_REQUEST;
  	__dwc3_gadget_kick_transfer(dep);
return 0;



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux