usb: cdc-wdm:Fix loss of data due to autosuspend
authorOliver Neukum <oliver@neukum.org>
Sat, 27 Feb 2010 19:56:22 +0000 (20:56 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 19 Mar 2010 14:24:16 +0000 (07:24 -0700)
The guarding flag must be set and tested under spinlock
and cleared before the URBs are resubmitted in resume.

Signed-off-by: Oliver Neukum <neukum@b1-systems.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/class/cdc-wdm.c

index a6b5e9f..07c1297 100644 (file)
@@ -794,14 +794,17 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
        dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
 
        mutex_lock(&desc->lock);
+       spin_lock_irq(&desc->iuspin);
 #ifdef CONFIG_PM
        if ((message.event & PM_EVENT_AUTO) &&
                        (test_bit(WDM_IN_USE, &desc->flags)
                        || test_bit(WDM_RESPONDING, &desc->flags))) {
+               spin_unlock_irq(&desc->iuspin);
                rv = -EBUSY;
        } else {
 #endif
                set_bit(WDM_SUSPENDING, &desc->flags);
+               spin_unlock_irq(&desc->iuspin);
                cancel_work_sync(&desc->rxwork);
                kill_urbs(desc);
 #ifdef CONFIG_PM
@@ -831,8 +834,8 @@ static int wdm_resume(struct usb_interface *intf)
 
        dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
        mutex_lock(&desc->lock);
-       rv = recover_from_urb_loss(desc);
        clear_bit(WDM_SUSPENDING, &desc->flags);
+       rv = recover_from_urb_loss(desc);
        mutex_unlock(&desc->lock);
        return rv;
 }