diff options
-rw-r--r-- | drivers/usb/dwc3/ep0.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index a6fc5c316743..f1e0a5eb0544 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c | |||
@@ -185,10 +185,29 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, | |||
185 | req->epnum = dep->number; | 185 | req->epnum = dep->number; |
186 | 186 | ||
187 | list_add_tail(&req->list, &dep->request_list); | 187 | list_add_tail(&req->list, &dep->request_list); |
188 | dwc3_map_buffer_to_dma(req); | 188 | if (req->request.length == 0) { |
189 | ret = dwc3_ep0_start_trans(dwc, dep->number, | ||
190 | dwc->ctrl_req_addr, 0); | ||
191 | } else if ((req->request.length % dep->endpoint.maxpacket) | ||
192 | && (dep->number == 0)) { | ||
193 | dwc->ep0_bounced = true; | ||
194 | |||
195 | WARN_ON(req->request.length > dep->endpoint.maxpacket); | ||
196 | |||
197 | /* | ||
198 | * REVISIT in case request length is bigger than EP0 | ||
199 | * wMaxPacketSize, we will need two chained TRBs to handle | ||
200 | * the transfer. | ||
201 | */ | ||
202 | ret = dwc3_ep0_start_trans(dwc, dep->number, | ||
203 | dwc->ep0_bounce_addr, dep->endpoint.maxpacket); | ||
204 | } else { | ||
205 | dwc3_map_buffer_to_dma(req); | ||
206 | |||
207 | ret = dwc3_ep0_start_trans(dwc, dep->number, | ||
208 | req->request.dma, req->request.length); | ||
209 | } | ||
189 | 210 | ||
190 | ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma, | ||
191 | req->request.length); | ||
192 | if (ret < 0) { | 211 | if (ret < 0) { |
193 | list_del(&req->list); | 212 | list_del(&req->list); |
194 | dwc3_unmap_buffer_from_dma(req); | 213 | dwc3_unmap_buffer_from_dma(req); |
@@ -655,8 +674,16 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, | |||
655 | 674 | ||
656 | dwc3_trb_to_nat(dwc->ep0_trb, &trb); | 675 | dwc3_trb_to_nat(dwc->ep0_trb, &trb); |
657 | 676 | ||
658 | transferred = ur->length - trb.length; | 677 | if (dwc->ep0_bounced) { |
659 | ur->actual += transferred; | 678 | struct dwc3_ep *ep0 = dwc->eps[0]; |
679 | |||
680 | transferred = min(ur->length, dep->endpoint.maxpacket - trb.length); | ||
681 | memcpy(ur->buf, dwc->ep0_bounce, transferred); | ||
682 | dwc->ep0_bounced = false; | ||
683 | } else { | ||
684 | transferred = ur->length - trb.length; | ||
685 | ur->actual += transferred; | ||
686 | } | ||
660 | 687 | ||
661 | if ((epnum & 1) && ur->actual < ur->length) { | 688 | if ((epnum & 1) && ur->actual < ur->length) { |
662 | /* for some reason we did not get everything out */ | 689 | /* for some reason we did not get everything out */ |