Skip to content

Commit d2ee3ff

Browse files
Thinh Nguyenfelipebalbi
authored andcommitted
usb: dwc3: gadget: Fix handling ZLP
The usb_request->zero doesn't apply for isoc. Also, if we prepare a 0-length (ZLP) TRB for the OUT direction, we need to prepare an extra TRB to pad up to the MPS alignment. Use the same bounce buffer for the ZLP TRB and the extra pad TRB. Cc: <[email protected]> # v4.5+ Fixes: d6e5a54 ("usb: dwc3: simplify ZLP handling") Fixes: 04c03d1 ("usb: dwc3: gadget: handle request->zero") Signed-off-by: Thinh Nguyen <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 5d187c0 commit d2ee3ff

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

drivers/usb/dwc3/gadget.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
11991199
req->request.no_interrupt,
12001200
req->request.is_last);
12011201
} else if (req->request.zero && req->request.length &&
1202+
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
12021203
(IS_ALIGNED(req->request.length, maxp))) {
12031204
struct dwc3 *dwc = dep->dwc;
12041205
struct dwc3_trb *trb;
@@ -1208,14 +1209,25 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
12081209
/* prepare normal TRB */
12091210
dwc3_prepare_one_trb(dep, req, length, true, 0);
12101211

1211-
/* Now prepare one extra TRB to handle ZLP */
1212+
/* Prepare one extra TRB to handle ZLP */
12121213
trb = &dep->trb_pool[dep->trb_enqueue];
12131214
req->num_trbs++;
12141215
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
1215-
false, 1, req->request.stream_id,
1216+
!req->direction, 1, req->request.stream_id,
12161217
req->request.short_not_ok,
12171218
req->request.no_interrupt,
12181219
req->request.is_last);
1220+
1221+
/* Prepare one more TRB to handle MPS alignment for OUT */
1222+
if (!req->direction) {
1223+
trb = &dep->trb_pool[dep->trb_enqueue];
1224+
req->num_trbs++;
1225+
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp,
1226+
false, 1, req->request.stream_id,
1227+
req->request.short_not_ok,
1228+
req->request.no_interrupt,
1229+
req->request.is_last);
1230+
}
12191231
} else {
12201232
dwc3_prepare_one_trb(dep, req, length, false, 0);
12211233
}
@@ -2690,8 +2702,17 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
26902702
status);
26912703

26922704
if (req->needs_extra_trb) {
2705+
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
2706+
26932707
ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
26942708
status);
2709+
2710+
/* Reclaim MPS padding TRB for ZLP */
2711+
if (!req->direction && req->request.zero && req->request.length &&
2712+
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
2713+
(IS_ALIGNED(req->request.length, maxp)))
2714+
ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status);
2715+
26952716
req->needs_extra_trb = false;
26962717
}
26972718

0 commit comments

Comments
 (0)