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
Unified · Split
| @@ -50,25 +50,25 @@ static const char serial21285_name[] = "Footbridge UART"; · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | static bool is_enabled(struct uart_port *port, int bit) |
| 52 | 52 | { |
| 53 | − unsigned long private_data = (unsigned long)port->private_data; | |
| 53 | + unsigned long *private_data = (unsigned long *)&port->private_data; | |
| 54 | 54 | |
| 55 | − if (test_bit(bit, &private_data)) | |
| 55 | + if (test_bit(bit, private_data)) | |
| 56 | 56 | return true; |
| 57 | 57 | return false; |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | static void enable(struct uart_port *port, int bit) |
| 61 | 61 | { |
| 62 | − unsigned long private_data = (unsigned long)port->private_data; | |
| 62 | + unsigned long *private_data = (unsigned long *)&port->private_data; | |
| 63 | 63 | |
| 64 | − set_bit(bit, &private_data); | |
| 64 | + set_bit(bit, private_data); | |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | static void disable(struct uart_port *port, int bit) |
| 68 | 68 | { |
| 69 | − unsigned long private_data = (unsigned long)port->private_data; | |
| 69 | + unsigned long *private_data = (unsigned long *)&port->private_data; | |
| 70 | 70 | |
| 71 | − clear_bit(bit, &private_data); | |
| 71 | + clear_bit(bit, private_data); | |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | 74 | #define is_tx_enabled(port) is_enabled(port, tx_enabled_bit) |
| @@ -314,9 +314,10 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids); · 313 unmodified lines | ||
| 314 | 314 | /* Forward declare this for the dma callbacks*/ |
| 315 | 315 | static void lpuart_dma_tx_complete(void *arg); |
| 316 | 316 | |
| 317 | −static inline bool is_ls1028a_lpuart(struct lpuart_port *sport) | |
| 317 | +static inline bool is_layerscape_lpuart(struct lpuart_port *sport) | |
| 318 | 318 | { |
| 319 | − return sport->devtype == LS1028A_LPUART; | |
| 319 | + return (sport->devtype == LS1021A_LPUART || | |
| 320 | + sport->devtype == LS1028A_LPUART); | |
| 320 | 321 | } |
| 321 | 322 | |
| 322 | 323 | static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport) |
| @@ -1701,11 +1702,11 @@ static int lpuart32_startup(struct uart_port *port) · 1378 unmodified lines | ||
| 1701 | 1702 | UARTFIFO_FIFOSIZE_MASK); |
| 1702 | 1703 | |
| 1703 | 1704 | /* |
| 1704 | − * The LS1028A has a fixed length of 16 words. Although it supports the | |
| 1705 | − * RX/TXSIZE fields their encoding is different. Eg the reference manual | |
| 1706 | − * states 0b101 is 16 words. | |
| 1705 | + * The LS1021A and LS1028A have a fixed FIFO depth of 16 words. | |
| 1706 | + * Although they support the RX/TXSIZE fields, their encoding is | |
| 1707 | + * different. Eg the reference manual states 0b101 is 16 words. | |
| 1707 | 1708 | */ |
| 1708 | − if (is_ls1028a_lpuart(sport)) { | |
| 1709 | + if (is_layerscape_lpuart(sport)) { | |
| 1709 | 1710 | sport->rxfifo_size = 16; |
| 1710 | 1711 | sport->txfifo_size = 16; |
| 1711 | 1712 | sport->port.fifosize = sport->txfifo_size; |
| @@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) · 742 unmodified lines | ||
| 743 | 743 | return; |
| 744 | 744 | |
| 745 | 745 | if ((unsigned)value < ARRAY_SIZE(func_table)) { |
| 746 | + unsigned long flags; | |
| 747 | + | |
| 748 | + spin_lock_irqsave(&func_buf_lock, flags); | |
| 746 | 749 | if (func_table[value]) |
| 747 | 750 | puts_queue(vc, func_table[value]); |
| 751 | + spin_unlock_irqrestore(&func_buf_lock, flags); | |
| 752 | + | |
| 748 | 753 | } else |
| 749 | 754 | pr_err("k_fn called with value=%d\n", value); |
| 750 | 755 | } |
| @@ -1991,13 +1996,11 @@ out: · 1240 unmodified lines | ||
| 1991 | 1996 | #undef s |
| 1992 | 1997 | #undef v |
| 1993 | 1998 | |
| 1994 | −/* FIXME: This one needs untangling and locking */ | |
| 1999 | +/* FIXME: This one needs untangling */ | |
| 1995 | 2000 | int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) |
| 1996 | 2001 | { |
| 1997 | 2002 | struct kbsentry *kbs; |
| 1998 | − char *p; | |
| 1999 | 2003 | u_char *q; |
| 2000 | − u_char __user *up; | |
| 2001 | 2004 | int sz, fnw_sz; |
| 2002 | 2005 | int delta; |
| 2003 | 2006 | char *first_free, *fj, *fnw; |
| @@ -2023,23 +2026,19 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) · 19 unmodified lines | ||
| 2023 | 2026 | i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC); |
| 2024 | 2027 | |
| 2025 | 2028 | switch (cmd) { |
| 2026 | − case KDGKBSENT: | |
| 2027 | − sz = sizeof(kbs->kb_string) - 1; /* sz should have been | |
| 2028 | − a struct member */ | |
| 2029 | − up = user_kdgkb->kb_string; | |
| 2030 | − p = func_table[i]; | |
| 2031 | − if(p) | |
| 2032 | − for ( ; *p && sz; p++, sz--) | |
| 2033 | − if (put_user(*p, up++)) { | |
| 2034 | − ret = -EFAULT; | |
| 2035 | − goto reterr; | |
| 2036 | − } | |
| 2037 | − if (put_user('\0', up)) { | |
| 2038 | − ret = -EFAULT; | |
| 2039 | − goto reterr; | |
| 2040 | − } | |
| 2041 | − kfree(kbs); | |
| 2042 | − return ((p && *p) ? -EOVERFLOW : 0); | |
| 2029 | + case KDGKBSENT: { | |
| 2030 | + /* size should have been a struct member */ | |
| 2031 | + ssize_t len = sizeof(user_kdgkb->kb_string); | |
| 2032 | + | |
| 2033 | + spin_lock_irqsave(&func_buf_lock, flags); | |
| 2034 | + len = strlcpy(kbs->kb_string, func_table[i] ? : "", len); | |
| 2035 | + spin_unlock_irqrestore(&func_buf_lock, flags); | |
| 2036 | + | |
| 2037 | + ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string, | |
| 2038 | + len + 1) ? -EFAULT : 0; | |
| 2039 | + | |
| 2040 | + goto reterr; | |
| 2041 | + } | |
| 2043 | 2042 | case KDSKBSENT: |
| 2044 | 2043 | if (!perm) { |
| 2045 | 2044 | ret = -EPERM; |
| @@ -549,7 +549,7 @@ static int vt_io_fontreset(struct console_font_op *op) · 548 unmodified lines | ||
| 549 | 549 | } |
| 550 | 550 | |
| 551 | 551 | static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, |
| 552 | − struct vc_data *vc) | |
| 552 | + bool perm, struct vc_data *vc) | |
| 553 | 553 | { |
| 554 | 554 | struct unimapdesc tmp; |
| 555 | 555 | |
| @@ -557,9 +557,11 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, · 1 unmodified line | ||
| 557 | 557 | return -EFAULT; |
| 558 | 558 | switch (cmd) { |
| 559 | 559 | case PIO_UNIMAP: |
| 560 | + if (!perm) | |
| 561 | + return -EPERM; | |
| 560 | 562 | return con_set_unimap(vc, tmp.entry_ct, tmp.entries); |
| 561 | 563 | case GIO_UNIMAP: |
| 562 | − if (fg_console != vc->vc_num) | |
| 564 | + if (!perm && fg_console != vc->vc_num) | |
| 563 | 565 | return -EPERM; |
| 564 | 566 | return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), |
| 565 | 567 | tmp.entries); |
| @@ -639,10 +641,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, · 73 unmodified lines | ||
| 639 | 641 | |
| 640 | 642 | case PIO_UNIMAP: |
| 641 | 643 | case GIO_UNIMAP: |
| 642 | − if (!perm) | |
| 643 | − return -EPERM; | |
| 644 | − | |
| 645 | − return do_unimap_ioctl(cmd, up, vc); | |
| 644 | + return do_unimap_ioctl(cmd, up, perm, vc); | |
| 646 | 645 | |
| 647 | 646 | default: |
| 648 | 647 | return -ENOIOCTLCMD; |