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