Skip to content

Commit

Permalink
USB: make sure usb serial drivers don't flush to logically disconnect…
Browse files Browse the repository at this point in the history
…ed devices

If disconnect() is called for a logical disconnect, no more IO must be
done after disconnect() returns, or the old and new drivers may conflict.
This patch avoids this by using the flag and lock introduced by the earlier
patch for the mos7720 driver.

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Oliver Neukum authored and Greg Kroah-Hartman committed Feb 1, 2008
1 parent 004b4f2 commit e33fe4d
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 21 deletions.
17 changes: 9 additions & 8 deletions drivers/usb/serial/mct_u232.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,21 +487,22 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
{
unsigned int c_cflag;
unsigned long flags;
unsigned int control_state;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
dbg("%s port %d", __FUNCTION__, port->number);

if (port->tty) {
c_cflag = port->tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
mct_u232_set_modem_ctrl(port->serial, control_state);
mutex_lock(&port->serial->disc_mutex);
if (c_cflag & HUPCL && !port->serial->disconnected) {
/* drop DTR and RTS */
spin_lock_irq(&priv->lock);
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
control_state = priv->control_state;
spin_unlock_irq(&priv->lock);
mct_u232_set_modem_ctrl(port->serial, control_state);
}
mutex_unlock(&port->serial->disc_mutex);
}


Expand Down
5 changes: 4 additions & 1 deletion drivers/usb/serial/option.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,10 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
portdata->dtr_state = 0;

if (serial->dev) {
option_send_setup(port);
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
option_send_setup(port);
mutex_unlock(&serial->disc_mutex);

/* Stop reading/writing urbs */
for (i = 0; i < N_IN_URB; i++)
Expand Down
5 changes: 4 additions & 1 deletion drivers/usb/serial/sierra.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,10 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
portdata->dtr_state = 0;

if (serial->dev) {
sierra_send_setup(port);
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
sierra_send_setup(port);
mutex_unlock(&serial->disc_mutex);

/* Stop reading/writing urbs */
for (i = 0; i < N_IN_URB; i++)
Expand Down
22 changes: 13 additions & 9 deletions drivers/usb/serial/visor.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,16 +349,20 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);

/* Try to send shutdown message, if the device is gone, this will just fail. */
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
if (transfer_buffer) {
usb_control_msg (port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
kfree (transfer_buffer);
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected) {
/* Try to send shutdown message, unless the device is gone */
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
if (transfer_buffer) {
usb_control_msg (port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
kfree (transfer_buffer);
}
}
mutex_lock(&port->serial->disc_mutex);

if (stats)
dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n",
Expand Down
7 changes: 5 additions & 2 deletions drivers/usb/serial/whiteheat.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,11 +658,14 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
struct list_head *tmp2;

dbg("%s - port %d", __FUNCTION__, port->number);


mutex_lock(&port->serial->disc_mutex);
/* filp is NULL when called from usb_serial_disconnect */
if (filp && (tty_hung_up_p(filp))) {
if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
mutex_unlock(&port->serial->disc_mutex);
return;
}
mutex_unlock(&port->serial->disc_mutex);

port->tty->closing = 1;

Expand Down

0 comments on commit e33fe4d

Please sign in to comment.