Commit 046833eae35d9a8c2ed8e87681a74d6a615a0395

Authored by balrog
1 parent 5ad265ee

Use a O_NONBLOCK pipe for iso completion signals for thread-safety, by Arnon Gilboa.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3492 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 29 additions and 22 deletions
usb-linux.c
@@ -68,6 +68,7 @@ struct endp_data { @@ -68,6 +68,7 @@ struct endp_data {
68 typedef struct USBHostDevice { 68 typedef struct USBHostDevice {
69 USBDevice dev; 69 USBDevice dev;
70 int fd; 70 int fd;
  71 + int pipe_fds[2];
71 USBPacket *packet; 72 USBPacket *packet;
72 struct endp_data endp_table[MAX_ENDPOINTS]; 73 struct endp_data endp_table[MAX_ENDPOINTS];
73 int configuration; 74 int configuration;
@@ -78,8 +79,6 @@ typedef struct USBHostDevice { @@ -78,8 +79,6 @@ typedef struct USBHostDevice {
78 79
79 typedef struct PendingURB { 80 typedef struct PendingURB {
80 struct usbdevfs_urb *urb; 81 struct usbdevfs_urb *urb;
81 - USBHostDevice *dev;  
82 - QEMUBH *bh;  
83 int status; 82 int status;
84 struct PendingURB *next; 83 struct PendingURB *next;
85 } PendingURB; 84 } PendingURB;
@@ -91,8 +90,6 @@ static int add_pending_urb(struct usbdevfs_urb *urb) @@ -91,8 +90,6 @@ static int add_pending_urb(struct usbdevfs_urb *urb)
91 PendingURB *purb = qemu_mallocz(sizeof(PendingURB)); 90 PendingURB *purb = qemu_mallocz(sizeof(PendingURB));
92 if (purb) { 91 if (purb) {
93 purb->urb = urb; 92 purb->urb = urb;
94 - purb->dev = NULL;  
95 - purb->bh = NULL;  
96 purb->status = 0; 93 purb->status = 0;
97 purb->next = pending_urbs; 94 purb->next = pending_urbs;
98 pending_urbs = purb; 95 pending_urbs = purb;
@@ -341,16 +338,21 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) @@ -341,16 +338,21 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
341 } 338 }
342 339
343 #ifdef USE_ASYNCIO 340 #ifdef USE_ASYNCIO
344 -static void usb_linux_bh_cb(void *opaque) 341 +static void urb_completion_pipe_read(void *opaque)
345 { 342 {
346 - PendingURB *pending_urb = (PendingURB *)opaque;  
347 - USBHostDevice *s = pending_urb->dev;  
348 - struct usbdevfs_urb *purb = NULL; 343 + USBHostDevice *s = opaque;
349 USBPacket *p = s->packet; 344 USBPacket *p = s->packet;
350 - int ret; 345 + PendingURB *pending_urb = NULL;
  346 + struct usbdevfs_urb *purb = NULL;
  347 + int len, ret;
  348 +
  349 + len = read(s->pipe_fds[0], &pending_urb, sizeof(pending_urb));
  350 + if (len != sizeof(pending_urb)) {
  351 + printf("urb_completion: error reading pending_urb, len=%d\n", len);
  352 + return;
  353 + }
351 354
352 - /* FIXME: handle purb->status */  
353 - qemu_free(pending_urb->bh); 355 + /* FIXME: handle pending_urb->status */
354 del_pending_urb(pending_urb->urb); 356 del_pending_urb(pending_urb->urb);
355 357
356 if (!p) { 358 if (!p) {
@@ -360,14 +362,14 @@ static void usb_linux_bh_cb(void *opaque) @@ -360,14 +362,14 @@ static void usb_linux_bh_cb(void *opaque)
360 362
361 ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb); 363 ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
362 if (ret < 0) { 364 if (ret < 0) {
363 - printf("usb_linux_bh_cb: REAPURBNDELAY ioctl=%d errno=%d\n", 365 + printf("urb_completion: REAPURBNDELAY ioctl=%d errno=%d\n",
364 ret, errno); 366 ret, errno);
365 return; 367 return;
366 } 368 }
367 369
368 #ifdef DEBUG_ISOCH 370 #ifdef DEBUG_ISOCH
369 if (purb == pending_urb->urb) { 371 if (purb == pending_urb->urb) {
370 - printf("usb_linux_bh_cb: urb mismatch reaped=%p pending=%p\n", 372 + printf("urb_completion: urb mismatch reaped=%p pending=%p\n",
371 purb, urb); 373 purb, urb);
372 } 374 }
373 #endif 375 #endif
@@ -391,12 +393,8 @@ static void isoch_done(int signum, siginfo_t *info, void *context) @@ -391,12 +393,8 @@ static void isoch_done(int signum, siginfo_t *info, void *context)
391 393
392 purb = get_pending_urb(urb); 394 purb = get_pending_urb(urb);
393 if (purb) { 395 if (purb) {
394 - purb->bh = qemu_bh_new(usb_linux_bh_cb, purb);  
395 - if (purb->bh) {  
396 - purb->dev = s;  
397 - purb->status = info->si_errno;  
398 - qemu_bh_schedule(purb->bh);  
399 - } 396 + purb->status = info->si_errno;
  397 + write(s->pipe_fds[1], &purb, sizeof(purb));
400 } 398 }
401 } 399 }
402 #endif 400 #endif
@@ -627,7 +625,7 @@ USBDevice *usb_host_device_open(const char *devname) @@ -627,7 +625,7 @@ USBDevice *usb_host_device_open(const char *devname)
627 /* read the device description */ 625 /* read the device description */
628 dev->descr_len = read(fd, dev->descr, sizeof(dev->descr)); 626 dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
629 if (dev->descr_len <= 0) { 627 if (dev->descr_len <= 0) {
630 - perror("usb_host_update_interfaces: reading device data failed"); 628 + perror("usb_host_device_open: reading device data failed");
631 goto fail; 629 goto fail;
632 } 630 }
633 631
@@ -650,7 +648,7 @@ USBDevice *usb_host_device_open(const char *devname) @@ -650,7 +648,7 @@ USBDevice *usb_host_device_open(const char *devname)
650 648
651 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); 649 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
652 if (ret < 0) { 650 if (ret < 0) {
653 - perror("USBDEVFS_CONNECTINFO"); 651 + perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
654 goto fail; 652 goto fail;
655 } 653 }
656 654
@@ -688,8 +686,17 @@ USBDevice *usb_host_device_open(const char *devname) @@ -688,8 +686,17 @@ USBDevice *usb_host_device_open(const char *devname)
688 sigact.sa_restorer = 0; 686 sigact.sa_restorer = 0;
689 ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL); 687 ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL);
690 if (ret < 0) { 688 if (ret < 0) {
691 - printf("sigaction SIG_ISOCOMPLETE=%d errno=%d\n", ret, errno); 689 + perror("usb_host_device_open: sigaction failed");
  690 + goto fail;
  691 + }
  692 +
  693 + if (pipe(dev->pipe_fds) < 0) {
  694 + perror("usb_host_device_open: pipe creation failed");
  695 + goto fail;
692 } 696 }
  697 + fcntl(dev->pipe_fds[0], F_SETFL, O_NONBLOCK | O_ASYNC);
  698 + fcntl(dev->pipe_fds[1], F_SETFL, O_NONBLOCK);
  699 + qemu_set_fd_handler(dev->pipe_fds[0], urb_completion_pipe_read, NULL, dev);
693 #endif 700 #endif
694 dev->urbs_ready = 0; 701 dev->urbs_ready = 0;
695 return (USBDevice *)dev; 702 return (USBDevice *)dev;