summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2020-09-24 11:21:43 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-11-05 13:07:00 +0300
commit388c2fdce04c07bc83283647867ce7334807d9d7 (patch)
tree24879825960ab2e4d6ba1611398586e0b7c650a5
parent0e8b5abab9da1b3183b88eacb39067381b7abdbf (diff)
downloadlinux-388c2fdce04c07bc83283647867ce7334807d9d7.tar.xz
usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
commit 66706077dc89c66a4777a4c6298273816afb848c upstream. The current ZLP handling for ep0 requests is only for control IN requests. For OUT direction, DWC3 needs to check and setup for MPS alignment. Usually, control OUT requests can indicate its transfer size via the wLength field of the control message. So usb_request->zero is usually not needed for OUT direction. To handle ZLP OUT for control endpoint, make sure the TRB is MPS size. Cc: stable@vger.kernel.org Fixes: c7fcdeb2627c ("usb: dwc3: ep0: simplify EP0 state machine") Fixes: d6e5a549cc4d ("usb: dwc3: simplify ZLP handling") Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Signed-off-by: Felipe Balbi <balbi@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/dwc3/ep0.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index cb50806d2459..f0d37a2fb66b 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -967,12 +967,16 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
struct dwc3_ep *dep, struct dwc3_request *req)
{
+ unsigned int trb_length = 0;
int ret;
req->direction = !!dep->number;
if (req->request.length == 0) {
- dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0,
+ if (!req->direction)
+ trb_length = dep->endpoint.maxpacket;
+
+ dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, trb_length,
DWC3_TRBCTL_CONTROL_DATA, false);
ret = dwc3_ep0_start_trans(dep);
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
@@ -1024,9 +1028,12 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];
+ if (!req->direction)
+ trb_length = dep->endpoint.maxpacket;
+
/* Now prepare one extra TRB to align transfer size */
dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
- 0, DWC3_TRBCTL_CONTROL_DATA,
+ trb_length, DWC3_TRBCTL_CONTROL_DATA,
false);
ret = dwc3_ep0_start_trans(dep);
} else {