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

Commit 15bdb565 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'serial'

* serial:
  imx: Check for NULL pointer deref before calling tty_encode_baud_rate
  atmel_serial: fix hang in set_termios when crtscts is enabled
  MAINTAINERS: update 8250 section, give Alan Cox a name
  tty: fix sanity check
  pty: Narrow the race on ldisc locking
  tty: fix unused warning when TCGETX is not defined
  ldisc: debug aids
  ldisc: Make sure the ldisc isn't active when we close it
  tty: Fix leaks introduced by the shift to separate ldisc objects

Fix conflicts in drivers/char/pty.c due to earlier version of the ldisc
race narrowing.
parents 98523d46 1a2c4b31
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -157,9 +157,10 @@ S: Maintained
F:	drivers/net/r8169.c

8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
P:	Alan Cox
M:	alan@lxorguk.ukuu.org.uk
L:	linux-serial@vger.kernel.org
W:	http://serial.sourceforge.net
M:	alan@lxorguk.ukuu.org.uk
S:	Odd Fixes
F:	drivers/serial/8250*
F:	include/linux/serial_8250.h
+42 −15
Original line number Diff line number Diff line
@@ -95,23 +95,34 @@ static void pty_unthrottle(struct tty_struct *tty)
 * a count.
 *
 * FIXME: Our pty_write method is called with our ldisc lock held but
 * not our partners. We can't just take the other one blindly without
 * risking deadlocks.
 * not our partners. We can't just wait on the other one blindly without
 * risking deadlocks. At some point when everything has settled down we need
 * to look into making pty_write at least able to sleep over an ldisc change.
 *
 * The return on no ldisc is a bit counter intuitive but the logic works
 * like this. During an ldisc change the other end will flush its buffers. We
 * thus return the full length which is identical to the case where we had
 * proper locking and happened to queue the bytes just before the flush during
 * the ldisc change.
 */
static int pty_write(struct tty_struct *tty, const unsigned char *buf,
								int count)
{
	struct tty_struct *to = tty->link;
	int	c;
	struct tty_ldisc *ld;
	int c = count;

	if (!to || !to->ldisc || tty->stopped)
	if (!to || tty->stopped)
		return 0;
	ld = tty_ldisc_ref(to);

	if (ld) {
		c = to->receive_room;
		if (c > count)
			c = count;
	to->ldisc->ops->receive_buf(to, buf, NULL, c);

		ld->ops->receive_buf(to, buf, NULL, c);
		tty_ldisc_deref(ld);
	}
	return c;
}

@@ -145,14 +156,23 @@ static int pty_write_room(struct tty_struct *tty)
static int pty_chars_in_buffer(struct tty_struct *tty)
{
	struct tty_struct *to = tty->link;
	int count;
	struct tty_ldisc *ld;
	int count = 0;

	/* We should get the line discipline lock for "tty->link" */
	if (!to || !to->ldisc || !to->ldisc->ops->chars_in_buffer)
	if (!to)
		return 0;
	/* We cannot take a sleeping reference here without deadlocking with
	   an ldisc change - but it doesn't really matter */
	ld = tty_ldisc_ref(to);
	if (ld == NULL)
		return 0;

	/* The ldisc must report 0 if no characters available to be read */
	count = to->ldisc->ops->chars_in_buffer(to);
	if (ld->ops->chars_in_buffer)
		count = ld->ops->chars_in_buffer(to);

	tty_ldisc_deref(ld);

	if (tty->driver->subtype == PTY_TYPE_SLAVE)
		return count;
@@ -182,12 +202,19 @@ static void pty_flush_buffer(struct tty_struct *tty)
{
	struct tty_struct *to = tty->link;
	unsigned long flags;
	struct tty_ldisc *ld;

	if (!to)
		return;
	ld = tty_ldisc_ref(to);

	if (!to || !to->ldisc)
	/* The other end is changing discipline */
	if (!ld)
		return;

	if (to->ldisc->ops->flush_buffer)
	if (ld->ops->flush_buffer)
		to->ldisc->ops->flush_buffer(to);
	tty_ldisc_deref(ld);

	if (to->packet) {
		spin_lock_irqsave(&tty->ctrl_lock, flags);
+2 −0
Original line number Diff line number Diff line
@@ -1263,7 +1263,9 @@ static int tty_reopen(struct tty_struct *tty)
	tty->count++;
	tty->driver = driver; /* N.B. why do this every time?? */

	mutex_lock(&tty->ldisc_mutex);
	WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
	mutex_unlock(&tty->ldisc_mutex);

	return 0;
}
+3 −2
Original line number Diff line number Diff line
@@ -947,7 +947,6 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
	void __user *p = (void __user *)arg;
	int ret = 0;
	struct ktermios kterm;
	struct termiox ktermx;

	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
	    tty->driver->subtype == PTY_TYPE_MASTER)
@@ -1049,7 +1048,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
		return ret;
#endif
#ifdef TCGETX
	case TCGETX:
	case TCGETX: {
		struct termiox ktermx;
		if (real_tty->termiox == NULL)
			return -EINVAL;
		mutex_lock(&real_tty->termios_mutex);
@@ -1058,6 +1058,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
		if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
			ret = -EFAULT;
		return ret;
	}
	case TCSETX:
		return set_termiox(real_tty, p, 0);
	case TCSETXW:
+3 −0
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ static void tty_ldisc_put(struct tty_ldisc *ld)
	ldo->refcount--;
	module_put(ldo->owner);
	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
	WARN_ON(ld->refcount);
	kfree(ld);
}

@@ -793,6 +794,8 @@ void tty_ldisc_hangup(struct tty_struct *tty)
		/* Avoid racing set_ldisc */
		mutex_lock(&tty->ldisc_mutex);
		/* Switch back to N_TTY */
		tty_ldisc_halt(tty);
		tty_ldisc_wait_idle(tty);
		tty_ldisc_reinit(tty);
		/* At this point we have a closed ldisc and we want to
		   reopen it. We could defer this to the next open but
Loading