diff options
-rw-r--r-- | drivers/usb/dwc3/ep0.c | 9 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 11 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.h | 1 |
3 files changed, 18 insertions, 3 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 1633807aee36..09318bceacfe 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -1123,13 +1123,18 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, __dwc3_ep0_do_control_status(dwc, dep); } -static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) +void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) { struct dwc3_gadget_ep_cmd_params params; u32 cmd; int ret; - if (!dep->resource_index) + /* + * For status/DATA OUT stage, TRB will be queued on ep0 out + * endpoint for which resource index is zero. Hence allow + * queuing ENDXFER command for ep0 out endpoint. + */ + if (!dep->resource_index && dep->number) return; cmd = DWC3_DEPCMD_ENDTRANSFER; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3cea65c86697..608352c70240 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2869,8 +2869,17 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) * that EP0 is in setup phase by issuing a stall * and restart if EP0 is not in setup phase. */ - if (dwc->ep0state != EP0_SETUP_PHASE) + if (dwc->ep0state != EP0_SETUP_PHASE) { + unsigned int dir; + + dbg_event(0xFF, "CONTRPEND", dwc->ep0state); + dir = !!dwc->ep0_expect_in; + if (dwc->ep0state == EP0_DATA_PHASE) + dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); + else + dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); dwc3_ep0_stall_and_restart(dwc); + } dwc3_stop_active_transfers(dwc); dwc3_clear_stall_all_ep(dwc); diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 5b3ffbe3056d..bbf9b5096846 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -98,6 +98,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, void dwc3_ep0_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event); void dwc3_ep0_out_start(struct dwc3 *dwc); +void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep); void dwc3_ep0_stall_and_restart(struct dwc3 *dwc); int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); |