[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 07/18] ehci: add async field to EHCIQueue
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [PATCH 07/18] ehci: add async field to EHCIQueue |
Date: |
Fri, 25 May 2012 14:40:23 +0200 |
Keep track whenever a EHCIQueue is part of the async or periodic
schedule. This way we don't have to pass around the async flag
everywhere but can look it up from the EHCIQueue struct when needed.
Signed-off-by: Gerd Hoffmann <address@hidden>
---
hw/usb/hcd-ehci.c | 92 ++++++++++++++++++++++++++++-------------------------
1 files changed, 49 insertions(+), 43 deletions(-)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index aa67af6..f363f14 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -364,6 +364,7 @@ struct EHCIQueue {
QTAILQ_ENTRY(EHCIQueue) next;
uint32_t seen;
uint64_t ts;
+ int async;
/* cached data from guest - needs to be flushed
* when guest removes an entry (doorbell, handshake sequence)
@@ -700,15 +701,16 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci,
uint32_t addr, int async)
q = g_malloc0(sizeof(*q));
q->ehci = ehci;
q->qhaddr = addr;
+ q->async = async;
QTAILQ_INIT(&q->packets);
QTAILQ_INSERT_HEAD(head, q, next);
trace_usb_ehci_queue_action(q, "alloc");
return q;
}
-static void ehci_free_queue(EHCIQueue *q, int async)
+static void ehci_free_queue(EHCIQueue *q)
{
- EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
+ EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
EHCIPacket *p;
trace_usb_ehci_queue_action(q, "free");
@@ -748,7 +750,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int
async, int flush)
/* allow 0.25 sec idle */
continue;
}
- ehci_free_queue(q, async);
+ ehci_free_queue(q);
}
}
@@ -761,7 +763,7 @@ static void ehci_queues_rip_device(EHCIState *ehci,
USBDevice *dev, int async)
if (q->dev != dev) {
continue;
}
- ehci_free_queue(q, async);
+ ehci_free_queue(q);
}
}
@@ -771,7 +773,7 @@ static void ehci_queues_rip_all(EHCIState *ehci, int async)
EHCIQueue *q, *tmp;
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
- ehci_free_queue(q, async);
+ ehci_free_queue(q);
}
}
@@ -1806,7 +1808,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int
async)
}
/* Section 4.10.2 - paragraph 3 */
-static int ehci_state_advqueue(EHCIQueue *q, int async)
+static int ehci_state_advqueue(EHCIQueue *q)
{
#if 0
/* TO-DO: 4.10.2 - paragraph 2
@@ -1825,27 +1827,27 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
(NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
q->qtdaddr = q->qh.altnext_qtd;
- ehci_set_state(q->ehci, async, EST_FETCHQTD);
+ ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
/*
* next qTD is valid
*/
} else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
q->qtdaddr = q->qh.next_qtd;
- ehci_set_state(q->ehci, async, EST_FETCHQTD);
+ ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
/*
* no valid qTD, try next QH
*/
} else {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
}
return 1;
}
/* Section 4.10.2 - paragraph 4 */
-static int ehci_state_fetchqtd(EHCIQueue *q, int async)
+static int ehci_state_fetchqtd(EHCIQueue *q)
{
EHCIqtd qtd;
EHCIPacket *p;
@@ -1865,41 +1867,41 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async)
ehci_qh_do_overlay(q);
ehci_flush_qh(q);
if (p->async == EHCI_ASYNC_INFLIGHT) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
} else {
- ehci_set_state(q->ehci, async, EST_EXECUTING);
+ ehci_set_state(q->ehci, q->async, EST_EXECUTING);
}
again = 1;
} else if (qtd.token & QTD_TOKEN_ACTIVE) {
p = ehci_alloc_packet(q);
p->qtdaddr = q->qtdaddr;
p->qtd = qtd;
- ehci_set_state(q->ehci, async, EST_EXECUTE);
+ ehci_set_state(q->ehci, q->async, EST_EXECUTE);
again = 1;
} else {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
}
return again;
}
-static int ehci_state_horizqh(EHCIQueue *q, int async)
+static int ehci_state_horizqh(EHCIQueue *q)
{
int again = 0;
- if (ehci_get_fetch_addr(q->ehci, async) != q->qh.next) {
- ehci_set_fetch_addr(q->ehci, async, q->qh.next);
- ehci_set_state(q->ehci, async, EST_FETCHENTRY);
+ if (ehci_get_fetch_addr(q->ehci, q->async) != q->qh.next) {
+ ehci_set_fetch_addr(q->ehci, q->async, q->qh.next);
+ ehci_set_state(q->ehci, q->async, EST_FETCHENTRY);
again = 1;
} else {
- ehci_set_state(q->ehci, async, EST_ACTIVE);
+ ehci_set_state(q->ehci, q->async, EST_ACTIVE);
}
return again;
}
-static void ehci_fill_queue(EHCIPacket *p, int async)
+static void ehci_fill_queue(EHCIPacket *p)
{
EHCIQueue *q = p->queue;
EHCIqtd qtd = p->qtd;
@@ -1928,7 +1930,7 @@ static void ehci_fill_queue(EHCIPacket *p, int async)
}
}
-static int ehci_state_execute(EHCIQueue *q, int async)
+static int ehci_state_execute(EHCIQueue *q)
{
EHCIPacket *p = QTAILQ_FIRST(&q->packets);
int again = 0;
@@ -1944,16 +1946,16 @@ static int ehci_state_execute(EHCIQueue *q, int async)
// TODO write back ptr to async list when done or out of time
// TODO Windows does not seem to ever set the MULT field
- if (!async) {
+ if (!q->async) {
int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
if (!transactCtr) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
goto out;
}
}
- if (async) {
+ if (q->async) {
ehci_set_usbsts(q->ehci, USBSTS_REC);
}
@@ -1966,20 +1968,20 @@ static int ehci_state_execute(EHCIQueue *q, int async)
ehci_flush_qh(q);
trace_usb_ehci_packet_action(p->queue, p, "async");
p->async = EHCI_ASYNC_INFLIGHT;
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
- ehci_fill_queue(p, async);
+ ehci_fill_queue(p);
goto out;
}
- ehci_set_state(q->ehci, async, EST_EXECUTING);
+ ehci_set_state(q->ehci, q->async, EST_EXECUTING);
again = 1;
out:
return again;
}
-static int ehci_state_executing(EHCIQueue *q, int async)
+static int ehci_state_executing(EHCIQueue *q)
{
EHCIPacket *p = QTAILQ_FIRST(&q->packets);
int again = 0;
@@ -1997,7 +1999,7 @@ static int ehci_state_executing(EHCIQueue *q, int async)
}
// 4.10.3
- if (!async) {
+ if (!q->async) {
int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
transactCtr--;
set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT);
@@ -2007,9 +2009,9 @@ static int ehci_state_executing(EHCIQueue *q, int async)
/* 4.10.5 */
if (p->usb_status == USB_RET_NAK) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
} else {
- ehci_set_state(q->ehci, async, EST_WRITEBACK);
+ ehci_set_state(q->ehci, q->async, EST_WRITEBACK);
}
again = 1;
@@ -2020,7 +2022,7 @@ out:
}
-static int ehci_state_writeback(EHCIQueue *q, int async)
+static int ehci_state_writeback(EHCIQueue *q)
{
EHCIPacket *p = QTAILQ_FIRST(&q->packets);
int again = 0;
@@ -2043,10 +2045,10 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
* bit is clear.
*/
if (q->qh.token & QTD_TOKEN_HALT) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
} else {
- ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE);
+ ehci_set_state(q->ehci, q->async, EST_ADVANCEQUEUE);
again = 1;
}
return again;
@@ -2056,8 +2058,7 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
* This is the state machine that is common to both async and periodic
*/
-static void ehci_advance_state(EHCIState *ehci,
- int async)
+static void ehci_advance_state(EHCIState *ehci, int async)
{
EHCIQueue *q = NULL;
int again;
@@ -2074,7 +2075,12 @@ static void ehci_advance_state(EHCIState *ehci,
case EST_FETCHQH:
q = ehci_state_fetchqh(ehci, async);
- again = q ? 1 : 0;
+ if (q != NULL) {
+ assert(q->async == async);
+ again = 1;
+ } else {
+ again = 0;
+ }
break;
case EST_FETCHITD:
@@ -2086,29 +2092,29 @@ static void ehci_advance_state(EHCIState *ehci,
break;
case EST_ADVANCEQUEUE:
- again = ehci_state_advqueue(q, async);
+ again = ehci_state_advqueue(q);
break;
case EST_FETCHQTD:
- again = ehci_state_fetchqtd(q, async);
+ again = ehci_state_fetchqtd(q);
break;
case EST_HORIZONTALQH:
- again = ehci_state_horizqh(q, async);
+ again = ehci_state_horizqh(q);
break;
case EST_EXECUTE:
- again = ehci_state_execute(q, async);
+ again = ehci_state_execute(q);
break;
case EST_EXECUTING:
assert(q != NULL);
- again = ehci_state_executing(q, async);
+ again = ehci_state_executing(q);
break;
case EST_WRITEBACK:
assert(q != NULL);
- again = ehci_state_writeback(q, async);
+ again = ehci_state_writeback(q);
break;
default:
--
1.7.1
- [Qemu-devel] [PATCH 14/18] ehci: fix halt status handling, (continued)
- [Qemu-devel] [PATCH 14/18] ehci: fix halt status handling, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 04/18] ehci: move ehci_flush_qh, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 13/18] ehci: update status bits in ehci_set_state, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 03/18] ehci: cache USBDevice in EHCIQueue, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 01/18] ehci: add EHCIPacket, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 09/18] ehci: schedule async bh on async packet completion, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 17/18] ehci: adaptive wakeup rate., Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 18/18] ehci: rework frame skipping, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 15/18] ehci: remove unused attach_poll_counter, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 16/18] ehci: create ehci_update_frindex, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 07/18] ehci: add async field to EHCIQueue,
Gerd Hoffmann <=
- [Qemu-devel] [PATCH 02/18] ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 08/18] ehci: move async schedule to bottom half, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 11/18] ehci: fix reset, Gerd Hoffmann, 2012/05/25
- [Qemu-devel] [PATCH 06/18] ehci: tweak queue initialization, Gerd Hoffmann, 2012/05/25