Commit 446ab1284e0648eb9e2bfd08edb769bcd22dccb2

Authored by aliguori
1 parent 9d0efc88

husb: Make control transactions asynchronous (Max Krasnyansky)

USB is 99.8% async now :). 0.2% is the three control requests that
we need to execute synchronously. We could off-load that to a thread
or something but it's not worth the pain since those requests are
performed only during device initialization (ie when device is
connected to the VM).

The change is a bit bigger than I wanted due to the fact that generic
handle_packet()/handle_control() interface was not designed for
async transactions. So I ended up adding custom handle_packet()
code to usb-linux. We can make that generic if/when some other
component needs it.

Signed-off-by: Max Krasnyansky <maxk@kernel.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5204 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 371 additions and 93 deletions
usb-linux.c
... ... @@ -25,28 +25,20 @@
25 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 26 * THE SOFTWARE.
27 27 */
  28 +
28 29 #include "qemu-common.h"
29 30 #include "qemu-timer.h"
30   -#include "hw/usb.h"
31 31 #include "console.h"
32 32  
33 33 #if defined(__linux__)
34 34 #include <dirent.h>
35 35 #include <sys/ioctl.h>
36   -#include <linux/usbdevice_fs.h>
37   -#include <linux/version.h>
38 36 #include <signal.h>
39 37  
40   -/* We redefine it to avoid version problems */
41   -struct usb_ctrltransfer {
42   - uint8_t bRequestType;
43   - uint8_t bRequest;
44   - uint16_t wValue;
45   - uint16_t wIndex;
46   - uint16_t wLength;
47   - uint32_t timeout;
48   - void *data;
49   -};
  38 +#include <linux/usb/ch9.h>
  39 +#include <linux/usbdevice_fs.h>
  40 +#include <linux/version.h>
  41 +#include "hw/usb.h"
50 42  
51 43 typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
52 44 int vendor_id, int product_id,
... ... @@ -54,7 +46,6 @@ typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
54 46 static int usb_host_find_device(int *pbus_num, int *paddr,
55 47 char *product_name, int product_name_size,
56 48 const char *devname);
57   -
58 49 //#define DEBUG
59 50  
60 51 #ifdef DEBUG
... ... @@ -67,14 +58,32 @@ static int usb_host_find_device(int *pbus_num, int *paddr,
67 58 #define PRODUCT_NAME_SZ 32
68 59 #define MAX_ENDPOINTS 16
69 60  
70   -struct sigaction sigact;
71   -
72 61 /* endpoint association data */
73 62 struct endp_data {
74 63 uint8_t type;
75 64 uint8_t halted;
76 65 };
77 66  
  67 +enum {
  68 + CTRL_STATE_IDLE = 0,
  69 + CTRL_STATE_SETUP,
  70 + CTRL_STATE_DATA,
  71 + CTRL_STATE_ACK
  72 +};
  73 +
  74 +/*
  75 + * Control transfer state.
  76 + * Note that 'buffer' _must_ follow 'req' field because
  77 + * we need contigious buffer when we submit control URB.
  78 + */
  79 +struct ctrl_struct {
  80 + uint16_t len;
  81 + uint16_t offset;
  82 + uint8_t state;
  83 + struct usb_ctrlrequest req;
  84 + uint8_t buffer[1024];
  85 +};
  86 +
78 87 typedef struct USBHostDevice {
79 88 USBDevice dev;
80 89 int fd;
... ... @@ -82,8 +91,10 @@ typedef struct USBHostDevice {
82 91 uint8_t descr[1024];
83 92 int descr_len;
84 93 int configuration;
  94 + int ninterfaces;
85 95 int closing;
86 96  
  97 + struct ctrl_struct ctrl;
87 98 struct endp_data endp_table[MAX_ENDPOINTS];
88 99  
89 100 /* Host side address */
... ... @@ -172,6 +183,26 @@ static void async_free(AsyncURB *aurb)
172 183 qemu_free(aurb);
173 184 }
174 185  
  186 +static void async_complete_ctrl(USBHostDevice *s, USBPacket *p)
  187 +{
  188 + switch(s->ctrl.state) {
  189 + case CTRL_STATE_SETUP:
  190 + if (p->len < s->ctrl.len)
  191 + s->ctrl.len = p->len;
  192 + s->ctrl.state = CTRL_STATE_DATA;
  193 + p->len = 8;
  194 + break;
  195 +
  196 + case CTRL_STATE_ACK:
  197 + s->ctrl.state = CTRL_STATE_IDLE;
  198 + p->len = 0;
  199 + break;
  200 +
  201 + default:
  202 + break;
  203 + }
  204 +}
  205 +
175 206 static void async_complete(void *opaque)
176 207 {
177 208 USBHostDevice *s = opaque;
... ... @@ -204,6 +235,8 @@ static void async_complete(void *opaque)
204 235 switch (aurb->urb.status) {
205 236 case 0:
206 237 p->len = aurb->urb.actual_length;
  238 + if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL)
  239 + async_complete_ctrl(s, p);
207 240 break;
208 241  
209 242 case -EPIPE:
... ... @@ -237,7 +270,7 @@ static void async_cancel(USBPacket *unused, void *opaque)
237 270 }
238 271 }
239 272  
240   -static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
  273 +static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
241 274 {
242 275 int dev_descr_len, config_descr_len;
243 276 int interface, nb_interfaces, nb_configurations;
... ... @@ -246,6 +279,8 @@ static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
246 279 if (configuration == 0) /* address state - ignore */
247 280 return 1;
248 281  
  282 + dprintf("husb: claiming interfaces. config %d\n", configuration);
  283 +
249 284 i = 0;
250 285 dev_descr_len = dev->descr[0];
251 286 if (dev_descr_len > dev->descr_len)
... ... @@ -265,8 +300,10 @@ static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
265 300  
266 301 printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
267 302  
268   - if (configuration < 0 || configuration == dev->descr[i + 5])
  303 + if (configuration < 0 || configuration == dev->descr[i + 5]) {
  304 + configuration = dev->descr[i + 5];
269 305 break;
  306 + }
270 307  
271 308 i += config_descr_len;
272 309 }
... ... @@ -310,17 +347,37 @@ static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
310 347 printf("husb: %d interfaces claimed for configuration %d\n",
311 348 nb_interfaces, configuration);
312 349  
  350 + dev->ninterfaces = nb_interfaces;
  351 + dev->configuration = configuration;
  352 + return 1;
  353 +}
  354 +
  355 +static int usb_host_release_interfaces(USBHostDevice *s)
  356 +{
  357 + int ret, i;
  358 +
  359 + dprintf("husb: releasing interfaces\n");
  360 +
  361 + for (i = 0; i < s->ninterfaces; i++) {
  362 + ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
  363 + if (ret < 0) {
  364 + perror("husb: failed to release interface");
  365 + return 0;
  366 + }
  367 + }
  368 +
313 369 return 1;
314 370 }
315 371  
316 372 static void usb_host_handle_reset(USBDevice *dev)
317 373 {
318   - USBHostDevice *s = (USBHostDevice *)dev;
  374 + USBHostDevice *s = (USBHostDevice *) dev;
319 375  
320 376 dprintf("husb: reset device %u.%u\n", s->bus_num, s->addr);
321 377  
322 378 ioctl(s->fd, USBDEVFS_RESET);
323   - usb_host_update_interfaces(s, s->configuration);
  379 +
  380 + usb_host_claim_interfaces(s, s->configuration);
324 381 }
325 382  
326 383 static void usb_host_handle_destroy(USBDevice *dev)
... ... @@ -343,73 +400,10 @@ static void usb_host_handle_destroy(USBDevice *dev)
343 400  
344 401 static int usb_linux_update_endp_table(USBHostDevice *s);
345 402  
346   -static int usb_host_handle_control(USBDevice *dev,
347   - int request,
348   - int value,
349   - int index,
350   - int length,
351   - uint8_t *data)
352   -{
353   - USBHostDevice *s = (USBHostDevice *)dev;
354   - struct usb_ctrltransfer ct;
355   - struct usbdevfs_setinterface si;
356   - int intf_update_required = 0;
357   - int ret;
358   -
359   - if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
360   - /* specific SET_ADDRESS support */
361   - dev->addr = value;
362   - return 0;
363   - } else if (request == ((USB_RECIP_INTERFACE << 8) |
364   - USB_REQ_SET_INTERFACE)) {
365   - /* set alternate setting for the interface */
366   - si.interface = index;
367   - si.altsetting = value;
368   - ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
369   - usb_linux_update_endp_table(s);
370   - } else if (request == (DeviceOutRequest | USB_REQ_SET_CONFIGURATION)) {
371   - dprintf("husb: ctrl set config %d\n", value & 0xff);
372   - if (s->configuration != (value & 0xff)) {
373   - s->configuration = (value & 0xff);
374   - intf_update_required = 1;
375   - }
376   - goto do_request;
377   - } else {
378   - do_request:
379   - ct.bRequestType = request >> 8;
380   - ct.bRequest = request;
381   - ct.wValue = value;
382   - ct.wIndex = index;
383   - ct.wLength = length;
384   - ct.timeout = 50;
385   - ct.data = data;
386   - ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
387   -
388   - dprintf("husb: ctrl req 0x%x val 0x%x index %u len %u ret %d\n",
389   - ct.bRequest, ct.wValue, ct.wIndex, ct.wLength, ret);
390   - }
391   -
392   - if (ret < 0) {
393   - switch(errno) {
394   - case ETIMEDOUT:
395   - return USB_RET_NAK;
396   - default:
397   - return USB_RET_STALL;
398   - }
399   - } else {
400   - if (intf_update_required) {
401   - dprintf("husb: updating interfaces\n");
402   - usb_host_update_interfaces(s, value & 0xff);
403   - }
404   - return ret;
405   - }
406   -}
407   -
408   -static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
  403 +static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
409 404 {
410   - USBHostDevice *s = (USBHostDevice *) dev;
411   - AsyncURB *aurb;
412 405 struct usbdevfs_urb *urb;
  406 + AsyncURB *aurb;
413 407 int ret;
414 408  
415 409 aurb = async_alloc();
... ... @@ -474,12 +468,292 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
474 468 return USB_RET_ASYNC;
475 469 }
476 470  
  471 +static int ctrl_error(void)
  472 +{
  473 + if (errno == ETIMEDOUT)
  474 + return USB_RET_NAK;
  475 + else
  476 + return USB_RET_STALL;
  477 +}
  478 +
  479 +static int usb_host_set_address(USBHostDevice *s, int addr)
  480 +{
  481 + dprintf("husb: ctrl set addr %u\n", addr);
  482 + s->dev.addr = addr;
  483 + return 0;
  484 +}
  485 +
  486 +static int usb_host_set_config(USBHostDevice *s, int config)
  487 +{
  488 + usb_host_release_interfaces(s);
  489 +
  490 + int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
  491 +
  492 + dprintf("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
  493 +
  494 + if (ret < 0)
  495 + return ctrl_error();
  496 +
  497 + usb_host_claim_interfaces(s, config);
  498 + return 0;
  499 +}
  500 +
  501 +static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
  502 +{
  503 + struct usbdevfs_setinterface si;
  504 + int ret;
  505 +
  506 + si.interface = iface;
  507 + si.altsetting = alt;
  508 + ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
  509 +
  510 + dprintf("husb: ctrl set iface %d altset %d ret %d errno %d\n",
  511 + iface, alt, ret, errno);
  512 +
  513 + if (ret < 0)
  514 + return ctrl_error();
  515 +
  516 + usb_linux_update_endp_table(s);
  517 + return 0;
  518 +}
  519 +
  520 +static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
  521 +{
  522 + struct usbdevfs_urb *urb;
  523 + AsyncURB *aurb;
  524 + int ret, value, index;
  525 +
  526 + /*
  527 + * Process certain standard device requests.
  528 + * These are infrequent and are processed synchronously.
  529 + */
  530 + value = le16_to_cpu(s->ctrl.req.wValue);
  531 + index = le16_to_cpu(s->ctrl.req.wIndex);
  532 +
  533 + dprintf("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
  534 + s->ctrl.req.bRequestType, s->ctrl.req.bRequest, value, index,
  535 + s->ctrl.len);
  536 +
  537 + if (s->ctrl.req.bRequestType == 0) {
  538 + switch (s->ctrl.req.bRequest) {
  539 + case USB_REQ_SET_ADDRESS:
  540 + return usb_host_set_address(s, value);
  541 +
  542 + case USB_REQ_SET_CONFIGURATION:
  543 + return usb_host_set_config(s, value & 0xff);
  544 + }
  545 + }
  546 +
  547 + if (s->ctrl.req.bRequestType == 1 &&
  548 + s->ctrl.req.bRequest == USB_REQ_SET_INTERFACE)
  549 + return usb_host_set_interface(s, index, value);
  550 +
  551 + /* The rest are asynchronous */
  552 +
  553 + aurb = async_alloc();
  554 + if (!aurb) {
  555 + dprintf("husb: async malloc failed\n");
  556 + return USB_RET_NAK;
  557 + }
  558 + aurb->hdev = s;
  559 + aurb->packet = p;
  560 +
  561 + /*
  562 + * Setup ctrl transfer.
  563 + *
  564 + * s->ctrl is layed out such that data buffer immediately follows
  565 + * 'req' struct which is exactly what usbdevfs expects.
  566 + */
  567 + urb = &aurb->urb;
  568 +
  569 + urb->type = USBDEVFS_URB_TYPE_CONTROL;
  570 + urb->endpoint = p->devep;
  571 +
  572 + urb->buffer = &s->ctrl.req;
  573 + urb->buffer_length = 8 + s->ctrl.len;
  574 +
  575 + urb->usercontext = s;
  576 +
  577 + ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
  578 +
  579 + dprintf("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
  580 +
  581 + if (ret < 0) {
  582 + dprintf("husb: submit failed. errno %d\n", errno);
  583 + async_free(aurb);
  584 +
  585 + switch(errno) {
  586 + case ETIMEDOUT:
  587 + return USB_RET_NAK;
  588 + case EPIPE:
  589 + default:
  590 + return USB_RET_STALL;
  591 + }
  592 + }
  593 +
  594 + usb_defer_packet(p, async_cancel, aurb);
  595 + return USB_RET_ASYNC;
  596 +}
  597 +
  598 +static int do_token_setup(USBDevice *dev, USBPacket *p)
  599 +{
  600 + USBHostDevice *s = (USBHostDevice *) dev;
  601 + int ret = 0;
  602 +
  603 + if (p->len != 8)
  604 + return USB_RET_STALL;
  605 +
  606 + memcpy(&s->ctrl.req, p->data, 8);
  607 + s->ctrl.len = le16_to_cpu(s->ctrl.req.wLength);
  608 + s->ctrl.offset = 0;
  609 + s->ctrl.state = CTRL_STATE_SETUP;
  610 +
  611 + if (s->ctrl.req.bRequestType & USB_DIR_IN) {
  612 + ret = usb_host_handle_control(s, p);
  613 + if (ret < 0)
  614 + return ret;
  615 +
  616 + if (ret < s->ctrl.len)
  617 + s->ctrl.len = ret;
  618 + s->ctrl.state = CTRL_STATE_DATA;
  619 + } else {
  620 + if (s->ctrl.len == 0)
  621 + s->ctrl.state = CTRL_STATE_ACK;
  622 + else
  623 + s->ctrl.state = CTRL_STATE_DATA;
  624 + }
  625 +
  626 + return ret;
  627 +}
  628 +
  629 +static int do_token_in(USBDevice *dev, USBPacket *p)
  630 +{
  631 + USBHostDevice *s = (USBHostDevice *) dev;
  632 + int ret = 0;
  633 +
  634 + if (p->devep != 0)
  635 + return usb_host_handle_data(s, p);
  636 +
  637 + switch(s->ctrl.state) {
  638 + case CTRL_STATE_ACK:
  639 + if (!(s->ctrl.req.bRequestType & USB_DIR_IN)) {
  640 + ret = usb_host_handle_control(s, p);
  641 + if (ret == USB_RET_ASYNC)
  642 + return USB_RET_ASYNC;
  643 +
  644 + s->ctrl.state = CTRL_STATE_IDLE;
  645 + return ret > 0 ? 0 : ret;
  646 + }
  647 +
  648 + return 0;
  649 +
  650 + case CTRL_STATE_DATA:
  651 + if (s->ctrl.req.bRequestType & USB_DIR_IN) {
  652 + int len = s->ctrl.len - s->ctrl.offset;
  653 + if (len > p->len)
  654 + len = p->len;
  655 + memcpy(p->data, s->ctrl.buffer + s->ctrl.offset, len);
  656 + s->ctrl.offset += len;
  657 + if (s->ctrl.offset >= s->ctrl.len)
  658 + s->ctrl.state = CTRL_STATE_ACK;
  659 + return len;
  660 + }
  661 +
  662 + s->ctrl.state = CTRL_STATE_IDLE;
  663 + return USB_RET_STALL;
  664 +
  665 + default:
  666 + return USB_RET_STALL;
  667 + }
  668 +}
  669 +
  670 +static int do_token_out(USBDevice *dev, USBPacket *p)
  671 +{
  672 + USBHostDevice *s = (USBHostDevice *) dev;
  673 +
  674 + if (p->devep != 0)
  675 + return usb_host_handle_data(s, p);
  676 +
  677 + switch(s->ctrl.state) {
  678 + case CTRL_STATE_ACK:
  679 + if (s->ctrl.req.bRequestType & USB_DIR_IN) {
  680 + s->ctrl.state = CTRL_STATE_IDLE;
  681 + /* transfer OK */
  682 + } else {
  683 + /* ignore additional output */
  684 + }
  685 + return 0;
  686 +
  687 + case CTRL_STATE_DATA:
  688 + if (!(s->ctrl.req.bRequestType & USB_DIR_IN)) {
  689 + int len = s->ctrl.len - s->ctrl.offset;
  690 + if (len > p->len)
  691 + len = p->len;
  692 + memcpy(s->ctrl.buffer + s->ctrl.offset, p->data, len);
  693 + s->ctrl.offset += len;
  694 + if (s->ctrl.offset >= s->ctrl.len)
  695 + s->ctrl.state = CTRL_STATE_ACK;
  696 + return len;
  697 + }
  698 +
  699 + s->ctrl.state = CTRL_STATE_IDLE;
  700 + return USB_RET_STALL;
  701 +
  702 + default:
  703 + return USB_RET_STALL;
  704 + }
  705 +}
  706 +
  707 +/*
  708 + * Packet handler.
  709 + * Called by the HC (host controller).
  710 + *
  711 + * Returns length of the transaction or one of the USB_RET_XXX codes.
  712 + */
  713 +int usb_host_handle_packet(USBDevice *s, USBPacket *p)
  714 +{
  715 + switch(p->pid) {
  716 + case USB_MSG_ATTACH:
  717 + s->state = USB_STATE_ATTACHED;
  718 + return 0;
  719 +
  720 + case USB_MSG_DETACH:
  721 + s->state = USB_STATE_NOTATTACHED;
  722 + return 0;
  723 +
  724 + case USB_MSG_RESET:
  725 + s->remote_wakeup = 0;
  726 + s->addr = 0;
  727 + s->state = USB_STATE_DEFAULT;
  728 + s->handle_reset(s);
  729 + return 0;
  730 + }
  731 +
  732 + /* Rest of the PIDs must match our address */
  733 + if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
  734 + return USB_RET_NODEV;
  735 +
  736 + switch (p->pid) {
  737 + case USB_TOKEN_SETUP:
  738 + return do_token_setup(s, p);
  739 +
  740 + case USB_TOKEN_IN:
  741 + return do_token_in(s, p);
  742 +
  743 + case USB_TOKEN_OUT:
  744 + return do_token_out(s, p);
  745 +
  746 + default:
  747 + return USB_RET_STALL;
  748 + }
  749 +}
  750 +
477 751 /* returns 1 on problem encountered or 0 for success */
478 752 static int usb_linux_update_endp_table(USBHostDevice *s)
479 753 {
480 754 uint8_t *descriptors;
481 755 uint8_t devep, type, configuration, alt_interface;
482   - struct usb_ctrltransfer ct;
  756 + struct usbdevfs_ctrltransfer ct;
483 757 int interface, ret, length, i;
484 758  
485 759 ct.bRequestType = USB_DIR_IN;
... ... @@ -624,10 +898,14 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
624 898 #endif
625 899  
626 900 dev->fd = fd;
627   - dev->configuration = 1;
628 901  
629   - /* XXX - do something about initial configuration */
630   - if (!usb_host_update_interfaces(dev, -1))
  902 + /*
  903 + * Initial configuration is -1 which makes us claim first
  904 + * available config. We used to start with 1, which does not
  905 + * always work. I've seen devices where first config starts
  906 + * with 2.
  907 + */
  908 + if (!usb_host_claim_interfaces(dev, -1))
631 909 goto fail;
632 910  
633 911 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
... ... @@ -646,11 +924,9 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
646 924 dev->dev.speed = USB_SPEED_LOW;
647 925 else
648 926 dev->dev.speed = USB_SPEED_HIGH;
649   - dev->dev.handle_packet = usb_generic_handle_packet;
650 927  
651   - dev->dev.handle_reset = usb_host_handle_reset;
652   - dev->dev.handle_control = usb_host_handle_control;
653   - dev->dev.handle_data = usb_host_handle_data;
  928 + dev->dev.handle_packet = usb_host_handle_packet;
  929 + dev->dev.handle_reset = usb_host_handle_reset;
654 930 dev->dev.handle_destroy = usb_host_handle_destroy;
655 931  
656 932 if (!prod_name || prod_name[0] == '\0')
... ... @@ -1055,6 +1331,8 @@ void usb_host_info(void)
1055 1331  
1056 1332 #else
1057 1333  
  1334 +#include "hw/usb.h"
  1335 +
1058 1336 void usb_host_info(void)
1059 1337 {
1060 1338 term_printf("USB host devices not supported\n");
... ...