diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 24 |
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 | */ |
197 | static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | 198 | static 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 | */ |
350 | static void serial_release(struct tty_struct *tty) | 352 | static 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 | }; |