[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 12/18] usb-linux: split large xfers
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [PATCH 12/18] usb-linux: split large xfers |
Date: |
Mon, 16 May 2011 21:56:16 +0200 |
Add support for splitting large transfers into multiple smaller ones.
This is needed for the upcoming EHCI emulation which allows guests
to submit requests up to 20k in size. The linux kernel allows 16k
max size though.
Roughly based on a patch from git://git.kiszka.org/qemu.git ehci
Signed-off-by: Gerd Hoffmann <address@hidden>
---
usb-linux.c | 68 +++++++++++++++++++++++++++++++++++++---------------------
1 files changed, 43 insertions(+), 25 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index b8f7705..b95c119 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -89,6 +89,9 @@ static int usb_fs_type;
#define ISO_URB_COUNT 3
#define INVALID_EP_TYPE 255
+/* devio.c limits single requests to 16k */
+#define MAX_USBFS_BUFFER_SIZE 16384
+
typedef struct AsyncURB AsyncURB;
struct endp_data {
@@ -229,6 +232,7 @@ struct AsyncURB
/* For regular async urbs */
USBPacket *packet;
+ int more; /* large transfer, more urbs follow */
/* For buffered iso handling */
int iso_frame_idx; /* -1 means in flight */
@@ -291,7 +295,7 @@ static void async_complete(void *opaque)
if (p) {
switch (aurb->urb.status) {
case 0:
- p->len = aurb->urb.actual_length;
+ p->len += aurb->urb.actual_length;
break;
case -EPIPE:
@@ -306,7 +310,7 @@ static void async_complete(void *opaque)
if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
usb_generic_async_ctrl_complete(&s->dev, p);
- } else {
+ } else if (!aurb->more) {
usb_packet_complete(&s->dev, p);
}
}
@@ -646,7 +650,8 @@ 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;
+ int ret, rem;
+ uint8_t *pbuf;
uint8_t ep;
if (!is_valid(s, p->devep)) {
@@ -673,32 +678,45 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket
*p)
return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
}
- aurb = async_alloc(s);
- aurb->packet = p;
+ rem = p->len;
+ pbuf = p->data;
+ p->len = 0;
+ while (rem) {
+ aurb = async_alloc(s);
+ aurb->packet = p;
- urb = &aurb->urb;
+ urb = &aurb->urb;
+ urb->endpoint = ep;
+ urb->type = USBDEVFS_URB_TYPE_BULK;
+ urb->usercontext = s;
+ urb->buffer = pbuf;
- urb->endpoint = ep;
- urb->buffer = p->data;
- urb->buffer_length = p->len;
- urb->type = USBDEVFS_URB_TYPE_BULK;
- urb->usercontext = s;
+ if (rem > 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;
+ rem -= urb->buffer_length;
- ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
+ ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
- DPRINTF("husb: data submit. ep 0x%x len %u aurb %p\n",
- urb->endpoint, p->len, aurb);
+ DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb
%p\n",
+ urb->endpoint, urb->buffer_length, aurb->more, p, aurb);
- if (ret < 0) {
- DPRINTF("husb: submit failed. errno %d\n", errno);
- async_free(aurb);
+ if (ret < 0) {
+ DPRINTF("husb: submit failed. errno %d\n", errno);
+ async_free(aurb);
- switch(errno) {
- case ETIMEDOUT:
- return USB_RET_NAK;
- case EPIPE:
- default:
- return USB_RET_STALL;
+ switch(errno) {
+ case ETIMEDOUT:
+ return USB_RET_NAK;
+ case EPIPE:
+ default:
+ return USB_RET_STALL;
+ }
}
}
--
1.7.1
- [Qemu-devel] [PATCH 06/18] usb: Pass the packet to the device's handle_control callback, (continued)
- [Qemu-devel] [PATCH 06/18] usb: Pass the packet to the device's handle_control callback, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 01/18] usb: Add Interface Association Descriptor descriptor type, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 13/18] usb-linux: fix max_packet_size for highspeed., Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 03/18] usb: remove fallback to bNumInterfaces if no .nif, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 09/18] usb-linux: add hostport property, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 05/18] Bug #757654: UHCI fails to signal stall response patch, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 10/18] usb-linux: track aurbs in list, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 11/18] usb-linux: walk async urb list in cancel, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 14/18] usb: add usb_handle_packet, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 02/18] usb: update config descriptors to identify number of interfaces, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 12/18] usb-linux: split large xfers,
Gerd Hoffmann <=
- [Qemu-devel] [PATCH 08/18] usb-linux: fix device path aka physical port handling, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 04/18] usb: add support for "grouped" interfaces and the Interface Association Descriptor, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 17/18] usb-storage: don't call usb_packet_complete twice, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 07/18] usb-linux: use usb_generic_handle_packet(), Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 15/18] usb: keep track of packet owner., Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 16/18] usb: move cancel callback to USBDeviceInfo, Gerd Hoffmann, 2011/05/16
- [Qemu-devel] [PATCH 18/18] usb: add ehci adapter, Gerd Hoffmann, 2011/05/16