[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 07/12] uhci: Add support for input queuing
From: |
Hans de Goede |
Subject: |
[Qemu-devel] [PATCH 07/12] uhci: Add support for input queuing |
Date: |
Mon, 8 Oct 2012 09:51:31 +0200 |
Signed-off-by: Hans de Goede <address@hidden>
---
hw/usb/hcd-uhci.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 124d43a..63f2161 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -678,6 +678,13 @@ static void uhci_wakeup(USBPort *port1)
}
}
+static void uhci_remove_from_queue(USBPort *port, USBPacket *p)
+{
+ UHCIAsync *async = DO_UPCAST(UHCIAsync, packet, p);
+ uhci_async_unlink(async);
+ uhci_async_cancel(async);
+}
+
static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr)
{
USBDevice *dev;
@@ -818,7 +825,8 @@ out:
}
static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
- uint32_t *int_mask, bool queuing)
+ uint32_t *int_mask, bool queuing,
+ struct USBEndpoint **ep_ret)
{
UHCIAsync *async;
int len = 0, max_len;
@@ -862,6 +870,9 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr,
UHCI_TD *td,
dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
+ if (ep_ret) {
+ *ep_ret = ep;
+ }
usb_packet_setup(&async->packet, pid, ep, addr);
qemu_sglist_add(&async->sgl, td->buffer, max_len);
usb_packet_map(&async->packet, &async->sgl);
@@ -875,6 +886,8 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr,
UHCI_TD *td,
break;
case USB_TOKEN_IN:
+ async->packet.short_not_ok = ((td->ctrl & TD_CTRL_SPD) != 0);
+ async->packet.int_req = ((td->ctrl & TD_CTRL_IOC) != 0);
len = usb_handle_packet(dev, &async->packet);
break;
@@ -975,7 +988,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr)
return 0;
}
-static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
+static void uhci_fill_queue(UHCIState *s, UHCI_TD *td, struct USBEndpoint *ep)
{
uint32_t int_mask = 0;
uint32_t plink = td->link;
@@ -984,7 +997,8 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
int ret;
ptd.ctrl = td->ctrl;
- while (is_valid(plink) && !(ptd.ctrl & TD_CTRL_SPD)) {
+ while (is_valid(plink) &&
+ (usb_ep_input_pipeline(ep) || !(ptd.ctrl & TD_CTRL_SPD))) {
pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));
le32_to_cpus(&ptd.link);
le32_to_cpus(&ptd.ctrl);
@@ -997,7 +1011,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
break;
}
trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
- ret = uhci_handle_td(s, plink, &ptd, &int_mask, true);
+ ret = uhci_handle_td(s, plink, &ptd, &int_mask, true, NULL);
if (ret == TD_RESULT_ASYNC_CONT) {
break;
}
@@ -1005,12 +1019,14 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
assert(int_mask == 0);
plink = ptd.link;
}
+ usb_ep_process_queue(ep);
}
static void uhci_process_frame(UHCIState *s)
{
uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
uint32_t curr_qh, td_count = 0;
+ struct USBEndpoint *curr_ep;
int cnt, ret;
UHCI_TD td;
UHCI_QH qh;
@@ -1081,7 +1097,7 @@ static void uhci_process_frame(UHCIState *s)
trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token);
old_td_ctrl = td.ctrl;
- ret = uhci_handle_td(s, link, &td, &int_mask, false);
+ ret = uhci_handle_td(s, link, &td, &int_mask, false, &curr_ep);
if (old_td_ctrl != td.ctrl) {
/* update the status bits of the TD */
val = cpu_to_le32(td.ctrl);
@@ -1100,7 +1116,7 @@ static void uhci_process_frame(UHCIState *s)
case TD_RESULT_ASYNC_START:
trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
- uhci_fill_queue(s, &td);
+ uhci_fill_queue(s, &td, curr_ep);
link = curr_qh ? qh.link : td.link;
continue;
@@ -1202,6 +1218,7 @@ static USBPortOps uhci_port_ops = {
.child_detach = uhci_child_detach,
.wakeup = uhci_wakeup,
.complete = uhci_async_complete,
+ .remove_from_queue = uhci_remove_from_queue,
};
static USBBusOps uhci_bus_ops = {
@@ -1238,6 +1255,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
USBPort *ports[NB_PORTS];
for(i = 0; i < NB_PORTS; i++) {
ports[i] = &s->ports[i].port;
+ ports[i]->supports_queuing = true;
}
if (usb_register_companion(s->masterbus, ports, NB_PORTS,
s->firstport, s, &uhci_port_ops,
@@ -1247,6 +1265,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
} else {
usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
for (i = 0; i < NB_PORTS; i++) {
+ s->ports[i].port.supports_queuing = true;
usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
}
--
1.7.12.1
- [Qemu-devel] [PATCH 00/12] RFC: usb: input pipelining support and other speedups, Hans de Goede, 2012/10/08
- [Qemu-devel] [PATCH 02/12] usb-redir: Add support for 32 bits bulk packet length, Hans de Goede, 2012/10/08
- [Qemu-devel] [PATCH 01/12] usb-redir: When a packet contains data on a stall, ignore the stall, Hans de Goede, 2012/10/08
- [Qemu-devel] [PATCH 07/12] uhci: Add support for input queuing,
Hans de Goede <=
- [Qemu-devel] [PATCH 08/12] ehci: Get rid of packet tbytes field, Hans de Goede, 2012/10/08
- [Qemu-devel] [PATCH 03/12] usb-host-linux: Only enabling pipeling for output endpoints, Hans de Goede, 2012/10/08
- [Qemu-devel] [PATCH 04/12] usb: Add support for input pipelining, Hans de Goede, 2012/10/08
- Re: [Qemu-devel] [PATCH 04/12] usb: Add support for input pipelining, Gerd Hoffmann, 2012/10/08
- Re: [Qemu-devel] [PATCH 04/12] usb: Add support for input pipelining, Hans de Goede, 2012/10/08
- Re: [Qemu-devel] [PATCH 04/12] usb: Add support for input pipelining, Gerd Hoffmann, 2012/10/09
- Re: [Qemu-devel] [PATCH 04/12] usb: Add support for input pipelining, Hans de Goede, 2012/10/09
- Re: [Qemu-devel] [PATCH 04/12] usb: Add support for input pipelining, Gerd Hoffmann, 2012/10/09
- Re: [Qemu-devel] [PATCH 04/12] usb: Add support for input pipelining, Hans de Goede, 2012/10/09
[Qemu-devel] [PATCH 06/12] uhci: Move checks to continue queuing to uhci_fill_queue(), Hans de Goede, 2012/10/08