-
Elson Roy Serrao authored
There are two ways of clearing the halt condition. (1) host initiated through control transfer CLEAR_FEATURE(endpoint) (2) device requesting UDC to clear the halt endpoint. In (1), we stop the active transfer and wait for it before sending the status response for the control transfer. So it involves delayed_response i.e USB_GADGET_DELAYED_STATUS. In (2) there is no delayed response involved since it is not a control transfer. However the current code does not distinguish the part of handling delayed response upon ENDPONT command completion. In both cases, we try to send the delayed response. This can result into unexpected behavior when the delayed status is imposed for a different reason which gets cleared by the case (2) like explained in the below scenario. 1. Vendor specific control transfer returns USB_GADGET_DELAYED_STATUS. 2. DWC3 gadget sets dwc->delayed_status to '1'. 3. Another function driver issues a usb_ep_clear_halt() call. 4. DWC3 gadget issues dwc3_stop_active_transfer() and sets DWC3_EP_PENDING_CLEAR_STALL. 5. EP command complete interrupt triggers for the end transfer, and dwc3_ep0_send_delayed_status() is allowed to run, as delayed_status is '1' due to step#1. 6. STATUS phase is sent, and delayed_status is cleared. 7. Vendor specific control transfer is finished being handled, and issues usb_composite_setup_continue(). This results in queuing of a data phase. The dwc3_gadget_ep_set_halt() API invoked by the two cases above is distinguished by the protocol flag. Cache this protocol flag so that DWC3 gadget is aware of when the clear halt is due to a SETUP request from the host versus when it is sourced from a function driver. This allows for the EP command complete interrupt to know if it needs to issue a delayed status phase. Change-Id: I3b07bbda674103191a793319e3e2e09059eb2a25 Signed-off-by: Elson Roy Serrao <quic_eserrao@quicinc.com>
972f8a7b