Skip to contentSkip to conversation

Patch "usb: dwc3: gadget: Correct ISOC DATA PIDs for short packets" has been added to the 4.9-stable tree

PATCH [email protected] 1 participant 1 message Oct 19, 2017

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

usb: dwc3: gadget: Correct ISOC DATA PIDs for short packets

to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
usb-dwc3-gadget-correct-isoc-data-pids-for-short-packets.patch
and it can be found in the queue-4.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 40d829fb2ec636b6b4b0cc95e2546ab9aca04cc9 Mon Sep 17 00:00:00 2001

From: Manu Gautam <[email protected]>
Date: Wed, 19 Jul 2017 17:07:10 +0530
Subject: usb: dwc3: gadget: Correct ISOC DATA PIDs for short packets

From: Manu Gautam <[email protected]>

commit 40d829fb2ec636b6b4b0cc95e2546ab9aca04cc9 upstream.

The PIDs for Isochronous data transfers are incorrect for high bandwidth IN endpoints when the request length is less than EP wMaxPacketSize.

As per spec correct PIDs for ISOC data transfers are:

1) For request length <= maxpacket
- DATA0,

2) For maxpacket < length <= (2 * maxpacket)
- DATA1, DATA0

3) For (2 * maxpacket) < length <= (3 * maxpacket)
- DATA2, DATA1, DATA0.

But driver always sets PCM fields based on wMaxPacketSize due to which DATA2 happens even for small requests.

Fix this by setting the PCM field of trb->size depending on request length rather than fixing it to the value depending on wMaxPacketSize.

Ideally it shouldn't give any issues as dwc3 will send 0-length packet for next IN token if host sends (even after receiving a short packet). Windows seems to ignore this but with MacOS frame loss observed when using f_uvc.

[[email protected] added following change for v4.9.]

- unsigned int maxp = usb_endpoint_maxp(ep->desc);
+ unsigned int maxp;
+ maxp = usb_endpoint_maxp(ep->desc) & 0x07ff;

---
 drivers/usb/dwc3/gadget.c |   35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)
drivers/usb/dwc3/gadget.c +34 -1
@@ -817,9 +817,42 @@ static void dwc3_prepare_one_trb(struct
 		if (!node) {
 			trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
 
+			/*
+			 * USB Specification 2.0 Section 5.9.2 states that: "If
+			 * there is only a single transaction in the microframe,
+			 * only a DATA0 data packet PID is used.  If there are
+			 * two transactions per microframe, DATA1 is used for
+			 * the first transaction data packet and DATA0 is used
+			 * for the second transaction data packet.  If there are
+			 * three transactions per microframe, DATA2 is used for
+			 * the first transaction data packet, DATA1 is used for
+			 * the second, and DATA0 is used for the third."
+			 *
+			 * IOW, we should satisfy the following cases:
+			 *
+			 * 1) length <= maxpacket
+			 *	- DATA0
+			 *
+			 * 2) maxpacket < length <= (2 * maxpacket)
+			 *	- DATA1, DATA0
+			 *
+			 * 3) (2 * maxpacket) < length <= (3 * maxpacket)
+			 *	- DATA2, DATA1, DATA0
+			 */
 			if (speed == USB_SPEED_HIGH) {
 				struct usb_ep *ep = &dep->endpoint;
-				trb->size |= DWC3_TRB_SIZE_PCM1(ep->mult - 1);
+				unsigned int mult = ep->mult - 1;
+				unsigned int maxp;
+
+				maxp = usb_endpoint_maxp(ep->desc) & 0x07ff;
+
+				if (length <= (2 * maxp))
+					mult--;
+
+				if (length <= maxp)
+					mult--;
+
+				trb->size |= DWC3_TRB_SIZE_PCM1(mult);
 			}
 		} else {
 			trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS;

Patches currently in stable-queue which might be from [email protected] are

queue-4.9/usb-dwc3-gadget-correct-isoc-data-pids-for-short-packets.patch