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

Commit dd8edd7e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tty/serial fixes from Greg KH:
 "Here's some TTY and serial driver fixes for reported issues.

  All of these have been in linux-next successfully"

* tag 'tty-4.1-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  pty: Fix input race when closing
  tty/n_gsm.c: fix a memory leak when gsmtty is removed
  Revert "serial/amba-pl011: Leave the TX IRQ alone when the UART is not open"
  serial: omap: Fix error handling in probe
  earlycon: Revert log warnings
parents 3f4741b1 1a48632f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -198,6 +198,9 @@ TTY_IO_ERROR If set, causes all subsequent userspace read/write

TTY_OTHER_CLOSED	Device is a pty and the other side has closed.

TTY_OTHER_DONE		Device is a pty and the other side has closed and
			all pending input processing has been completed.

TTY_NO_WRITE_SPLIT	Prevent driver from splitting up writes into
			smaller chunks.

+2 −3
Original line number Diff line number Diff line
@@ -3170,7 +3170,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
	return gsmtty_modem_update(dlci, encode);
}

static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty)
static void gsmtty_cleanup(struct tty_struct *tty)
{
	struct gsm_dlci *dlci = tty->driver_data;
	struct gsm_mux *gsm = dlci->gsm;
@@ -3178,7 +3178,6 @@ static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty)
	dlci_put(dlci);
	dlci_put(gsm->dlci[0]);
	mux_put(gsm);
	driver->ttys[tty->index] = NULL;
}

/* Virtual ttys for the demux */
@@ -3199,7 +3198,7 @@ static const struct tty_operations gsmtty_ops = {
	.tiocmget		= gsmtty_tiocmget,
	.tiocmset		= gsmtty_tiocmset,
	.break_ctl		= gsmtty_break_ctl,
	.remove			= gsmtty_remove,
	.cleanup		= gsmtty_cleanup,
};


+2 −2
Original line number Diff line number Diff line
@@ -600,7 +600,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
	add_wait_queue(&tty->read_wait, &wait);

	for (;;) {
		if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
		if (test_bit(TTY_OTHER_DONE, &tty->flags)) {
			ret = -EIO;
			break;
		}
@@ -828,7 +828,7 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
		/* set bits for operations that won't block */
		if (n_hdlc->rx_buf_list.head)
			mask |= POLLIN | POLLRDNORM;	/* readable */
		if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
		if (test_bit(TTY_OTHER_DONE, &tty->flags))
			mask |= POLLHUP;
		if (tty_hung_up_p(filp))
			mask |= POLLHUP;
+18 −4
Original line number Diff line number Diff line
@@ -1949,6 +1949,18 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
		return ldata->commit_head - ldata->read_tail >= amt;
}

static inline int check_other_done(struct tty_struct *tty)
{
	int done = test_bit(TTY_OTHER_DONE, &tty->flags);
	if (done) {
		/* paired with cmpxchg() in check_other_closed(); ensures
		 * read buffer head index is not stale
		 */
		smp_mb__after_atomic();
	}
	return done;
}

/**
 *	copy_from_read_buf	-	copy read data directly
 *	@tty: terminal device
@@ -2167,7 +2179,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
	struct n_tty_data *ldata = tty->disc_data;
	unsigned char __user *b = buf;
	DEFINE_WAIT_FUNC(wait, woken_wake_function);
	int c;
	int c, done;
	int minimum, time;
	ssize_t retval = 0;
	long timeout;
@@ -2235,8 +2247,10 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
		    ((minimum - (b - buf)) >= 1))
			ldata->minimum_to_wake = (minimum - (b - buf));

		done = check_other_done(tty);

		if (!input_available_p(tty, 0)) {
			if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
			if (done) {
				retval = -EIO;
				break;
			}
@@ -2443,12 +2457,12 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,

	poll_wait(file, &tty->read_wait, wait);
	poll_wait(file, &tty->write_wait, wait);
	if (check_other_done(tty))
		mask |= POLLHUP;
	if (input_available_p(tty, 1))
		mask |= POLLIN | POLLRDNORM;
	if (tty->packet && tty->link->ctrl_status)
		mask |= POLLPRI | POLLIN | POLLRDNORM;
	if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
		mask |= POLLHUP;
	if (tty_hung_up_p(file))
		mask |= POLLHUP;
	if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
+3 −2
Original line number Diff line number Diff line
@@ -53,9 +53,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
	/* Review - krefs on tty_link ?? */
	if (!tty->link)
		return;
	tty_flush_to_ldisc(tty->link);
	set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
	wake_up_interruptible(&tty->link->read_wait);
	tty_flip_buffer_push(tty->link->port);
	wake_up_interruptible(&tty->link->write_wait);
	if (tty->driver->subtype == PTY_TYPE_MASTER) {
		set_bit(TTY_OTHER_CLOSED, &tty->flags);
@@ -243,7 +242,9 @@ static int pty_open(struct tty_struct *tty, struct file *filp)
		goto out;

	clear_bit(TTY_IO_ERROR, &tty->flags);
	/* TTY_OTHER_CLOSED must be cleared before TTY_OTHER_DONE */
	clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
	clear_bit(TTY_OTHER_DONE, &tty->link->flags);
	set_bit(TTY_THROTTLED, &tty->flags);
	return 0;

Loading