Blame 0126-usb-ehci-Handle-ISO-packets-failing-with-an-error-ot.patch

Hans de Goede 1b1995
From 7a3acb928b617b33605c779e7df05c2c896844b1 Mon Sep 17 00:00:00 2001
Hans de Goede 1b1995
From: Hans de Goede <hdegoede@redhat.com>
Hans de Goede 1b1995
Date: Mon, 20 Feb 2012 16:27:47 +0100
Hans de Goede 1b1995
Subject: [PATCH 126/140] usb-ehci: Handle ISO packets failing with an error
Hans de Goede 1b1995
 other then NAK
Hans de Goede 1b1995
Hans de Goede 1b1995
Before this patch the ehci code was not checking for any other errors other
Hans de Goede 1b1995
then USB_RET_NAK. This causes 2 problems:
Hans de Goede 1b1995
1) Other errors are not reported to the guest.
Hans de Goede 1b1995
2) When transactions with the ITD_XACT_IOC bit set completing with another
Hans de Goede 1b1995
   error would not result in USBSTS_INT getting set.
Hans de Goede 1b1995
Hans de Goede 1b1995
I hit this problem when unplugging devices while iso data was streaming from
Hans de Goede 1b1995
the device to the guest. When this happens it takes a while for the guest to
Hans de Goede 1b1995
process the unplugging and remove ISO transactions from the ehci schedule, in
Hans de Goede 1b1995
the mean time these transactions would complete with a result of USB_RET_NODEV,
Hans de Goede 1b1995
which was not handled. This lead to the Linux guest's usb subsystem "hanging",
Hans de Goede 1b1995
that is it would no longer see new usb devices getting plugged in and running
Hans de Goede 1b1995
for example lsusb would lead to a stuck (D state) lsusb process. This patch
Hans de Goede 1b1995
fixes this.
Hans de Goede 1b1995
Hans de Goede 1b1995
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Hans de Goede 1b1995
---
Hans de Goede 1b1995
 hw/usb-ehci.c |   22 +++++++++++++++++++---
Hans de Goede 1b1995
 1 file changed, 19 insertions(+), 3 deletions(-)
Hans de Goede 1b1995
Hans de Goede 1b1995
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
Hans de Goede 1b1995
index 69bcc4b..a6b6ae5 100644
Hans de Goede 1b1995
--- a/hw/usb-ehci.c
Hans de Goede 1b1995
+++ b/hw/usb-ehci.c
Hans de Goede 1b1995
@@ -1512,11 +1512,27 @@ static int ehci_process_itd(EHCIState *ehci,
Hans de Goede 1b1995
                     /* IN */
Hans de Goede 1b1995
                     set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
Hans de Goede 1b1995
                 }
Hans de Goede 1b1995
-
Hans de Goede 1b1995
-                if (itd->transact[i] & ITD_XACT_IOC) {
Hans de Goede 1b1995
-                    ehci_record_interrupt(ehci, USBSTS_INT);
Hans de Goede 1b1995
+            } else {
Hans de Goede 1b1995
+                switch (ret) {
Hans de Goede 1b1995
+                default:
Hans de Goede 1b1995
+                    fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
Hans de Goede 1b1995
+                    /* Fall through */
Hans de Goede 1b1995
+                case USB_RET_NODEV:
Hans de Goede 1b1995
+                    /* 3.3.2: XACTERR is only allowed on IN transactions */
Hans de Goede 1b1995
+                    if (dir) {
Hans de Goede 1b1995
+                        itd->transact[i] |= ITD_XACT_XACTERR;
Hans de Goede 1b1995
+                        ehci_record_interrupt(ehci, USBSTS_ERRINT);
Hans de Goede 1b1995
+                    }
Hans de Goede 1b1995
+                    break;
Hans de Goede 1b1995
+                case USB_RET_BABBLE:
Hans de Goede 1b1995
+                    itd->transact[i] |= ITD_XACT_BABBLE;
Hans de Goede 1b1995
+                    ehci_record_interrupt(ehci, USBSTS_ERRINT);
Hans de Goede 1b1995
+                    break;
Hans de Goede 1b1995
                 }
Hans de Goede 1b1995
             }
Hans de Goede 1b1995
+            if (itd->transact[i] & ITD_XACT_IOC) {
Hans de Goede 1b1995
+                ehci_record_interrupt(ehci, USBSTS_INT);
Hans de Goede 1b1995
+            }
Hans de Goede 1b1995
             itd->transact[i] &= ~ITD_XACT_ACTIVE;
Hans de Goede 1b1995
         }
Hans de Goede 1b1995
     }
Hans de Goede 1b1995
-- 
Hans de Goede 1b1995
1.7.9.3
Hans de Goede 1b1995