From ddf6583f88e29b2ec47fa81010c80868bfff7c83 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 14 Dec 2010 18:19:47 +0100 Subject: uhci: switch to QTAILQ --- hw/usb-uhci.c | 63 ++++++++++++++--------------------------------------------- 1 file changed, 15 insertions(+), 48 deletions(-) (limited to 'hw/usb-uhci.c') diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 346db3e..2de0cf2 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -113,7 +113,7 @@ static void dump_data(const uint8_t *data, int len) {} */ typedef struct UHCIAsync { USBPacket packet; - struct UHCIAsync *next; + QTAILQ_ENTRY(UHCIAsync) next; uint32_t td; uint32_t token; int8_t valid; @@ -145,8 +145,7 @@ typedef struct UHCIState { uint32_t pending_int_mask; /* Active packets */ - UHCIAsync *async_pending; - UHCIAsync *async_pool; + QTAILQ_HEAD(,UHCIAsync) async_pending; uint8_t num_ports_vmstate; } UHCIState; @@ -172,7 +171,6 @@ static UHCIAsync *uhci_async_alloc(UHCIState *s) async->token = 0; async->done = 0; async->isoc = 0; - async->next = NULL; return async; } @@ -184,24 +182,12 @@ static void uhci_async_free(UHCIState *s, UHCIAsync *async) static void uhci_async_link(UHCIState *s, UHCIAsync *async) { - async->next = s->async_pending; - s->async_pending = async; + QTAILQ_INSERT_HEAD(&s->async_pending, async, next); } static void uhci_async_unlink(UHCIState *s, UHCIAsync *async) { - UHCIAsync *curr = s->async_pending; - UHCIAsync **prev = &s->async_pending; - - while (curr) { - if (curr == async) { - *prev = curr->next; - return; - } - - prev = &curr->next; - curr = curr->next; - } + QTAILQ_REMOVE(&s->async_pending, async, next); } static void uhci_async_cancel(UHCIState *s, UHCIAsync *async) @@ -220,11 +206,10 @@ static void uhci_async_cancel(UHCIState *s, UHCIAsync *async) */ static UHCIAsync *uhci_async_validate_begin(UHCIState *s) { - UHCIAsync *async = s->async_pending; + UHCIAsync *async; - while (async) { + QTAILQ_FOREACH(async, &s->async_pending, next) { async->valid--; - async = async->next; } return NULL; } @@ -234,47 +219,30 @@ static UHCIAsync *uhci_async_validate_begin(UHCIState *s) */ static void uhci_async_validate_end(UHCIState *s) { - UHCIAsync *curr = s->async_pending; - UHCIAsync **prev = &s->async_pending; - UHCIAsync *next; + UHCIAsync *curr, *n; - while (curr) { + QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) { if (curr->valid > 0) { - prev = &curr->next; - curr = curr->next; continue; } - - next = curr->next; - - /* Unlink */ - *prev = next; - + uhci_async_unlink(s, curr); uhci_async_cancel(s, curr); - - curr = next; } } static void uhci_async_cancel_all(UHCIState *s) { - UHCIAsync *curr = s->async_pending; - UHCIAsync *next; - - while (curr) { - next = curr->next; + UHCIAsync *curr, *n; + QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) { + uhci_async_unlink(s, curr); uhci_async_cancel(s, curr); - - curr = next; } - - s->async_pending = NULL; } static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token) { - UHCIAsync *async = s->async_pending; + UHCIAsync *async; UHCIAsync *match = NULL; int count = 0; @@ -291,7 +259,7 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token * If we ever do we'd want to optimize this algorithm. */ - while (async) { + QTAILQ_FOREACH(async, &s->async_pending, next) { if (async->token == token) { /* Good match */ match = async; @@ -301,8 +269,6 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token break; } } - - async = async->next; count++; } @@ -1137,6 +1103,7 @@ static int usb_uhci_common_initfn(UHCIState *s) s->expire_time = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / FRAME_TIMER_FREQ); s->num_ports_vmstate = NB_PORTS; + QTAILQ_INIT(&s->async_pending); qemu_register_reset(uhci_reset, s); -- cgit v1.1 From 7b5a44c546d9b836859c48bcfb7f1d4ef57ac3e1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 15 Dec 2010 10:26:15 +0100 Subject: uhci: keep uhci state pointer in async packet struct. Signed-off-by: Gerd Hoffmann --- hw/usb-uhci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'hw/usb-uhci.c') diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 2de0cf2..2b63b3f 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -106,6 +106,8 @@ static void dump_data(const uint8_t *data, int len) static void dump_data(const uint8_t *data, int len) {} #endif +typedef struct UHCIState UHCIState; + /* * Pending async transaction. * 'packet' must be the first field because completion @@ -113,6 +115,7 @@ static void dump_data(const uint8_t *data, int len) {} */ typedef struct UHCIAsync { USBPacket packet; + UHCIState *uhci; QTAILQ_ENTRY(UHCIAsync) next; uint32_t td; uint32_t token; @@ -127,7 +130,7 @@ typedef struct UHCIPort { uint16_t ctrl; } UHCIPort; -typedef struct UHCIState { +struct UHCIState { PCIDevice dev; USBBus bus; uint16_t cmd; /* cmd register */ @@ -147,7 +150,7 @@ typedef struct UHCIState { /* Active packets */ QTAILQ_HEAD(,UHCIAsync) async_pending; uint8_t num_ports_vmstate; -} UHCIState; +}; typedef struct UHCI_TD { uint32_t link; @@ -166,6 +169,7 @@ static UHCIAsync *uhci_async_alloc(UHCIState *s) UHCIAsync *async = qemu_malloc(sizeof(UHCIAsync)); memset(&async->packet, 0, sizeof(async->packet)); + async->uhci = s; async->valid = 0; async->td = 0; async->token = 0; @@ -830,8 +834,8 @@ done: static void uhci_async_complete(USBPacket *packet, void *opaque) { - UHCIState *s = opaque; - UHCIAsync *async = (UHCIAsync *) packet; + UHCIAsync *async = container_of(packet, UHCIAsync, packet); + UHCIState *s = async->uhci; DPRINTF("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token); -- cgit v1.1 From 13a9a0d3e253e272744b523e39642c9b6d564f4d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 16 Dec 2010 17:03:44 +0100 Subject: usb: move complete callback to port ops --- hw/usb-uhci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'hw/usb-uhci.c') diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 2b63b3f..a65e0b3 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -642,7 +642,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p) return ret; } -static void uhci_async_complete(USBPacket * packet, void *opaque); +static void uhci_async_complete(USBDevice *dev, USBPacket *packet); static void uhci_process_frame(UHCIState *s); /* return -1 if fatal error (frame must be stopped) @@ -795,8 +795,6 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in async->packet.devep = (td->token >> 15) & 0xf; async->packet.data = async->buffer; async->packet.len = max_len; - async->packet.complete_cb = uhci_async_complete; - async->packet.complete_opaque = s; switch(pid) { case USB_TOKEN_OUT: @@ -832,7 +830,7 @@ done: return len; } -static void uhci_async_complete(USBPacket *packet, void *opaque) +static void uhci_async_complete(USBDevice *dev, USBPacket *packet) { UHCIAsync *async = container_of(packet, UHCIAsync, packet); UHCIState *s = async->uhci; @@ -1083,6 +1081,7 @@ static USBPortOps uhci_port_ops = { .attach = uhci_attach, .detach = uhci_detach, .wakeup = uhci_wakeup, + .complete = uhci_async_complete, }; static int usb_uhci_common_initfn(UHCIState *s) -- cgit v1.1 From 8656954aedbd9995e68e998df734a849f8e63ade Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Mon, 9 May 2011 12:16:50 +0200 Subject: Bug #757654: UHCI fails to signal stall response patch UHCI host controller status register indicates error and an interrupt is triggered on BABBLE and STALL errors. Signed-off-by: Jan Vesely Signed-off-by: Gerd Hoffmann --- hw/usb-uhci.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'hw/usb-uhci.c') diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index a65e0b3..1e9c1e7 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -702,11 +702,15 @@ out: case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; td->ctrl &= ~TD_CTRL_ACTIVE; + s->status |= UHCI_STS_USBERR; + uhci_update_irq(s); return 1; case USB_RET_BABBLE: td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; td->ctrl &= ~TD_CTRL_ACTIVE; + s->status |= UHCI_STS_USBERR; + uhci_update_irq(s); /* frame interrupted */ return -1; -- cgit v1.1 From 53aa8c0e2af473050fa765533a8d69f3450788ab Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 12 May 2011 13:20:39 +0200 Subject: usb: add usb_handle_packet Add a usb_handle_packet function, put it into use everywhere. Right now it just calls dev->info->handle_packet(), that will change in future patches though. Signed-off-by: Gerd Hoffmann --- hw/usb-uhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/usb-uhci.c') diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 1e9c1e7..c0de05b 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -632,7 +632,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p) USBDevice *dev = port->port.dev; if (dev && (port->ctrl & UHCI_PORT_EN)) - ret = dev->info->handle_packet(dev, p); + ret = usb_handle_packet(dev, p); } DPRINTF("uhci: packet exit. ret %d len %d\n", ret, p->len); -- cgit v1.1