static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { switch (event->status) { case DEPEVT_STATUS_CONTROL_SETUP: dev_vdbg(dwc->dev, "Control Setup\n"); dwc3_ep0_do_control_setup(dwc, event); break; case DEPEVT_STATUS_CONTROL_DATA: dev_vdbg(dwc->dev, "Control Data\n"); if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) { dev_vdbg(dwc->dev, "Expected %d got %d\n", dwc->ep0_next_event, DWC3_EP0_NRDY_DATA); dwc3_ep0_stall_and_restart(dwc); return; } /* * One of the possible error cases is when Host _does_ * request for Data Phase, but it does so on the wrong * direction. * * Here, we already know ep0_next_event is DATA (see above), * so we only need to check for direction. */ if (dwc->ep0_expect_in != event->endpoint_number) { dev_vdbg(dwc->dev, "Wrong direction for Data phase\n"); dwc3_ep0_stall_and_restart(dwc); return; } dwc3_ep0_do_control_data(dwc, event); break; case DEPEVT_STATUS_CONTROL_STATUS: dev_vdbg(dwc->dev, "Control Status\n"); if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) { dev_vdbg(dwc->dev, "Expected %d got %d\n", dwc->ep0_next_event, DWC3_EP0_NRDY_STATUS); dwc3_ep0_stall_and_restart(dwc); return; } dwc3_ep0_do_control_status(dwc, event); } }
static void dwc3_ep0_complete_data(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r = NULL; struct usb_request *ur; struct dwc3_trb *trb; struct dwc3_ep *ep0; u32 transferred; u32 status; u32 length; u8 epnum; epnum = event->endpoint_number; ep0 = dwc->eps[0]; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; r = next_request(&ep0->request_list); ur = &r->request; trb = (struct dwc3_trb*)dwc->ep0_trb; status = trb->trbsts; if (status == DWC3_TRBSTS_SETUP_PENDING) { dev_dbg(dwc->dev, "Setup Pending received\n"); if (r) dwc3_gadget_giveback(ep0, r, -ECONNRESET); return; } length = trb->length; if (dwc->ep0_bounced) { unsigned transfer_size = ur->length; unsigned maxp = ep0->endpoint.maxpacket; transfer_size += (maxp - (transfer_size % maxp)); transferred = min_t(u32, ur->length, transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); } else { transferred = ur->length - length; } ur->actual += transferred; if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ dwc3_ep0_stall_and_restart(dwc); } else { /* * handle the case where we have to send a zero packet. This * seems to be case when req.length > maxpacket. Could it be? */ if (r) dwc3_gadget_giveback(ep0, r, 0); } }
/* * Send a zero length packet for the status phase of the control transfer */ static void dwc3_ep0_do_setup_status(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_ep *dep; int ret; u32 epnum; epnum = event->endpoint_number; dep = dwc->eps[epnum]; if (epnum) dwc->ep0state = EP0_IN_STATUS_PHASE; else dwc->ep0state = EP0_OUT_STATUS_PHASE; /* * Not sure Why I need a buffer for a zero transfer. Maybe the * HW reacts strange on a NULL pointer */ ret = dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, 0); if (ret) { dev_dbg(dwc->dev, "failed to start transfer, stalling\n"); dwc3_ep0_stall_and_restart(dwc); } }
static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct usb_ctrlrequest *ctrl = dwc->ctrl_req; int ret; u32 len; if (!dwc->gadget_driver) goto err; len = le16_to_cpu(ctrl->wLength); if (!len) { dwc->ep0state = EP0_IN_WAIT_GADGET; dwc->three_stage_setup = 0; } else { dwc->three_stage_setup = 1; if (ctrl->bRequestType & USB_DIR_IN) dwc->ep0state = EP0_IN_DATA_PHASE; else dwc->ep0state = EP0_OUT_DATA_PHASE; } if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) ret = dwc3_ep0_std_request(dwc, ctrl); else ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret >= 0) return; err: dwc3_ep0_stall_and_restart(dwc); }
static void dwc3_ep0_complete_req(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r; struct dwc3_ep *dep; dep = dwc->eps[0]; if (!list_empty(&dep->request_list)) { r = next_request(&dep->request_list); dwc3_gadget_giveback(dep, r, 0); } if (dwc->test_mode) { int ret; ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); if (ret < 0) { dev_dbg(dwc->dev, "Invalid Test #%d\n", dwc->test_mode_nr); dwc3_ep0_stall_and_restart(dwc); } } dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); }
static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct usb_ctrlrequest *ctrl = dwc->ctrl_req; int ret = -EINVAL; u32 len; if (!dwc->gadget_driver) goto out; len = le16_to_cpu(ctrl->wLength); if (!len) { dwc->three_stage_setup = false; dwc->ep0_expect_in = false; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; } else { dwc->three_stage_setup = true; dwc->ep0_expect_in = !!(ctrl->bRequestType & USB_DIR_IN); dwc->ep0_next_event = DWC3_EP0_NRDY_DATA; } if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) ret = dwc3_ep0_std_request(dwc, ctrl); else ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret == USB_GADGET_DELAYED_STATUS) dwc->delayed_status = true; out: if (ret < 0) dwc3_ep0_stall_and_restart(dwc); }
static void dwc3_ep0_complete_data(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r = NULL; struct usb_request *ur; struct dwc3_trb *trb; struct dwc3_ep *ep0; unsigned maxp; unsigned remaining_ur_length; void *buf; u32 transferred = 0; u32 status; u32 length; u8 epnum; epnum = event->endpoint_number; ep0 = dwc->eps[0]; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; trb = dwc->ep0_trb; trace_dwc3_complete_trb(ep0, trb); r = next_request(&ep0->pending_list); if (!r) return; status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (status == DWC3_TRBSTS_SETUP_PENDING) { dwc->setup_packet_pending = true; if (r) dwc3_gadget_giveback(ep0, r, -ECONNRESET); return; } ur = &r->request; buf = ur->buf; remaining_ur_length = ur->length; length = trb->size & DWC3_TRB_SIZE_MASK; maxp = ep0->endpoint.maxpacket; transferred = ur->length - length; ur->actual += transferred; if ((IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && ur->length && ur->zero) || dwc->ep0_bounced) { trb++; trb->ctrl &= ~DWC3_TRB_CTRL_HWO; trace_dwc3_complete_trb(ep0, trb); ep0->trb_enqueue = 0; dwc->ep0_bounced = false; } if ((epnum & 1) && ur->actual < ur->length) dwc3_ep0_stall_and_restart(dwc); else dwc3_gadget_giveback(ep0, r, 0); }
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) { struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; dwc3_ep0_stall_and_restart(dwc); return 0; }
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) { struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; dbg_event(dep->number, "EP0STAL", value); dwc3_ep0_stall_and_restart(dwc); return 0; }
static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { switch (event->status) { case DEPEVT_STATUS_CONTROL_DATA: /* * We already have a DATA transfer in the controller's cache, * if we receive a XferNotReady(DATA) we will ignore it, unless * it's for the wrong direction. * * In that case, we must issue END_TRANSFER command to the Data * Phase we already have started and issue SetStall on the * control endpoint. */ if (dwc->ep0_expect_in != event->endpoint_number) { struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in]; dev_err(dwc->dev, "unexpected direction for Data Phase\n"); dwc3_ep0_end_control_data(dwc, dep); dwc3_ep0_stall_and_restart(dwc); return; } break; case DEPEVT_STATUS_CONTROL_STATUS: if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) return; dwc->ep0state = EP0_STATUS_PHASE; if (dwc->delayed_status) { struct dwc3_ep *dep = dwc->eps[0]; WARN_ON_ONCE(event->endpoint_number != 1); /* * We should handle the delay STATUS phase here if the * request for handling delay STATUS has been queued * into the list. */ if (!list_empty(&dep->pending_list)) { dwc->delayed_status = false; usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); dwc3_ep0_do_control_status(dwc, event); } return; } dwc3_ep0_do_control_status(dwc, event); } }
static void dwc3_ep0_complete_data(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r = NULL; struct usb_request *ur; struct dwc3_trb trb; struct dwc3_ep *dep; u32 transferred; u8 epnum; epnum = event->endpoint_number; dep = dwc->eps[epnum]; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; if (!dwc->ep0_status_pending) { r = next_request(&dwc->eps[0]->request_list); ur = &r->request; } else { ur = &dwc->ep0_usb_req; dwc->ep0_status_pending = 0; } dwc3_trb_to_nat(dwc->ep0_trb, &trb); if (dwc->ep0_bounced) { struct dwc3_ep *ep0 = dwc->eps[0]; transferred = min_t(u32, ur->length, ep0->endpoint.maxpacket - trb.length); memcpy(ur->buf, dwc->ep0_bounce, transferred); dwc->ep0_bounced = false; } else { transferred = ur->length - trb.length; } ur->actual += transferred; if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ dwc3_ep0_stall_and_restart(dwc); } else { /* * handle the case where we have to send a zero packet. This * seems to be case when req.length > maxpacket. Could it be? */ if (r) dwc3_gadget_giveback(dep, r, 0); } }
static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { dwc->setup_packet_pending = true; switch (event->status) { case DEPEVT_STATUS_CONTROL_DATA: dwc3_trace(trace_dwc3_ep0, "Control Data"); /* * We already have a DATA transfer in the controller's cache, * if we receive a XferNotReady(DATA) we will ignore it, unless * it's for the wrong direction. * * In that case, we must issue END_TRANSFER command to the Data * Phase we already have started and issue SetStall on the * control endpoint. */ if (dwc->ep0_expect_in != event->endpoint_number) { struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in]; dwc3_trace(trace_dwc3_ep0, "Wrong direction for Data phase"); dwc3_ep0_end_control_data(dwc, dep); dwc3_ep0_stall_and_restart(dwc); return; } break; case DEPEVT_STATUS_CONTROL_STATUS: if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) return; dwc3_trace(trace_dwc3_ep0, "Control Status"); dwc->ep0state = EP0_STATUS_PHASE; if (dwc->delayed_status) { WARN_ON_ONCE(event->endpoint_number != 1); dwc3_trace(trace_dwc3_ep0, "Delayed Status"); return; } dwc3_ep0_do_control_status(dwc, event); } }
static void dwc3_ep0_complete_data(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r = NULL; struct usb_request *ur; struct dwc3_trb trb; struct dwc3_ep *dep; u32 transfered; u8 epnum; epnum = event->endpoint_number; dep = dwc->eps[epnum]; if (!dwc->ep0_status_pending) { r = next_request(&dep->request_list); ur = &r->request; } else { ur = &dwc->ep0_usb_req; dwc->ep0_status_pending = 0; } dwc3_trb_to_nat(dwc->ep0_trb, &trb); transfered = ur->length - trb.length; ur->actual += transfered; if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ dwc3_ep0_stall_and_restart(dwc); dwc3_gadget_giveback(dep, r, -ECONNRESET); } else { /* * handle the case where we have to send a zero packet. This * seems to be case when req.length > maxpacket. Could it be? */ /* The transfer is complete, wait for HOST */ if (epnum & 1) dwc->ep0state = EP0_IN_WAIT_NRDY; else dwc->ep0state = EP0_OUT_WAIT_NRDY; if (r) dwc3_gadget_giveback(dep, r, 0); } }
static void dwc3_ep0_complete_data(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r = NULL; struct usb_request *ur; struct dwc3_trb *trb; struct dwc3_ep *ep0; u32 transferred; u32 length; u8 epnum; epnum = event->endpoint_number; ep0 = dwc->eps[0]; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; r = next_request(&ep0->request_list); ur = &r->request; trb = dwc->ep0_trb; length = trb->size & DWC3_TRB_SIZE_MASK; if (dwc->ep0_bounced) { transferred = min_t(u32, ur->length, ep0->endpoint.maxpacket - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); dwc->ep0_bounced = false; } else { transferred = ur->length - length; ur->actual += transferred; } if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ dwc3_ep0_stall_and_restart(dwc); } else { /* * handle the case where we have to send a zero packet. This * seems to be case when req.length > maxpacket. Could it be? */ if (r) dwc3_gadget_giveback(ep0, r, 0); } }
static void dwc3_ep0_complete_status(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r; struct dwc3_ep *dep; struct dwc3_trb *trb; u32 status; dep = dwc->eps[0]; trb = dwc->ep0_trb; trace_dwc3_complete_trb(dep, trb); if (!list_empty(&dep->request_list)) { r = next_request(&dep->request_list); dwc3_gadget_giveback(dep, r, 0); } if (dwc->test_mode) { int ret; ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); if (ret < 0) { dwc3_trace(trace_dwc3_ep0, "Invalid Test #%d", dwc->test_mode_nr); dwc3_ep0_stall_and_restart(dwc); return; } } status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (status == DWC3_TRBSTS_SETUP_PENDING) { dwc->setup_packet_pending = true; dwc3_trace(trace_dwc3_ep0, "Setup Pending received"); } dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); }
static void dwc3_ep0_complete_status(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r; struct dwc3_ep *dep; struct dwc3_trb *trb; u32 status; dep = dwc->eps[0]; trb = dwc->ep0_trb; if (!list_empty(&dep->request_list)) { r = next_request(&dep->request_list); dwc3_gadget_giveback(dep, r, 0); } if (dwc->test_mode) { int ret; ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); if (ret < 0) { dev_dbg(dwc->dev, "Invalid Test #%d\n", dwc->test_mode_nr); dbg_event(0x00, "INVALTEST", ret); dwc3_ep0_stall_and_restart(dwc); return; } } status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (status == DWC3_TRBSTS_SETUP_PENDING) dev_dbg(dwc->dev, "Setup Pending received\n"); dbg_print(dep->number, "DONE", status, "STATUS"); dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); }
static void dwc3_ep0_complete_data(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r = NULL; struct usb_request *ur; struct dwc3_trb *trb; struct dwc3_ep *ep0; u32 transferred; u32 status; u32 length; u8 epnum; epnum = event->endpoint_number; ep0 = dwc->eps[0]; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; trb = dwc->ep0_trb; r = next_request(&ep0->request_list); if (!r) return; status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (status == DWC3_TRBSTS_SETUP_PENDING) { dev_dbg(dwc->dev, "Setup Pending received\n"); if (r) dwc3_gadget_giveback(ep0, r, -ECONNRESET); return; } if (dwc->ep0_zlp_sent) goto finish_zlp; ur = &r->request; length = trb->size & DWC3_TRB_SIZE_MASK; if (dwc->ep0_bounced) { unsigned transfer_size = ur->length; unsigned maxp = ep0->endpoint.maxpacket; transfer_size += (maxp - (transfer_size % maxp)); transferred = min_t(u32, ur->length, transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); } else { transferred = ur->length - length; } ur->actual += transferred; if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ dwc3_ep0_stall_and_restart(dwc); return; } /* handle the case where we have to send a zero packet */ if ((epnum & 1) && ur->zero && (ur->length % ep0->endpoint.maxpacket == 0)) { int ret; ret = dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, 0, DWC3_TRBCTL_CONTROL_DATA); WARN_ON(ret < 0); dwc->ep0_zlp_sent = 1; return; } finish_zlp: dwc3_gadget_giveback(ep0, r, 0); }
static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { dwc->setup_packet_pending = true; switch (event->status) { case DEPEVT_STATUS_CONTROL_DATA: dev_vdbg(dwc->dev, "Control Data\n"); /* * We already have a DATA transfer in the controller's cache, * if we receive a XferNotReady(DATA) we will ignore it, unless * it's for the wrong direction. * * In that case, we must issue END_TRANSFER command to the Data * Phase we already have started and issue SetStall on the * control endpoint. */ if (dwc->ep0_expect_in != event->endpoint_number) { struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in]; dev_vdbg(dwc->dev, "Wrong direction for Data phase\n"); dwc3_ep0_end_control_data(dwc, dep); dwc3_ep0_stall_and_restart(dwc); return; } /* * Per databook, if an XferNotready(Data) is received after * XferComplete(Data), one possible reason is host is trying * to complete data stage by moving a 0-length packet. * * REVISIT in case of other cases */ if (dwc->ep0_next_event == DWC3_EP0_NRDY_STATUS) { u32 size = 0; struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; if (dep->number == 0) size = dep->endpoint.maxpacket; dwc3_ep0_start_trans(dwc, dep->number, dwc->ctrl_req_addr, size, DWC3_TRBCTL_CONTROL_DATA); } break; case DEPEVT_STATUS_CONTROL_STATUS: if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) return; dev_vdbg(dwc->dev, "Control Status\n"); dwc->ep0state = EP0_STATUS_PHASE; if (dwc->delayed_status) { WARN_ON_ONCE(event->endpoint_number != 1); dev_vdbg(dwc->dev, "Mass Storage delayed status\n"); if (list_empty(&dwc->eps[0]->request_list)) return; else dwc->delayed_status = false; } dwc3_ep0_do_control_status(dwc, event); } }
static void dwc3_ep0_complete_data(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r = NULL; struct usb_request *ur; struct dwc3_trb *trb; struct dwc3_ep *ep0; unsigned transfer_size = 0; unsigned maxp; unsigned remaining_ur_length; void *buf; u32 transferred = 0; u32 status; u32 length; u8 epnum; epnum = event->endpoint_number; ep0 = dwc->eps[0]; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; trb = dwc->ep0_trb; trace_dwc3_complete_trb(ep0, trb); r = next_request(&ep0->request_list); if (!r) return; status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (status == DWC3_TRBSTS_SETUP_PENDING) { dwc->setup_packet_pending = true; dwc3_trace(trace_dwc3_ep0, "Setup Pending received"); if (r) dwc3_gadget_giveback(ep0, r, -ECONNRESET); return; } ur = &r->request; buf = ur->buf; remaining_ur_length = ur->length; length = trb->size & DWC3_TRB_SIZE_MASK; maxp = ep0->endpoint.maxpacket; if (dwc->ep0_bounced) { /* * Handle the first TRB before handling the bounce buffer if * the request length is greater than the bounce buffer size */ if (ur->length > DWC3_EP0_BOUNCE_SIZE) { transfer_size = ALIGN(ur->length - maxp, maxp); transferred = transfer_size - length; buf = (u8 *)buf + transferred; ur->actual += transferred; remaining_ur_length -= transferred; trb++; length = trb->size & DWC3_TRB_SIZE_MASK; ep0->free_slot = 0; } transfer_size = roundup((ur->length - transfer_size), maxp); transferred = min_t(u32, remaining_ur_length, transfer_size - length); memcpy(buf, dwc->ep0_bounce, transferred); } else { transferred = ur->length - length; } ur->actual += transferred; if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ dwc3_ep0_stall_and_restart(dwc); } else { dwc3_gadget_giveback(ep0, r, 0); if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && ur->length && ur->zero) { int ret; dwc->ep0_next_event = DWC3_EP0_COMPLETE; ret = dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, 0, DWC3_TRBCTL_CONTROL_DATA, false); WARN_ON(ret < 0); } } }
static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { dwc->setup_packet_pending = true; /* * This part is very tricky: If we has just handled * XferNotReady(Setup) and we're now expecting a * XferComplete but, instead, we receive another * XferNotReady(Setup), we should STALL and restart * the state machine. * * In all other cases, we just continue waiting * for the XferComplete event. * * We are a little bit unsafe here because we're * not trying to ensure that last event was, indeed, * XferNotReady(Setup). * * Still, we don't expect any condition where that * should happen and, even if it does, it would be * another error condition. */ if (dwc->ep0_next_event == DWC3_EP0_COMPLETE) { switch (event->status) { case DEPEVT_STATUS_CONTROL_SETUP: dev_vdbg(dwc->dev, "Unexpected XferNotReady(Setup)\n"); dwc3_ep0_stall_and_restart(dwc); break; case DEPEVT_STATUS_CONTROL_DATA: /* FALLTHROUGH */ case DEPEVT_STATUS_CONTROL_STATUS: /* FALLTHROUGH */ default: dev_vdbg(dwc->dev, "waiting for XferComplete\n"); } return; } switch (event->status) { case DEPEVT_STATUS_CONTROL_SETUP: dev_vdbg(dwc->dev, "Control Setup\n"); dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_do_control_setup(dwc, event); break; case DEPEVT_STATUS_CONTROL_DATA: dev_vdbg(dwc->dev, "Control Data\n"); dwc->ep0state = EP0_DATA_PHASE; if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) { dev_vdbg(dwc->dev, "Expected %d got %d\n", dwc->ep0_next_event, DWC3_EP0_NRDY_DATA); dwc3_ep0_stall_and_restart(dwc); return; } /* * One of the possible error cases is when Host _does_ * request for Data Phase, but it does so on the wrong * direction. * * Here, we already know ep0_next_event is DATA (see above), * so we only need to check for direction. */ if (dwc->ep0_expect_in != event->endpoint_number) { dev_vdbg(dwc->dev, "Wrong direction for Data phase\n"); dwc3_ep0_stall_and_restart(dwc); return; } dwc3_ep0_do_control_data(dwc, event); break; case DEPEVT_STATUS_CONTROL_STATUS: dev_vdbg(dwc->dev, "Control Status\n"); dwc->ep0state = EP0_STATUS_PHASE; if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) { dev_vdbg(dwc->dev, "Expected %d got %d\n", dwc->ep0_next_event, DWC3_EP0_NRDY_STATUS); dwc3_ep0_stall_and_restart(dwc); return; } if (dwc->delayed_status) { WARN_ON_ONCE(event->endpoint_number != 1); dev_vdbg(dwc->dev, "Mass Storage delayed status\n"); return; } dwc3_ep0_do_control_status(dwc, event->endpoint_number); } }
static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { u8 epnum; int ret; dwc->setup_packet_pending = true; epnum = event->endpoint_number; switch (event->status) { case DEPEVT_STATUS_CONTROL_DATA: dev_vdbg(dwc->dev, "Control Data\n"); /* * We already have a DATA transfer in the controller's cache, * if we receive a XferNotReady(DATA) we will ignore it, unless * it's for the wrong direction. * * In that case, we must issue END_TRANSFER command to the Data * Phase we already have started and issue SetStall on the * control endpoint. */ if (dwc->ep0_expect_in != event->endpoint_number) { struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in]; dev_vdbg(dwc->dev, "Wrong direction for Data phase\n"); dwc3_ep0_end_control_data(dwc, dep); dwc3_ep0_stall_and_restart(dwc); return; } if (zlp_required) { zlp_required = false; ret = dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, 0, DWC3_TRBCTL_CONTROL_DATA); dbg_event(epnum, "ZLP", ret); WARN_ON(ret < 0); } break; case DEPEVT_STATUS_CONTROL_STATUS: if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) return; dev_vdbg(dwc->dev, "Control Status\n"); zlp_required = false; dwc->ep0state = EP0_STATUS_PHASE; if (dwc->delayed_status && list_empty(&dwc->eps[0]->request_list)) { WARN_ON_ONCE(event->endpoint_number != 1); dev_vdbg(dwc->dev, "Mass Storage delayed status\n"); return; } dwc->delayed_status = false; dwc3_ep0_do_control_status(dwc, event); } }