summary refs log tree commit diff stats
path: root/hw/usb.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2012-03-01 14:39:28 +0100
committerGerd Hoffmann <kraxel@redhat.com>2012-03-07 12:28:05 +0100
commit7936e0f0d2fcd05bf5a78985a53b6b2276115749 (patch)
treedac03441220377576b3b7252a19ab6e9d6b37ea2 /hw/usb.c
parenteb9d4673e3594baaa857a4c033fc7c21f4ea904b (diff)
downloadfocaccia-qemu-7936e0f0d2fcd05bf5a78985a53b6b2276115749.tar.gz
focaccia-qemu-7936e0f0d2fcd05bf5a78985a53b6b2276115749.zip
usb: add pipelining option to usb endpoints
With this patch applied USB drivers can enable pipelining per endpoint.
With pipelining enabled the usb core will continue submitting packets
even when there are still async transfers in flight instead of passing
them on one by one.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb.c')
-rw-r--r--hw/usb.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/hw/usb.c b/hw/usb.c
index fc41d62438..800d912a27 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -323,7 +323,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
     assert(p->state == USB_PACKET_SETUP);
     assert(p->ep != NULL);
 
-    if (QTAILQ_EMPTY(&p->ep->queue)) {
+    if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
         ret = usb_process_one(p);
         if (ret == USB_RET_ASYNC) {
             usb_packet_set_state(p, USB_PACKET_ASYNC);
@@ -468,6 +468,7 @@ void usb_ep_init(USBDevice *dev)
     dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
     dev->ep_ctl.ifnum = 0;
     dev->ep_ctl.dev = dev;
+    dev->ep_ctl.pipeline = false;
     QTAILQ_INIT(&dev->ep_ctl.queue);
     for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
         dev->ep_in[ep].nr = ep + 1;
@@ -480,6 +481,8 @@ void usb_ep_init(USBDevice *dev)
         dev->ep_out[ep].ifnum = 0;
         dev->ep_in[ep].dev = dev;
         dev->ep_out[ep].dev = dev;
+        dev->ep_in[ep].pipeline = false;
+        dev->ep_out[ep].pipeline = false;
         QTAILQ_INIT(&dev->ep_in[ep].queue);
         QTAILQ_INIT(&dev->ep_out[ep].queue);
     }
@@ -593,3 +596,9 @@ int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
     struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
     return uep->max_packet_size;
 }
+
+void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    uep->pipeline = enabled;
+}