Commit 2754a42e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tty/serial fixes from Greg KH:
 "Here are some small TTY and Serial driver fixes for reported issues
  for 5.10-rc2. They include:

   - vt ioctl bugfix for reported problems

   - fsl_lpuart serial driver fix

   - 21285 serial driver bugfix

  All have been in linux-next with no reported issues"

* tag 'tty-5.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  vt_ioctl: fix GIO_UNIMAP regression
  vt: keyboard, extend func_buf_lock to readers
  vt: keyboard, simplify vt_kdgkbsent
  tty: serial: fsl_lpuart: LS1021A has a FIFO size of 16 words, like LS1028A
  tty: serial: 21285: fix lockup on open
parents 9b5ff3c9 d5465479
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -50,25 +50,25 @@ static const char serial21285_name[] = "Footbridge UART";

static bool is_enabled(struct uart_port *port, int bit)
{
	unsigned long private_data = (unsigned long)port->private_data;
	unsigned long *private_data = (unsigned long *)&port->private_data;

	if (test_bit(bit, &private_data))
	if (test_bit(bit, private_data))
		return true;
	return false;
}

static void enable(struct uart_port *port, int bit)
{
	unsigned long private_data = (unsigned long)port->private_data;
	unsigned long *private_data = (unsigned long *)&port->private_data;

	set_bit(bit, &private_data);
	set_bit(bit, private_data);
}

static void disable(struct uart_port *port, int bit)
{
	unsigned long private_data = (unsigned long)port->private_data;
	unsigned long *private_data = (unsigned long *)&port->private_data;

	clear_bit(bit, &private_data);
	clear_bit(bit, private_data);
}

#define is_tx_enabled(port)	is_enabled(port, tx_enabled_bit)
+7 −6
Original line number Diff line number Diff line
@@ -314,9 +314,10 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
/* Forward declare this for the dma callbacks*/
static void lpuart_dma_tx_complete(void *arg);

static inline bool is_ls1028a_lpuart(struct lpuart_port *sport)
static inline bool is_layerscape_lpuart(struct lpuart_port *sport)
{
	return sport->devtype == LS1028A_LPUART;
	return (sport->devtype == LS1021A_LPUART ||
		sport->devtype == LS1028A_LPUART);
}

static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
@@ -1701,11 +1702,11 @@ static int lpuart32_startup(struct uart_port *port)
					    UARTFIFO_FIFOSIZE_MASK);

	/*
	 * The LS1028A has a fixed length of 16 words. Although it supports the
	 * RX/TXSIZE fields their encoding is different. Eg the reference manual
	 * states 0b101 is 16 words.
	 * The LS1021A and LS1028A have a fixed FIFO depth of 16 words.
	 * Although they support the RX/TXSIZE fields, their encoding is
	 * different. Eg the reference manual states 0b101 is 16 words.
	 */
	if (is_ls1028a_lpuart(sport)) {
	if (is_layerscape_lpuart(sport)) {
		sport->rxfifo_size = 16;
		sport->txfifo_size = 16;
		sport->port.fifosize = sport->txfifo_size;
+19 −20
Original line number Diff line number Diff line
@@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
		return;

	if ((unsigned)value < ARRAY_SIZE(func_table)) {
		unsigned long flags;

		spin_lock_irqsave(&func_buf_lock, flags);
		if (func_table[value])
			puts_queue(vc, func_table[value]);
		spin_unlock_irqrestore(&func_buf_lock, flags);

	} else
		pr_err("k_fn called with value=%d\n", value);
}
@@ -1991,13 +1996,11 @@ out:
#undef s
#undef v

/* FIXME: This one needs untangling and locking */
/* FIXME: This one needs untangling */
int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
{
	struct kbsentry *kbs;
	char *p;
	u_char *q;
	u_char __user *up;
	int sz, fnw_sz;
	int delta;
	char *first_free, *fj, *fnw;
@@ -2023,23 +2026,19 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
	i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);

	switch (cmd) {
	case KDGKBSENT:
		sz = sizeof(kbs->kb_string) - 1; /* sz should have been
						  a struct member */
		up = user_kdgkb->kb_string;
		p = func_table[i];
		if(p)
			for ( ; *p && sz; p++, sz--)
				if (put_user(*p, up++)) {
					ret = -EFAULT;
					goto reterr;
				}
		if (put_user('\0', up)) {
			ret = -EFAULT;
	case KDGKBSENT: {
		/* size should have been a struct member */
		ssize_t len = sizeof(user_kdgkb->kb_string);

		spin_lock_irqsave(&func_buf_lock, flags);
		len = strlcpy(kbs->kb_string, func_table[i] ? : "", len);
		spin_unlock_irqrestore(&func_buf_lock, flags);

		ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string,
				len + 1) ? -EFAULT : 0;

		goto reterr;
	}
		kfree(kbs);
		return ((p && *p) ? -EOVERFLOW : 0);
	case KDSKBSENT:
		if (!perm) {
			ret = -EPERM;
+5 −6
Original line number Diff line number Diff line
@@ -549,7 +549,7 @@ static int vt_io_fontreset(struct console_font_op *op)
}

static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
		struct vc_data *vc)
		bool perm, struct vc_data *vc)
{
	struct unimapdesc tmp;

@@ -557,9 +557,11 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
		return -EFAULT;
	switch (cmd) {
	case PIO_UNIMAP:
		if (!perm)
			return -EPERM;
		return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
	case GIO_UNIMAP:
		if (fg_console != vc->vc_num)
		if (!perm && fg_console != vc->vc_num)
			return -EPERM;
		return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
				tmp.entries);
@@ -639,10 +641,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,

	case PIO_UNIMAP:
	case GIO_UNIMAP:
		if (!perm)
			return -EPERM;

		return do_unimap_ioctl(cmd, up, vc);
		return do_unimap_ioctl(cmd, up, perm, vc);

	default:
		return -ENOIOCTLCMD;