aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2012-01-16 06:41:48 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-24 15:17:29 -0500
commite8537bd2c4f325a4796da33564ddcef9489b7feb (patch)
tree50d5d643591ed620197c0d7bba8263acb1afba7f /drivers/usb/class
parentc428b70c1e115c5649707a602742e34130d19428 (diff)
USB: cdc-wdm: use two mutexes to allow simultaneous read and write
using a separate read and write mutex for locking is sufficient to make the driver accept simultaneous read and write. This improves useability a lot. Signed-off-by: Bjørn Mork <bjorn@mork.no> Cc: stable <stable@vger.kernel.org> Cc: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-wdm.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 1f6b5c8394b4..023d271c2614 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -88,7 +88,8 @@ struct wdm_device {
88 int count; 88 int count;
89 dma_addr_t shandle; 89 dma_addr_t shandle;
90 dma_addr_t ihandle; 90 dma_addr_t ihandle;
91 struct mutex lock; 91 struct mutex wlock;
92 struct mutex rlock;
92 wait_queue_head_t wait; 93 wait_queue_head_t wait;
93 struct work_struct rxwork; 94 struct work_struct rxwork;
94 int werr; 95 int werr;
@@ -323,7 +324,7 @@ static ssize_t wdm_write
323 } 324 }
324 325
325 /* concurrent writes and disconnect */ 326 /* concurrent writes and disconnect */
326 r = mutex_lock_interruptible(&desc->lock); 327 r = mutex_lock_interruptible(&desc->wlock);
327 rv = -ERESTARTSYS; 328 rv = -ERESTARTSYS;
328 if (r) { 329 if (r) {
329 kfree(buf); 330 kfree(buf);
@@ -386,7 +387,7 @@ static ssize_t wdm_write
386out: 387out:
387 usb_autopm_put_interface(desc->intf); 388 usb_autopm_put_interface(desc->intf);
388outnp: 389outnp:
389 mutex_unlock(&desc->lock); 390 mutex_unlock(&desc->wlock);
390outnl: 391outnl:
391 return rv < 0 ? rv : count; 392 return rv < 0 ? rv : count;
392} 393}
@@ -399,7 +400,7 @@ static ssize_t wdm_read
399 struct wdm_device *desc = file->private_data; 400 struct wdm_device *desc = file->private_data;
400 401
401 402
402 rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */ 403 rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
403 if (rv < 0) 404 if (rv < 0)
404 return -ERESTARTSYS; 405 return -ERESTARTSYS;
405 406
@@ -476,7 +477,7 @@ retry:
476 rv = cntr; 477 rv = cntr;
477 478
478err: 479err:
479 mutex_unlock(&desc->lock); 480 mutex_unlock(&desc->rlock);
480 return rv; 481 return rv;
481} 482}
482 483
@@ -542,7 +543,8 @@ static int wdm_open(struct inode *inode, struct file *file)
542 } 543 }
543 intf->needs_remote_wakeup = 1; 544 intf->needs_remote_wakeup = 1;
544 545
545 mutex_lock(&desc->lock); 546 /* using write lock to protect desc->count */
547 mutex_lock(&desc->wlock);
546 if (!desc->count++) { 548 if (!desc->count++) {
547 desc->werr = 0; 549 desc->werr = 0;
548 desc->rerr = 0; 550 desc->rerr = 0;
@@ -555,7 +557,7 @@ static int wdm_open(struct inode *inode, struct file *file)
555 } else { 557 } else {
556 rv = 0; 558 rv = 0;
557 } 559 }
558 mutex_unlock(&desc->lock); 560 mutex_unlock(&desc->wlock);
559 usb_autopm_put_interface(desc->intf); 561 usb_autopm_put_interface(desc->intf);
560out: 562out:
561 mutex_unlock(&wdm_mutex); 563 mutex_unlock(&wdm_mutex);
@@ -567,9 +569,11 @@ static int wdm_release(struct inode *inode, struct file *file)
567 struct wdm_device *desc = file->private_data; 569 struct wdm_device *desc = file->private_data;
568 570
569 mutex_lock(&wdm_mutex); 571 mutex_lock(&wdm_mutex);
570 mutex_lock(&desc->lock); 572
573 /* using write lock to protect desc->count */
574 mutex_lock(&desc->wlock);
571 desc->count--; 575 desc->count--;
572 mutex_unlock(&desc->lock); 576 mutex_unlock(&desc->wlock);
573 577
574 if (!desc->count) { 578 if (!desc->count) {
575 dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); 579 dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
@@ -667,7 +671,8 @@ next_desc:
667 desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); 671 desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
668 if (!desc) 672 if (!desc)
669 goto out; 673 goto out;
670 mutex_init(&desc->lock); 674 mutex_init(&desc->rlock);
675 mutex_init(&desc->wlock);
671 spin_lock_init(&desc->iuspin); 676 spin_lock_init(&desc->iuspin);
672 init_waitqueue_head(&desc->wait); 677 init_waitqueue_head(&desc->wait);
673 desc->wMaxCommand = maxcom; 678 desc->wMaxCommand = maxcom;
@@ -781,10 +786,12 @@ static void wdm_disconnect(struct usb_interface *intf)
781 /* to terminate pending flushes */ 786 /* to terminate pending flushes */
782 clear_bit(WDM_IN_USE, &desc->flags); 787 clear_bit(WDM_IN_USE, &desc->flags);
783 spin_unlock_irqrestore(&desc->iuspin, flags); 788 spin_unlock_irqrestore(&desc->iuspin, flags);
784 mutex_lock(&desc->lock); 789 mutex_lock(&desc->rlock);
790 mutex_lock(&desc->wlock);
785 kill_urbs(desc); 791 kill_urbs(desc);
786 cancel_work_sync(&desc->rxwork); 792 cancel_work_sync(&desc->rxwork);
787 mutex_unlock(&desc->lock); 793 mutex_unlock(&desc->wlock);
794 mutex_unlock(&desc->rlock);
788 wake_up_all(&desc->wait); 795 wake_up_all(&desc->wait);
789 if (!desc->count) 796 if (!desc->count)
790 cleanup(desc); 797 cleanup(desc);
@@ -800,8 +807,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
800 dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); 807 dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
801 808
802 /* if this is an autosuspend the caller does the locking */ 809 /* if this is an autosuspend the caller does the locking */
803 if (!PMSG_IS_AUTO(message)) 810 if (!PMSG_IS_AUTO(message)) {
804 mutex_lock(&desc->lock); 811 mutex_lock(&desc->rlock);
812 mutex_lock(&desc->wlock);
813 }
805 spin_lock_irq(&desc->iuspin); 814 spin_lock_irq(&desc->iuspin);
806 815
807 if (PMSG_IS_AUTO(message) && 816 if (PMSG_IS_AUTO(message) &&
@@ -817,8 +826,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
817 kill_urbs(desc); 826 kill_urbs(desc);
818 cancel_work_sync(&desc->rxwork); 827 cancel_work_sync(&desc->rxwork);
819 } 828 }
820 if (!PMSG_IS_AUTO(message)) 829 if (!PMSG_IS_AUTO(message)) {
821 mutex_unlock(&desc->lock); 830 mutex_unlock(&desc->wlock);
831 mutex_unlock(&desc->rlock);
832 }
822 833
823 return rv; 834 return rv;
824} 835}
@@ -856,7 +867,8 @@ static int wdm_pre_reset(struct usb_interface *intf)
856{ 867{
857 struct wdm_device *desc = usb_get_intfdata(intf); 868 struct wdm_device *desc = usb_get_intfdata(intf);
858 869
859 mutex_lock(&desc->lock); 870 mutex_lock(&desc->rlock);
871 mutex_lock(&desc->wlock);
860 kill_urbs(desc); 872 kill_urbs(desc);
861 873
862 /* 874 /*
@@ -878,7 +890,8 @@ static int wdm_post_reset(struct usb_interface *intf)
878 int rv; 890 int rv;
879 891
880 rv = recover_from_urb_loss(desc); 892 rv = recover_from_urb_loss(desc);
881 mutex_unlock(&desc->lock); 893 mutex_unlock(&desc->wlock);
894 mutex_unlock(&desc->rlock);
882 return 0; 895 return 0;
883} 896}
884 897