summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-09-03 11:35:58 +0200
committerGerd Hoffmann <kraxel@redhat.com>2012-09-11 07:42:59 +0200
commiteff6dce79bd7ad3c16d75c5e55b5a2a137ba6a60 (patch)
treedebe7c57070b02cbc85fabc345d2efb616dc372b
parentef5b234477df80700b128f561f5877a0688a70c8 (diff)
downloadqemu-eff6dce79bd7ad3c16d75c5e55b5a2a137ba6a60.zip
ehci: Handle USB_RET_PROCERR in ehci_fill_queue
USB_RET_PROCERR can be triggered by the guest (by for example requesting more then BUFFSIZE bytes), so don't assert on it. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--hw/usb/hcd-ehci.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d87aca8331..2534394202 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2076,7 +2076,7 @@ static int ehci_state_horizqh(EHCIQueue *q)
return again;
}
-static void ehci_fill_queue(EHCIPacket *p)
+static int ehci_fill_queue(EHCIPacket *p)
{
EHCIQueue *q = p->queue;
EHCIqtd qtd = p->qtd;
@@ -2100,9 +2100,13 @@ static void ehci_fill_queue(EHCIPacket *p)
p->qtdaddr = qtdaddr;
p->qtd = qtd;
p->usb_status = ehci_execute(p, "queue");
+ if (p->usb_status == USB_RET_PROCERR) {
+ break;
+ }
assert(p->usb_status == USB_RET_ASYNC);
p->async = EHCI_ASYNC_INFLIGHT;
}
+ return p->usb_status;
}
static int ehci_state_execute(EHCIQueue *q)
@@ -2144,8 +2148,7 @@ static int ehci_state_execute(EHCIQueue *q)
trace_usb_ehci_packet_action(p->queue, p, "async");
p->async = EHCI_ASYNC_INFLIGHT;
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
- again = 1;
- ehci_fill_queue(p);
+ again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1;
goto out;
}