Patchwork [07/16] usb-host: iovec support

login
register
mail settings
Submitter Gerd Hoffmann
Date Aug. 4, 2011, 3:10 p.m.
Message ID <1312470626-25872-8-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/108510/
State New
Headers show

Comments

Gerd Hoffmann - Aug. 4, 2011, 3:10 p.m.
Add full support for iovecs to usb-host.  The code can split large
transfers into smaller ones already, we are using this to also split
requests at iovec borders.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 usb-linux.c |   27 ++++++++++++++++++---------
 1 files changed, 18 insertions(+), 9 deletions(-)

Patch

diff --git a/usb-linux.c b/usb-linux.c
index 184f56f..5562187 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -707,7 +707,7 @@  static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
     USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
     struct usbdevfs_urb *urb;
     AsyncURB *aurb;
-    int ret, rem;
+    int ret, rem, prem, v;
     uint8_t *pbuf;
     uint8_t ep;
 
@@ -735,10 +735,18 @@  static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
     }
 
-    assert(p->iov.niov == 1); /* temporary */
-    rem = p->iov.iov[0].iov_len;
-    pbuf = p->iov.iov[0].iov_base;
+    v = 0;
+    prem = p->iov.iov[v].iov_len;
+    pbuf = p->iov.iov[v].iov_base;
+    rem = p->iov.size;
     while (rem) {
+        if (prem == 0) {
+            v++;
+            assert(v < p->iov.niov);
+            prem = p->iov.iov[v].iov_len;
+            pbuf = p->iov.iov[v].iov_base;
+            assert(prem <= rem);
+        }
         aurb = async_alloc(s);
         aurb->packet = p;
 
@@ -747,16 +755,17 @@  static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         urb->type          = USBDEVFS_URB_TYPE_BULK;
         urb->usercontext   = s;
         urb->buffer        = pbuf;
+        urb->buffer_length = prem;
 
-        if (rem > MAX_USBFS_BUFFER_SIZE) {
+        if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) {
             urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
-            aurb->more         = 1;
-        } else {
-            urb->buffer_length = rem;
-            aurb->more         = 0;
         }
         pbuf += urb->buffer_length;
+        prem -= urb->buffer_length;
         rem  -= urb->buffer_length;
+        if (rem) {
+            aurb->more         = 1;
+        }
 
         ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);