Revision 0cae7b1a
b/hw/usb.h | ||
---|---|---|
45 | 45 |
#define USB_RET_IOERROR (-5) |
46 | 46 |
#define USB_RET_ASYNC (-6) |
47 | 47 |
#define USB_RET_ADD_TO_QUEUE (-7) |
48 |
#define USB_RET_REMOVE_FROM_QUEUE (-8) |
|
48 | 49 |
|
49 | 50 |
#define USB_SPEED_LOW 0 |
50 | 51 |
#define USB_SPEED_FULL 1 |
b/hw/usb/core.c | ||
---|---|---|
442 | 442 |
usb_packet_check_state(p, USB_PACKET_ASYNC); |
443 | 443 |
usb_packet_complete_one(dev, p); |
444 | 444 |
|
445 |
while (!ep->halted && !QTAILQ_EMPTY(&ep->queue)) {
|
|
445 |
while (!QTAILQ_EMPTY(&ep->queue)) { |
|
446 | 446 |
p = QTAILQ_FIRST(&ep->queue); |
447 |
if (ep->halted) { |
|
448 |
/* Empty the queue on a halt */ |
|
449 |
p->result = USB_RET_REMOVE_FROM_QUEUE; |
|
450 |
dev->port->ops->complete(dev->port, p); |
|
451 |
continue; |
|
452 |
} |
|
447 | 453 |
if (p->state == USB_PACKET_ASYNC) { |
448 | 454 |
break; |
449 | 455 |
} |
b/hw/usb/hcd-ehci.c | ||
---|---|---|
1457 | 1457 |
} |
1458 | 1458 |
|
1459 | 1459 |
p = container_of(packet, EHCIPacket, packet); |
1460 |
trace_usb_ehci_packet_action(p->queue, p, "wakeup"); |
|
1461 | 1460 |
assert(p->async == EHCI_ASYNC_INFLIGHT); |
1461 |
|
|
1462 |
if (packet->result == USB_RET_REMOVE_FROM_QUEUE) { |
|
1463 |
trace_usb_ehci_packet_action(p->queue, p, "remove"); |
|
1464 |
ehci_free_packet(p); |
|
1465 |
return; |
|
1466 |
} |
|
1467 |
|
|
1468 |
trace_usb_ehci_packet_action(p->queue, p, "wakeup"); |
|
1462 | 1469 |
p->async = EHCI_ASYNC_FINISHED; |
1463 | 1470 |
p->usb_status = packet->result; |
1464 | 1471 |
|
... | ... | |
2216 | 2223 |
* bit is clear. |
2217 | 2224 |
*/ |
2218 | 2225 |
if (q->qh.token & QTD_TOKEN_HALT) { |
2219 |
/* |
|
2220 |
* We should not do any further processing on a halted queue! |
|
2221 |
* This is esp. important for bulk endpoints with pipelining enabled |
|
2222 |
* (redirection to a real USB device), where we must cancel all the |
|
2223 |
* transfers after this one so that: |
|
2224 |
* 1) If they've completed already, they are not processed further |
|
2225 |
* causing more stalls, originating from the same failed transfer |
|
2226 |
* 2) If still in flight, they are cancelled before the guest does |
|
2227 |
* a clear stall, otherwise the guest and device can loose sync! |
|
2228 |
*/ |
|
2229 |
while ((p = QTAILQ_FIRST(&q->packets)) != NULL) { |
|
2230 |
ehci_free_packet(p); |
|
2231 |
} |
|
2232 | 2226 |
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); |
2233 | 2227 |
again = 1; |
2234 | 2228 |
} else { |
b/hw/usb/hcd-uhci.c | ||
---|---|---|
744 | 744 |
return TD_RESULT_COMPLETE; |
745 | 745 |
|
746 | 746 |
out: |
747 |
/* |
|
748 |
* We should not do any further processing on a queue with errors! |
|
749 |
* This is esp. important for bulk endpoints with pipelining enabled |
|
750 |
* (redirection to a real USB device), where we must cancel all the |
|
751 |
* transfers after this one so that: |
|
752 |
* 1) If they've completed already, they are not processed further |
|
753 |
* causing more stalls, originating from the same failed transfer |
|
754 |
* 2) If still in flight, they are cancelled before the guest does |
|
755 |
* a clear stall, otherwise the guest and device can loose sync! |
|
756 |
*/ |
|
757 |
while (!QTAILQ_EMPTY(&async->queue->asyncs)) { |
|
758 |
UHCIAsync *as = QTAILQ_FIRST(&async->queue->asyncs); |
|
759 |
uhci_async_unlink(as); |
|
760 |
uhci_async_cancel(as); |
|
761 |
} |
|
762 |
|
|
763 | 747 |
switch(ret) { |
764 | 748 |
case USB_RET_STALL: |
765 | 749 |
td->ctrl |= TD_CTRL_STALL; |
... | ... | |
918 | 902 |
UHCIAsync *async = container_of(packet, UHCIAsync, packet); |
919 | 903 |
UHCIState *s = async->queue->uhci; |
920 | 904 |
|
905 |
if (packet->result == USB_RET_REMOVE_FROM_QUEUE) { |
|
906 |
uhci_async_unlink(async); |
|
907 |
uhci_async_cancel(async); |
|
908 |
return; |
|
909 |
} |
|
910 |
|
|
921 | 911 |
if (async->isoc) { |
922 | 912 |
UHCI_TD td; |
923 | 913 |
uint32_t link = async->td; |
b/hw/usb/hcd-xhci.c | ||
---|---|---|
2839 | 2839 |
{ |
2840 | 2840 |
XHCITransfer *xfer = container_of(packet, XHCITransfer, packet); |
2841 | 2841 |
|
2842 |
if (packet->result == USB_RET_REMOVE_FROM_QUEUE) { |
|
2843 |
xhci_ep_nuke_one_xfer(xfer); |
|
2844 |
return; |
|
2845 |
} |
|
2842 | 2846 |
xhci_complete_packet(xfer, packet->result); |
2843 | 2847 |
xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid); |
2844 | 2848 |
} |
Also available in: Unified diff