2013-04-21 00:14:03 +00:00
|
|
|
From b4d71f364924655c47f7e54a9726e303c91978d1 Mon Sep 17 00:00:00 2001
|
2013-04-03 09:29:31 +00:00
|
|
|
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
|
Date: Wed, 14 Nov 2012 16:21:37 +0000
|
2013-04-21 00:14:03 +00:00
|
|
|
Subject: [PATCH] ehci: Fixup q->qtdaddr after cancelling an already completed
|
|
|
|
packet
|
2013-04-03 09:29:31 +00:00
|
|
|
|
|
|
|
This avoids the q->qtdaddr == p->qtdaddr asserts we have triggering, when
|
|
|
|
a queue contains multiple completed packages when we cancel the queue.
|
|
|
|
|
|
|
|
I triggered this with windows7 + async interrupt endpoint handling (*)
|
|
|
|
+ not detecting circles in ehci_fill_queue() properly, which makes the qtd
|
|
|
|
validation in ehci_fill_queue fail, causing cancellation of the queue on every
|
|
|
|
mouse event ...
|
|
|
|
|
|
|
|
*) Which is not going upstream as it will cause loss of interrupt events on
|
|
|
|
migration.
|
|
|
|
|
|
|
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
|
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
|
(cherry picked from ff80ce599e0465cc6109a38bd3a8ca1890e88891)
|
|
|
|
---
|
|
|
|
hw/usb/hcd-ehci.c | 4 ++++
|
|
|
|
1 file changed, 4 insertions(+)
|
|
|
|
|
|
|
|
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
|
|
|
|
index 4229061..6be11c5 100644
|
|
|
|
--- a/hw/usb/hcd-ehci.c
|
|
|
|
+++ b/hw/usb/hcd-ehci.c
|
|
|
|
@@ -488,6 +488,7 @@ static const char *ehci_mmio_names[] = {
|
|
|
|
|
|
|
|
static int ehci_state_executing(EHCIQueue *q);
|
|
|
|
static int ehci_state_writeback(EHCIQueue *q);
|
|
|
|
+static int ehci_state_advqueue(EHCIQueue *q);
|
|
|
|
|
|
|
|
static const char *nr2str(const char **n, size_t len, uint32_t nr)
|
|
|
|
{
|
|
|
|
@@ -758,6 +759,9 @@ static void ehci_free_packet(EHCIPacket *p)
|
|
|
|
fprintf(stderr, "EHCI: Warning packet completed but not processed\n");
|
|
|
|
ehci_state_executing(q);
|
|
|
|
ehci_state_writeback(q);
|
|
|
|
+ if (!(q->qh.token & QTD_TOKEN_HALT)) {
|
|
|
|
+ ehci_state_advqueue(q);
|
|
|
|
+ }
|
|
|
|
ehci_set_state(q->ehci, q->async, state);
|
|
|
|
/* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */
|
|
|
|
return;
|