summaryrefslogtreecommitdiff
path: root/libusb/os/linux_usbfs.c
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2008-05-05 01:00:31 +0100
committerDaniel Drake <dsd@gentoo.org>2008-05-05 01:00:31 +0100
commit7da521954ba661d3f537440c31a84b66e974d56b (patch)
treed273a0e06399f8aced15884dcaa58d62da247af5 /libusb/os/linux_usbfs.c
parent470b1bc42bf53373ce678fc76bab9160a54d6881 (diff)
downloadlibusb-7da521954ba661d3f537440c31a84b66e974d56b.tar.gz
Linux: fix logical URB allocation
We were allocating the wrong number of URBs for transfers of size multiples of 16k.
Diffstat (limited to 'libusb/os/linux_usbfs.c')
-rw-r--r--libusb/os/linux_usbfs.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 40a32f1..ec7907f 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -598,7 +598,13 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer,
* into smaller units to meet such restriction, then fire off all the
* units at once. it would be simpler if we just fired one unit at a time,
* but there is a big performance gain through doing it this way. */
- int num_urbs = (transfer->length / MAX_BULK_BUFFER_LENGTH) + 1;
+ int num_urbs = transfer->length / MAX_BULK_BUFFER_LENGTH;
+ int last_urb_partial = 0;
+
+ if ((transfer->length % MAX_BULK_BUFFER_LENGTH) > 0) {
+ last_urb_partial = 1;
+ num_urbs++;
+ }
usbi_dbg("need %d urbs for new transfer with length %d", num_urbs,
transfer->length);
alloc_size = num_urbs * sizeof(struct usbfs_urb);
@@ -618,7 +624,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer,
urb->type = urb_type;
urb->endpoint = transfer->endpoint;
urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);
- if (i == num_urbs - 1)
+ if (i == num_urbs - 1 && last_urb_partial)
urb->buffer_length = transfer->length % MAX_BULK_BUFFER_LENGTH;
else
urb->buffer_length = MAX_BULK_BUFFER_LENGTH;