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); }
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_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 = dwc->ep0_trb; 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; } 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); } 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_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); } } }