diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bd7581b3a48a..99188c92068b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/list.h> | 33 | #include <linux/list.h> |
34 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | #include <linux/serial.h> | ||
35 | #include <linux/usb.h> | 36 | #include <linux/usb.h> |
36 | #include <linux/usb/serial.h> | 37 | #include <linux/usb/serial.h> |
37 | #include "pl2303.h" | 38 | #include "pl2303.h" |
@@ -184,6 +185,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
184 | struct usb_serial_port *port; | 185 | struct usb_serial_port *port; |
185 | unsigned int portNumber; | 186 | unsigned int portNumber; |
186 | int retval = 0; | 187 | int retval = 0; |
188 | int first = 0; | ||
187 | 189 | ||
188 | dbg("%s", __func__); | 190 | dbg("%s", __func__); |
189 | 191 | ||
@@ -223,7 +225,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
223 | 225 | ||
224 | /* If the console is attached, the device is already open */ | 226 | /* If the console is attached, the device is already open */ |
225 | if (port->port.count == 1 && !port->console) { | 227 | if (port->port.count == 1 && !port->console) { |
226 | 228 | first = 1; | |
227 | /* lock this module before we call it | 229 | /* lock this module before we call it |
228 | * this may fail, which means we must bail out, | 230 | * this may fail, which means we must bail out, |
229 | * safe because we are called with BKL held */ | 231 | * safe because we are called with BKL held */ |
@@ -246,13 +248,21 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
246 | if (retval) | 248 | if (retval) |
247 | goto bailout_interface_put; | 249 | goto bailout_interface_put; |
248 | mutex_unlock(&serial->disc_mutex); | 250 | mutex_unlock(&serial->disc_mutex); |
251 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); | ||
249 | } | 252 | } |
250 | mutex_unlock(&port->mutex); | 253 | mutex_unlock(&port->mutex); |
251 | /* Now do the correct tty layer semantics */ | 254 | /* Now do the correct tty layer semantics */ |
252 | retval = tty_port_block_til_ready(&port->port, tty, filp); | 255 | retval = tty_port_block_til_ready(&port->port, tty, filp); |
253 | if (retval == 0) | 256 | if (retval == 0) { |
257 | if (!first) | ||
258 | usb_serial_put(serial); | ||
254 | return 0; | 259 | return 0; |
255 | 260 | } | |
261 | mutex_lock(&port->mutex); | ||
262 | if (first == 0) | ||
263 | goto bailout_mutex_unlock; | ||
264 | /* Undo the initial port actions */ | ||
265 | mutex_lock(&serial->disc_mutex); | ||
256 | bailout_interface_put: | 266 | bailout_interface_put: |
257 | usb_autopm_put_interface(serial->interface); | 267 | usb_autopm_put_interface(serial->interface); |
258 | bailout_module_put: | 268 | bailout_module_put: |
@@ -340,6 +350,22 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
340 | 350 | ||
341 | dbg("%s - port %d", __func__, port->number); | 351 | dbg("%s - port %d", __func__, port->number); |
342 | 352 | ||
353 | /* FIXME: | ||
354 | This leaves a very narrow race. Really we should do the | ||
355 | serial_do_free() on tty->shutdown(), but tty->shutdown can | ||
356 | be called from IRQ context and serial_do_free can sleep. | ||
357 | |||
358 | The right fix is probably to make the tty free (which is rare) | ||
359 | and thus tty->shutdown() occur via a work queue and simplify all | ||
360 | the drivers that use it. | ||
361 | */ | ||
362 | if (tty_hung_up_p(filp)) { | ||
363 | /* serial_hangup already called serial_down at this point. | ||
364 | Another user may have already reopened the port but | ||
365 | serial_do_free is refcounted */ | ||
366 | serial_do_free(port); | ||
367 | return; | ||
368 | } | ||
343 | 369 | ||
344 | if (tty_port_close_start(&port->port, tty, filp) == 0) | 370 | if (tty_port_close_start(&port->port, tty, filp) == 0) |
345 | return; | 371 | return; |
@@ -355,7 +381,8 @@ static void serial_hangup(struct tty_struct *tty) | |||
355 | struct usb_serial_port *port = tty->driver_data; | 381 | struct usb_serial_port *port = tty->driver_data; |
356 | serial_do_down(port); | 382 | serial_do_down(port); |
357 | tty_port_hangup(&port->port); | 383 | tty_port_hangup(&port->port); |
358 | serial_do_free(port); | 384 | /* We must not free port yet - the USB serial layer depends on it's |
385 | continued existence */ | ||
359 | } | 386 | } |
360 | 387 | ||
361 | static int serial_write(struct tty_struct *tty, const unsigned char *buf, | 388 | static int serial_write(struct tty_struct *tty, const unsigned char *buf, |
@@ -394,7 +421,6 @@ static int serial_chars_in_buffer(struct tty_struct *tty) | |||
394 | struct usb_serial_port *port = tty->driver_data; | 421 | struct usb_serial_port *port = tty->driver_data; |
395 | dbg("%s = port %d", __func__, port->number); | 422 | dbg("%s = port %d", __func__, port->number); |
396 | 423 | ||
397 | WARN_ON(!port->port.count); | ||
398 | /* if the device was unplugged then any remaining characters | 424 | /* if the device was unplugged then any remaining characters |
399 | fell out of the connector ;) */ | 425 | fell out of the connector ;) */ |
400 | if (port->serial->disconnected) | 426 | if (port->serial->disconnected) |