diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-08-31 10:04:54 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-08-31 10:04:54 -0500 |
commit | 23aec6005af30e29180496b434edcc51660ce94e (patch) | |
tree | e62432e156d83ff419eff2129edf691ecf20dd6a /hw/usb/hcd-uhci.c | |
parent | cdedd9d867f2e955e022f07808b10a4a5d383841 (diff) | |
parent | 347e40ffe61b7cc8d4565be476c20acd00611669 (diff) |
Merge remote-tracking branch 'kraxel/usb.61' into staging
* kraxel/usb.61:
uas: move transfer kickoff
ehci: Fix interrupt endpoints no longer working
ehci: handle TD deactivation of inflight packets
ehci: add ehci_cancel_queue()
ehci: simplify ehci_state_executing
ehci: Remove unnecessary ehci_flush_qh call
ehci: Schedule async-bh when IAAD bit gets set
ehci: Fix NULL ptr deref when unplugging an USB dev with an iso stream active
usb: unique packet ids
usb: Halt ep queue en cancel pending packets on a packet error
fix info qtree indention
Diffstat (limited to 'hw/usb/hcd-uhci.c')
-rw-r--r-- | hw/usb/hcd-uhci.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 1ace2a41da..b0db92145a 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -748,6 +748,22 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ return TD_RESULT_COMPLETE; out: + /* + * We should not do any further processing on a queue with errors! + * This is esp. important for bulk endpoints with pipelining enabled + * (redirection to a real USB device), where we must cancel all the + * transfers after this one so that: + * 1) If they've completed already, they are not processed further + * causing more stalls, originating from the same failed transfer + * 2) If still in flight, they are cancelled before the guest does + * a clear stall, otherwise the guest and device can loose sync! + */ + while (!QTAILQ_EMPTY(&async->queue->asyncs)) { + UHCIAsync *as = QTAILQ_FIRST(&async->queue->asyncs); + uhci_async_unlink(as); + uhci_async_cancel(as); + } + switch(ret) { case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; @@ -843,14 +859,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, * for initial isochronous requests */ async->queue->valid = 32; - async->isoc = td->ctrl & TD_CTRL_IOS; + async->isoc = td->ctrl & TD_CTRL_IOS; max_len = ((td->token >> 21) + 1) & 0x7ff; pid = td->token & 0xff; dev = uhci_find_device(s, (td->token >> 8) & 0x7f); ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); - usb_packet_setup(&async->packet, pid, ep); + usb_packet_setup(&async->packet, pid, ep, addr); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); |