Skip to content

Commit

Permalink
usb: dwc3: gadget: Fix handling ZLP
Browse files Browse the repository at this point in the history
[ Upstream commit d2ee3ff ]

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: <stable@vger.kernel.org> # v4.5+
Fixes: d6e5a54 ("usb: dwc3: simplify ZLP handling")
Fixes: 04c03d1 ("usb: dwc3: gadget: handle request->zero")
Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Thinh Nguyen authored and Greg Kroah-Hartman committed Sep 3, 2020
1 parent c4d7362 commit 7012bf6
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
req->request.short_not_ok,
req->request.no_interrupt);
} else if (req->request.zero && req->request.length &&
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
(IS_ALIGNED(req->request.length, maxp))) {
struct dwc3 *dwc = dep->dwc;
struct dwc3_trb *trb;
Expand All @@ -1168,13 +1169,23 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
/* prepare normal TRB */
dwc3_prepare_one_trb(dep, req, length, true, 0);

/* Now prepare one extra TRB to handle ZLP */
/* Prepare one extra TRB to handle ZLP */
trb = &dep->trb_pool[dep->trb_enqueue];
req->num_trbs++;
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
false, 1, req->request.stream_id,
!req->direction, 1, req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);

/* Prepare one more TRB to handle MPS alignment for OUT */
if (!req->direction) {
trb = &dep->trb_pool[dep->trb_enqueue];
req->num_trbs++;
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp,
false, 1, req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
}
} else {
dwc3_prepare_one_trb(dep, req, length, false, 0);
}
Expand Down Expand Up @@ -2347,8 +2358,17 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
status);

if (req->needs_extra_trb) {
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);

ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
status);

/* Reclaim MPS padding TRB for ZLP */
if (!req->direction && req->request.zero && req->request.length &&
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
(IS_ALIGNED(req->request.length, maxp)))
ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status);

req->needs_extra_trb = false;
}

Expand Down

0 comments on commit 7012bf6

Please sign in to comment.