f375e62
From 7fdcb0738e43e49ac3081cc28212c1b7985f8bae Mon Sep 17 00:00:00 2001
f375e62
From: Hans de Goede <hdegoede@redhat.com>
f375e62
Date: Wed, 10 Oct 2012 15:50:36 +0200
f375e62
Subject: [PATCH] uhci: Raise interrupt when requested even for non active tds
f375e62
f375e62
According to the spec we must raise an interrupt when one is requested
f375e62
even for non active tds.
f375e62
f375e62
Linux depends on this, for bulk transfers it runs an inactivity timer
f375e62
to work around a bug in early uhci revisions, when we take longer then
f375e62
200 ms to process a packet, this timer goes of, and as part of the
f375e62
handling Linux then unlinks the qh, and relinks it after the frindex
f375e62
has increased by atleast 1, the problem is Linux only checks for the
f375e62
frindex increases on an interrupt, and we don't send that, causing
f375e62
the qh to go inactive for more then 32 frames, at which point we
f375e62
consider the packet cancelled.
f375e62
f375e62
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
f375e62
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
f375e62
(cherry picked from commit 883bca776daa43111e9c39008f0038f7c62ae723)
f375e62
f375e62
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
f375e62
---
f375e62
 hw/usb/hcd-uhci.c | 10 +++++++++-
f375e62
 1 file changed, 9 insertions(+), 1 deletion(-)
f375e62
f375e62
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
f375e62
index cdc8bc3..c2f08e3 100644
f375e62
--- a/hw/usb/hcd-uhci.c
f375e62
+++ b/hw/usb/hcd-uhci.c
f375e62
@@ -826,8 +826,16 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
f375e62
     USBEndpoint *ep;
f375e62
 
f375e62
     /* Is active ? */
f375e62
-    if (!(td->ctrl & TD_CTRL_ACTIVE))
f375e62
+    if (!(td->ctrl & TD_CTRL_ACTIVE)) {
f375e62
+        /*
f375e62
+         * ehci11d spec page 22: "Even if the Active bit in the TD is already
f375e62
+         * cleared when the TD is fetched ... an IOC interrupt is generated"
f375e62
+         */
f375e62
+        if (td->ctrl & TD_CTRL_IOC) {
f375e62
+                *int_mask |= 0x01;
f375e62
+        }
f375e62
         return TD_RESULT_NEXT_QH;
f375e62
+    }
f375e62
 
f375e62
     async = uhci_async_find_td(s, addr, td);
f375e62
     if (async) {