aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb-serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r--drivers/usb/serial/usb-serial.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index ff75a3589e7e..bd3fa7ff15b1 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -156,7 +156,8 @@ static void destroy_serial(struct kref *kref)
156 if (serial->minor != SERIAL_TTY_NO_MINOR) 156 if (serial->minor != SERIAL_TTY_NO_MINOR)
157 return_serial(serial); 157 return_serial(serial);
158 158
159 serial->type->release(serial); 159 if (serial->attached)
160 serial->type->release(serial);
160 161
161 /* Now that nothing is using the ports, they can be freed */ 162 /* Now that nothing is using the ports, they can be freed */
162 for (i = 0; i < serial->num_port_pointers; ++i) { 163 for (i = 0; i < serial->num_port_pointers; ++i) {
@@ -192,7 +193,7 @@ void usb_serial_put(struct usb_serial *serial)
192 * This is the first place a new tty gets used. Hence this is where we 193 * This is the first place a new tty gets used. Hence this is where we
193 * acquire references to the usb_serial structure and the driver module, 194 * acquire references to the usb_serial structure and the driver module,
194 * where we store a pointer to the port, and where we do an autoresume. 195 * where we store a pointer to the port, and where we do an autoresume.
195 * All these actions are reversed in serial_release(). 196 * All these actions are reversed in serial_cleanup().
196 */ 197 */
197static int serial_install(struct tty_driver *driver, struct tty_struct *tty) 198static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
198{ 199{
@@ -339,15 +340,16 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
339} 340}
340 341
341/** 342/**
342 * serial_release - free resources post close/hangup 343 * serial_cleanup - free resources post close/hangup
343 * @port: port to free up 344 * @port: port to free up
344 * 345 *
345 * Do the resource freeing and refcount dropping for the port. 346 * Do the resource freeing and refcount dropping for the port.
346 * Avoid freeing the console. 347 * Avoid freeing the console.
347 * 348 *
348 * Called when the last tty kref is dropped. 349 * Called asynchronously after the last tty kref is dropped,
350 * and the tty layer has already done the tty_shutdown(tty);
349 */ 351 */
350static void serial_release(struct tty_struct *tty) 352static void serial_cleanup(struct tty_struct *tty)
351{ 353{
352 struct usb_serial_port *port = tty->driver_data; 354 struct usb_serial_port *port = tty->driver_data;
353 struct usb_serial *serial; 355 struct usb_serial *serial;
@@ -361,9 +363,6 @@ static void serial_release(struct tty_struct *tty)
361 363
362 dbg("%s - port %d", __func__, port->number); 364 dbg("%s - port %d", __func__, port->number);
363 365
364 /* Standard shutdown processing */
365 tty_shutdown(tty);
366
367 tty->driver_data = NULL; 366 tty->driver_data = NULL;
368 367
369 serial = port->serial; 368 serial = port->serial;
@@ -1061,12 +1060,15 @@ int usb_serial_probe(struct usb_interface *interface,
1061 module_put(type->driver.owner); 1060 module_put(type->driver.owner);
1062 if (retval < 0) 1061 if (retval < 0)
1063 goto probe_error; 1062 goto probe_error;
1063 serial->attached = 1;
1064 if (retval > 0) { 1064 if (retval > 0) {
1065 /* quietly accept this device, but don't bind to a 1065 /* quietly accept this device, but don't bind to a
1066 serial port as it's about to disappear */ 1066 serial port as it's about to disappear */
1067 serial->num_ports = 0; 1067 serial->num_ports = 0;
1068 goto exit; 1068 goto exit;
1069 } 1069 }
1070 } else {
1071 serial->attached = 1;
1070 } 1072 }
1071 1073
1072 if (get_free_serial(serial, num_ports, &minor) == NULL) { 1074 if (get_free_serial(serial, num_ports, &minor) == NULL) {
@@ -1166,8 +1168,10 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1166 1168
1167 if (serial->type->suspend) { 1169 if (serial->type->suspend) {
1168 r = serial->type->suspend(serial, message); 1170 r = serial->type->suspend(serial, message);
1169 if (r < 0) 1171 if (r < 0) {
1172 serial->suspending = 0;
1170 goto err_out; 1173 goto err_out;
1174 }
1171 } 1175 }
1172 1176
1173 for (i = 0; i < serial->num_ports; ++i) { 1177 for (i = 0; i < serial->num_ports; ++i) {
@@ -1210,7 +1214,7 @@ static const struct tty_operations serial_ops = {
1210 .chars_in_buffer = serial_chars_in_buffer, 1214 .chars_in_buffer = serial_chars_in_buffer,
1211 .tiocmget = serial_tiocmget, 1215 .tiocmget = serial_tiocmget,
1212 .tiocmset = serial_tiocmset, 1216 .tiocmset = serial_tiocmset,
1213 .shutdown = serial_release, 1217 .cleanup = serial_cleanup,
1214 .install = serial_install, 1218 .install = serial_install,
1215 .proc_fops = &serial_proc_fops, 1219 .proc_fops = &serial_proc_fops,
1216}; 1220};