Revision 66f092d2 hw/usb/hcd-ehci.c

b/hw/usb/hcd-ehci.c
365 365
    uint32_t seen;
366 366
    uint64_t ts;
367 367
    int async;
368
    int revalidate;
369 368

  
370 369
    /* cached data from guest - needs to be flushed
371 370
     * when guest removes an entry (doorbell, handshake sequence)
......
805 804
    return NULL;
806 805
}
807 806

  
808
static void ehci_queues_tag_unused_async(EHCIState *ehci)
809
{
810
    EHCIQueue *q;
811

  
812
    QTAILQ_FOREACH(q, &ehci->aqueues, next) {
813
        if (!q->seen) {
814
            q->revalidate = 1;
815
        }
816
    }
817
}
818

  
819
static void ehci_queues_rip_unused(EHCIState *ehci, int async)
807
static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
820 808
{
821 809
    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
822 810
    uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
......
828 816
            q->ts = ehci->last_run_ns;
829 817
            continue;
830 818
        }
831
        if (ehci->last_run_ns < q->ts + maxage) {
819
        if (!flush && ehci->last_run_ns < q->ts + maxage) {
832 820
            continue;
833 821
        }
834 822
        ehci_free_queue(q);
......
1684 1672
        ehci_set_usbsts(ehci, USBSTS_REC);
1685 1673
    }
1686 1674

  
1687
    ehci_queues_rip_unused(ehci, async);
1675
    ehci_queues_rip_unused(ehci, async, 0);
1688 1676

  
1689 1677
    /*  Find the head of the list (4.9.1.1) */
1690 1678
    for(i = 0; i < MAX_QH; i++) {
......
1769 1757
    EHCIPacket *p;
1770 1758
    uint32_t entry, devaddr;
1771 1759
    EHCIQueue *q;
1772
    EHCIqh qh;
1773 1760

  
1774 1761
    entry = ehci_get_fetch_addr(ehci, async);
1775 1762
    q = ehci_find_queue_by_qh(ehci, entry, async);
......
1787 1774
    }
1788 1775

  
1789 1776
    get_dwords(ehci, NLPTR_GET(q->qhaddr),
1790
               (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
1791
    if (q->revalidate && (q->qh.epchar      != qh.epchar ||
1792
                          q->qh.epcap       != qh.epcap  ||
1793
                          q->qh.current_qtd != qh.current_qtd)) {
1794
        ehci_free_queue(q);
1795
        q = ehci_alloc_queue(ehci, entry, async);
1796
        q->seen++;
1797
        p = NULL;
1798
    }
1799
    q->qh = qh;
1800
    q->revalidate = 0;
1777
               (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
1801 1778
    ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
1802 1779

  
1803 1780
    devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
......
2306 2283
         */
2307 2284
        if (ehci->usbcmd & USBCMD_IAAD) {
2308 2285
            /* Remove all unseen qhs from the async qhs queue */
2309
            ehci_queues_tag_unused_async(ehci);
2286
            ehci_queues_rip_unused(ehci, async, 1);
2310 2287
            DPRINTF("ASYNC: doorbell request acknowledged\n");
2311 2288
            ehci->usbcmd &= ~USBCMD_IAAD;
2312 2289
            ehci_raise_irq(ehci, USBSTS_IAA);
......
2359 2336
        ehci_set_fetch_addr(ehci, async,entry);
2360 2337
        ehci_set_state(ehci, async, EST_FETCHENTRY);
2361 2338
        ehci_advance_state(ehci, async);
2362
        ehci_queues_rip_unused(ehci, async);
2339
        ehci_queues_rip_unused(ehci, async, 0);
2363 2340
        break;
2364 2341

  
2365 2342
    default:

Also available in: Unified diff