Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ba24610 authored by Thinh Nguyen's avatar Thinh Nguyen Committed by Greg Kroah-Hartman
Browse files

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: c7fcdeb2 ("usb: dwc3: ep0: simplify EP0 state machine")
Fixes: d6e5a549 ("usb: dwc3: simplify ZLP handling")
Signed-off-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9b1f935a
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -935,12 +935,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)
@@ -987,9 +991,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 {