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