Revision df5d5c5c
b/hw/usb-ehci.c | ||
---|---|---|
347 | 347 |
struct EHCIQueue { |
348 | 348 |
EHCIState *ehci; |
349 | 349 |
QTAILQ_ENTRY(EHCIQueue) next; |
350 |
bool async_schedule; |
|
351 | 350 |
uint32_t seen; |
352 | 351 |
uint64_t ts; |
353 | 352 |
|
... | ... | |
367 | 366 |
int usb_status; |
368 | 367 |
}; |
369 | 368 |
|
369 |
typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; |
|
370 |
|
|
370 | 371 |
struct EHCIState { |
371 | 372 |
PCIDevice dev; |
372 | 373 |
USBBus bus; |
... | ... | |
410 | 411 |
USBPort ports[NB_PORTS]; |
411 | 412 |
USBPort *companion_ports[NB_PORTS]; |
412 | 413 |
uint32_t usbsts_pending; |
413 |
QTAILQ_HEAD(, EHCIQueue) queues; |
|
414 |
EHCIQueueHead aqueues; |
|
415 |
EHCIQueueHead pqueues; |
|
414 | 416 |
|
415 | 417 |
uint32_t a_fetch_addr; // which address to look at next |
416 | 418 |
uint32_t p_fetch_addr; // which address to look at next |
... | ... | |
660 | 662 |
|
661 | 663 |
static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async) |
662 | 664 |
{ |
665 |
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; |
|
663 | 666 |
EHCIQueue *q; |
664 | 667 |
|
665 | 668 |
q = g_malloc0(sizeof(*q)); |
666 | 669 |
q->ehci = ehci; |
667 |
q->async_schedule = async; |
|
668 |
QTAILQ_INSERT_HEAD(&ehci->queues, q, next); |
|
670 |
QTAILQ_INSERT_HEAD(head, q, next); |
|
669 | 671 |
trace_usb_ehci_queue_action(q, "alloc"); |
670 | 672 |
return q; |
671 | 673 |
} |
672 | 674 |
|
673 |
static void ehci_free_queue(EHCIQueue *q) |
|
675 |
static void ehci_free_queue(EHCIQueue *q, int async)
|
|
674 | 676 |
{ |
677 |
EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues; |
|
675 | 678 |
trace_usb_ehci_queue_action(q, "free"); |
676 | 679 |
if (q->async == EHCI_ASYNC_INFLIGHT) { |
677 | 680 |
usb_cancel_packet(&q->packet); |
678 | 681 |
} |
679 |
QTAILQ_REMOVE(&q->ehci->queues, q, next);
|
|
682 |
QTAILQ_REMOVE(head, q, next);
|
|
680 | 683 |
g_free(q); |
681 | 684 |
} |
682 | 685 |
|
683 |
static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr) |
|
686 |
static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr, |
|
687 |
int async) |
|
684 | 688 |
{ |
689 |
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; |
|
685 | 690 |
EHCIQueue *q; |
686 | 691 |
|
687 |
QTAILQ_FOREACH(q, &ehci->queues, next) {
|
|
692 |
QTAILQ_FOREACH(q, head, next) {
|
|
688 | 693 |
if (addr == q->qhaddr) { |
689 | 694 |
return q; |
690 | 695 |
} |
... | ... | |
692 | 697 |
return NULL; |
693 | 698 |
} |
694 | 699 |
|
695 |
static void ehci_queues_rip_unused(EHCIState *ehci) |
|
700 |
static void ehci_queues_rip_unused(EHCIState *ehci, int async)
|
|
696 | 701 |
{ |
702 |
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; |
|
697 | 703 |
EHCIQueue *q, *tmp; |
698 | 704 |
|
699 |
QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
|
|
705 |
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
|
700 | 706 |
if (q->seen) { |
701 | 707 |
q->seen = 0; |
702 | 708 |
q->ts = ehci->last_run_ns; |
... | ... | |
706 | 712 |
/* allow 0.25 sec idle */ |
707 | 713 |
continue; |
708 | 714 |
} |
709 |
ehci_free_queue(q); |
|
715 |
ehci_free_queue(q, async);
|
|
710 | 716 |
} |
711 | 717 |
} |
712 | 718 |
|
713 |
static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev) |
|
719 |
static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
|
|
714 | 720 |
{ |
721 |
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; |
|
715 | 722 |
EHCIQueue *q, *tmp; |
716 | 723 |
|
717 |
QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
|
|
724 |
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
|
718 | 725 |
if (!usb_packet_is_inflight(&q->packet) || |
719 | 726 |
q->packet.ep->dev != dev) { |
720 | 727 |
continue; |
721 | 728 |
} |
722 |
ehci_free_queue(q); |
|
729 |
ehci_free_queue(q, async);
|
|
723 | 730 |
} |
724 | 731 |
} |
725 | 732 |
|
726 |
static void ehci_queues_rip_all(EHCIState *ehci) |
|
733 |
static void ehci_queues_rip_all(EHCIState *ehci, int async)
|
|
727 | 734 |
{ |
735 |
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; |
|
728 | 736 |
EHCIQueue *q, *tmp; |
729 | 737 |
|
730 |
QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
|
|
731 |
ehci_free_queue(q); |
|
738 |
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
|
739 |
ehci_free_queue(q, async);
|
|
732 | 740 |
} |
733 | 741 |
} |
734 | 742 |
|
... | ... | |
773 | 781 |
return; |
774 | 782 |
} |
775 | 783 |
|
776 |
ehci_queues_rip_device(s, port->dev); |
|
784 |
ehci_queues_rip_device(s, port->dev, 0); |
|
785 |
ehci_queues_rip_device(s, port->dev, 1); |
|
777 | 786 |
|
778 | 787 |
*portsc &= ~(PORTSC_CONNECT|PORTSC_PED); |
779 | 788 |
*portsc |= PORTSC_CSC; |
... | ... | |
793 | 802 |
return; |
794 | 803 |
} |
795 | 804 |
|
796 |
ehci_queues_rip_device(s, child); |
|
805 |
ehci_queues_rip_device(s, child, 0); |
|
806 |
ehci_queues_rip_device(s, child, 1); |
|
797 | 807 |
} |
798 | 808 |
|
799 | 809 |
static void ehci_wakeup(USBPort *port) |
... | ... | |
911 | 921 |
usb_device_reset(devs[i]); |
912 | 922 |
} |
913 | 923 |
} |
914 |
ehci_queues_rip_all(s); |
|
924 |
ehci_queues_rip_all(s, 0); |
|
925 |
ehci_queues_rip_all(s, 1); |
|
915 | 926 |
qemu_del_timer(s->frame_timer); |
916 | 927 |
} |
917 | 928 |
|
... | ... | |
1526 | 1537 |
ehci_set_usbsts(ehci, USBSTS_REC); |
1527 | 1538 |
} |
1528 | 1539 |
|
1529 |
ehci_queues_rip_unused(ehci); |
|
1540 |
ehci_queues_rip_unused(ehci, async);
|
|
1530 | 1541 |
|
1531 | 1542 |
/* Find the head of the list (4.9.1.1) */ |
1532 | 1543 |
for(i = 0; i < MAX_QH; i++) { |
... | ... | |
1613 | 1624 |
int reload; |
1614 | 1625 |
|
1615 | 1626 |
entry = ehci_get_fetch_addr(ehci, async); |
1616 |
q = ehci_find_queue_by_qh(ehci, entry); |
|
1627 |
q = ehci_find_queue_by_qh(ehci, entry, async);
|
|
1617 | 1628 |
if (NULL == q) { |
1618 | 1629 |
q = ehci_alloc_queue(ehci, async); |
1619 | 1630 |
} |
... | ... | |
2064 | 2075 |
|
2065 | 2076 |
static void ehci_advance_async_state(EHCIState *ehci) |
2066 | 2077 |
{ |
2067 |
int async = 1; |
|
2078 |
const int async = 1;
|
|
2068 | 2079 |
|
2069 | 2080 |
switch(ehci_get_state(ehci, async)) { |
2070 | 2081 |
case EST_INACTIVE: |
... | ... | |
2121 | 2132 |
{ |
2122 | 2133 |
uint32_t entry; |
2123 | 2134 |
uint32_t list; |
2124 |
int async = 0; |
|
2135 |
const int async = 0;
|
|
2125 | 2136 |
|
2126 | 2137 |
// 4.6 |
2127 | 2138 |
|
... | ... | |
2354 | 2365 |
} |
2355 | 2366 |
|
2356 | 2367 |
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s); |
2357 |
QTAILQ_INIT(&s->queues); |
|
2368 |
QTAILQ_INIT(&s->aqueues); |
|
2369 |
QTAILQ_INIT(&s->pqueues); |
|
2358 | 2370 |
|
2359 | 2371 |
qemu_register_reset(ehci_reset, s); |
2360 | 2372 |
|
Also available in: Unified diff