diff options
Diffstat (limited to 'drivers/usb/serial/usb_wwan.c')
-rw-r--r-- | drivers/usb/serial/usb_wwan.c | 68 |
1 files changed, 29 insertions, 39 deletions
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index f35971dff4a5..6855d5ed0331 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -565,62 +565,52 @@ bail_out_error: } EXPORT_SYMBOL(usb_wwan_startup); -static void stop_read_write_urbs(struct usb_serial *serial) +int usb_wwan_port_remove(struct usb_serial_port *port) { - int i, j; - struct usb_serial_port *port; + int i; struct usb_wwan_port_private *portdata; - /* Stop reading/writing urbs */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); - for (j = 0; j < N_IN_URB; j++) - usb_kill_urb(portdata->in_urbs[j]); - for (j = 0; j < N_OUT_URB; j++) - usb_kill_urb(portdata->out_urbs[j]); + portdata = usb_get_serial_port_data(port); + usb_set_serial_port_data(port, NULL); + + /* Stop reading/writing urbs and free them */ + for (i = 0; i < N_IN_URB; i++) { + usb_kill_urb(portdata->in_urbs[i]); + usb_free_urb(portdata->in_urbs[i]); + free_page((unsigned long)portdata->in_buffer[i]); + } + for (i = 0; i < N_OUT_URB; i++) { + usb_kill_urb(portdata->out_urbs[i]); + usb_free_urb(portdata->out_urbs[i]); + kfree(portdata->out_buffer[i]); } -} -void usb_wwan_disconnect(struct usb_serial *serial) -{ - stop_read_write_urbs(serial); + /* Now free port private data */ + kfree(portdata); + return 0; } -EXPORT_SYMBOL(usb_wwan_disconnect); +EXPORT_SYMBOL(usb_wwan_port_remove); -void usb_wwan_release(struct usb_serial *serial) +#ifdef CONFIG_PM +static void stop_read_write_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct usb_wwan_port_private *portdata; - /* Now free them */ + /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); - - for (j = 0; j < N_IN_URB; j++) { - usb_free_urb(portdata->in_urbs[j]); - free_page((unsigned long) - portdata->in_buffer[j]); - portdata->in_urbs[j] = NULL; - } - for (j = 0; j < N_OUT_URB; j++) { - usb_free_urb(portdata->out_urbs[j]); - kfree(portdata->out_buffer[j]); - portdata->out_urbs[j] = NULL; - } - } - - /* Now free per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - kfree(usb_get_serial_port_data(port)); + if (!portdata) + continue; + for (j = 0; j < N_IN_URB; j++) + usb_kill_urb(portdata->in_urbs[j]); + for (j = 0; j < N_OUT_URB; j++) + usb_kill_urb(portdata->out_urbs[j]); } } -EXPORT_SYMBOL(usb_wwan_release); -#ifdef CONFIG_PM int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) { struct usb_wwan_intf_private *intfdata = serial->private; @@ -712,7 +702,7 @@ int usb_wwan_resume(struct usb_serial *serial) /* skip closed ports */ spin_lock_irq(&intfdata->susp_lock); - if (!portdata->opened) { + if (!portdata || !portdata->opened) { spin_unlock_irq(&intfdata->susp_lock); continue; } |