From 7937c1fdfe3678d0dcad2831d1c7badb5bb7ac5c Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Wed, 13 Oct 2010 14:52:44 -0700 Subject: [PATCH] mdm6600: Fix mdm6600_close 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 --- drivers/usb/serial/mdm6600.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/usb/serial/mdm6600.c b/drivers/usb/serial/mdm6600.c index 58ec4468b233..9944826a518f 100644 --- a/drivers/usb/serial/mdm6600.c +++ b/drivers/usb/serial/mdm6600.c @@ -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; } -- 2.34.1