Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e33fe4d8 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman
Browse files

USB: make sure usb serial drivers don't flush to logically disconnected 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: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 004b4f2d
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -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) {
		mutex_lock(&port->serial->disc_mutex);
		if (c_cflag & HUPCL && !port->serial->disconnected) {
			/* drop DTR and RTS */
		   spin_lock_irqsave(&priv->lock, flags);
			spin_lock_irq(&priv->lock);
			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
			control_state = priv->control_state;
		   spin_unlock_irqrestore(&priv->lock, flags);
			spin_unlock_irq(&priv->lock);
			mct_u232_set_modem_ctrl(port->serial, control_state);
		}
		mutex_unlock(&port->serial->disc_mutex);
	}


+4 −1
Original line number Diff line number Diff line
@@ -641,7 +641,10 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
	portdata->dtr_state = 0;

	if (serial->dev) {
		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++)
+4 −1
Original line number Diff line number Diff line
@@ -597,7 +597,10 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
	portdata->dtr_state = 0;

	if (serial->dev) {
		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++)
+13 −9
Original line number Diff line number Diff line
@@ -349,7 +349,9 @@ 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. */
	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,
@@ -359,6 +361,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
					 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",
+5 −2
Original line number Diff line number Diff line
@@ -659,10 +659,13 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)

	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;