mdm6600: Fix mdm6600_close
authorBenoit Goby <benoit@android.com>
Wed, 13 Oct 2010 21:52:44 +0000 (14:52 -0700)
committerBenoit Goby <benoit@android.com>
Wed, 20 Oct 2010 01:27:31 +0000 (18:27 -0700)
Some urbs might succeed while running mdm6600_close, don't re-enqueue
them.

Add autopm_get_interface to balance the put_interface in open.

Change-Id: I947e6223d06d523169b458f4c324eff6f1fd24fe
Signed-off-by: Benoit Goby <benoit@android.com>
drivers/usb/serial/mdm6600.c

index 58ec4468b23369ea6846a91b5836d9950226fb3c..9944826a518fb140e449d3a7a5944624d741e955 100644 (file)
@@ -255,6 +255,9 @@ static void mdm6600_kill_urbs(struct mdm6600_port *modem)
        usb_scuttle_anchored_urbs(&modem->read.in_flight);
 
        usb_kill_urb(modem->port->interrupt_in_urb);
+
+       if (!usb_wait_anchor_empty_timeout(&modem->read.pending, 1000))
+               usb_scuttle_anchored_urbs(&modem->read.pending);
 }
 
 static void mdm6600_disconnect(struct usb_serial *serial)
@@ -263,6 +266,8 @@ static void mdm6600_disconnect(struct usb_serial *serial)
 
        dbg("%s: port %d", __func__, modem->number);
 
+       modem->opened = 0;
+
        if (modem->number == MODEM_INTERFACE_NUM) {
                disable_irq_wake(mdm6600_wake_irq);
                free_irq(mdm6600_wake_irq, modem);
@@ -273,9 +278,6 @@ static void mdm6600_disconnect(struct usb_serial *serial)
        /* cancel read bottom half */
        cancel_work_sync(&modem->read.work);
 
-       /* drop pending reads */
-       usb_scuttle_anchored_urbs(&modem->read.pending);
-
        modem->tiocm_status = 0;
 
        wake_lock_destroy(&modem->readlock);
@@ -360,15 +362,14 @@ static void mdm6600_close(struct usb_serial_port *port)
 
        dbg("%s: port %d", __func__, modem->number);
 
+       usb_autopm_get_interface(modem->serial->interface);
+
        modem->opened = 0;
        mdm6600_kill_urbs(modem);
 
        /* cancel read bottom half */
        cancel_work_sync(&modem->read.work);
 
-       /* drop pending reads */
-       usb_scuttle_anchored_urbs(&modem->read.pending);
-
        modem->tiocm_status = 0;
 }
 
@@ -740,10 +741,13 @@ static void mdm6600_read_bulk_work(struct work_struct *work)
 
 next:
                usb_unanchor_urb(u);
-               if (modem->susp_count) {
+               spin_lock_irqsave(&modem->susp_lock, flags);
+               if (modem->susp_count || !modem->opened) {
+                       spin_unlock_irqrestore(&modem->susp_lock, flags);
                        usb_put_urb(u);
                        continue;
                }
+               spin_unlock_irqrestore(&modem->susp_lock, flags);
 
                usb_anchor_urb(u, &modem->read.in_flight);
                usb_put_urb(u);
@@ -808,8 +812,6 @@ static int mdm6600_suspend(struct usb_interface *intf, pm_message_t message)
                spin_unlock_irq(&modem->susp_lock);
                dbg("%s: kill urbs", __func__);
                mdm6600_kill_urbs(modem);
-               if (!usb_wait_anchor_empty_timeout(&modem->read.pending, 1000))
-                       usb_scuttle_anchored_urbs(&modem->read.pending);
                return 0;
        }