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.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 497e29a700ca..3ce98e8d7bce 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -225,16 +225,21 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
225 goto bailout_mutex_unlock; 225 goto bailout_mutex_unlock;
226 } 226 }
227 227
228 retval = usb_autopm_get_interface(serial->interface);
229 if (retval)
230 goto bailout_module_put;
228 /* only call the device specific open if this 231 /* only call the device specific open if this
229 * is the first time the port is opened */ 232 * is the first time the port is opened */
230 retval = serial->type->open(port, filp); 233 retval = serial->type->open(port, filp);
231 if (retval) 234 if (retval)
232 goto bailout_module_put; 235 goto bailout_interface_put;
233 } 236 }
234 237
235 mutex_unlock(&port->mutex); 238 mutex_unlock(&port->mutex);
236 return 0; 239 return 0;
237 240
241bailout_interface_put:
242 usb_autopm_put_interface(serial->interface);
238bailout_module_put: 243bailout_module_put:
239 module_put(serial->type->driver.owner); 244 module_put(serial->type->driver.owner);
240bailout_mutex_unlock: 245bailout_mutex_unlock:
@@ -264,17 +269,21 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
264 } 269 }
265 270
266 --port->open_count; 271 --port->open_count;
267 if (port->open_count == 0) { 272 if (port->open_count == 0)
268 /* only call the device specific close if this 273 /* only call the device specific close if this
269 * port is being closed by the last owner */ 274 * port is being closed by the last owner */
270 port->serial->type->close(port, filp); 275 port->serial->type->close(port, filp);
271 276
277 if (port->open_count == (port->console? 1 : 0)) {
272 if (port->tty) { 278 if (port->tty) {
273 if (port->tty->driver_data) 279 if (port->tty->driver_data)
274 port->tty->driver_data = NULL; 280 port->tty->driver_data = NULL;
275 port->tty = NULL; 281 port->tty = NULL;
276 } 282 }
283 }
277 284
285 if (port->open_count == 0) {
286 usb_autopm_put_interface(port->serial->interface);
278 module_put(port->serial->type->driver.owner); 287 module_put(port->serial->type->driver.owner);
279 } 288 }
280 289
@@ -625,6 +634,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
625 serial->type = driver; 634 serial->type = driver;
626 serial->interface = interface; 635 serial->interface = interface;
627 kref_init(&serial->kref); 636 kref_init(&serial->kref);
637 mutex_init(&serial->disc_mutex);
628 638
629 return serial; 639 return serial;
630} 640}
@@ -1080,20 +1090,22 @@ void usb_serial_disconnect(struct usb_interface *interface)
1080 usb_serial_console_disconnect(serial); 1090 usb_serial_console_disconnect(serial);
1081 dbg ("%s", __FUNCTION__); 1091 dbg ("%s", __FUNCTION__);
1082 1092
1093 mutex_lock(&serial->disc_mutex);
1083 usb_set_intfdata (interface, NULL); 1094 usb_set_intfdata (interface, NULL);
1084 if (serial) { 1095 /* must set a flag, to signal subdrivers */
1085 for (i = 0; i < serial->num_ports; ++i) { 1096 serial->disconnected = 1;
1086 port = serial->port[i]; 1097 for (i = 0; i < serial->num_ports; ++i) {
1087 if (port) { 1098 port = serial->port[i];
1088 if (port->tty) 1099 if (port) {
1089 tty_hangup(port->tty); 1100 if (port->tty)
1090 kill_traffic(port); 1101 tty_hangup(port->tty);
1091 } 1102 kill_traffic(port);
1092 } 1103 }
1093 /* let the last holder of this object
1094 * cause it to be cleaned up */
1095 usb_serial_put(serial);
1096 } 1104 }
1105 /* let the last holder of this object
1106 * cause it to be cleaned up */
1107 mutex_unlock(&serial->disc_mutex);
1108 usb_serial_put(serial);
1097 dev_info(dev, "device disconnected\n"); 1109 dev_info(dev, "device disconnected\n");
1098} 1110}
1099 1111
@@ -1103,9 +1115,6 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1103 struct usb_serial_port *port; 1115 struct usb_serial_port *port;
1104 int i, r = 0; 1116 int i, r = 0;
1105 1117
1106 if (!serial) /* device has been disconnected */
1107 return 0;
1108
1109 for (i = 0; i < serial->num_ports; ++i) { 1118 for (i = 0; i < serial->num_ports; ++i) {
1110 port = serial->port[i]; 1119 port = serial->port[i];
1111 if (port) 1120 if (port)
@@ -1253,6 +1262,7 @@ static void fixup_generic(struct usb_serial_driver *device)
1253 set_to_generic_if_null(device, read_bulk_callback); 1262 set_to_generic_if_null(device, read_bulk_callback);
1254 set_to_generic_if_null(device, write_bulk_callback); 1263 set_to_generic_if_null(device, write_bulk_callback);
1255 set_to_generic_if_null(device, shutdown); 1264 set_to_generic_if_null(device, shutdown);
1265 set_to_generic_if_null(device, resume);
1256} 1266}
1257 1267
1258int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ 1268int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */