usb: dwc3: gadget: delay clearing run/stop when setup just arrived
There still exists a small window in which dwc3_gadget_pullup() is called while a new control transfer setup packet had newly arrived. In the case where it needs to be delegated to the gadget driver, it releases dwc3->lock and allows pullup() to proceed to call run_stop() to attempt to stop the controller. The lock will get released again when calling dwc3_stop_active_transfers() which allows the gadget driver to meanwhile call ep_queue() for a three-stage control transfer and sneak in a Start Transfer. By the time the DCTL register is written, the controller will fail to halt due to having an outstanding transfer in progress. CPU0 CPU1 ...dwc3->lock held... dwc3_ep0_inspect_setup() dwc3_gadget_pullup() dwc3_ep0_delegate_req() spin_lock_irq_save() spin_unlock() ... unblocked composite_setup() dwc3_gadget_run_stop() usb_ep_queue() dwc3_stop_active_transfers() dwc3_gadget_ep0_queue() dwc3_gadget_remove_requests() spin_lock_irqsave() dwc3_gadget_giveback() ... unblocked spin_unlock() __dwc3_ep0_do_control_data() spin_lock() issues Start Transfer spin_unlock_irqrestore() ... unblocked spin_lock() clear DCTL_RUN_STOP ... wait for DSTS_DEVCTRLHLT time out This change attempts to fix the issue by additionally checking the dwc->ep0_next_event state in dwc3_gadget_pullup() to catch the case when a SETUP packet had just been received and handled by dwc3_ep0_inspect_setup but is still waiting to proceed to either a DATA or STATUS stage. This allows pullup() to wait for completion of the transfer before moving on to clear run/stop. Change-Id: Ib2da3c86213ade1a61fb82f95a1f7c9534d9df3f Signed-off-by:Jack Pham <jackp@codeaurora.org> Signed-off-by:
Hemant Kumar <hemantk@codeaurora.org>
Loading
Please register or sign in to comment