[3.11.y.z extended stable] Patch "usb: chipidea: udc: using MultO at TD as real mult value for ISO-TX" has been added to staging queue
Luis Henriques
luis.henriques at canonical.com
Wed Feb 5 13:13:58 UTC 2014
This is a note to let you know that I have just added a patch titled
usb: chipidea: udc: using MultO at TD as real mult value for ISO-TX
to the linux-3.11.y-queue branch of the 3.11.y.z extended stable tree
which can be found at:
http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.11.y-queue
If you, or anyone else, feels it should not be added to this tree, please
reply to this email.
For more information about the 3.11.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
Thanks.
-Luis
------
>From 27905cacd15f4c2ec6812378f8735a5b3d3086f3 Mon Sep 17 00:00:00 2001
From: Peter Chen <peter.chen at freescale.com>
Date: Fri, 10 Jan 2014 13:51:32 +0800
Subject: usb: chipidea: udc: using MultO at TD as real mult value for ISO-TX
commit 2fc5a7dace3c43e62402ab4e8800a8f1834ffe2a upstream.
We have met a bug that the high bandwidth ISO-TX transfer has failed
at the last packet if it is less than 1024, the TD status shows it
is "Transaction Error".
The root cause of this problem is: the mult value at qh is not correct
for current TD's transfer length. We use TD list to queue un-transfer
TDs, and change mult for new adding TDs. If new adding TDs transfer length
less than 1024, but the queued un-transfer TDs transfer length is larger
than 1024, the transfer error will occur, and vice versa.
Usually, this problem occurs at the last packet, and the first packet for
new frame.
We fixed this problem by setting Mult at QH as the largest value (3), and
set MultO (Multiplier Override) at TD according to every transfer length.
It can cover both hardware version less than 2.3 (the real mult is MultO
if it is not 0) and 2.3+ (the real mult is min(qh.mult, td.multo)).
Since the MultO bits are only existed at TX TD, we keep the ISO-RX behavior
unchanged.
For stable tree: 3.11+.
Cc: Michael Grzeschik <m.grzeschik at pengutronix.de>
Reported-by: Matthieu Vanin <b47495 at freescale.com>
Tested-by: Matthieu Vanin <b47495 at freescale.com>
Signed-off-by: Peter Chen <peter.chen at freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
---
drivers/usb/chipidea/udc.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index e475fcd..3a223a8 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -391,6 +391,14 @@ static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq,
node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES));
node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES);
node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE);
+ if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == TX) {
+ u32 mul = hwreq->req.length / hwep->ep.maxpacket;
+
+ if (hwreq->req.length == 0
+ || hwreq->req.length % hwep->ep.maxpacket)
+ mul++;
+ node->ptr->token |= mul << __ffs(TD_MULTO);
+ }
temp = (u32) (hwreq->req.dma + hwreq->req.actual);
if (length) {
@@ -513,10 +521,11 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
hwep->qh.ptr->td.token &=
cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
- if (hwep->type == USB_ENDPOINT_XFER_ISOC) {
+ if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == RX) {
u32 mul = hwreq->req.length / hwep->ep.maxpacket;
- if (hwreq->req.length % hwep->ep.maxpacket)
+ if (hwreq->req.length == 0
+ || hwreq->req.length % hwep->ep.maxpacket)
mul++;
hwep->qh.ptr->cap |= mul << __ffs(QH_MULT);
}
@@ -1169,6 +1178,12 @@ static int ep_enable(struct usb_ep *ep,
if (hwep->num)
cap |= QH_ZLT;
cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT;
+ /*
+ * For ISO-TX, we set mult at QH as the largest value, and use
+ * MultO at TD as real mult value.
+ */
+ if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == TX)
+ cap |= 3 << __ffs(QH_MULT);
hwep->qh.ptr->cap = cpu_to_le32(cap);
--
1.8.3.2
More information about the kernel-team
mailing list