[U-Boot] [PATCH] fastboot: Fix OUT transaction length alignment

Semen Protsenko semen.protsenko at linaro.org
Wed Apr 13 14:01:02 CEST 2016


From: Sam Protsenko <semen.protsenko at linaro.org>

Some UDC controllers may require buffer size to be aligned to
wMaxPacketSize. It's indicated by gadget->quirk_ep_out_aligned_size
field being set to "true" (in UDC driver code). In that case
rx_bytes_expected must be aligned to wMaxPacket size, otherwise stuck on
transaction will happen. For example, it's required by DWC3 controller
data manual:

    section 8.2.3.3 Buffer Size Rules and Zero-Length Packets:

    For OUT endpoints, the following rules apply:
    - The BUFSIZ field must be ≥ 1 byte.
    - The total size of a Buffer Descriptor must be a multiple of
      MaxPacketSize
    - A received zero-length packet still requires a MaxPacketSize buffer.
      Therefore, if the expected amount of data to be received is a multiple
      of MaxPacketSize, software should add MaxPacketSize bytes to the buffer
      to sink a possible zero-length packet at the end of the transfer.

But other UDC controllers don't need such alignment, so mentioned field
is set to "false". If buffer size is aligned to wMaxPacketSize, those
controllers may stuck on transaction. The example is DWC2.

This patch checks gadget->quirk_ep_out_aligned_size field and aligns
rx_bytes_expected to wMaxPacketSize only when it's needed.

Signed-off-by: Sam Protsenko <semen.protsenko at linaro.org>
---
 drivers/usb/gadget/f_fastboot.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 2e87fee..54dcce0 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -58,6 +58,7 @@ static unsigned int fastboot_flash_session_id;
 static unsigned int download_size;
 static unsigned int download_bytes;
 static bool is_high_speed;
+static bool quirk_ep_out_aligned_size;
 
 static struct usb_endpoint_descriptor fs_ep_in = {
 	.bLength            = USB_DT_ENDPOINT_SIZE,
@@ -240,6 +241,8 @@ static int fastboot_set_alt(struct usb_function *f,
 	debug("%s: func: %s intf: %d alt: %d\n",
 	      __func__, f->name, interface, alt);
 
+	quirk_ep_out_aligned_size = gadget->quirk_ep_out_aligned_size;
+
 	/* make sure we don't enable the ep twice */
 	if (gadget->speed == USB_SPEED_HIGH) {
 		ret = usb_ep_enable(f_fb->out_ep, &hs_ep_out);
@@ -435,12 +438,18 @@ static unsigned int rx_bytes_expected(unsigned int maxpacket)
 		return 0;
 	if (rx_remain > EP_BUFFER_SIZE)
 		return EP_BUFFER_SIZE;
+
+	if (!quirk_ep_out_aligned_size)
+		goto out;
+
 	if (rx_remain < maxpacket) {
 		rx_remain = maxpacket;
 	} else if (rx_remain % maxpacket != 0) {
 		rem = rx_remain % maxpacket;
 		rx_remain = rx_remain + (maxpacket - rem);
 	}
+
+out:
 	return rx_remain;
 }
 
-- 
2.8.0.rc3



More information about the U-Boot mailing list