Commit 2754a42e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tty-5.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

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
...@@ -50,25 +50,25 @@ static const char serial21285_name[] = "Footbridge UART"; ...@@ -50,25 +50,25 @@ static const char serial21285_name[] = "Footbridge UART";
static bool is_enabled(struct uart_port *port, int bit) 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 true;
return false; return false;
} }
static void enable(struct uart_port *port, int bit) 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) 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) #define is_tx_enabled(port) is_enabled(port, tx_enabled_bit)
......
...@@ -314,9 +314,10 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids); ...@@ -314,9 +314,10 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
/* Forward declare this for the dma callbacks*/ /* Forward declare this for the dma callbacks*/
static void lpuart_dma_tx_complete(void *arg); 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) static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
...@@ -1701,11 +1702,11 @@ static int lpuart32_startup(struct uart_port *port) ...@@ -1701,11 +1702,11 @@ static int lpuart32_startup(struct uart_port *port)
UARTFIFO_FIFOSIZE_MASK); UARTFIFO_FIFOSIZE_MASK);
/* /*
* The LS1028A has a fixed length of 16 words. Although it supports the * The LS1021A and LS1028A have a fixed FIFO depth of 16 words.
* RX/TXSIZE fields their encoding is different. Eg the reference manual * Although they support the RX/TXSIZE fields, their encoding is
* states 0b101 is 16 words. * 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->rxfifo_size = 16;
sport->txfifo_size = 16; sport->txfifo_size = 16;
sport->port.fifosize = sport->txfifo_size; sport->port.fifosize = sport->txfifo_size;
......
...@@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) ...@@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
return; return;
if ((unsigned)value < ARRAY_SIZE(func_table)) { if ((unsigned)value < ARRAY_SIZE(func_table)) {
unsigned long flags;
spin_lock_irqsave(&func_buf_lock, flags);
if (func_table[value]) if (func_table[value])
puts_queue(vc, func_table[value]); puts_queue(vc, func_table[value]);
spin_unlock_irqrestore(&func_buf_lock, flags);
} else } else
pr_err("k_fn called with value=%d\n", value); pr_err("k_fn called with value=%d\n", value);
} }
...@@ -1991,13 +1996,11 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, ...@@ -1991,13 +1996,11 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
#undef s #undef s
#undef v #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) int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
{ {
struct kbsentry *kbs; struct kbsentry *kbs;
char *p;
u_char *q; u_char *q;
u_char __user *up;
int sz, fnw_sz; int sz, fnw_sz;
int delta; int delta;
char *first_free, *fj, *fnw; char *first_free, *fj, *fnw;
...@@ -2023,23 +2026,19 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) ...@@ -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); i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
switch (cmd) { switch (cmd) {
case KDGKBSENT: case KDGKBSENT: {
sz = sizeof(kbs->kb_string) - 1; /* sz should have been /* size should have been a struct member */
a struct member */ ssize_t len = sizeof(user_kdgkb->kb_string);
up = user_kdgkb->kb_string;
p = func_table[i]; spin_lock_irqsave(&func_buf_lock, flags);
if(p) len = strlcpy(kbs->kb_string, func_table[i] ? : "", len);
for ( ; *p && sz; p++, sz--) spin_unlock_irqrestore(&func_buf_lock, flags);
if (put_user(*p, up++)) {
ret = -EFAULT; ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string,
goto reterr; len + 1) ? -EFAULT : 0;
}
if (put_user('\0', up)) {
ret = -EFAULT;
goto reterr; goto reterr;
} }
kfree(kbs);
return ((p && *p) ? -EOVERFLOW : 0);
case KDSKBSENT: case KDSKBSENT:
if (!perm) { if (!perm) {
ret = -EPERM; ret = -EPERM;
......
...@@ -549,7 +549,7 @@ static int vt_io_fontreset(struct console_font_op *op) ...@@ -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, 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; struct unimapdesc tmp;
...@@ -557,9 +557,11 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, ...@@ -557,9 +557,11 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
return -EFAULT; return -EFAULT;
switch (cmd) { switch (cmd) {
case PIO_UNIMAP: case PIO_UNIMAP:
if (!perm)
return -EPERM;
return con_set_unimap(vc, tmp.entry_ct, tmp.entries); return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
case GIO_UNIMAP: case GIO_UNIMAP:
if (fg_console != vc->vc_num) if (!perm && fg_console != vc->vc_num)
return -EPERM; return -EPERM;
return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
tmp.entries); tmp.entries);
...@@ -639,10 +641,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, ...@@ -639,10 +641,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
case PIO_UNIMAP: case PIO_UNIMAP:
case GIO_UNIMAP: case GIO_UNIMAP:
if (!perm) return do_unimap_ioctl(cmd, up, perm, vc);
return -EPERM;
return do_unimap_ioctl(cmd, up, vc);
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment