diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 14:12:55 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 14:13:53 -0500 |
commit | 7483948fdd31a8642ef0288aab6f368b98d53c29 (patch) | |
tree | 031020a5553701d2aae8dddb0fa509aa65854eb1 /drivers/usb/class/cdc-wdm.c | |
parent | 22a416c4e0f2179b57028e084ac0ed2c110333bd (diff) | |
parent | fe250923bbbbcbccc9aa7b84d05ee7a060450534 (diff) |
Merge tag 'usb-3.3-rc3' into usb-next
This is done to resolve a merge conflict with:
drivers/usb/class/cdc-wdm.c
and to better handle future patches for this driver as it is under
active development at the moment.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class/cdc-wdm.c')
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 23cf9d38eb54..f63601a2054c 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -105,7 +105,8 @@ struct wdm_device { | |||
105 | int count; | 105 | int count; |
106 | dma_addr_t shandle; | 106 | dma_addr_t shandle; |
107 | dma_addr_t ihandle; | 107 | dma_addr_t ihandle; |
108 | struct mutex lock; | 108 | struct mutex wlock; |
109 | struct mutex rlock; | ||
109 | wait_queue_head_t wait; | 110 | wait_queue_head_t wait; |
110 | struct work_struct rxwork; | 111 | struct work_struct rxwork; |
111 | int werr; | 112 | int werr; |
@@ -314,7 +315,7 @@ static ssize_t wdm_write | |||
314 | } | 315 | } |
315 | 316 | ||
316 | /* concurrent writes and disconnect */ | 317 | /* concurrent writes and disconnect */ |
317 | r = mutex_lock_interruptible(&desc->lock); | 318 | r = mutex_lock_interruptible(&desc->wlock); |
318 | rv = -ERESTARTSYS; | 319 | rv = -ERESTARTSYS; |
319 | if (r) { | 320 | if (r) { |
320 | kfree(buf); | 321 | kfree(buf); |
@@ -377,7 +378,7 @@ static ssize_t wdm_write | |||
377 | out: | 378 | out: |
378 | usb_autopm_put_interface(desc->intf); | 379 | usb_autopm_put_interface(desc->intf); |
379 | outnp: | 380 | outnp: |
380 | mutex_unlock(&desc->lock); | 381 | mutex_unlock(&desc->wlock); |
381 | outnl: | 382 | outnl: |
382 | return rv < 0 ? rv : count; | 383 | return rv < 0 ? rv : count; |
383 | } | 384 | } |
@@ -390,7 +391,7 @@ static ssize_t wdm_read | |||
390 | struct wdm_device *desc = file->private_data; | 391 | struct wdm_device *desc = file->private_data; |
391 | 392 | ||
392 | 393 | ||
393 | rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */ | 394 | rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ |
394 | if (rv < 0) | 395 | if (rv < 0) |
395 | return -ERESTARTSYS; | 396 | return -ERESTARTSYS; |
396 | 397 | ||
@@ -458,14 +459,16 @@ retry: | |||
458 | for (i = 0; i < desc->length - cntr; i++) | 459 | for (i = 0; i < desc->length - cntr; i++) |
459 | desc->ubuf[i] = desc->ubuf[i + cntr]; | 460 | desc->ubuf[i] = desc->ubuf[i + cntr]; |
460 | 461 | ||
462 | spin_lock_irq(&desc->iuspin); | ||
461 | desc->length -= cntr; | 463 | desc->length -= cntr; |
464 | spin_unlock_irq(&desc->iuspin); | ||
462 | /* in case we had outstanding data */ | 465 | /* in case we had outstanding data */ |
463 | if (!desc->length) | 466 | if (!desc->length) |
464 | clear_bit(WDM_READ, &desc->flags); | 467 | clear_bit(WDM_READ, &desc->flags); |
465 | rv = cntr; | 468 | rv = cntr; |
466 | 469 | ||
467 | err: | 470 | err: |
468 | mutex_unlock(&desc->lock); | 471 | mutex_unlock(&desc->rlock); |
469 | return rv; | 472 | return rv; |
470 | } | 473 | } |
471 | 474 | ||
@@ -531,7 +534,8 @@ static int wdm_open(struct inode *inode, struct file *file) | |||
531 | } | 534 | } |
532 | intf->needs_remote_wakeup = 1; | 535 | intf->needs_remote_wakeup = 1; |
533 | 536 | ||
534 | mutex_lock(&desc->lock); | 537 | /* using write lock to protect desc->count */ |
538 | mutex_lock(&desc->wlock); | ||
535 | if (!desc->count++) { | 539 | if (!desc->count++) { |
536 | desc->werr = 0; | 540 | desc->werr = 0; |
537 | desc->rerr = 0; | 541 | desc->rerr = 0; |
@@ -544,7 +548,7 @@ static int wdm_open(struct inode *inode, struct file *file) | |||
544 | } else { | 548 | } else { |
545 | rv = 0; | 549 | rv = 0; |
546 | } | 550 | } |
547 | mutex_unlock(&desc->lock); | 551 | mutex_unlock(&desc->wlock); |
548 | usb_autopm_put_interface(desc->intf); | 552 | usb_autopm_put_interface(desc->intf); |
549 | out: | 553 | out: |
550 | mutex_unlock(&wdm_mutex); | 554 | mutex_unlock(&wdm_mutex); |
@@ -556,9 +560,11 @@ static int wdm_release(struct inode *inode, struct file *file) | |||
556 | struct wdm_device *desc = file->private_data; | 560 | struct wdm_device *desc = file->private_data; |
557 | 561 | ||
558 | mutex_lock(&wdm_mutex); | 562 | mutex_lock(&wdm_mutex); |
559 | mutex_lock(&desc->lock); | 563 | |
564 | /* using write lock to protect desc->count */ | ||
565 | mutex_lock(&desc->wlock); | ||
560 | desc->count--; | 566 | desc->count--; |
561 | mutex_unlock(&desc->lock); | 567 | mutex_unlock(&desc->wlock); |
562 | 568 | ||
563 | if (!desc->count) { | 569 | if (!desc->count) { |
564 | dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); | 570 | dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); |
@@ -655,7 +661,8 @@ next_desc: | |||
655 | desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); | 661 | desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); |
656 | if (!desc) | 662 | if (!desc) |
657 | goto out; | 663 | goto out; |
658 | mutex_init(&desc->lock); | 664 | mutex_init(&desc->rlock); |
665 | mutex_init(&desc->wlock); | ||
659 | spin_lock_init(&desc->iuspin); | 666 | spin_lock_init(&desc->iuspin); |
660 | init_waitqueue_head(&desc->wait); | 667 | init_waitqueue_head(&desc->wait); |
661 | desc->wMaxCommand = maxcom; | 668 | desc->wMaxCommand = maxcom; |
@@ -771,11 +778,13 @@ static void wdm_disconnect(struct usb_interface *intf) | |||
771 | /* to terminate pending flushes */ | 778 | /* to terminate pending flushes */ |
772 | clear_bit(WDM_IN_USE, &desc->flags); | 779 | clear_bit(WDM_IN_USE, &desc->flags); |
773 | spin_unlock_irqrestore(&desc->iuspin, flags); | 780 | spin_unlock_irqrestore(&desc->iuspin, flags); |
774 | mutex_lock(&desc->lock); | 781 | wake_up_all(&desc->wait); |
782 | mutex_lock(&desc->rlock); | ||
783 | mutex_lock(&desc->wlock); | ||
775 | kill_urbs(desc); | 784 | kill_urbs(desc); |
776 | cancel_work_sync(&desc->rxwork); | 785 | cancel_work_sync(&desc->rxwork); |
777 | mutex_unlock(&desc->lock); | 786 | mutex_unlock(&desc->wlock); |
778 | wake_up_all(&desc->wait); | 787 | mutex_unlock(&desc->rlock); |
779 | if (!desc->count) | 788 | if (!desc->count) |
780 | cleanup(desc); | 789 | cleanup(desc); |
781 | mutex_unlock(&wdm_mutex); | 790 | mutex_unlock(&wdm_mutex); |
@@ -790,8 +799,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
790 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); | 799 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); |
791 | 800 | ||
792 | /* if this is an autosuspend the caller does the locking */ | 801 | /* if this is an autosuspend the caller does the locking */ |
793 | if (!PMSG_IS_AUTO(message)) | 802 | if (!PMSG_IS_AUTO(message)) { |
794 | mutex_lock(&desc->lock); | 803 | mutex_lock(&desc->rlock); |
804 | mutex_lock(&desc->wlock); | ||
805 | } | ||
795 | spin_lock_irq(&desc->iuspin); | 806 | spin_lock_irq(&desc->iuspin); |
796 | 807 | ||
797 | if (PMSG_IS_AUTO(message) && | 808 | if (PMSG_IS_AUTO(message) && |
@@ -807,8 +818,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
807 | kill_urbs(desc); | 818 | kill_urbs(desc); |
808 | cancel_work_sync(&desc->rxwork); | 819 | cancel_work_sync(&desc->rxwork); |
809 | } | 820 | } |
810 | if (!PMSG_IS_AUTO(message)) | 821 | if (!PMSG_IS_AUTO(message)) { |
811 | mutex_unlock(&desc->lock); | 822 | mutex_unlock(&desc->wlock); |
823 | mutex_unlock(&desc->rlock); | ||
824 | } | ||
812 | 825 | ||
813 | return rv; | 826 | return rv; |
814 | } | 827 | } |
@@ -846,7 +859,8 @@ static int wdm_pre_reset(struct usb_interface *intf) | |||
846 | { | 859 | { |
847 | struct wdm_device *desc = usb_get_intfdata(intf); | 860 | struct wdm_device *desc = usb_get_intfdata(intf); |
848 | 861 | ||
849 | mutex_lock(&desc->lock); | 862 | mutex_lock(&desc->rlock); |
863 | mutex_lock(&desc->wlock); | ||
850 | kill_urbs(desc); | 864 | kill_urbs(desc); |
851 | 865 | ||
852 | /* | 866 | /* |
@@ -868,7 +882,8 @@ static int wdm_post_reset(struct usb_interface *intf) | |||
868 | int rv; | 882 | int rv; |
869 | 883 | ||
870 | rv = recover_from_urb_loss(desc); | 884 | rv = recover_from_urb_loss(desc); |
871 | mutex_unlock(&desc->lock); | 885 | mutex_unlock(&desc->wlock); |
886 | mutex_unlock(&desc->rlock); | ||
872 | return 0; | 887 | return 0; |
873 | } | 888 | } |
874 | 889 | ||