Skip to content

Commit 04c03d1

Browse files
author
Felipe Balbi
committed
usb: dwc3: gadget: handle request->zero
So far, dwc3 has always missed request->zero handling for every endpoint. Let's implement that so we can handle cases where transfer must be finished with a ZLP. Note that dwc3 is a little special. Even though we're dealing with a ZLP, we still need a buffer of wMaxPacketSize bytes; to hide that detail from every gadget driver, we have a preallocated buffer of 1024 bytes (biggest bulk size) to use (and share) among all endpoints. Reported-by: Ravi B <ravibabu@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
1 parent 3ff4b57 commit 04c03d1

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

drivers/usb/dwc3/core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define DWC3_MSG_MAX 500
3838

3939
/* Global constants */
40+
#define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */
4041
#define DWC3_EP0_BOUNCE_SIZE 512
4142
#define DWC3_ENDPOINTS_NUM 32
4243
#define DWC3_XHCI_RESOURCES_NUM 2
@@ -647,6 +648,7 @@ struct dwc3_scratchpad_array {
647648
* @ctrl_req: usb control request which is used for ep0
648649
* @ep0_trb: trb which is used for the ctrl_req
649650
* @ep0_bounce: bounce buffer for ep0
651+
* @zlp_buf: used when request->zero is set
650652
* @setup_buf: used while precessing STD USB requests
651653
* @ctrl_req_addr: dma address of ctrl_req
652654
* @ep0_trb: dma address of ep0_trb
@@ -734,6 +736,7 @@ struct dwc3 {
734736
struct usb_ctrlrequest *ctrl_req;
735737
struct dwc3_trb *ep0_trb;
736738
void *ep0_bounce;
739+
void *zlp_buf;
737740
void *scratchbuf;
738741
u8 *setup_buf;
739742
dma_addr_t ctrl_req_addr;

drivers/usb/dwc3/gadget.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,32 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
11591159
return ret;
11601160
}
11611161

1162+
static void __dwc3_gadget_ep_zlp_complete(struct usb_ep *ep,
1163+
struct usb_request *request)
1164+
{
1165+
dwc3_gadget_ep_free_request(ep, request);
1166+
}
1167+
1168+
static int __dwc3_gadget_ep_queue_zlp(struct dwc3 *dwc, struct dwc3_ep *dep)
1169+
{
1170+
struct dwc3_request *req;
1171+
struct usb_request *request;
1172+
struct usb_ep *ep = &dep->endpoint;
1173+
1174+
dwc3_trace(trace_dwc3_gadget, "queueing ZLP\n");
1175+
request = dwc3_gadget_ep_alloc_request(ep, GFP_ATOMIC);
1176+
if (!request)
1177+
return -ENOMEM;
1178+
1179+
request->length = 0;
1180+
request->buf = dwc->zlp_buf;
1181+
request->complete = __dwc3_gadget_ep_zlp_complete;
1182+
1183+
req = to_dwc3_request(request);
1184+
1185+
return __dwc3_gadget_ep_queue(dep, req);
1186+
}
1187+
11621188
static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
11631189
gfp_t gfp_flags)
11641190
{
@@ -1172,6 +1198,16 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
11721198

11731199
spin_lock_irqsave(&dwc->lock, flags);
11741200
ret = __dwc3_gadget_ep_queue(dep, req);
1201+
1202+
/*
1203+
* Okay, here's the thing, if gadget driver has requested for a ZLP by
1204+
* setting request->zero, instead of doing magic, we will just queue an
1205+
* extra usb_request ourselves so that it gets handled the same way as
1206+
* any other request.
1207+
*/
1208+
if (ret == 0 && request->zero && (request->length % ep->maxpacket == 0))
1209+
ret = __dwc3_gadget_ep_queue_zlp(dwc, dep);
1210+
11751211
spin_unlock_irqrestore(&dwc->lock, flags);
11761212

11771213
return ret;
@@ -2744,6 +2780,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
27442780
goto err3;
27452781
}
27462782

2783+
dwc->zlp_buf = kzalloc(DWC3_ZLP_BUF_SIZE, GFP_KERNEL);
2784+
if (!dwc->zlp_buf) {
2785+
ret = -ENOMEM;
2786+
goto err4;
2787+
}
2788+
27472789
dwc->gadget.ops = &dwc3_gadget_ops;
27482790
dwc->gadget.speed = USB_SPEED_UNKNOWN;
27492791
dwc->gadget.sg_supported = true;
@@ -2785,16 +2827,19 @@ int dwc3_gadget_init(struct dwc3 *dwc)
27852827

27862828
ret = dwc3_gadget_init_endpoints(dwc);
27872829
if (ret)
2788-
goto err4;
2830+
goto err5;
27892831

27902832
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
27912833
if (ret) {
27922834
dev_err(dwc->dev, "failed to register udc\n");
2793-
goto err4;
2835+
goto err5;
27942836
}
27952837

27962838
return 0;
27972839

2840+
err5:
2841+
kfree(dwc->zlp_buf);
2842+
27982843
err4:
27992844
dwc3_gadget_free_endpoints(dwc);
28002845
dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
@@ -2827,6 +2872,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
28272872
dwc->ep0_bounce, dwc->ep0_bounce_addr);
28282873

28292874
kfree(dwc->setup_buf);
2875+
kfree(dwc->zlp_buf);
28302876

28312877
dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
28322878
dwc->ep0_trb, dwc->ep0_trb_addr);

0 commit comments

Comments
 (0)