diff options
| -rw-r--r-- | drivers/usb/class/cdc-wdm.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 07c12974fe14..b57490508860 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
| @@ -776,9 +776,9 @@ static void wdm_disconnect(struct usb_interface *intf) | |||
| 776 | /* to terminate pending flushes */ | 776 | /* to terminate pending flushes */ |
| 777 | clear_bit(WDM_IN_USE, &desc->flags); | 777 | clear_bit(WDM_IN_USE, &desc->flags); |
| 778 | spin_unlock_irqrestore(&desc->iuspin, flags); | 778 | spin_unlock_irqrestore(&desc->iuspin, flags); |
| 779 | cancel_work_sync(&desc->rxwork); | ||
| 780 | mutex_lock(&desc->lock); | 779 | mutex_lock(&desc->lock); |
| 781 | kill_urbs(desc); | 780 | kill_urbs(desc); |
| 781 | cancel_work_sync(&desc->rxwork); | ||
| 782 | mutex_unlock(&desc->lock); | 782 | mutex_unlock(&desc->lock); |
| 783 | wake_up_all(&desc->wait); | 783 | wake_up_all(&desc->wait); |
| 784 | if (!desc->count) | 784 | if (!desc->count) |
| @@ -786,6 +786,7 @@ static void wdm_disconnect(struct usb_interface *intf) | |||
| 786 | mutex_unlock(&wdm_mutex); | 786 | mutex_unlock(&wdm_mutex); |
| 787 | } | 787 | } |
| 788 | 788 | ||
| 789 | #ifdef CONFIG_PM | ||
| 789 | static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | 790 | static int wdm_suspend(struct usb_interface *intf, pm_message_t message) |
| 790 | { | 791 | { |
| 791 | struct wdm_device *desc = usb_get_intfdata(intf); | 792 | struct wdm_device *desc = usb_get_intfdata(intf); |
| @@ -793,27 +794,30 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 793 | 794 | ||
| 794 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); | 795 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); |
| 795 | 796 | ||
| 796 | mutex_lock(&desc->lock); | 797 | /* if this is an autosuspend the caller does the locking */ |
| 798 | if (!(message.event & PM_EVENT_AUTO)) | ||
| 799 | mutex_lock(&desc->lock); | ||
| 797 | spin_lock_irq(&desc->iuspin); | 800 | spin_lock_irq(&desc->iuspin); |
| 798 | #ifdef CONFIG_PM | 801 | |
| 799 | if ((message.event & PM_EVENT_AUTO) && | 802 | if ((message.event & PM_EVENT_AUTO) && |
| 800 | (test_bit(WDM_IN_USE, &desc->flags) | 803 | (test_bit(WDM_IN_USE, &desc->flags) |
| 801 | || test_bit(WDM_RESPONDING, &desc->flags))) { | 804 | || test_bit(WDM_RESPONDING, &desc->flags))) { |
| 802 | spin_unlock_irq(&desc->iuspin); | 805 | spin_unlock_irq(&desc->iuspin); |
| 803 | rv = -EBUSY; | 806 | rv = -EBUSY; |
| 804 | } else { | 807 | } else { |
| 805 | #endif | 808 | |
| 806 | set_bit(WDM_SUSPENDING, &desc->flags); | 809 | set_bit(WDM_SUSPENDING, &desc->flags); |
| 807 | spin_unlock_irq(&desc->iuspin); | 810 | spin_unlock_irq(&desc->iuspin); |
| 808 | cancel_work_sync(&desc->rxwork); | 811 | /* callback submits work - order is essential */ |
| 809 | kill_urbs(desc); | 812 | kill_urbs(desc); |
| 810 | #ifdef CONFIG_PM | 813 | cancel_work_sync(&desc->rxwork); |
| 811 | } | 814 | } |
| 812 | #endif | 815 | if (!(message.event & PM_EVENT_AUTO)) |
| 813 | mutex_unlock(&desc->lock); | 816 | mutex_unlock(&desc->lock); |
| 814 | 817 | ||
| 815 | return rv; | 818 | return rv; |
| 816 | } | 819 | } |
| 820 | #endif | ||
| 817 | 821 | ||
| 818 | static int recover_from_urb_loss(struct wdm_device *desc) | 822 | static int recover_from_urb_loss(struct wdm_device *desc) |
| 819 | { | 823 | { |
| @@ -827,6 +831,8 @@ static int recover_from_urb_loss(struct wdm_device *desc) | |||
| 827 | } | 831 | } |
| 828 | return rv; | 832 | return rv; |
| 829 | } | 833 | } |
| 834 | |||
| 835 | #ifdef CONFIG_PM | ||
| 830 | static int wdm_resume(struct usb_interface *intf) | 836 | static int wdm_resume(struct usb_interface *intf) |
| 831 | { | 837 | { |
| 832 | struct wdm_device *desc = usb_get_intfdata(intf); | 838 | struct wdm_device *desc = usb_get_intfdata(intf); |
| @@ -839,6 +845,7 @@ static int wdm_resume(struct usb_interface *intf) | |||
| 839 | mutex_unlock(&desc->lock); | 845 | mutex_unlock(&desc->lock); |
| 840 | return rv; | 846 | return rv; |
| 841 | } | 847 | } |
| 848 | #endif | ||
| 842 | 849 | ||
| 843 | static int wdm_pre_reset(struct usb_interface *intf) | 850 | static int wdm_pre_reset(struct usb_interface *intf) |
| 844 | { | 851 | { |
| @@ -862,9 +869,11 @@ static struct usb_driver wdm_driver = { | |||
| 862 | .name = "cdc_wdm", | 869 | .name = "cdc_wdm", |
| 863 | .probe = wdm_probe, | 870 | .probe = wdm_probe, |
| 864 | .disconnect = wdm_disconnect, | 871 | .disconnect = wdm_disconnect, |
| 872 | #ifdef CONFIG_PM | ||
| 865 | .suspend = wdm_suspend, | 873 | .suspend = wdm_suspend, |
| 866 | .resume = wdm_resume, | 874 | .resume = wdm_resume, |
| 867 | .reset_resume = wdm_resume, | 875 | .reset_resume = wdm_resume, |
| 876 | #endif | ||
| 868 | .pre_reset = wdm_pre_reset, | 877 | .pre_reset = wdm_pre_reset, |
| 869 | .post_reset = wdm_post_reset, | 878 | .post_reset = wdm_post_reset, |
| 870 | .id_table = wdm_ids, | 879 | .id_table = wdm_ids, |
