aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-12-14 14:35:24 +0100
committerGerd Hoffmann <kraxel@redhat.com>2013-01-07 12:57:23 +0100
commitd066c57b1c97a1967c949aba643bba35329b32ee (patch)
treed479cd920116ed55440b749c7b69291b559c4856
parentc643263409b42a31fd9b1458cd5158280b9c62e1 (diff)
ehci: Verify guest does not change the token of inflight qtd-s
This is not allowed, except for clearing active on cancellation, so don't warn when the new token does not have its active bit set. This unifies the cancellation path for modified qtd-s, and prepares ehci_verify_qtd to be used ad an extra check inside ehci_writeback_async_complete_packet(). Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--hw/usb/hcd-ehci.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 0d315971a9..04301ce173 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -461,6 +461,7 @@ static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd)
(p->queue->async && !NLPTR_TBIT(p->qtd.next) &&
(p->qtd.next != qtd->next)) ||
(!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd->altnext)) ||
+ p->qtd.token != qtd->token ||
p->qtd.bufptr[0] != qtd->bufptr[0]) {
return false;
} else {
@@ -1793,7 +1794,9 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
if (p != NULL) {
if (!ehci_verify_qtd(p, &qtd)) {
ehci_cancel_queue(q);
- ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD");
+ if (qtd.token & QTD_TOKEN_ACTIVE) {
+ ehci_trace_guest_bug(q->ehci, "guest updated active qTD");
+ }
p = NULL;
} else {
p->qtd = qtd;
@@ -1802,11 +1805,6 @@ 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);
- p = NULL;
- }
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
} else if (p != NULL) {
switch (p->async) {