usb: dwc3: gadget: Prevent queue on endpoints after bus reset

There is a race between ep_queue from function driver and
ep_disable during function disable as part of bus reset.
This race is leading to a scenario where the endpoint is
disabled with an active transfer. And when the endpoint is enabled
back, this leads to a stale buffer access by the controller.

The race is as below:
						qdss_disable
usb_qdss_write					    |  -----> Waits on qdss_lock
     |  ----> Acquires qdss_lock		    |
     |  ----> Checks for qdss_connected		    |
     |  ----> Releases qdss_lock		    |  ------> Acquires qdss_lock
     |						    |  ------> Clears usb_connected
     |						    |  ------> Releases qdss_lock
     |						usb_ep_disable
     |						    |  ------> Acquires dwc->lock
     |						dwc3_remove_reuests
     |						    |
     |						dwc3_stop_active_transfer
     |						    |
     |						    |  ------> Releases dwc->lock
usb_ep_queue					    |
     | ----> Acquires dwc->lock			usb_gadget_giveback
     |						    |
dwc3_gadget_kick_transfer			    |
     | ----> Releases dwc->lock			    |
						    | ----> Acquires dwc->lock
						    |
						disable_endpoint

After this state when the endpoint is enabled back, there is already
and active transfer on this endpoint. Any START TRANSFER command
on this endpoint would lead to "No Transfer Resource" error
from the controller.

Fix this by preventing the ep_queue when a reset of the gadget
is in progress. This is done by clearing the connected flag
as part of dwc3_gadget_reset and checking for this as part of
ep_queue. Set this flag once we have received the CONNECTION
DONE interrupt from the controller.

Signed-off-by: Sriharsha Allenki <sallenki@codeaurora.org>

Bug: 189997061
Bug: 203135867
Test: Build Pass
Signed-off-by: Jimmy Hu <hhhuuu@google.com>
Signed-off-by: Peggy Chan <peichi@google.com>
Change-Id: Ieaab0b9a3025a224e0b68324de5f089ff402bfe4
1 file changed