summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-08-29 10:50:51 +0200
committerHans de Goede <hdegoede@redhat.com>2012-08-29 10:51:26 +0200
commitfe4bd86820fd32a2b0cd950f17dc4778fd5c722f (patch)
tree0338ba8fb4b8aa8c787da2942dcbf711c20328d9
parenta9c2e0b3b99d3e20ece777df2f82ffc3affe1438 (diff)
ehci: Print a warning when a queue unexpectedly contains packets on cancel
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--hw/usb/hcd-ehci.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 86b6cd5db..1f6b03e59 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -765,7 +765,7 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
return q;
}
-static void ehci_cancel_queue(EHCIQueue *q)
+static void ehci_cancel_queue(EHCIQueue *q, const char *warn)
{
EHCIPacket *p;
@@ -774,6 +774,10 @@ static void ehci_cancel_queue(EHCIQueue *q)
return;
}
+ if (warn) {
+ fprintf(stderr, "EHCI: Warning queue not empty on %s\n", warn);
+ }
+
trace_usb_ehci_queue_action(q, "cancel");
do {
ehci_free_packet(p);
@@ -783,17 +787,17 @@ static void ehci_cancel_queue(EHCIQueue *q)
static void ehci_reset_queue(EHCIQueue *q)
{
trace_usb_ehci_queue_action(q, "reset");
- ehci_cancel_queue(q);
+ ehci_cancel_queue(q, "queue reset");
q->dev = NULL;
q->qtdaddr = 0;
}
-static void ehci_free_queue(EHCIQueue *q)
+static void ehci_free_queue(EHCIQueue *q, const char *warn)
{
EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
trace_usb_ehci_queue_action(q, "free");
- ehci_cancel_queue(q);
+ ehci_cancel_queue(q, warn);
QTAILQ_REMOVE(head, q, next);
g_free(q);
}
@@ -827,7 +831,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
if (!flush && ehci->last_run_ns < q->ts + maxage) {
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, flush ? NULL : "rip unused");
}
}
@@ -840,7 +844,7 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
if (q->dev != dev) {
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, NULL);
}
}
@@ -850,7 +854,7 @@ static void ehci_queues_rip_all(EHCIState *ehci, int async)
EHCIQueue *q, *tmp;
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
- ehci_free_queue(q);
+ ehci_free_queue(q, "rip all");
}
}
@@ -1949,7 +1953,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
p->qtd.altnext != qtd.altnext ||
p->qtd.bufptr[0] != qtd.bufptr[0]) {
/* guest bug: guest updated active QH or qTD underneath us */
- ehci_cancel_queue(q);
+ ehci_cancel_queue(q, "qtd change");
p = NULL;
} else {
p->qtd = qtd;
@@ -1960,7 +1964,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
if (p != NULL) {
/* transfer canceled by guest (clear active) */
- ehci_cancel_queue(q);
+ ehci_cancel_queue(q, NULL);
p = NULL;
}
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);