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