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 f35971dff4a..6855d5ed033 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;  		}  |