[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 03/13] usb-ehci: split our qh queue into async and p
From: |
Hans de Goede |
Subject: |
[Qemu-devel] [PATCH 03/13] usb-ehci: split our qh queue into async and periodic queues |
Date: |
Fri, 2 Mar 2012 21:27:10 +0100 |
qhs can be part of both the async and the periodic schedule, as is shown
in later patches in this series it is useful to keep track of the qhs on
a per schedule basis.
Signed-off-by: Hans de Goede <address@hidden>
---
hw/usb-ehci.c | 62 ++++++++++++++++++++++++++++++++++-----------------------
1 files changed, 37 insertions(+), 25 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index d41b80e..840022d 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -347,7 +347,6 @@ enum async_state {
struct EHCIQueue {
EHCIState *ehci;
QTAILQ_ENTRY(EHCIQueue) next;
- bool async_schedule;
uint32_t seen;
uint64_t ts;
@@ -367,6 +366,8 @@ struct EHCIQueue {
int usb_status;
};
+typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
+
struct EHCIState {
PCIDevice dev;
USBBus bus;
@@ -410,7 +411,8 @@ struct EHCIState {
USBPort ports[NB_PORTS];
USBPort *companion_ports[NB_PORTS];
uint32_t usbsts_pending;
- QTAILQ_HEAD(, EHCIQueue) queues;
+ EHCIQueueHead aqueues;
+ EHCIQueueHead pqueues;
uint32_t a_fetch_addr; // which address to look at next
uint32_t p_fetch_addr; // which address to look at next
@@ -660,31 +662,34 @@ static void ehci_trace_sitd(EHCIState *s,
target_phys_addr_t addr,
static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q;
q = g_malloc0(sizeof(*q));
q->ehci = ehci;
- q->async_schedule = async;
- QTAILQ_INSERT_HEAD(&ehci->queues, q, next);
+ QTAILQ_INSERT_HEAD(head, q, next);
trace_usb_ehci_queue_action(q, "alloc");
return q;
}
-static void ehci_free_queue(EHCIQueue *q)
+static void ehci_free_queue(EHCIQueue *q, int async)
{
+ EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
trace_usb_ehci_queue_action(q, "free");
if (q->async == EHCI_ASYNC_INFLIGHT) {
usb_cancel_packet(&q->packet);
}
- QTAILQ_REMOVE(&q->ehci->queues, q, next);
+ QTAILQ_REMOVE(head, q, next);
g_free(q);
}
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
+ int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q;
- QTAILQ_FOREACH(q, &ehci->queues, next) {
+ QTAILQ_FOREACH(q, head, next) {
if (addr == q->qhaddr) {
return q;
}
@@ -692,11 +697,12 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci,
uint32_t addr)
return NULL;
}
-static void ehci_queues_rip_unused(EHCIState *ehci)
+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
if (q->seen) {
q->seen = 0;
q->ts = ehci->last_run_ns;
@@ -706,29 +712,31 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
/* allow 0.25 sec idle */
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, async);
}
}
-static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
+static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
if (!usb_packet_is_inflight(&q->packet) ||
q->packet.ep->dev != dev) {
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, async);
}
}
-static void ehci_queues_rip_all(EHCIState *ehci)
+static void ehci_queues_rip_all(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
- ehci_free_queue(q);
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
+ ehci_free_queue(q, async);
}
}
@@ -773,7 +781,8 @@ static void ehci_detach(USBPort *port)
return;
}
- ehci_queues_rip_device(s, port->dev);
+ ehci_queues_rip_device(s, port->dev, 0);
+ ehci_queues_rip_device(s, port->dev, 1);
*portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
*portsc |= PORTSC_CSC;
@@ -793,7 +802,8 @@ static void ehci_child_detach(USBPort *port, USBDevice
*child)
return;
}
- ehci_queues_rip_device(s, child);
+ ehci_queues_rip_device(s, child, 0);
+ ehci_queues_rip_device(s, child, 1);
}
static void ehci_wakeup(USBPort *port)
@@ -911,7 +921,8 @@ static void ehci_reset(void *opaque)
usb_device_reset(devs[i]);
}
}
- ehci_queues_rip_all(s);
+ ehci_queues_rip_all(s, 0);
+ ehci_queues_rip_all(s, 1);
qemu_del_timer(s->frame_timer);
}
@@ -1526,7 +1537,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int
async)
ehci_set_usbsts(ehci, USBSTS_REC);
}
- ehci_queues_rip_unused(ehci);
+ ehci_queues_rip_unused(ehci, async);
/* Find the head of the list (4.9.1.1) */
for(i = 0; i < MAX_QH; i++) {
@@ -1613,7 +1624,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int
async)
int reload;
entry = ehci_get_fetch_addr(ehci, async);
- q = ehci_find_queue_by_qh(ehci, entry);
+ q = ehci_find_queue_by_qh(ehci, entry, async);
if (NULL == q) {
q = ehci_alloc_queue(ehci, async);
}
@@ -2064,7 +2075,7 @@ static void ehci_advance_state(EHCIState *ehci,
static void ehci_advance_async_state(EHCIState *ehci)
{
- int async = 1;
+ const int async = 1;
switch(ehci_get_state(ehci, async)) {
case EST_INACTIVE:
@@ -2121,7 +2132,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
{
uint32_t entry;
uint32_t list;
- int async = 0;
+ const int async = 0;
// 4.6
@@ -2354,7 +2365,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
}
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
- QTAILQ_INIT(&s->queues);
+ QTAILQ_INIT(&s->aqueues);
+ QTAILQ_INIT(&s->pqueues);
qemu_register_reset(ehci_reset, s);
--
1.7.7.6
- [Qemu-devel] usb patches [v2], Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 02/13] usb-ehci: Never follow table entries with the T-bit set, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 03/13] usb-ehci: split our qh queue into async and periodic queues,
Hans de Goede <=
- [Qemu-devel] [PATCH 06/13] usb-ehci: Rip the queues when the async or period schedule is halted, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 07/13] usb-ehci: Any packet completion except for NAK should set the interrupt, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 08/13] usb-ehci: Fix cerr tracking, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 10/13] usb-ehci: Fix and simplify nakcnt handling, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 11/13] usb-ehci: Cleanup itd error handling, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 12/13] usb: return BABBLE rather then NAK when we receive too much data, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 13/13] usb: add USB_RET_IOERROR, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 01/13] usb-redir: Set ep type and interface, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 04/13] usb-ehci: always call ehci_queues_rip_unused for period queues, Hans de Goede, 2012/03/02
- [Qemu-devel] [PATCH 05/13] usb-ehci: Drop cached qhs when the doorbell gets rung, Hans de Goede, 2012/03/02