From 028e687474d9ecb8c180241efe8b0fe3e9c831a7 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 4 Mar 2012 11:57:51 +0100
Subject: [PATCH 29/35] usb-ehci: Fix cerr tracking

RH-Author: Hans de Goede <hdegoede@redhat.com>
Message-id: <1330862278-22314-15-git-send-email-hdegoede@redhat.com>
Patchwork-id: 37929
O-Subject: [PATCH 14/21] usb-ehci: Fix cerr tracking
Bugzilla: 758104
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
RH-Acked-by: Alon Levy <alevy@redhat.com>
RH-Acked-by: Markus Armbruster <armbru@redhat.com>

cerr should only be decremented on errors which cause XactErr to be set, and
when that happens the failing transaction should be retried until cerr reaches
0 and only then should USBSTS_ERRINT be set (and inactive cleared and
USBSTS_INT set if requested).

Since we don't have any hardware level errors (and in case of redirection
the real hardware has already retried), re-trying makes no sense, so
immediately set cerr to 0 on errors which set XactErr.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Upstream commit: dd54cfe0bcf30d1f3a34e9c397f619d423fe0c5b
Upstream: http://patchwork.ozlabs.org/patch/144364/
(waiting for next usb pull request)
---
 hw/usb-ehci.c |   19 ++++++-------------
 1 files changed, 6 insertions(+), 13 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/usb-ehci.c |   19 ++++++-------------
 1 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index ecd6a70..47975c1 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1258,7 +1258,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 
 static void ehci_execute_complete(EHCIQueue *q)
 {
-    int c_err, reload;
+    int reload;
 
     assert(q->async != EHCI_ASYNC_INFLIGHT);
     q->async = EHCI_ASYNC_NONE;
@@ -1267,15 +1267,10 @@ static void ehci_execute_complete(EHCIQueue *q)
             q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
 
     if (q->usb_status < 0) {
-err:
-        /* TO-DO: put this is in a function that can be invoked below as well */
-        c_err = get_field(q->qh.token, QTD_TOKEN_CERR);
-        c_err--;
-        set_field(&q->qh.token, c_err, QTD_TOKEN_CERR);
-
         switch(q->usb_status) {
         case USB_RET_NODEV:
             q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
+            set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
             ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
             break;
         case USB_RET_STALL:
@@ -1303,15 +1298,13 @@ err:
             assert(0);
             break;
         }
+    } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
+        q->usb_status = USB_RET_BABBLE;
+        q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
+        ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
     } else {
-        // DPRINTF("Short packet condition\n");
         // TODO check 4.12 for splits
 
-        if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
-            q->usb_status = USB_RET_BABBLE;
-            goto err;
-        }
-
         if (q->tbytes && q->pid == USB_TOKEN_IN) {
             if (ehci_buffer_rw(q, q->usb_status, 1) != 0) {
                 q->usb_status = USB_RET_PROCERR;
-- 
1.7.7.6

