Commit c56d3000 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

usb_serial: Fix remaining ref count/lock bugs

This fixes
- locking bug that was hidden by ecc2e05e
- Regression #13821
- Spurious warning when closing and blocking for data write out

With these changes my PL2303 always ends up as ttyUSB0 when it should and
the module refcounts stay correct.

I'll do a more wholesale split & tidy of _open in the next release or two
as we get a standard tty_port_open and port->ops->init port->ops->shutdown
call backs.

Copy sent to Alan Stern and Carlos Mafra just to confirm it fixes all the
reports but it passes local testing with the same hardware as Alan Stern.
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent fc013a58
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/serial.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/serial.h> #include <linux/usb/serial.h>
#include "pl2303.h" #include "pl2303.h"
...@@ -184,6 +185,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -184,6 +185,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
struct usb_serial_port *port; struct usb_serial_port *port;
unsigned int portNumber; unsigned int portNumber;
int retval = 0; int retval = 0;
int first = 0;
dbg("%s", __func__); dbg("%s", __func__);
...@@ -223,7 +225,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -223,7 +225,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
/* If the console is attached, the device is already open */ /* If the console is attached, the device is already open */
if (port->port.count == 1 && !port->console) { if (port->port.count == 1 && !port->console) {
first = 1;
/* lock this module before we call it /* lock this module before we call it
* this may fail, which means we must bail out, * this may fail, which means we must bail out,
* safe because we are called with BKL held */ * safe because we are called with BKL held */
...@@ -246,13 +248,21 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -246,13 +248,21 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
if (retval) if (retval)
goto bailout_interface_put; goto bailout_interface_put;
mutex_unlock(&serial->disc_mutex); mutex_unlock(&serial->disc_mutex);
set_bit(ASYNCB_INITIALIZED, &port->port.flags);
} }
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
/* Now do the correct tty layer semantics */ /* Now do the correct tty layer semantics */
retval = tty_port_block_til_ready(&port->port, tty, filp); retval = tty_port_block_til_ready(&port->port, tty, filp);
if (retval == 0) if (retval == 0) {
if (!first)
usb_serial_put(serial);
return 0; return 0;
}
mutex_lock(&port->mutex);
if (first == 0)
goto bailout_mutex_unlock;
/* Undo the initial port actions */
mutex_lock(&serial->disc_mutex);
bailout_interface_put: bailout_interface_put:
usb_autopm_put_interface(serial->interface); usb_autopm_put_interface(serial->interface);
bailout_module_put: bailout_module_put:
...@@ -411,7 +421,6 @@ static int serial_chars_in_buffer(struct tty_struct *tty) ...@@ -411,7 +421,6 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
dbg("%s = port %d", __func__, port->number); dbg("%s = port %d", __func__, port->number);
WARN_ON(!port->port.count);
/* if the device was unplugged then any remaining characters /* if the device was unplugged then any remaining characters
fell out of the connector ;) */ fell out of the connector ;) */
if (port->serial->disconnected) if (port->serial->disconnected)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment