dcavalca / rpms / qemu

Forked from rpms/qemu a year ago
Clone

Blame 0128-usb-ehci-split-our-qh-queue-into-async-and-periodic-.patch

1b1995
From 0f1e5b8d4f36de8b6b1301740226c9858b5a0318 Mon Sep 17 00:00:00 2001
1b1995
From: Hans de Goede <hdegoede@redhat.com>
1b1995
Date: Tue, 28 Feb 2012 16:34:38 +0100
1b1995
Subject: [PATCH 128/140] usb-ehci: split our qh queue into async and periodic
1b1995
 queues
1b1995
1b1995
qhs can be part of both the async and the periodic schedule, as is shown
1b1995
in later patches in this series it is useful to keep track of the qhs on
1b1995
a per schedule basis.
1b1995
1b1995
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1b1995
---
1b1995
 hw/usb-ehci.c |   62 ++++++++++++++++++++++++++++++++++-----------------------
1b1995
 1 file changed, 37 insertions(+), 25 deletions(-)
1b1995
1b1995
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
1b1995
index 37076a9..980cce3 100644
1b1995
--- a/hw/usb-ehci.c
1b1995
+++ b/hw/usb-ehci.c
1b1995
@@ -347,7 +347,6 @@ enum async_state {
1b1995
 struct EHCIQueue {
1b1995
     EHCIState *ehci;
1b1995
     QTAILQ_ENTRY(EHCIQueue) next;
1b1995
-    bool async_schedule;
1b1995
     uint32_t seen;
1b1995
     uint64_t ts;
1b1995
 
1b1995
@@ -367,6 +366,8 @@ struct EHCIQueue {
1b1995
     int usb_status;
1b1995
 };
1b1995
 
1b1995
+typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
1b1995
+
1b1995
 struct EHCIState {
1b1995
     PCIDevice dev;
1b1995
     USBBus bus;
1b1995
@@ -410,7 +411,8 @@ struct EHCIState {
1b1995
     USBPort ports[NB_PORTS];
1b1995
     USBPort *companion_ports[NB_PORTS];
1b1995
     uint32_t usbsts_pending;
1b1995
-    QTAILQ_HEAD(, EHCIQueue) queues;
1b1995
+    EHCIQueueHead aqueues;
1b1995
+    EHCIQueueHead pqueues;
1b1995
 
1b1995
     uint32_t a_fetch_addr;   // which address to look at next
1b1995
     uint32_t p_fetch_addr;   // which address to look at next
1b1995
@@ -660,31 +662,34 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
1b1995
 
1b1995
 static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
1b1995
 {
1b1995
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
1b1995
     EHCIQueue *q;
1b1995
 
1b1995
     q = g_malloc0(sizeof(*q));
1b1995
     q->ehci = ehci;
1b1995
-    q->async_schedule = async;
1b1995
-    QTAILQ_INSERT_HEAD(&ehci->queues, q, next);
1b1995
+    QTAILQ_INSERT_HEAD(head, q, next);
1b1995
     trace_usb_ehci_queue_action(q, "alloc");
1b1995
     return q;
1b1995
 }
1b1995
 
1b1995
-static void ehci_free_queue(EHCIQueue *q)
1b1995
+static void ehci_free_queue(EHCIQueue *q, int async)
1b1995
 {
1b1995
+    EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
1b1995
     trace_usb_ehci_queue_action(q, "free");
1b1995
     if (q->async == EHCI_ASYNC_INFLIGHT) {
1b1995
         usb_cancel_packet(&q->packet);
1b1995
     }
1b1995
-    QTAILQ_REMOVE(&q->ehci->queues, q, next);
1b1995
+    QTAILQ_REMOVE(head, q, next);
1b1995
     g_free(q);
1b1995
 }
1b1995
 
1b1995
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
1b1995
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
1b1995
+                                        int async)
1b1995
 {
1b1995
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
1b1995
     EHCIQueue *q;
1b1995
 
1b1995
-    QTAILQ_FOREACH(q, &ehci->queues, next) {
1b1995
+    QTAILQ_FOREACH(q, head, next) {
1b1995
         if (addr == q->qhaddr) {
1b1995
             return q;
1b1995
         }
1b1995
@@ -692,11 +697,12 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
1b1995
     return NULL;
1b1995
 }
1b1995
 
1b1995
-static void ehci_queues_rip_unused(EHCIState *ehci)
1b1995
+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
1b1995
 {
1b1995
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
1b1995
     EHCIQueue *q, *tmp;
1b1995
 
1b1995
-    QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
1b1995
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
1b1995
         if (q->seen) {
1b1995
             q->seen = 0;
1b1995
             q->ts = ehci->last_run_ns;
1b1995
@@ -706,28 +712,30 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
1b1995
             /* allow 0.25 sec idle */
1b1995
             continue;
1b1995
         }
1b1995
-        ehci_free_queue(q);
1b1995
+        ehci_free_queue(q, async);
1b1995
     }
1b1995
 }
1b1995
 
1b1995
-static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
1b1995
+static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
1b1995
 {
1b1995
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
1b1995
     EHCIQueue *q, *tmp;
1b1995
 
1b1995
-    QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
1b1995
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
1b1995
         if (q->packet.owner != dev) {
1b1995
             continue;
1b1995
         }
1b1995
-        ehci_free_queue(q);
1b1995
+        ehci_free_queue(q, async);
1b1995
     }
1b1995
 }
1b1995
 
1b1995
-static void ehci_queues_rip_all(EHCIState *ehci)
1b1995
+static void ehci_queues_rip_all(EHCIState *ehci, int async)
1b1995
 {
1b1995
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
1b1995
     EHCIQueue *q, *tmp;
1b1995
 
1b1995
-    QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
1b1995
-        ehci_free_queue(q);
1b1995
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
1b1995
+        ehci_free_queue(q, async);
1b1995
     }
1b1995
 }
1b1995
 
1b1995
@@ -772,7 +780,8 @@ static void ehci_detach(USBPort *port)
1b1995
         return;
1b1995
     }
1b1995
 
1b1995
-    ehci_queues_rip_device(s, port->dev);
1b1995
+    ehci_queues_rip_device(s, port->dev, 0);
1b1995
+    ehci_queues_rip_device(s, port->dev, 1);
1b1995
 
1b1995
     *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
1b1995
     *portsc |= PORTSC_CSC;
1b1995
@@ -792,7 +801,8 @@ static void ehci_child_detach(USBPort *port, USBDevice *child)
1b1995
         return;
1b1995
     }
1b1995
 
1b1995
-    ehci_queues_rip_device(s, child);
1b1995
+    ehci_queues_rip_device(s, child, 0);
1b1995
+    ehci_queues_rip_device(s, child, 1);
1b1995
 }
1b1995
 
1b1995
 static void ehci_wakeup(USBPort *port)
1b1995
@@ -890,7 +900,8 @@ static void ehci_reset(void *opaque)
1b1995
             usb_send_msg(devs[i], USB_MSG_RESET);
1b1995
         }
1b1995
     }
1b1995
-    ehci_queues_rip_all(s);
1b1995
+    ehci_queues_rip_all(s, 0);
1b1995
+    ehci_queues_rip_all(s, 1);
1b1995
 }
1b1995
 
1b1995
 static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
1b1995
@@ -1554,7 +1565,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
1b1995
         ehci_set_usbsts(ehci, USBSTS_REC);
1b1995
     }
1b1995
 
1b1995
-    ehci_queues_rip_unused(ehci);
1b1995
+    ehci_queues_rip_unused(ehci, async);
1b1995
 
1b1995
     /*  Find the head of the list (4.9.1.1) */
1b1995
     for(i = 0; i < MAX_QH; i++) {
1b1995
@@ -1641,7 +1652,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
1b1995
     int reload;
1b1995
 
1b1995
     entry = ehci_get_fetch_addr(ehci, async);
1b1995
-    q = ehci_find_queue_by_qh(ehci, entry);
1b1995
+    q = ehci_find_queue_by_qh(ehci, entry, async);
1b1995
     if (NULL == q) {
1b1995
         q = ehci_alloc_queue(ehci, async);
1b1995
     }
1b1995
@@ -2092,7 +2103,7 @@ static void ehci_advance_state(EHCIState *ehci,
1b1995
 
1b1995
 static void ehci_advance_async_state(EHCIState *ehci)
1b1995
 {
1b1995
-    int async = 1;
1b1995
+    const int async = 1;
1b1995
 
1b1995
     switch(ehci_get_state(ehci, async)) {
1b1995
     case EST_INACTIVE:
1b1995
@@ -2149,7 +2160,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
1b1995
 {
1b1995
     uint32_t entry;
1b1995
     uint32_t list;
1b1995
-    int async = 0;
1b1995
+    const int async = 0;
1b1995
 
1b1995
     // 4.6
1b1995
 
1b1995
@@ -2366,7 +2377,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
1b1995
     }
1b1995
 
1b1995
     s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
1b1995
-    QTAILQ_INIT(&s->queues);
1b1995
+    QTAILQ_INIT(&s->aqueues);
1b1995
+    QTAILQ_INIT(&s->pqueues);
1b1995
 
1b1995
     qemu_register_reset(ehci_reset, s);
1b1995
 
1b1995
-- 
1b1995
1.7.9.3
1b1995