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

Commit 4455e344 authored by Alan Cox's avatar Alan Cox Committed by Live-CD User
Browse files

tty: USB can now use the shutdown method for kref based freeing of ports



Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 9a68e39d
Loading
Loading
Loading
Loading
+7 −21
Original line number Diff line number Diff line
@@ -316,16 +316,19 @@ static void serial_do_down(struct usb_serial_port *port)
 *
 *	Do the resource freeing and refcount dropping for the port. We must
 *	be careful about ordering and we must avoid freeing up the console.
 *
 *	Called when the last tty kref is dropped.
 */

static void serial_do_free(struct usb_serial_port *port)
static void serial_do_free(struct tty_struct *tty)
{
	struct usb_serial_port *port = tty->driver_data;
	struct usb_serial *serial;
	struct module *owner;

	/* The console is magical, do not hang up the console hardware
	   or there will be tears */
	if (port->console)
	if (port == NULL || port->console)
		return;

	serial = port->serial;
@@ -350,30 +353,12 @@ static void serial_close(struct tty_struct *tty, struct file *filp)

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

	/* FIXME:
	   This leaves a very narrow race. Really we should do the
	   serial_do_free() on tty->shutdown(), but tty->shutdown can
	   be called from IRQ context and serial_do_free can sleep.

	   The right fix is probably to make the tty free (which is rare)
	   and thus tty->shutdown() occur via a work queue and simplify all
	   the drivers that use it.
	*/
	if (tty_hung_up_p(filp)) {
		/* serial_hangup already called serial_down at this point.
		   Another user may have already reopened the port but
		   serial_do_free is refcounted */
		serial_do_free(port);
		return;
	}

	if (tty_port_close_start(&port->port, tty, filp) == 0)
		return;

	serial_do_down(port);		
	tty_port_close_end(&port->port, tty);
	tty_port_tty_set(&port->port, NULL);
	serial_do_free(port);

}

static void serial_hangup(struct tty_struct *tty)
@@ -1243,6 +1228,7 @@ static const struct tty_operations serial_ops = {
	.chars_in_buffer =	serial_chars_in_buffer,
	.tiocmget =		serial_tiocmget,
	.tiocmset =		serial_tiocmset,
	.shutdown =		serial_do_free,
	.proc_fops =		&serial_proc_fops,
};